Ldd hierárquico (1)
Pergunta
Devido ao uso do Gentoo, muitas vezes acontece que após uma atualização os programas são vinculados a versões antigas de bibliotecas.Normalmente, revdep-rebuild ajuda a resolver isso, mas desta vez é uma dependência de uma biblioteca python, e python-updater
não vou atender.
Existe uma variante "hierárquica" de ldd
o que me mostra qual biblioteca compartilhada depende de qual outra biblioteca compartilhada?Na maioria das vezes, bibliotecas e executáveis são vinculados apenas a um punhado de outras bibliotecas compartilhadas, que por sua vez foram vinculadas a um punhado, transformando a dependência da biblioteca em uma grande lista.Quero saber qual dependência devo reconstruir com a nova versão de outra biblioteca que atualizei.
Solução
Se você estiver executando o Portage≥2.2 com FEATURES=preserve-libs
, você raramente precisará revdep-rebuild
mais tão velho .so.
vers será preservado conforme necessário (embora você ainda precise reconstruir com cuidado, já que as coisas ainda dão errado quando libA.so.0
quer libC.so.0
e libB.so.0
quer libC.so.1
e algum binário quer ambos libA.so.0
e libB.so.0
).
Dito isto, o que ldd
O que faz é fazer com que o vinculador dinâmico carregue o executável ou a biblioteca como normalmente faria, mas imprima algumas informações ao longo do caminho.Esta é uma pesquisa recursiva "biblioteca de necessidades binárias precisa de outra biblioteca e inferno", porque é isso que o vinculador dinâmico faz.
Atualmente estou executando Linux/ppc32;no Linux/x86, o vinculador dinâmico geralmente é /lib/ld-linux.so.2
, e no Linux/x86_64, o vinculador dinâmico geralmente é /lib/ld-linux-x86-64.so.2
.Aqui, eu chamo isso diretamente apenas para enfatizar que todos ldd
nada mais é do que um script de shell que invoca o vinculador dinâmico para realizar sua mágica.
$ /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
não lista libpthread.so.0
como uma dependência de biblioteca, mas é puxada por libcom_err.so.2
.
O seu problema é esse ldd
não produz uma árvore de dependência bonita?Usar 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
Se desejar, você pode ler os cabeçalhos ELF diretamente, em vez de depender do vinculador dinâmico.
$ 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]
Você também pode man ld.so
para outros truques fofos com os quais você pode brincar glibc
vinculador dinâmico de.
Outras dicas
Vejo muitos detalhes interessantes, mas nenhuma resposta direta à pergunta feita.
A versão “hierárquica” ldd
é lddtree
(de 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
Eu precisava de algo assim, então escrevi tldd
, aqui está mostrando suas próprias dependências de biblioteca:
$ ./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)
Eu também sugeriria "readelf -d", mas também garantiria que você construísse com LDFLAGS="-Wl,--as-needed" se ainda não o fez.Isso fará com que você encontre esse problema com menos frequência.As preserve-libs do Portage 2.2 são legais, mas suponho que foram mascaradas principalmente por causa disso - elas têm falhas.