【发布时间】:2011-04-05 15:26:27
【问题描述】:
ldd 怎么知道它依赖于 libc.so.6,而不是 libc.so.5 或 libc.so.7?
libc.so.6 => /lib64/libc.so.6 (0x00000034f4000000)
/lib64/ld-linux-x86-64.so.2 (0x00000034f3c00000)
【问题讨论】:
ldd 怎么知道它依赖于 libc.so.6,而不是 libc.so.5 或 libc.so.7?
libc.so.6 => /lib64/libc.so.6 (0x00000034f4000000)
/lib64/ld-linux-x86-64.so.2 (0x00000034f3c00000)
【问题讨论】:
它记录在应用程序二进制文件本身中(在编译时指定,更准确地说是在链接步骤,使用ld 完成):
$ readelf -d /bin/echo
Dynamic section at offset 0x5f1c contains 21 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libc.so.6]
...
(还有一些关于 elf 如何在动态部分中存储信息的附加列。但是您可以看到 libc.so.6 是用.6 后缀硬编码的,因为SONAME)
甚至对 ELF 文件格式一无所知:
$ strings /bin/echo |grep libc.so
libc.so.6
要查找,链接器如何找到库(在编译的最后一步完成),使用gcc 选项-Wl,--verbose(这要求gcc 将选项--verbose 传递给ld):
$ gcc a.c -Wl,--verbose
...
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/libc.so failed
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/libc.a failed
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/libc.so failed
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/libc.a failed
attempt to open /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/../../../libc.so succeeded
opened script file /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/../../../libc.so
opened script file /usr/lib/gcc/i686-pc-linux-gnu/4.4.4/../../../libc.so
attempt to open /lib/libc.so.6 succeeded
/lib/libc.so.6
链接器对.digit 后缀一无所知,它只是遍历所有试图打开libLIBNAME.so 和libLIBNAME.a 的库搜索目录,其中LIBNAME 是-l 选项之后的字符串。 (默认添加-lc选项)。
第一个成功是/usr/lib/libc.so,它本身不是一个库,而是一个链接器脚本(文本文件)。以下是典型 libc.so 脚本的内容:
$ cat /usr/lib/libc.so
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf32-i386)
GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.2 ) )
所以,脚本/usr/lib/libc.so 比实际库更早找到,这个脚本说,什么文件将被链接,libc.so.6 在这种情况下。
在更常见的情况下,lib___.so 是某个版本的符号链接,例如lib___.so.3.4.5,并且在lib___.so.3.4.5 中填写了 SONAME 字段,表示ld 链接不是lib___.so,而是lib___.so.3.4,这是另一个符号链接到lib___.so.3.4.5。 .3.4 名称将记录在二进制的 NEEDED 字段中。
【讨论】:
0x00000001 (NEEDED) 是什么意思?
ldconfig 是否真的会将libc.so.6 链接到libc.so.6.x 的最新版本,并将lib.so 链接到libc.so.x 的最新版本?假设lib.so链接到lib.so.7,那么gcc -l lib.so ...生成的二进制文件将依赖于lib.so.7,对吧?
/usr/lib/libc.so 是一个文本文件,所以我用 cat 打开它。在我们的机器上,或者使用其他库,您应该运行 gcc -Wl,--verbose 以了解链接器如何搜索 lib,以及链接器脚本在哪里。
http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#dynamic_section
具有各个动态标签的含义。 1 表示它是一个 DT_NEEDED 标签,在这种情况下意味着
typedef struct {
Elf32_Sword d_tag;
union {
Elf32_Word d_val;
Elf32_Addr d_ptr;
} d_un;
} Elf32_Dyn;
结构的 d_val union 有效,并在 DT_STRTAB 表中查找由 thi union 成员指定的偏移量,以查找此二进制/SO 所依赖的库的名称。
【讨论】: