How does the linker know which archives to link together? - gcc

Suppose that I'm compiling a simple Hello World program with GCC.
When run with gcc -v hello-world.c, we could get the last line from the output which generates the ELF binary:
/usr/libexec/gcc/x86_64-pc-linux-gnu/4.5.3/collect2 --eh-frame-hdr -m
elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/../../../../lib64/crt1.o
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/../../../../lib64/crti.o
/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/crtbegin.o
-L/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/../../../../x86_64-pc-linux-gnu/lib
-L/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/../../.. /tmp/ccRykv97.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.5.3/../../../../lib64/crtn.o
From this output we could see that some objects like crtbegin.o and crtend.o are being linked together. But how does the linker know that these files should be linked togeter?
A separate but similar question is that, if I don't want to use the standard C library, when given a directory of object files that contain the definitions of these functions, how to know the files that are needed to pass to the linker, so that it won't complain about unknown symbols?

we could get the last line from the output which generates the ELF binary
That in fact isn't the actual command that generates the ELF binary. collect in turn invokes ld, and that command generates the binary.
how does the linker know that these files should be linked
It doesn't. GCC told it (by supplying them on command line).
GCC has a compiled-in specs file, which is a domain-specific language little program, that tells GCC what arguments it should supply to the linker.
You can examine the built-in specs with gcc -dumpspecs. You will see that the program is actually quite complicated, and that crtbegin.o is only used when -static and -pie or -shared are not. The -shared implies crtbeginS.o, and -static implies crtbeginT.o.
if I don't want to use the standard C library
Use -nostdlib flag in that case.
given a directory of object files that contain the definitions of these functions, how to know the files that are needed to pass to the linker
The ones that define functions that you use. This might help.

Related

What do link editor (LD) params mean?

I write NASM (netwide assembler) program and for some reasons I needed to use some functions written in C. So, I tried to link compiled C object files with compiled Assembly objects using ld link editor. I did it by this way :
ld -m elf_x86_64 -lc --dynamic-linker=/lib64/ld-linux-x86-64.so.2 object_files -o program.
And it didn't want to link and work long enough until I picked up the necessary parameters. Now this works as expected with this parameter set. But I don't understand the meaning of -lc and --dynamic-linker=/lib64/ld-linux-x86-64.so.2. What do they do ?
-lc - link c standard library
--dynamic-linker=/lib64/ld-linux-x86-64.so.2. - set the program loader. Linux ELF binaries have a field for this.
Afaik the latter is needed even for static binaries, anything other will confuse the loader, and it won't execute.
man ld lists its parameters.

What does gcc -lnsl this flag do?

Sorry for noobie question but I could not understand this .. what does gcc -lnsl flag do .
I tried searching over internet also read about rpc.
This flag tells gcc to link the binary with nsl library. To be more clear, the line gcc -lnsl could be rewritten to more verbose equivalent gcc -l nsl. See man gcc:
-llibrary
-l library
Search the library named library when linking. (The second
alternative with the library as a separate argument is only for
POSIX compliance and is not recommended.)
The -l option is passed directly to the linker by GCC. Refer to
your linker documentation for exact details. The general
description below applies to the GNU linker.
The linker searches a standard list of directories for the
library. The directories searched include several standard
system directories plus any that you specify with -L.

Why isn't boost build preferring the static library?

