簡體   English   中英

鏈接:為什么 linker 不支持到庫的符號鏈接?

[英]Linking: Why does linker not honour symlink to library?

我有以下 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 而不是 libz.so.1.2.11 (實名)? 我假設 linker 正在使用符號鏈接,但事實並非如此。

除此之外,如果我執行以下命令:

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

我的問題是,它是使用符號鏈接提供的文件中的符號鏈接名稱還是 SONAME?

如果 linker 將 libz.so.1.2.11 放入您的可執行文件中,那么當您更新庫時它會中斷。 相反,它會將 ldconfig 已知的主要版本放入可執行文件中,這反過來又是指向當前安裝版本的鏈接。

參見 ldconfig http://man7.org/linux/man-pages/man8/ldconfig.8.html

我發現在 /lib/x86_64-linux-gnu 下有兩個 libz.so 的符號鏈接,它們是:

libz.so
libz.so.1

當我編譯時,linker 使用 libz.so 作為指向 another.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 后,我得到以下 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)

因此,要回答我的問題,不是在可執行文件的運行時依賴項中添加條目的符號鏈接,而是共享 object 中的 SONAME 條目。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM