Hierarchical ldd (1)

A causa dell’utilizzo di Gentoo, spesso accade che dopo un aggiornamento i programmi siano collegati a vecchie versioni di librerie. Normalmente, revdep-rebuild aiuta a risolverlo, ma questa volta è una dipendenza da una libreria python, e python-updater non la raccoglierà.

Esiste una variante “gerarchica” di ldd che mi mostra quale libreria condivisa dipende da quale altra libreria condivisa? La maggior parte delle volte le librerie e gli eseguibili sono collegati solo con una manciata di altre librerie condivise, che a loro volta erano collegate a una manciata, trasformando la dipendenza della biblioteca in una grande lista. Voglio sapere quale dipendenza devo ribuild con la nuova versione di un’altra libreria che ho aggiornato.

Se esegui Portage≥2.2 con FEATURES=preserve-libs , raramente dovresti avere più bisogno di revdep-rebuild come vecchio .so. vers sarà conservato in base alle necessità (sebbene sia ancora necessario ribuild attentamente, dato che roba va ancora kaboom quando libA.so.0 vuole libC.so.0 e libB.so.0 vuole libC.so.1 e alcuni binari vogliono entrambi libA.so.0 e libB.so.0 ).


Detto questo, ciò che fa ldd è far sì che il linker dinamico carichi l’eseguibile o la libreria come di solito, ma stampa alcune informazioni lungo la strada. Questa è una ricerca ricorsiva di “binary needs library other and hellip”, perché è ciò che fa il linker dinamico.

Attualmente sto usando Linux / ppc32; su Linux / x86, il linker dinamico è in genere /lib/ld-linux.so.2 e su Linux / x86_64, il linker dinamico è in genere /lib/ld-linux-x86-64.so.2 . Qui, lo chiamo direttamente solo per martellare nel punto che tutto ldd non è altro che uno script di shell che invoca il linker dinamico per eseguire la sua magia.

 $ /lib/ld.so.1 / sbin / badblocks
 Uso: / sbin / badblocks [-b block_size] [-i file_input] [-o file_output] [-svwnf]
        [-c blocks_at_once] [-d delay_factor_between_reads] [-e max_bad_blocks]
        [-p num_passes] [-t test_pattern [-t test_pattern [...]]]
        dispositivo [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 non elenca libpthread.so.0 come dipendenza da libreria, ma viene libcom_err.so.2 da libcom_err.so.2 .

Il tuo problema è che ldd non produca un albero delle dipendenze dall’aspetto gradevole? Usa 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)

         Informazioni sulla versione:
         / 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 lo desideri, puoi leggere direttamente le intestazioni ELF anziché a seconda del linker dinamico.

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

Puoi anche man ld.so per altri trucchi carini che puoi giocare con il linker dinamico di glibc .

Vedo molti dettagli interessanti ma nessuna risposta diretta alla domanda posta.

La versione “gerarchica” di ldd è lddtree (da 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 

Avevo bisogno di qualcosa di simile, quindi ho scritto tldd , qui mostra le sue dipendenze della libreria:

 $ ./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)

Avevo anche intenzione di suggerire “read -d”, ma assicurarmi anche di creare con LDFLAGS = “- Wl, – come necessario” se non lo hai già fatto. Questo ti farà colpire questo problema meno spesso. Le librerie di riserva di Portage 2.2 sono belle, ma ritengo che sia stata mascherata principalmente a causa di esso – ha dei difetti.