I am using boost.build.
In one of the steps "g++" -o "testbed/bin/gcc-5.3.0/debug/link-static/get_tag34_tag34_processed" -Wl,--start-group "testbed/bin/gcc-5.3.0/debug/link-static/get_tag34_tag34_processed.o" "/usr/local/lib64/librabbitmq.a" "/usr/lib64/libmysqlcppconn-static.a" "/apps/boost/root/bin.v2/libs/date_time/build/gcc-5.3.0/debug/link-static/libboost_date_time.a" -Wl,-Bstatic -lz -lbz2 -Wl,-Bdynamic -Wl,--end-group -g -lSimpleAmqpClient -lcrypto -ldl -lmysqlcppconn -lpthread -lrdkafka -lrdkafka++ -lssl
I am trying to link to a kafka library.
In the system directory there is the .so and .a /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/librdkafka++.so and /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/librdkafka++.a. However it is preferring the .so.
How do I fix that?
Use full path for .a file. So instead of
-lrdkafka
use
"/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/librdkafka++.a"
(notice lack of '-l')
Alternatively, delete .so. :)
This is not boost.build behavior, this is how gcc and ld work:
-l namespec
--library=namespec
Add the archive or object file specified by namespec to the list of files to link. This option may be used any number of times. If namespec is of the form :filename, ld will search the library path for a file called filename, otherwise it will search the library path for a file called libnamespec.a.
On systems which support shared libraries, ld may also search for files other than libnamespec.a. Specifically, on ELF and SunOS systems, ld will search a directory for a library called libnamespec.so before searching for one called libnamespec.a. (By convention, a ".so" extension indicates a shared library.) Note that this behavior does not apply to :filename, which always specifies a file called filename.
The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause the linker to search the archive again.
See the -( option for a way to force the linker to search archives multiple times.
You may list the same archive multiple times on the command line.
This type of archive searching is standard for Unix linkers. However, if you are using ld on AIX , note that it is different from the behaviour of the AIX linker.

What is the signification of LDFLAGS

I'm trying to compile AODV for ARM linux. I use a SabreLite as a board with kernel version 3.0.35_4.1.0. It's worth mention that i'm using openembedded to create my Linux Distribution for my board.
The AODV source code (http://sourceforge.net/projects/aodvuu/) has a README file which give some indications on how to install it on ARM as stated a bit here.
(http://w3.antd.nist.gov/wctg/aodv_kernel/kaodv_arm.html).
I was able to upgrade the makefile in order to be used with post 2.6 kernel version ( as stated above, i have the 3.0.35_4.1.0 kernel version).
So, basically, what i am trying to do is that i have to create a module (let's say file.ko) and then load it into the ARM (with insmod file.ko command).
To do that, i am using a cross compiler which some values are stated below:
echo $CC :
arm-oe-linux-gnueabi-gcc -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/usr/local/oecore-x86_64/sysroots/cortexa9hf-vfp-neon-oe-linux-gnueabi
echo $ARCH=arm
echo $CFLAGS: O2 -pipe -g -feliminate-unused-debug-types
echo $LD :
arm-oe-linux-gnueabi-ld --sysroot=/usr/local/oecore-x86_64/sysroots/cortexa9hf-vfp-neon-oe-linux-gnueabi
echo $LDFLAGS :
-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -Wl,--as-needed
when i launch "make command", i get the following errors:
LD [M] /home/scof/script_emulation/AODV/aodv-uu/lnx/kaodv.o
arm-oe-linux-gnueabi-ld: unrecognized option '-Wl,-O1'
arm-oe-linux-gnueabi-ld: use the --help option for usage information
It states that there is something wrong with the linker. This linker comes from the cross compilation tools and i normally shouldn't touch it.
Anyway, to get this above errors fixed, i try to withdraw the LDFLAGS like this:
export LDFLAGS='',
and after this, the make command works and i get the module kaodv.ko. But when i insert it into my ARM to check, it does not work. It actually freeze my terminal
So my question is, do i have to specify the LDFLAGS when compiling ? Does withdrawing LDFLAGS can have impact on the generated kernel module.
Actually, i try to understand where might be the problem and the only thing that come to me is that may be i should not change manually the LDFLAGS. But if i don't change de LDFLAGS, i get the unrecognized option error.
My second question related to that is, what are the possibly value of LDFLAGS
in ARM compilation
Thanks !!
echo $LDFLAGS : -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -Wl,--as-needed
There are two common methods of invoking the linker in a GCC-based toolchain. One is to do it directly, but another is to use GCC as a front end to invoke the linker, rather than invoke it directly. When doing this, options intended for the linker are prefixed with -Wl, so that GCC knows to pass them through rather than interpret them itself.
In your case the error message from LD itself
arm-oe-linux-gnueabi-ld: unrecognized option '-Wl,-O1'
Indicates that your build system is passing LDFLAGS directly to the linker, and not by way of GCC.
Therefore, you should remove the -Wl, prefix and your LDFLAGS would instead be
-O1 --hash-style=gnu --as-needed --as-needed
(the duplication of the last argument is probably pointless but benign)
-O1 is an option that tells the linker to optimize. I believe it something new, and your linker may be slightly out of date. Try removing -Wl,-O1, it should still work.

gcc compiling linking .a file

in my homework i must use this command to compile my program:
gcc -o mtm_rentals -std=c99 -Wall -pedantic-errors -Werror -DNDEBUG mtm_ex2.c rentals.c list.c -L -lmtm
what i can change in that line are the files im writing after -DNDEBUG. when i do this the gcc says that there are undefined references to specific functions. now those functions are declared in an .h file and are implemented in a given file called libmtm.a
i concluded that it doesnt recognize libmtm.a, but our homework task says that the -lmtm flag(which is not declared anywhere) is supposed to link libmtm.a to the program.
what am i missing here? am i supposed to implement somehow the -lmtm flag?
thank you!
You are missing a . (single dot) behind the -L.
-lmtm will link against a libmtm library, this is correct. It's not an -lmtm flag, it's a -l flag concatenated with mtm, the library you want to link against. This library is searched in some predefined paths (like /usr/lib/) and additionally in the paths given by -L. Assuming libmtm lives in your current directory, you need to add that to -L, which is done with a ..

Resources