how does a linker functions? - c

In static linking, how does the linker knows which library file to link the user's compiled object code against? I mean the header only contains the function protoytpes that may be used in the source code, not the library file name.. isn't it?

That's why you provide the linker with a list of libraries to link against!
e.g. for GCC, you might do something like:
gcc my_prog.o -lm -lpthread -o my_prog
Here, the -l flag is used to tell the linker to link against libm and libpthread.

It gets a list of libraries from the command line. The specifics will depend on the OS and the compiler.

Related

How to use LibFuzz on a C project that is not a library

I am trying to run libFuzz on a C project that usually compiles to an executable. The examples I found for libFuzz almost exclusively link with a library, i.e. a mylibary.a file. So I compiled the project with the normal Makefile, and combined the generated object files into a library with ar rcs a.o b.o etc.. Now I want to link this library file with the fuzzing target using clang++, but the linker is not able to find the implementation of the function I want to fuzz.
The command I use for linking inside the src directory of the project is
clang++ -Wall -fsanitize=fuzzer -Wno-cpp -Wpedantic -std=c++11 -O2 -g  -I/usr/include/libxml2 -g -O2 -rdynamic  -o fuzzing libmylib.a fuzztarget.cc -lcurl -lxml2 -I.
The error I get is "Undefined reference to function_xy()"
So the compiler finds the import of the function but not the implementation of it.
I am new to clang and generally building complex C projects so all help is greatly appreciated. Thank you!
I tried compiling the project with the included Makefile, then combining the generated object files into a .a library and finally linking the library with my fuzzing target.
The error you got is about linking, not the LibFuzzer. If you can compile and link your file without implementing function in LLVMFuzzerTestOneInput, then the fuzz-target should work: Include header in your code, call the function, compile file and link with libraries. Please check the order of include path, file, linked libraries. Be careful with the option of optimization (-O2), sometimes the fuzzer does not give crash with this option.

GCC/ld not using shared object with -l

I've read this question: ld cannot find shared library even with -L specified, but I'm asking a follow-up: why does GCC do this?
This is something I ran into while building a binary with links to two in-house libraries.
gcc cannot find the symbols from one of the libraries with -l, but uses the other one just fine!
Originally, the command from my Makefile was gcc baz.o qux.o -lfoo -lbar, with the linker unable to find the symbols from libfoo, while finding the symbols from -lbar. The libraries are the exact same type of file in the same locations: headers in /usr/local/include and libraries in /usr/local/lib. In fact, libfoo depends on libbar.
Corrected, the command is now gcc baz.o qux.o -lbar /usr/local/lib/libfoo.so. I have determined this is not an ordering issue.
Why does gcc need the shared object instead of an -l? Is there a better way to do this, other than using the absolute path? This solution seems kludgy to me.
The exact code and output I'm using are as follows:
Output from using -lsandbox
The content of libsandbox.h
The Makefile I'm referencing, annotated.
Thanks!

How do I link a library file in GCC that does not start with lib?

When I link a library such as libm in with ld, I need to drop the lib prefix. What if the file does not follow this naming convention? Is there a way to link it other than renaming the file?
You can have the linker search for a library named without the lib prefix:
gcc main.o -L/path/to/foo -l:foo.a
This is especially useful in environments where a list of libraries is specified and the -l flag is prepended later (eg some makefiles or eclipse CDT)
You can link against any library, e.g. foo.a, by specifying full path to it on the link line:
gcc main.o /path/to/foo.a
What you lose with non-standard library name is the ability for the linker to search for it, e.g. this will not work:
gcc main.o -L/path/to foo.a
You can avoid that lack of search by using -l:foo.a syntax:
gcc main.o -L/path/one -L/path/two -l:foo.a
When I link a library such as libm in with ld
Note that in general you should not link anything with ld. Use the compiler driver instead -- it adds objects and libraries to the link line that are required for correct result.

gcc detect duplicate symbols/functions in static libraries

Is there any way we can get gcc to detect a duplicate symbol in static libraries vs the main code (Or another static library ?)
Here's the situation:
main.c erroneously contained a function definition, e.g. with the signature uint foohash(const char*)
foo.c also contains a function definition with the signature uint foohash(const char*)
foo.c and other source files are compiled to a static util library, which the main program links in, i.e. something like:
gcc -o main main.o util.o -L ./libs -lfooutils
So, now main.o and libs/libfooutils.a both contain a foohash function. Presumably the linker found that symbol in main.o and doesn't bother looking for it elsewhere.
Is there any way we can get gcc to detect such a situation ?
Indeed as Simon Richter stated, --whole-archive option can be useful. Try to change your command-line to:
gcc -o main main.o util.o -L ./libs -Wl,--whole-archive -lfooutils -Wl,--no-whole-archive
and you'll see a multiple definition error.
gcc calls the ld program for linking. The relevant ld options are:
--no-define-common
--traditional-format
--warn-common
See the man page for ld. These should be what you need to experiment with to get the warnings sought.
Short answer: no.
GCC does not actually do anything with libraries. It is the task of ld, the linker (called automatically by GCC) to pull in symbols from libraries, and that's really a fairly dumb tool.
The linker has lots of complex jiggery pokery for combining different types of data from different sources, and supporting different file formats, and all the evil little details of binary executables, but in the end, all it really does is look for undefined symbols and find the definitions.
What you can do is a link trace (pass -t to gcc) to see what comes from where. Or else run nm on all the object files and libraries in your system, and write a script to detect duplicates.

Statically linking against LAPACK

I'm attempting to do a release of some software and am currently working through a script for the build process. I'm stuck on something I never thought I would be, statically linking LAPACK on x86_64 linux. During configuration AC_SEARCH_LIB([main],[lapack]) works, but compilation of the lapack units do not work, for example undefiend reference to 'dsyev_' --no lapack/blas routine goes unnoticed.
I've confirmed I have the libraries installed and even compiled them myself with the appropriate options to make them static with the same results.
Here is an example I had used in my first experience with LAPACK a few years ago that works dynamically, but not statically: http://pastebin.com/cMm3wcwF
The two methods I'm using to compile are the following,
gcc -llapack -o eigen eigen.c
gcc -static -llapack -o eigen eigen.c
Your linking order is wrong. Link libraries after the code that requires them, not before. Like this:
gcc -o eigen eigen.c -llapack
gcc -static -o eigen eigen.c -llapack
That should resolve the linkage problems.
To answer the subsequent question why this works, the GNU ld documentation say this:
It makes a difference where in the command you write this option; the
linker searches and processes libraries and object files in the order
they are specified. Thus, foo.o -lz bar.o' searches libraryz' after
file foo.o but before bar.o. If bar.o refers to functions in `z',
those functions may not be loaded.
........
Normally the files found this way are library files—archive files
whose members are object files. The linker handles an archive file by
scanning through it for members which define symbols that have so far
been referenced but not defined. But if the file that is found is an
ordinary object file, it is linked in the usual fashion.
ie. the linker is going to make one pass through a file looking for unresolved symbols, and it follows files in the order you provide them (ie. "left to right"). If you have not yet specified a dependency when a file is read, the linker will not be able to satisfy the dependency. Every object in the link list is parsed only once.
Note also that GNU ld can do reordering in cases where circular dependencies are detected when linking shared libraries or object files. But static libraries are only parsed for unknown symbols once.

Resources