简体   繁体   English

分层ldd(1)

[英]Hierarchical ldd(1)

Due to using Gentoo, it often happens that after an update programs are linked against old versions of libraries. 由于使用Gentoo,经常会在更新程序与旧版本的库链接之后发生。 Normally, revdep-rebuild helps resolving that, but this time it's a dependency on a python library, and python-updater won't pick it up. 通常,revdep-rebuild有助于解决这个问题,但这次它是对python库的依赖,而python-updater不会解析它。

Is there a "hierarchical" variant of ldd which shows me what shared library depends on which another shared library? 是否存在ldd的“分层”变体,它向我展示了共享库依赖于哪个共享库? Most of the time libraries and executables are linked only against a handful of other shared libraries, which in turn were linked against a handful, turning the library dependency into a big list. 大多数情况下,库和可执行文件仅与少数其他共享库链接,而这些共享库又与少数共享库相关联,将库依赖项转换为大型列表。 I want to know which dependency I've got to rebuild with the new version of another library that I upgraded. 我想知道我使用我升级的另一个库的新版本重建哪个依赖项。

I see many interesting details but no direct answer to the question asked. 我看到许多有趣的细节,但没有直接回答问题。

The 'hierarchical' version of ldd is lddtree (from app-misc/pax-utils ): ldd的“层次结构”版本是lddtree (来自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

If you are running Portage≥2.2 with FEATURES=preserve-libs , you should rarely ever need revdep-rebuild anymore as old .so. 如果你使用FEATURES=preserve-libs运行Portage≥2.2,那么你应该很少需要revdep-rebuild作为旧的.so. vers will be preserved as needed (though you still need to rebuild carefully, as stuff still goes kaboom when libA.so.0 wants libC.so.0 and libB.so.0 wants libC.so.1 and some binary wants both libA.so.0 and libB.so.0 ). 将根据需要保留vers(虽然你仍然需要仔细重建,因为当libA.so.0想要libC.so.0libB.so.0想要libC.so.1并且一些二进制文件想要libA时,东西仍然会变成libA.so.0libB.so.0 )。


That being said, what ldd does is to get the dynamic linker to do load the executable or library as it usually would, but print out some info along the way. 话虽这么说, ldd做的是让动态链接器像往常一样加载可执行文件或库,但是沿途打印出一些信息。 This is a recursive "binary needs library needs other library&hellip" search, because that's what the dynamic linker does. 这是一个递归的“二进制需求库需要其他库和hellip”搜索,因为这是动态链接器的作用。

I'm currently running Linux/ppc32; 我目前正在运行Linux / ppc32; on Linux/x86, the dynamic linker is usually /lib/ld-linux.so.2 , and on Linux/x86_64, the dynamic linker is usually /lib/ld-linux-x86-64.so.2 . 在Linux / x86上,动态链接器通常是/lib/ld-linux.so.2 ,而在Linux / x86_64上,动态链接器通常是/lib/ld-linux-x86-64.so.2 Here, I call it directly just to hammer in the point that all ldd is nothing more than a shell script that calls upon the dynamic linker to perform its magic. 在这里,我直接调用它只是为了说明所有ldd只不过是一个shell脚本,它调用动态链接器来执行它的魔法。

$ /lib/ld.so.1 /sbin/badblocks
Usage: /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 [...]]]
       device [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 doesn't list libpthread.so.0 as a library dependency, but it gets pulled in by libcom_err.so.2 . /sbin/badblocks没有将libpthread.so.0列为库依赖项,但它被libcom_err.so.2libcom_err.so.2

Is your problem that ldd doesn't output a nice-looking dependency tree? 你的问题是ldd没有输出漂亮的依赖树吗? Use ldd -v . 使用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)

        Version information:
        /sbin/badblocks:
                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

If you want, you can read the ELF headers directly instead of depending on the dynamic linker. 如果需要,可以直接读取ELF头,而不是依赖于动态链接器。

$ readelf -d /sbin/badblocks | grep NEEDED
 0x00000001 (NEEDED)                     Shared library: [libext2fs.so.2]
 0x00000001 (NEEDED)                     Shared library: [libcom_err.so.2]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
$ readelf -d /lib/libcom_err.so.2 | grep NEEDED
 0x00000001 (NEEDED)                     Shared library: [libpthread.so.0]
 0x00000001 (NEEDED)                     Shared library: [libc.so.6]
 0x00000001 (NEEDED)                     Shared library: [ld.so.1]

You can also man ld.so for other cute tricks you can play with glibc 's dynamic linker. 你也可以通过glibc的动态链接器为man ld.so寻找其他可爱的技巧。

I needed something like this, so I wrote tldd , here it is showing its own library dependencies: 我需要这样的东西,所以我写了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)

I was also going to suggest "readelf -d" but also ensure you build with LDFLAGS="-Wl,--as-needed" if you don't already. 我还打算建议“readelf -d”,但也确保你使用LDFLAGS =“ - Wl, - as-needed”构建,如果你还没有。 This will make you hit this problem less often. 这会让你不那么频繁地解决这个问题。 Portage 2.2's preserve-libs is nice but I gather it was masked primarily because of it - it does have flaws. Portage 2.2的保留库很不错,但我认为它主要是因为它而被掩盖 - 它确实有缺陷。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM