How to list library dependencies of a non-native binary?

后端 未结 9 801
孤城傲影
孤城傲影 2020-12-12 16:03

When developing for native platform, I can use ldd to list all the shared libraries (.so files) a binary executable I build will try to load upon start-up. But when cross-co

相关标签:
9条回答
  • 2020-12-12 16:36

    is there any way to get a list of the dynamically linked dependency for of a foreign binary

    You can list direct dependencies of a binary easily enough:

    readelf -d a.out | grep NEEDED
    
     0x0000000000000001 (NEEDED)             Shared library: [librt.so.1]
     0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
    

    I know of no way to recursively continue this to get the full list (as ldd does). You'll have to repeat the process for every NEEDED library by hand.

    0 讨论(0)
  • 2020-12-12 16:36

    while in gdb, info shared is similar to ldd. It gives complete human readable runtime information of the executable.
    readelf would miss path and other libraries information.
    readelf is a very good tool for on the host study. Developer may choose that works.

    0 讨论(0)
  • 2020-12-12 16:39

    A bit late for this addition but someone might benefit/clarify. Doesn't the -A flag to readelf give the same result as 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
    

    The only info missing here seems to be the full path where those libraries are located.

    On the other hand, the tools mentioned so far are only useful once you have an installation known to work. My most common problems are:

    1. Installing a program (mostly via rpm) that then fails to start or crashes during start up. Somehow I think this is related to library incompatibilities but I haven't found an easy way of checking these thing before installing a program (nor indeed after)
    2. In an attemtp to overcome (1), sometimes I have resorted to downloading the sources and compiling locally. The typical configure script is partially helpful because it tells you which libraries you are missing. However, it fails to tell you what the lowest version of such libraries are required

    Can anyone shed some light on these issues? BTW, I have tried reading installation instructions and release notes but they are almost always nowhere near sufficient.

    A beefy example may put everything into context, so please try compiling Cinelerra.

    0 讨论(0)
  • 2020-12-12 16:40

    some depends idiot just uploaded this. i'm sure it shows things LDD doesn't but it's not well tested yet. a small bit of output is shown below.

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

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

    should show total dependancy table of what ldconfig(1) will load (or has already loaded) and show which libs are NOT_FOUND (ie, no version or file) and then also what is effected.

    try it, enjoy. it's very new so don't say i didn't tell you. it did just find some things below i didn't know about my lib system - i'm just about to go fix that.

    # 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 讨论(0)
  • 2020-12-12 16:45

    Sorry to make a zombie thread, but I am working on some things for my OpenWRT router and wanted this to check some dependencies to see if I had enough space on my jffs2 partition to copy over just e2fsck. Short answer: nope.avi.

    Anyhoo, I made a little script that uses the accepted answer plus some (probably overly verbose) grep calls and with a little hand waving and some unicorn tears (no worries, they were happy tears!) I managed to put together the following script that gives you all the dependencies. I'm sure there's lots of room for improvement especially RE: the loops and recursion, as well as the fact that it's all bashisms all the time (i.e. indexed arrays) but this is at least nominally working for 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="$@"
        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:
    # shelleybutterfly@mojoprocode.com
    
    # 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 shelleybutterfly@mojoprocode.com, as I imagine it
    # will be rare enough to make my day, every time. ♥
    

    So, there ya go. Hope it helps someone. Egads it's taken me a long time to even get good enough with shell scripting to be able to pull something like this off, nevermind the fact that it took me much longer than it probably should have, so please forgive what has likely shaken some of you script gurus out there to the very core of your being. :)

    0 讨论(0)
  • 2020-12-12 16:48

    To list shared libraries dependency of a non-native binary, you can try the following tool: http://www.mathembedded.com/component/k2/item/1-cross-ldd.html

    I use it on SH4 and MIPS. As reported in other answer, you can achieve the same using readelf output and a recursive loop, but I have never try by myself since cross-ldd exist.

    0 讨论(0)
提交回复
热议问题