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.
You can do a few things to help yourself understand this.
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
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
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 -o cat.trace /usr/bin/cat /etc/motd
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
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.