2012-04-07 11 views
51

Durante lo sviluppo per piattaforma nativa, posso usare ldd per elencare tutte le librerie condivise (file .so) un eseguibile binario che costruirò tenterà di caricare all'avvio. Ma quando cross-compiling, non so come ottenere le stesse informazioni. Il ldd non è una normale utility binutils, come strip o ar, che può essere costruita insieme a gcc per la compilazione incrociata, ma invece è uno script di shell criptico che apparentemente può essere eseguito solo su piattaforma nativa.Come elencare le dipendenze della libreria di un binario non nativo?

Quindi, utilizzando gli strumenti binutils cross-target, esiste un modo per ottenere un elenco della dipendenza collegata dinamicamente per un binario straniero?

risposta

71

C'è un modo per ottenere un elenco di dipendenza legata in modo dinamico per una straniera binario

Si possono elencare diretti dipendenze di un binario abbastanza facilmente:

readelf -d a.out | grep NEEDED 

0x0000000000000001 (NEEDED)    Shared library: [librt.so.1] 
0x0000000000000001 (NEEDED)    Shared library: [libc.so.6] 

Non conosco alcun modo di ricorsivamente continuate con questo per ottenere l'elenco completo (come fa ldd). Dovrai ripetere la procedura per ogni libreria NEEDED a mano.

+0

@Shuman Probabilmente stai guardando uno script di shell. In caso contrario, dovresti fare una domanda a parte. –

12

È possibile fare bash -x ldd /bin/ls per capire cosa sta facendo ldd. Lo script ldd non è "criptico". Funziona fondamentalmente

LD_TRACE_LOADED_OBJECTS=1 /lib64/ld-linux-x86-64.so.2 /bin/ls 

in modo che utilizza il caricatore dinamico del sistema (perché il risultato del ldd dipende dal vostro ambiente reale e sistema!). Ma puoi esaminare con objdump -x /bin/ls la sezione dinamica di un eseguibile, ad es.

% objdump -x /bin/ls 
    /bin/ls:  file format elf64-x86-64 
    /bin/ls 
    architecture: i386:x86-64, flags 0x00000112: 
    EXEC_P, HAS_SYMS, D_PAGED 
    start address 0x00000000004046d4 

    Program Header: 
     PHDR off 0x0000000000000040 vaddr 0x0000000000400040 paddr 0x0000000000400040 align 2**3 
      filesz 0x00000000000001c0 memsz 0x00000000000001c0 flags r-x 
    INTERP off 0x0000000000000200 vaddr 0x0000000000400200 paddr 0x0000000000400200 align 2**0 
      filesz 0x000000000000001c memsz 0x000000000000001c flags r-- 
     LOAD off 0x0000000000000000 vaddr 0x0000000000400000 paddr 0x0000000000400000 align 2**21 
      filesz 0x0000000000019ef4 memsz 0x0000000000019ef4 flags r-x 
     LOAD off 0x000000000001a000 vaddr 0x000000000061a000 paddr 0x000000000061a000 align 2**21 
      filesz 0x000000000000077c memsz 0x0000000000001500 flags rw- 
    DYNAMIC off 0x000000000001a028 vaddr 0x000000000061a028 paddr 0x000000000061a028 align 2**3 
      filesz 0x00000000000001d0 memsz 0x00000000000001d0 flags rw- 
     NOTE off 0x000000000000021c vaddr 0x000000000040021c paddr 0x000000000040021c align 2**2 
      filesz 0x0000000000000044 memsz 0x0000000000000044 flags r-- 
    EH_FRAME off 0x0000000000017768 vaddr 0x0000000000417768 paddr 0x0000000000417768 align 2**2 
      filesz 0x00000000000006fc memsz 0x00000000000006fc flags r-- 
    STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**3 
      filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw- 

    Dynamic Section: 
    NEEDED    libselinux.so.1 
    NEEDED    librt.so.1 
    NEEDED    libacl.so.1 
    NEEDED    libc.so.6 
    INIT     0x0000000000402148 
    FINI     0x00000000004125f8 
    HASH     0x0000000000400260 
    GNU_HASH    0x00000000004005c0 
    STRTAB    0x0000000000401100 
    SYMTAB    0x0000000000400620 
    STRSZ    0x00000000000004d7 
    SYMENT    0x0000000000000018 
    DEBUG    0x0000000000000000 
    PLTGOT    0x000000000061a208 
    PLTRELSZ    0x0000000000000990 
    PLTREL    0x0000000000000007 
    JMPREL    0x00000000004017b8 
    RELA     0x0000000000401740 
    RELASZ    0x0000000000000078 
    RELAENT    0x0000000000000018 
    VERNEED    0x00000000004016c0 
    VERNEEDNUM   0x0000000000000003 
    VERSYM    0x00000000004015d8 

    Version References: 
    required from librt.so.1: 
     0x09691a75 0x00 05 GLIBC_2.2.5 
    required from libacl.so.1: 
     0x05822452 0x00 06 ACL_1.2 
     0x05822450 0x00 04 ACL_1.0 
    required from libc.so.6: 
     0x09691a75 0x00 03 GLIBC_2.2.5 
     0x0d696913 0x00 02 GLIBC_2.3 

Anche in questo caso, la dipendenza effettiva dipende dal sistema in cui viene eseguito il file binario (per esempio perché ho potuto avere un LD_LIBRARY_PATH con la mia libc.so.6 da qualche parte, che sarebbe una cattiva idea).

quindi è necessario una variante croce di objdump

+0

tua spiegazione non ha spiegato quale parte * * di OP objdump ha bisogno di guardare. Inoltre, nativo 'read -d' può leggere il binario ELF non nativo, quindi non c'è bisogno di creare cross-readelf o cross-objdump (anche se di solito * sono * costruiti come parte di crosstool comunque). –

0

Per elencare le librerie condivise dipendenza di un binario non nativa, è possibile provare i seguenti attrezzi: http://www.mathembedded.com/component/k2/item/1-cross-ldd.html

Io lo uso su SH4 e MIPS. Come riportato in un'altra risposta, è possibile ottenere lo stesso utilizzando l'output readelf e un ciclo ricorsivo, ma non ho mai provato da solo poiché esiste cross-ldd.

+0

Questo è un URL morto al momento. –

+0

Grazie Craig, ho modificato per aggiornare l'URL. –

+0

L'URL è morto in questo momento. –

5

mentre in gdb, informazioni condivise è simile a ldd. Fornisce informazioni runtime umane leggibili complete dell'eseguibile.
readelfpercorso miss e altre informazioni sulle librerie.
readelf è un ottimo strumento per lo studio dell'host. Lo sviluppatore può scegliere che funzioni.

0

Mi dispiace fare un thread di zombi, ma sto lavorando su alcune cose per il mio router OpenWRT e volevo controllare alcune dipendenze per vedere se avevo abbastanza spazio sulla mia partizione jffs2 da copiare solo su e2fsck.Risposta breve: nope.avi.

Anyhoo, ho fatto un piccolo script che utilizza i accepted answer più alcuni (probabilmente eccessivamente verbose) grep chiamate e con un po 'la mano agitando e qualche lacrima unicorno (nessun problema, erano lacrime di gioia!) Sono riuscito a mettere insieme la seguente script che ti dà tutte le dipendenze. Sono sicuro che c'è un sacco di spazio per ulteriori miglioramenti soprattutto Re: loop e ricorsione, così come il fatto che si tratta di tutti i bashismi tutto il tempo (cioè array indicizzati), ma questo è, almeno nominalmente, che lavora per me:

#!/bin/bash 

declare -a search_path 
declare -a found_deps 

find_dependencies() { 
    local file="$1" 
    local -a deps 
    local -a deps_to_process 

    deps=($(readelf -d "$file" | grep "NEEDED" | \ 
     grep -o -E "\[[^]]*\]" | grep -o -E "[^][]*")) 

    local add_this_dep=true 

    # always assume we've found $file and add it to the $found_deps list 
    # if it's not there 
    for found_dep in "${found_deps[@]}" 
    do 
     if [ "$found_dep" = "$(basename $file)" ] 
     then 
      add_this_dep=false 
      break 
     fi 
    done 

    # if $add_this_dep is true, go ahead and add to the found_deps list 
    if $add_this_dep 
    then 
     found_deps+=("$(basename $file)") 
    fi 

    # for every dependency found by readelf (no path) 
    for dep in "${deps[@]}" 
    do 
     local process_dep=true 

     # if the basename of the file passed into the function is 
     # this dep, skip processing altogether 
     if [ "$dep" = "$(basename $file)" ] 
     then 
      break 
     else 
      # otherwise, if it's one of the 'found deps' don't process it 
      for found_dep in "${found_deps[@]}" 
      do 
       if [ "$dep" = "$found_dep" ] 
       then 
        process_dep=false 
        break 
       fi 
      done 

      # it wasn't one of the 'found deps' so add 
      # it to the found_deps list 
      if $process_dep 
      then 
       found_deps+=($dep) 
      fi 
     fi 

     # if we are supposed to process this dep 
     if $process_dep 
     then 
      local file_path= 

      # check each search path for a file named $dep underneath it 
      for dir in $search_path 
      do 
       file_path=$(find "$dir" -name "$dep" | head -n 1) 

       # if the $file_path is not empty, then we found 
       # a copy of it, so break out of the loop 
       if [ -n "$file_path" ]; then break; fi; 
      done 

      # if the $file_path is not empty, then we found a copy 
      # of the file, place it the list of deps to be processed 
      if [ -n "$file_path" ] 
      then 
       deps_to_process+=($file_path) 
      fi 
     fi 
    done 

    # now, go through all of our $deps_to_process (with path) 
    # and run "find_dependencies" on them 
    for dep_to_process in "${deps_to_process[@]}" 
    do 
     find_dependencies "$dep_to_process" 
    done 
} 

argc=$# 

if [ $argc -eq 0 ] 
then 
    printf '%s: prints dependencies of a (potentially) non-native elf executable, recursively\n' 
    printf '\n' 
    printf 'usage:\n' 
    printf '\t%s <non-native elf executable> [ --supress-header ] [ <path> ... ]\n' "$(basename $0)" 
    printf '\twhere\n' 
    printf '\t\t<non-native elf executable> is the name of a file to find the dependencies of.\n' 
    printf '\t\t[ <path> ... ] is an optional list of directories under which to search for libraries.\n' 
    printf '\t\t[ --supress-header ] is an optional flag that prints nothing other than the list of files to stdout.\n' 
    printf '\t\t\t(without the parameter a banner is sent to stderr)' 
    printf '\n' 
else 
    file="$1" 
    shift 1 

    show_header=true 

    if [ "$1" = "--supress-header" ]; then show_header=false; shift 1; fi; 

    if $show_header 
    then 
     printf ' -------------------------------------------------------------------------------------------------------------\n' 1>&2 
     printf ' ldd-nonnative: find all dependencies of a (potentially) non-native binary %s\n' "$file" 1>&2 
     printf ' -------------------------------------------------------------------------------------------------------------\n' 1>&2 
    fi 

    search_path="[email protected]" 
    find_dependencies $file 

    printf '\t%s\n' "${found_deps[@]}" 
fi 

# ❤ copyheart, shelleybutterfly, 2014 
# love is never subject to the low; please copy and share with love :) 

# contact information: 
# [email protected] 

# I hereby dedicate this software to the public domain in all jurisdictions 
# where possible. In other jurisdictions, I license it to you under your 
# choice of permissive license, as defined by the Open Source Institute (OSI), 
# found at URL http://opensource.org. Should such a license be unavailable in 
# your jurisdiection, you may use any copyleft open source license, again as 
# defined by OSI; and if that too is unavailable, then you are licensed this 
# software under the least restrictive possible terms allowed in your 
# jurisdiction. 

