GCC linker does not link standard library - c

I'm developing a basic kernel for my term project. Until now, I haven't used any standard libraries in my project but I needed gets(), I included <stdio.h>. GCC finds the header location but the linker gives error :
ld -melf_i386 -Tlink.ld -o kernel boot.o main.o monitor.o common.o descriptor_tables.o isr.o interrupt.o gdt.o timer.o
main.o: In function `main':
main.c:(.text+0x53): undefined reference to `gets'
This is my Makefile file,
SOURCES=boot.o main.o monitor.o common.o descriptor_tables.o isr.o interrupt.o gdt.o timer.o
CFLAGS= -m32 -fno-stack-protector -fstack-check
LDFLAGS= -melf_i386 -Tlink.ld
ASFLAGS=-felf
all: $(SOURCES) link
clean:
-rm *.o kernel
link:
ld $(LDFLAGS) -o kernel $(SOURCES)
.s.o:
nasm $(ASFLAGS) $<

You cannot use the C library for a kernel as it is build for an existing kernel and relies on the syscalls of its target OS. Instead, you have to write a driver for keyboards and everything else you need to get characters from anywhere. getc() is a very advanced function from that point of view and you should consider making the basic functions of the kernel stable before programming anything to interact with.
By the way, you should really build a cross compiler. It has many advantages over feeding the system compiler with awkward options. After all, the kernel is meant to run on different machines, so it should be compiled for bare x86, which is what a cross-compiler does.
Keep coding this thing!
leitimmel

Related

makefile used compile program in Mac and cross compiler flags it uses in it.what they means & alternative 4 the flags if I am not using cross-compiler

I have a simple OS and Bootloader code downloaded from https://github.com/FRosner/FrOS/tree/minimal-c-kernel
tutorial is at https://dev.to/frosnerd/writing-my-own-boot-loader-3mld
I have some questions about the make file
in below makefile what is x86_64-elf-ld, ld I belive is to link the object files and libraries into output .a and bin files which are libraries. So I believe to output a library called kernel.bin the author used ld's -o flag since its linker then the output is .bin file. I like to know can I output .o file from ld program (by using only ld program can I output .o binary executable, if no, then I assumed its a linker not compiler and compiler can output only executable/or self executable with main() and linker can output only library which needed by some other executable code to call its functions )
the first line is noticed is
kernel.bin: kernel_entry.o kernel.o
x86_64-elf-ld -m elf_i386 -o $# -Ttext 0x1000 $^ --oformat binary
since the author built the program in Mac computer and wanted to output binary from code that runs on x86-64 architecture so he needed x86-64 linker which is x86_64-elf-ld and can be easily installed on Mac. But I do not have Mac, I have x86-64 computer then can I use only ld instead of cross platform ld which is x86_64-elf-ld on authors computer also what is -m flag? does -m is an option and elf_i386 is a value of the option -m, can any one please clarify this. or are they (-m and elf_i386 are two separate things if yes then what they mean?) and is with flag -Ttext can I specify the address of output file? so what exactly above two lines means along with there flags
this is next is
kernel_entry.o: kernel_entry.asm
nasm $< -f elf -o $#
what is -f flag and what is elf in above two lines? in above its output-ing .o $# target file which is executable. with NASM assembly compiler
so in rest of the makefile what are -m32,-b,-f,-ffreestanding,-fda flags and what is xxd program?
These are many questions or someone just direct me to some page where I will not like to be lost in dozens of flags. May concise page where these flags can be covered. Or if some one take time to explain them then very thanks
# $# = target file
# $< = first dependency
# $^ = all dependencies
# First rule is the one executed when no parameters are fed to the Makefile
all: run
# Notice how dependencies are built as needed
kernel.bin: kernel_entry.o kernel.o
x86_64-elf-ld -m elf_i386 -o $# -Ttext 0x1000 $^ --oformat binary
kernel_entry.o: kernel_entry.asm
nasm $< -f elf -o $#
kernel.o: kernel.c
x86_64-elf-gcc -m32 -ffreestanding -c $< -o $#
# Disassemble
kernel.dis: kernel.bin
ndisasm -b 32 $< > $#
mbr.bin: mbr.asm
nasm $< -f bin -o $#
os-image.bin: mbr.bin kernel.bin
cat $^ > $#
run: os-image.bin
qemu-system-i386 -fda $<
echo: os-image.bin
xxd $<
clean:
$(RM) *.bin *.o *.dis
now the only question I have is why I have to resort to using
x86_64-elf-ld linker and x86_64-elf-gcc compiler since the author used
them because he was not developinh makefile and program on x86-64. But
why I have to use them. So question actually is now: can I use only
gcc instead of x86_64-elf-gcc cross compiler and can I use ld as
linker instead of x86_64-elf-ld cross platform linker.
in short, it is recommended to use a cross compiler when developing an os because it:
allows you to leave the current operating system behind, meaning that
no headers or libraries of your host operating system will be used.
You need a cross-compiler for operating system development, otherwise
a lot of unexpected things can happen because the compiler assumes
that your code is running on your host operating system.
for more information see:
Why do I need a Cross Compiler?
GCC Cross-Compiler
hence, even if you are on x86-64 it is still recommended to use a cross compiler, because it will save you a lot of trouble.
as for the linker, on osdev.org they recommend to:
Linking with your compiler rather than ld
You shouldn't be invoking ld directly. Your cross-compiler is able to
work as a linker and using it as the linker allows it control at the
linking stage. This control includes expanding the -lgcc to the full
path of libgcc that only the compiler knows about. If you get weird
errors during compilation, use your cross-compiler for linking and it
may go away. If you do need ld, be sure to use the cross-linker
(i686-elf-ld) rather than the system linker.
see also: https://wiki.osdev.org/Category:FAQ

compile multiple cuda files (that have dynamic parallelism) and MPI code

I have a bunch of .cu files that use dynamic parallelism (a.cu, b.cu, c.cu.., e.cu, f.cu), and a main.c file that uses MPI to call functions from a.cu on multiple nodes. I'm trying to write a make file to compile the executable, but I keep facing the following errors:
cudafiles.o: In function `__cudaRegisterLinkedBinary_66_tmpxft_00001a84_00000000_17_cuda_device_runtime_compute_61_cpp1_ii_8b1a5d37':
link.stub:(.text+0x1fb): undefined reference to `__fatbinwrap_66_tmpxft_00001a84_00000000_17_cuda_device_runtime_compute_61_cpp1_ii_8b1a5d37'
Here is my makefile:
INCFILES=-I/usr/local/cuda-8.0/include -I/opt/mpi/mvapich2-gnu/2.2/include -I./
LIBFILES=-L/usr/local/cuda-8.0/lib64 -L/opt/mpi/mvapich2-gnu/2.2/lib
LIBS=-lcudart -lcudadevrt -lcublas_device -lmpi
ARCH=-gencode arch=compute_60,code=sm_60
NVCC=nvcc -ccbin g++
default: all
all: clean final.o
io.o: io.cpp
g++ -c -std=c++11 io.cpp
final.o: io.o a.cu b.cu c.cu d.cu e.cu f.cu main.cpp
$(NVCC) -std=c++11 $(INCFILES) $(LIBFILES) $(LIBS) -g -G -Xptxas -v -dc $(ARCH) a.cu b.cu c.cu d.cu e.cu f.cu
$(NVCC) -std=c++11 $(ARCH) $(INCFILES) $(LIBFILES) $(LIBS) -rdc=true -dlink a.o b.o c.o d.o e.o f.o io.o -o cudafiles.o
mpicxx -O3 $(INCFILES) $(LIBFILES) -c main.cpp -o main.o
mpicxx $(INCFILES) $(LIBFILES) $(LIBS) cudafiles.o a.o b.o c.o d.o e.o f.o io.o main.o -o exec
clean:
rm -rf *.o exec
The original problem reported was an undefined reference to main. This was arising from this line in the Makefile:
$(NVCC) -std=c++11 $(ARCH) $(INCFILES) $(LIBFILES) $(LIBS) -rdc=true a.o b.o c.o d.o e.o f.o io.o -o cudafiles.o
As constructed, this actually instructs nvcc to perform full/final linking. However the intent of this line was to perform the device-link step only, required when compiling with -rdc=true or -dc, and when not performing the final link with nvcc. In this case, the final link was being performed by mpicc/mpicxx. To perform the device-link step only, we need to specify -dlink. Without that switch, nvcc expects to do final linking, but fails because none of the supplied objects contain a main function. The correct solution, since we have no intent to do final link at this point, is to use the -dlink switch.
I also suggested converting everything to C++ style linking, since nvcc links that way. It might be possible to sort out a C-style link with a C++-style link, but this just seems troublesome to me. Therefore I suggested converting the only .c file (main.c) to a .cpp file, and convert from mpicc to mpicxx
The next problem that arose was undefined references to e.g. cudaSetDevice() and cudaFree(). These are part of the CUDA runtime API library ("libcudart"). When performing final link with nvcc, these are linked automatically. But since final link is being performed by mpicxx (basically a wrapper on g++), it's necessary to call out the link against that library specifically with -lcudart.
Finally, the remaining problem was a link-order problem. In a nutshell, link dependencies need to be satisfied from left to right in the linker command line. Different compilers are more or less picky about this. The final reordering changes were to specify the libraries to link against in the correct order, and also to specify these libraries at the end of the link command line, so that any dependencies on these libraries, to their left in the link command line, are satisfied.

