【问题标题】:Understanding ldd output了解 ldd 输出
【发布时间】:2011-04-05 15:26:27
【问题描述】:

ldd 怎么知道它依赖于 libc.so.6,而不是 libc.so.5libc.so.7

libc.so.6 => /lib64/libc.so.6 (0x00000034f4000000)
/lib64/ld-linux-x86-64.so.2 (0x00000034f3c00000)

【问题讨论】:

    标签: linker ldd


    【解决方案1】:

    它记录在应用程序二进制文件本身中(在编译时指定,更准确地说是在链接步骤,使用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.solibLIBNAME.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,对吧?
    • +1 用于编辑您的答案以包含如此多有用的信息。这是一个经典的 SO 帖子。谢谢。
    • @osgx,你最初是如何打开链接描述文件的?
    • @compile-fan,在我的机器上 /usr/lib/libc.so 是一个文本文件,所以我用 cat 打开它。在我们的机器上,或者使用其他库,您应该运行 gcc -Wl,--verbose 以了解链接器如何搜索 lib,以及链接器脚本在哪里。
    【解决方案2】:

    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 所依赖的库的名称。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      • 1970-01-01
      • 2021-05-26
      • 2017-04-18
      • 2016-12-24
      相关资源
      最近更新 更多