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

When developing for my own platform, I can use ldd to list all shared libraries (.so files) that the binary executable that I am building will try to load at startup. But when cross compiling, I do not know how to get the same information. ldd not a common binutils utility, such as strip or ar , which can be built with gcc for cross-compilation, but instead is a mysterious shell script that, apparently, can only work on native platforms.

So, using the cross-target binutils tools, is there a way to get a list of dynamically related dependencies for an external binary?

+49
gcc linux shared-libraries cross-compiling binutils
Apr 7 2018-12-12T00:
source share
8 answers

is there any way to get a list of dynamically related dependencies for an external binary

You can easily view the direct dependencies of a binary file:

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

I don't know how to recursively continue this to get a complete list (as ldd does). You will need to repeat the process for each NEEDED library manually.

+70
Apr 07 2018-12-12T00:
source share

You can do bash -x ldd /bin/ls to understand what ldd does. ldd script is not "cryptic". It basically works

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

therefore, it uses a dynamic system loader (because the result of ldd depends on your real environment and system!). But you can examine objdump -x /bin/ls dynamic section of the executable, for example

 % 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 rx 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 rx 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 

Again, the actual dependency depends on the system your binary is running on (for example, since I could have LD_LIBRARY_PATH with my own libc.so.6 somewhere, which would be a bad idea).

So you need a cross version of objdump

+12
Apr 07 2018-12-12T00:
source share

and in gdb info shared is similar to ldd . It gives full user-accessible information about the execution time of the executable file.
readelf will skip the path and other library data .
readelf is a very good tool for exploring the host. The developer can choose what works.

+5
Apr 18 '13 at 12:50
source share

A bit late for this addition, but someone might win / clarify. Does the -A flag for reading not 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 information missing here seems to be the full path where these libraries are located.

On the other hand, the tools mentioned so far are only useful after you know how this setup works. My most common problems:

  • Installing a program (mainly through rpm), which then does not start or does not start during startup. Somehow I think this is due to incompatibility with the library, but I did not find an easy way to check these things before installing the program (and not immediately)
  • In an attempt to overcome (1), sometimes I resorted to downloading sources and compiling locally. A typical script configuration is partially useful because it tells you which libraries you are missing. However, he cannot tell you which minimum version of such libraries is required.

Can anyone shed light on these issues? By the way, I tried to read the installation instructions and release notes, but they almost never come anywhere.

A mild example can put everything in context, so please try compiling Cinelerra .

+1
Mar 24 '14 at 9:22
source share

By design, ldd can only be performed as intended. However, you can simulate the behavior of ldd using readelf. A script called `xldd 'was developed in the crosstool-ng project. An independent version of this script is available here:

https://gist.github.com/jerome-pouiller/c403786c1394f53f44a3b61214489e6f

+1
Nov 17 '16 at 16:25
source share

To list the dependent libraries of a non-local 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 another answer, you can achieve the same as using readelf output and a recursive loop, but I never tried it on my own since there is cross-ldd.

0
Apr 09 2018-12-12T00:
source share

Sorry to create 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 section to copy only e2fsck . Short answer: nope.avi .

Anyhoo, I made a little script that uses the accepted answer, as well as some (possibly too verbose) grep calls and with a little swing knob and some unicorn tears (don't worry, they were happy tears!) I managed to put together the following script, which gives you are all addicted. I am sure there are many opportunities for improvement, especially RE: loops and recursion, as well as the fact that all the basisms are all the time (i.e. Indexed arrays), but this at least works nominally 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 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 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 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 fat, and throwing your computer in the # dishwasher to make sure it 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 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, I will go. Hope this helps someone. Egad, it took me a long time to even get good enough with shell scripts to be able to pull something like this, even though it took me a lot longer than it probably should be, so please forgive that will probably shock some of you script gurus there to the very core of your being. :)

0
Mar 23 '14 at 7:00
source share

someone depends, idiot just downloaded it. I'm sure it shows that LDD is wrong, but it has not passed the validation yet. a small bit is shown below.

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

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

should display a general dependency table of what ldconfig (1) will load (or have already loaded) and show which libraries are NOT_FOUND (that is, not the version or file), and then what is being produced.

try it, enjoy it. It is very new, so do not say that I did not tell you. it just found some things below, i didn't know about my lib system - i'm just going to fix it.

 # 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 
-2
Dec 05 '14 at 3:22
source share



All Articles