链接:链接器为什么不遵守与库的符号链接?

时间:2020-05-20 14:03:30

标签: linux compilation ld shared-objects libz

我有以下C程序:

#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;
}

这是使用zlib的基本helloworld程序。

如果我搜索libz库,可以在/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

,它指向的是libz的真实版本,而不是soname。

我用以下命令编译它并检查依赖项:

$ 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)

由于libz.so.1的符号链接指向libz.so.1.2.11(真实名称),因此它如何指向libz.so.1?我假设链接器正在使用符号链接,但事实并非如此。

此外,如果我执行以下命令:

$ objdump -p libz.so.1.2.11 | grep SONAME
SONAME               libz.so.1 

我的问题是,它是使用符号链接名称还是符号链接提供的文件中的SONAME?

2 个答案:

答案 0 :(得分:2)

如果链接器将libz.so.1.2.11放入可执行文件中,则在更新库时它将断开。而是将ldconfig已知的主要版本放入可执行文件中,该文件又是指向当前已安装版本的链接。

请参见ldconfig http://man7.org/linux/man-pages/man8/ldconfig.8.html

答案 1 :(得分:0)

我发现/ lib / x86_64-linux-gnu下有两个libz.so的符号链接:

libz.so
libz.so.1

编译时,链接器将libz.so用作符号链接,以指向另一个.so文件。

libz.so指向的.so文件包含一个SONAME条目,可以这样查看:

$ objdump -p ./libz.so | grep SONAME
SONAME               libz.so.1

我还可以看到符号链接指向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

如果我像这样编辑该库的.dynstr部分:

$ 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

然后重新编译我的二进制文件,我注意到:

$ 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)

一旦我在/lib/x86_64-linux-gnu/libz.so.2下创建libz.so.2的符号链接,指向libz.so.1.2.11,我将得到以下输出:

$ 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)

因此要回答我的问题,不是符号链接在可执行文件的运行时依赖项中添加条目,而是在共享库中添加了SONAME条目。

相关问题