C Makefile error: ld returned 1 exit

My teacher is not the best at explain C so I'm having a bit of trouble understanding the connection of makefiles. I have already added the code for complex.c, complex.h, and main.c. I'm just having trouble compiling it all using the make command. I followed the example on the powerpoint he handed up and I don't understand why its failing to get to complex.
makefile
complex: main.o complex.o
gcc -o complex main.o complex.o
main.o: main.c complex.h
gcc -c main.c -lm
complex.o: complex.c complex.h
gcc -c complex.c -lm
clean:
rm*.o complex
ls
main.o
main.o: complex.h
gcc -c main.c
complex.o
complex.o: complex.h
gcc -c complex.c
Error
mason% make
gcc -o complex main.o complex.o
ld: fatal: file main.o: unknown file type
ld: fatal: file processing errors. No output written to complex
collect2: error: ld returned 1 exit status
*** Error code 1
make: Fatal error: Command failed for target `complex'
It looks like you have put Makefile fragments inside main.o and complex.o. These should be generated by the compiler, not by you.
Delete these files, and make again.
Additionally, your make clean rule is missing a space.
clean:
rm *.o complex
ls
One more thing. No need for -lm in the compile lines.
main.o: main.c complex.h
gcc -c main.c
complex.o: complex.c complex.h
gcc -c complex.c
You should add -lm at the linking phase.
complex: main.o complex.o
gcc -o complex main.o complex.o -lm
The "Makefile" defines and controls the build dependencies.
For example, you can't build the main executable binary without first building the binary object/module files that go with it. In this case, those are main.o and complex.o.
Generally any object file you need also needs a rule (though some rules can use "wildcards" to build more).
This is all rather academic. Best to take errors at their word and try to disprove them (this one basically says that main.o exists and is incorrect). In this case the hypothesis that main.o exists is supported by the fact that it didn't compile when you ran the make command.
Until you learn more you could invoke "make" using "targets". Like: make clean and make complex. It might help bring clarity.
A lot of makefiles put an "all" target to sort of reset the build. That then depends on "clean" and the executable and library targets. Like:
all: clean complex
So then you "make all" to clean and build.
A good tutorial is here. Mrbook Makefile Tutorial

How to properly link msgpack into a shared library

I'm trying to compile a few .c files that used msgpack-c functions into a shared library. I have the following Makefile:
MSGPACK_CS = msgpack.c
CFLAGS = -std=c99
MSGPACK_OBJECTS = $(subst .c,.o,$(MSGPACK_CS))
MSGPACK_LIBS = msgpack.so
all: $(MSGPACK_OBJECTS) $(MSGPACK_LIBS)
%.o: %.c
$(CC) -c -shared -fPIC $(CFLAGS) $<
$(MSGPACK_LIBS): $(MSGPACK_OBJECTS)
ld -Lmsgpack/.libs -share -o $# $(MSGPACK_OBJECTS) -lmsgpack
I can compile a program that uses msgpack without problem, but this gives me the following error:
msgpack.o: In function `msgpack_pack_int64':
/usr/local/include/msgpack/pack_template.h:373: undefined reference to `__stack_chk_fail_local'
ld: msgpack.so: hidden symbol `__stack_chk_fail_local' isn't defined
ld: final link failed: Bad value
Apparently the linkage process isn't going well, but I don't know what is wrong. What can I do?
Try linking with the gcc driver instead of calling ld directly. ld doesn't know about the gcc support libs that are needed for the C runtime:
gcc -Lmsgpack/.libs -shared -o $# $(MSGPACK_OBJECTS) -lmsgpack
If this still doesnt't work, you might need to add -fno-stack-protector to your CFLAGS to supress runtime stack checking.

