As far as my understanding goes, when I compile my C source code, GCC/LD does the address binding at compile time. Typically, this address starts at zero. When I call a function from shared library, how does the compiler know the address of the shared library in advance? I know shared libraries get their address at load time. Please correct me if I am wrong.
-
Searching for "dynamic linking" (which you already appear to know since you selected that tag) yields loads of information already. What specific questions do you have? (Covering the whole process is quite a task.)– MatOct 27, 2015 at 10:53
-
suppose I called the printf() function. How the compiler will know the memory location of printf() function at compile time?– SaberOct 27, 2015 at 12:03
-
4It doesn't, that's why it's called dynamic linking.– MatOct 27, 2015 at 12:05
1 Answer
You can do a few things to help yourself understand this.
ldd /usr/bin/cat
On my laptop, that gives this output:
1771 % ldd /usr/bin/cat
linux-vdso.so.1 (0x00007ffc37fba000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f1ea7018000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1ea73bc000)
You'll notice that linux-vdso.so.1
and libc.so.6
don't have a fully qualified path, and that ldd
shows you what the actual path that would be used to dynamically link in libc.so.6
is.
You can check that (and learn a bit) by doing the ldd
again, with a little variation:
1790 % export LD_LIBRARY_PATH=/lib
1791 % ldd /usr/bin/cat
linux-vdso.so.1 (0x00007fff0a5a0000)
libc.so.6 => /lib/libc.so.6 (0x00007fa257535000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa2578d9000)
Looking closely, you can see that the dynamic linker (/lib64/ld-linux-x86-64.so.2
in this case) will now choose /lib/libc.so.6
as the C library. So the enironment variable LD_LIBRARY_PATH is important to deciding which files actually get used in dynamic linking.
The other thing you can do is strace
:
strace -o cat.trace /usr/bin/cat /etc/motd
The file cat.trace
will have a record of what system calls your subject process performs. Some of them will be mmap()
of the files shown by ldd
as getting dynamically linked in. Follow up by googlling for mmap
.
Further reading: man ld.so
.
See if you have the readelf
command installed, or if you can install it, or compile it. Run readelf -a /usr/bin/cat
. The actual ELF specification is impenetrable in my opinion, but there is some good ELF format information out there. Try to find it.
If you have the musl libc
installed, or can install it, doing the same experiments as above on a simple executable compiled with musl libc can be very informative. Even something as complex as dynamic linking can have two different, working implementations on the same operating system.
-
1