50

由于使用 Gentoo,经常会发生更新程序与旧版本库链接后的情况。通常, revdep-rebuild 有助于解决这个问题,但这次它依赖于 python 库,并且python-updater不会选择它。

是否有一个“分层”变体ldd向我展示了哪个共享库依赖于另一个共享库?大多数情况下,库和可执行文件仅与少数几个其他共享库链接,而这些共享库又与少数几个共享库链接,从而将库依赖关系变成一个大列表。我想知道我必须用我升级的另一个库的新版本重建哪个依赖项。

4

4 回答 4

96

我看到了许多有趣的细节,但没有直接回答所提出的问题。

的“分层”版本lddlddtree(来自app-misc/pax-utils):

$ lddtree /usr/bin/xmllint 
xmllint => /usr/bin/xmllint (interpreter => /lib64/ld-linux-x86-64.so.2)
    libreadline.so.6 => /lib64/libreadline.so.6
        libncurses.so.5 => /lib64/libncurses.so.5
            libdl.so.2 => /lib64/libdl.so.2
    libxml2.so.2 => /usr/lib64/libxml2.so.2
        libicui18n.so.49 => /usr/lib64/libicui18n.so.49
            libstdc++.so.6 => /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.1/32/libstdc++.so.6
                ld-linux.so.2 => /lib64/ld-linux.so.2
            libgcc_s.so.1 => /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.1/32/libgcc_s.so.1
        libicuuc.so.49 => /usr/lib64/libicuuc.so.49
        libicudata.so.49 => /usr/lib64/libicudata.so.49
        libz.so.1 => /lib64/libz.so.1
        liblzma.so.5 => /usr/lib64/liblzma.so.5
        libm.so.6 => /lib64/libm.so.6
    libpthread.so.0 => /lib64/libpthread.so.0
    libc.so.6 => /lib64/libc.so.6
于 2012-08-18T07:58:56.313 回答
24

如果你使用 运行 Portage≥2.2 ,FEATURES=preserve-libs你应该很少需要revdep-rebuild了,因为旧版本会.so.根据需要保留(尽管你仍然需要仔细重建,因为当需要和需要时,东西仍然会变得很糟糕,而一些二进制文件同时需要和)。libA.so.0libC.so.0libB.so.0libC.so.1libA.so.0libB.so.0


话虽如此,这样ldd做是让动态链接器像往常一样加载可执行文件或库,但在此过程中会打印出一些信息。这是一个递归的“二进制需要库需要其他库&hellip”搜索,因为这就是动态链接器所做的。

我目前正在运行 Linux/ppc32;在 Linux/x86 上,动态链接器通常是/lib/ld-linux.so.2,而在 Linux/x86_64 上,动态链接器通常是/lib/ld-linux-x86-64.so.2. 在这里,我直接调用它只是为了强调一点,一切ldd只不过是一个调用动态链接器来执行其魔法的 shell 脚本。

$ /lib/ld.so.1 /sbin/badblocks
用法:/sbin/badblocks [-b block_size] [-i input_file] [-o output_file] [-svwnf]
       [-c blocks_at_once] [-d delay_factor_between_reads] [-e max_bad_blocks]
       [-p num_passes] [-t test_pattern [-t test_pattern [...]]]
       设备 [last_block [first_block]]
$ LD_TRACE_LOADED_OBJECTS=1 /lib/ld.so.1 /sbin/badblocks
        linux-vdso32.so.1 => (0x00100000)
        libext2fs.so.2 => /lib/libext2fs.so.2 (0x0ffa8000)
        libcom_err.so.2 => /lib/libcom_err.so.2 (0x0ff84000)
        libc.so.6 => /lib/libc.so.6 (0x0fdfa000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x0fdc0000)
        /lib/ld.so.1 (0x48000000)
$ LD_TRACE_LOADED_OBJECTS=1 /lib/ld.so.1 /lib/libcom_err.so.2
        linux-vdso32.so.1 => (0x00100000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x6ffa2000)
        libc.so.6 => /lib/libc.so.6 (0x6fe18000)
        /lib/ld.so.1 (0x203ba000)