Compiling/ Linking SoftFloat library using mips-linux-gnu-gcc

I am trying to compile and link a small C benchmark with floating-point operations for a MIPS target. The floating-point emulation library used with the benchmark is the SoftFloat. http://www.jhauser.us/arithmetic/SoftFloat.html
The MIPS compiler is an LLVM retargetted MIPS compiler release by MIPS Technologies: http://www.imgtec.com/mips/developers/clang-llvm.asp
Compilation is successful with the main program and also the library files. However, during linking, an error is thrown:
softfloat-macros:70: undefined reference to `__ucmpdi2'
In my opinion, the SoftFloat library is already a comprehensive library of functions which does not require me to write any new ones. However, my conclusion may be inaccurate due to my limited knowledge in compiling and linking libraries.
My main questions are:
Can the SoftFloat library be incomplete for my target and do I need to write the missing function of __ucmpdi2? Or is there something else that I am missing?
Am I compiling or linking the SoftFloat library incorrectly?
Below is an excerpt of my Makefile. I hope someone can help point out in case there is something wrong.
FILENAME = dfadd
MARCH = -mips1
MIPSGCC = mips-linux-gnu-gcc
MIPSLD = mips-linux-gnu-ld
CFLAGS = -Wall -c -g -msoft-float -mno-abicalls -I. $(MARCH)
mips: softfloat-macros softfloat-specialize milieu.h softfloat.h SPARC-GCC.h softfloat.c dfadd.c
$(MIPSGCC) -$(OPT) $(CFLAGS) $(FILENAME).c
$(MIPSAS) -o boot.o boot.asm
$(MIPSLD) -Ttext 0 -eentry -Map $(FILENAME).map -s -N -o $(FILENAME).elf boot.o $(FILENAME).o
The commands executed and the error is thrown at linker stage:
mips-linux-gnu-gcc -O0 -Wall -c -g -msoft-float -mno-abicalls -I. -mips1 dfadd.c
mips-linux-gnu-as -o boot.o boot.asm
mips-linux-gnu-ld -Ttext 0 -eentry -Map dfadd.map -s -N -o dfadd.elf boot.o dfadd.o
dfadd.o: In function `shift64RightJamming':
/home/jon/Work/bennchmark/dfadd/softfloat-macros:70: undefined reference to `__ucmpdi2'
make: *** [mips] Error 1

Resources