I have the following C program:
#include <stdio.h>
#include <zlib.h>
int main()
{
z_stream strm;
int integer = 0;
scanf("heloworld %d", &integer);
printf("ok\n");
if (integer == 10)
{
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
deflateInit(&strm, 0);
}
return 0;
}
This is a basic helloworld program which uses zlib.
If I search for the libz library, I can find it under /usr/lib/x86_64-linux-gnu/libz.so:
$ ls -lah libz.so
lrwxrwxrwx 1 root root 40 May 20 14:55 libz.so -> /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
and it is pointing to the real version of libz rather than the soname.
I compile it with the following command and check the dependencies:
$ gcc a.c -lz
$ ldd a.out
linux-vdso.so.1 (0x00007ffec44b6000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f6674055000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6673e63000)
/lib64/ld-linux-x86-64.so.2 (0x00007f667408c000)
How is it pointing to libz.so.1 instead of libz.so.1.2.11 (realname) since the symlink of libz.so.1 is pointing there? I am assuming that the linker is using the symlink however this is not the case.
Further to this, if I perform the following command:
$ objdump -p libz.so.1.2.11 | grep SONAME
SONAME libz.so.1
My question is, is it using the symlink name or the SONAME from the file the symlink provides?
I have discovered that under /lib/x86_64-linux-gnu there are two symlinks for libz.so which are:
libz.so
libz.so.1
When I compile, the linker uses the libz.so as a symlink to point to another .so file.
The .so file which libz.so is pointing to contains an SONAME entry which can be viewed as so:
$ objdump -p ./libz.so | grep SONAME
SONAME libz.so.1
Further I can see that the symlink points to libz.so.1.2.11
$ ls -alh libz.so
lrwxrwxrwx 1 root root 36 May 21 00:51 libz.so -> /lib/x86_64-linux-gnu/libz.so.1.2.11
If I edit the .dynstr section of that library like so:
$ sudo objcopy --dump-section .dynstr=/tmp/dyn.dump ./libz.so.1.2.11
# Find the bytes for libz.so.1 and change them to libz.so.2
$ hexedit /tmp/dyn.dump
$ sudo objcopy --update-section .dynstr=/tmp/dyn.dump ./libz.so.1.2.11
and then recompile my binary I notice:
$ ldd a.out
linux-vdso.so.1 (0x00007ffe54bbe000)
libz.so.2 => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f58bb5c7000)
/lib64/ld-linux-x86-64.so.2 (0x00007f58bb7f0000)
Once I create a symlink of libz.so.2 under /lib/x86_64-linux-gnu/libz.so.2 to point to libz.so.1.2.11 I get the following output:
$ ldd a.out
linux-vdso.so.1 (0x00007ffe54bbe000)
libz.so.2 => /lib/x86_64-linux-gnu/libz.so.2 (0x00007f58bb7b9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f58bb5c7000)
/lib64/ld-linux-x86-64.so.2 (0x00007f58bb7f0000)
Therefore to answer my question it is not the symlink which adds an entry in the runtime dependencies of the executable but the SONAME entry in the shared object.