Иерархический ldd (1)

Из-за использования Gentoo часто бывает, что после того, как программы обновления связаны с старыми версиями библиотек. Обычно revdep-rebuild помогает это разрешить, но на этот раз это зависит от библиотеки python и python-updater не подберет ее.

Существует ли "иерархический" вариант ldd, который показывает мне, какая общая библиотека зависит от какой-либо другой общей библиотеки? Большую часть времени библиотеки и исполняемые файлы связаны только с несколькими другими разделяемыми библиотеками, которые, в свою очередь, были связаны с несколькими, превращая зависимость библиотеки в большой список. Я хочу знать, какую зависимость я должен перестроить с новой версией другой библиотеки, которую я обновил.

Ответ 1

Если вы используете Portage & ge; 2.2 с FEATURES=preserve-libs, вам редко нужно будет revdep-rebuild больше, так как старый .so. vers будет сохранен по мере необходимости (хотя вам все равно нужно тщательно перестроить, поскольку материал по-прежнему остается kaboom, когда libA.so.0 хочет libC.so.0 и libB.so.0 хочет libC.so.1, а некоторые двоичные файлы хотят как libA.so.0, так и libB.so.0).


Говоря, что ldd заключается в том, чтобы заставить динамический компоновщик загружать исполняемый файл или библиотеку, как обычно, но распечатывать некоторую информацию на этом пути. Это рекурсивная библиотека бинарных потребностей нуждается в другом поиске библиотеки и hellip, потому что это то, что делает динамический компоновщик.

В настоящее время я запускаю Linux/ppc32; на Linux/x86 динамический компоновщик обычно /lib/ld-linux.so.2, а на Linux/x86_64 динамический компоновщик обычно /lib/ld-linux-x86-64.so.2. Здесь я называю это непосредственно, чтобы забить то, что все ldd - это не что иное, как оболочка script, которая призывает динамический компоновщик выполнять свою магию.

$ /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 не перечисляет 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)

        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

Если вы хотите, вы можете читать заголовки 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]

Вы также можете man ld.so для других милых трюков, которые вы можете играть с динамическим компоновщиком glibc.

Ответ 2

Я вижу много интересных деталей, но прямого ответа на заданный вопрос нет.

"Иерархическая" версия 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

Ответ 3

Мне нужно было что-то вроде этого, поэтому я написал 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)

Ответ 4

Я также собирался предложить "readelf -d", но также обеспечить, чтобы вы строили с помощью LDFLAGS = "- Wl, - по мере необходимости", если вы этого еще не сделали. Это позволит вам решить эту проблему реже. Portage 2.2 save-libs хорош, но я понимаю, что он был замаскирован в первую очередь из-за него - у него есть недостатки.