# I request but do not require that you give credit to me, shelleybutterfly, 
# which I will accept in cases of licensing other than the public domain as 
# valuable consideration for your use of my software. (I love to know that 
# my name is plastered all over some obscure piece of code that's at least 
# appreciated by those who do see it, and I consider that more than enough 
# consideration. :D) This software is provided completely as-is, and I take 
# absolutely no responsibility for any damages that it may cause. It has 
# not been fully tested and should be considered pre-alpha release quality, 
# (that is to say, it is likely unstable and unsafe to use without your own 
# validation to ensure that it meets some or any your needs without: among 
# other things: melting your computer, calling your grandma at midnight, 
# telling your girlfriend she's fat, and throwing your computer in the 
# dishwasher to make sure it's clean, and you take full responsibility for 
# doing your own testing to ensure that it suits your needs, and operates 
# properly int the conditions under which you intend to use it. 

# Should you not be willing to take this risk, it is highly recommended 
# that you do not use this software at all, ever, and that you instead find 
# a real commercial piece of software, or other warranted piece of software, 
# as I can not and do not and shall not provide any warranty of fitness for 
# any purpose whatsoever, even to scrub your toilet, and it's provided with 
# the understanding that it will be used primarily as an educational tool 
# rather than any sort of production code. I disclaim any responsibility for 
# anything that may happen to you due to your use of software, even if it 
# causes huge zits, a rash under your boobs that wont go away, or a burning 
# sensation when you pee. Sorry, **especially** for a burning sensation when 
# you pee. 

# Your use of this software implies acceptance of these terms as well as 
# any painful urination or other issues it may cause in your life. 

# [deep breath] 

# my love to you all; I hope this software was useful to you in some way; if 
# you end up using it despite the dire warnings against doing so, feel free 
# to drop me a note at [email protected], as I imagine it 
# will be rare enough to make my day, every time. ♥ 

Allora, ci sei. Spero che aiuti qualcuno. Egads mi ci è voluto molto tempo per diventare abbastanza buono con lo scripting della shell per essere in grado di estrarre qualcosa del genere, non importa che mi ci sia voluto molto più tempo di quello che probabilmente dovrebbe avere, quindi per favore perdona ciò che probabilmente ha scosso alcuni di voi guru dello script là fuori al centro del tuo essere. :)

1

Un po 'tardi per questa aggiunta, ma qualcuno potrebbe beneficiare/chiarire. Il flag -A non fornisce lo stesso risultato di ldd?

$ readelf -AW /bin/vi 

Library list section '.gnu.liblist' contains 8 entries: 
    Library    Time Stamp   Checksum Version Flags 
    0: libselinux.so.1  2011-07-25T08:02:58 0x17a7d5f7 0  0 
    1: libtermcap.so.2  2011-07-25T08:02:59 0x29ae9ff7 0  0 
    2: libacl.so.1   2011-07-25T08:02:58 0x60748842 0  0 
    3: libc.so.6   2011-07-25T08:02:58 0x0c2c7eeb 0  0 
    4: libdl.so.2   2011-07-25T08:02:58 0xdfbfc467 0  0 
    5: libsepol.so.1  2011-07-25T08:02:58 0x857499cb 0  0 
    6: /lib64/ld-linux-x86-64.so.2 2011-07-25T08:02:58 0x9e6549b7 0  0 
    7: libattr.so.1   2011-07-25T08:02:58 0x862f1546 0  0 

Le uniche informazioni mancanti qui sembrano essere il percorso completo in cui si trovano tali librerie.

D'altro canto, gli strumenti citati finora sono utili solo dopo aver verificato che un'installazione funziona. I miei problemi più comuni sono:

  1. Installazione di un programma (per lo più tramite rpm), che poi non si avvia o si blocca durante l'avvio. In qualche modo penso che questo sia legato alle incompatibilità delle librerie, ma non ho trovato un modo semplice per controllare queste cose prima di installare un programma (e nemmeno dopo)
  2. In un tentativo di superare (1), a volte ho fatto ricorso al download del fonti e compilazione locale. Lo script di configurazione tipico è parzialmente utile perché ti dice quali librerie ti mancano. Tuttavia, non è in grado di dirti quale è la versione più bassa di tali librerie richiesta

Qualcuno può far luce su questi problemi? A proposito, ho provato a leggere le istruzioni di installazione e le note di rilascio, ma sono quasi sempre quasi del tutto insufficienti.

Un bizzarro esempio può mettere tutto in un contesto, quindi per favore prova a compilare Cinelerra.

-2

alcuni dipende da idiota appena caricato questo. sono sicuro che mostri cose che LDD non ha, ma non è ancora ben collaudato. di seguito viene mostrato un piccolo bit di output.

http://sourceforge.net/p/dep-trace/

http://sourceforge.net/projects/dep-trace/files/libdeps

dovrebbe mostrare tabella totale dipendenza di ciò ldconfig (1) verrà caricato (o ha già caricato) e mostra quali librerie sono NOT_FOUND (cioè, nessuna versione o file) e quindi anche cosa viene effettuato

provalo, divertiti. è molto nuovo quindi non dire che non te l'ho detto. ha appena trovato alcune cose di seguito che non sapevo sul mio sistema di lib, sto per aggiustarlo.

# libdeps objdump -h 
Experimental - see help 
libdeps [objdump | ldd] [-l | file] 
     -l use find *.so is used on ldconfig dirs 
    file one file.so per line 
snip... 

# libdeps objdump -d 

LIBTABLE 

ld-linux.so.2(file) 

ld-linux.so.2(GLIBC_2.0)(file) 

ld-linux.so.2(GLIBC_2.1)(file) 

ld-linux.so.2(GLIBC_2.0)(file) 

ld-linux.so.2(GLIBC_2.3)(file) 

ld-linux.so.2(GLIBC_2.1)(file) 

ld-linux.so.2(GLIBC_PRIVATE)(file) 

ld-linux.so.2(GLIBC_2.3)(file) 

libBrokenLocale.so.1(file) 

snip ... 

libc.so.6 libc.so.6(file) ld-linux.so.2 ld-linux.so.2(GLIBC_2.0) ld-linux.so.2(GLIBC_2.1) ld-linux.so.2(GLIBC_PRIVATE) 

snip ... 

libanl.so.1 libanl.so.1(file) ld-linux.so.2 ld-linux.so.2(GLIBC_2.0) ld-linux.so.2(GLIBC_2.1) ld-linux.so.2(GLIBC_PRIVATE) libc.so.6(GLIBC_2.1.3) libc.so.6(GLIBC_2.0) libc.so.6 libc.so.6(GLIBC_2.1) libc.so.6(GLIBC_2.3) libc.so.6(GLIBC_2.2) libc.so.6(GLIBC_PRIVATE) libc.so.6(GLIBC_2.3.2) libc.so.6(GLIBC_2.1.2) libpthread.so.0(GLIBC_2.1) libpthread.so.0 


libnss_db.so.2 libnss_db.so.2(file) ld-linux.so.2 ld-linux.so.2(GLIBC_2.0) ld-linux.so.2(GLIBC_2.1) ld-linux.so.2(GLIBC_PRIVATE) libc.so.6(GLIBC_2.1.3) libc.so.6(GLIBC_2.0) libc.so.6 libc.so.6(GLIBC_2.1) libc.so.6(GLIBC_2.3) libc.so.6(GLIBC_2.2) libc.so.6(GLIBC_PRIVATE) libnss_files.so.2 libnss_files.so.2(GLIBC_PRIVATE) libdb3.so.3(NOT_FOUND) libdb3.so.3(DB3_2)(NOT_FOUND) 

snip... 

NOT_FOUND 
libctutils.so.0 

libdb3.so.3 

libdb3.so.3(DB3_2) 

EFFECTED 
libctutils.so.0 libconsole.so.0 

libdb3.so.3 libnss_db.so.2 

libdb3.so.3(DB3_2) libnss_db.so.2 

libconsole.so.0 

libnss_db.so.2 

12/04/14 21:56 -0500  Thursday, December 04, 2014, 09:56:35 PM EST 
0

questo mi ha aiutato

objdump -p /path/to/program | grep NEEDED 
Problemi correlati