$ grep -l pthread /sbin/badblocks /lib/libcom_err.so.2
/lib/libcom_err.so.2

/sbin/badblocks没有libpthread.so.0列为库依赖项,但它被libcom_err.so.2.

您的问题是ldd没有输出漂亮的依赖树吗?使用ldd -v.

$ LD_TRACE_LOADED_OBJECTS=1 LD_VERBOSE=1 /lib/ld.so.1 /sbin/badblocks
        linux-vdso32.so.1 => (0x00100000)
        libext2fs.so.2 => /lib/libext2fs.so.2 (0x0ffa8000)
        libcom_err.so.2 => /lib/libcom_err.so.2 (0x0ff84000)
        libc.so.6 => /lib/libc.so.6 (0x0fdfa000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x0fdc0000)
        /lib/ld.so.1 (0x201f9000)

        版本信息:
        /sbin/坏块:
                libc.so.6 (GLIBC_2.2) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.4) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.1) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.0) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.3.4) => /lib/libc.so.6
        /lib/libext2fs.so.2:
                libc.so.6 (GLIBC_2.1.3) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.4) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.3) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.2) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.1) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.0) => /lib/libc.so.6
        /lib/libcom_err.so.2:
                ld.so.1 (GLIBC_2.3) => /lib/ld.so.1
                libpthread.so.0 (GLIBC_2.1) => /lib/libpthread.so.0
                libpthread.so.0 (GLIBC_2.0) => /lib/libpthread.so.0
                libc.so.6 (GLIBC_2.1.3) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.4) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.1) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.0) => /lib/libc.so.6
        /lib/libc.so.6:
                ld.so.1 (GLIBC_PRIVATE) => /lib/ld.so.1
                ld.so.1 (GLIBC_2.3) => /lib/ld.so.1
        /lib/libpthread.so.0:
                ld.so.1 (GLIBC_2.3) => /lib/ld.so.1
                ld.so.1 (GLIBC_2.1) => /lib/ld.so.1
                ld.so.1 (GLIBC_PRIVATE) => /lib/ld.so.1
                libc.so.6 (GLIBC_2.1.3) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.3.4) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.4) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.1) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.3.2) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.2) => /lib/libc.so.6
                libc.so.6 (GLIBC_PRIVATE) => /lib/libc.so.6
                libc.so.6 (GLIBC_2.0) => /lib/libc.so.6

如果需要,您可以直接读取 ELF 标头,而不是依赖于动态链接器。

$ readelf -d /sbin/badblocks | 需要 grep
 0x00000001(需要)共享库:[libext2fs.so.2]
 0x00000001(需要)共享库:[libcom_err.so.2]
 0x00000001(需要)共享库:[libc.so.6]
$ readelf -d /lib/libcom_err.so.2 | 需要 grep
 0x00000001(需要)共享库:[libpthread.so.0]
 0x00000001(需要)共享库:[libc.so.6]
 0x00000001(需要)共享库:[ld.so.1]

您还可以使用的动态链接器man ld.so来玩其他可爱的技巧。glibc

于 2009-09-29T03:58:01.247 回答
16

我需要这样的东西,所以我写了tldd,这里显示了它自己的库依赖项:

$ ./tldd ./tldd
./tldd
└─libstdc++.so.6 => /lib64/libstdc++.so.6 (0x0000003687c00000)
  ├─libm.so.6 => /lib64/libm.so.6 (0x0000003685000000)
  │ └─libc.so.6 => /lib64/libc.so.6 (0x0000003684c00000)
  │ └─ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x0000003684400000)
  └─libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003686c00000)
于 2014-01-29T01:29:34.777 回答
-2

我还建议使用“readelf -d”,但如果您还没有使用 LDFLAGS="-Wl,--as-needed",请确保您使用它进行构建。这将使您减少遇到此问题的频率。Portage 2.2 的 preserve-libs 很好,但我认为它被掩盖主要是因为它——它确实有缺陷。

于 2012-08-18T07:32:31.147 回答