如何列出非本地二进制文件的库依赖关系?
在为本地平台开发时,我可以使用ldd列出所有的共享库(.so文件),我构build的二进制可执行文件将在启动时尝试加载。 但是在交叉编译时,我不知道如何获得相同的信息。 ldd
不是一个普通的binutils工具,比如strip
或者ar
,它们可以和gcc
一起构build,用于交叉编译,相反,它是一个神秘的shell脚本,显然只能在本地平台上运行。
所以,使用跨目标binutils工具,有什么办法可以得到一个外国二进制文件的dynamic链接依赖列表?
有什么办法可以得到一个外部二进制文件的dynamic链接依赖列表
你可以很容易地列出一个二进制文件的直接依赖关系:
readelf -d a.out | grep NEEDED 0x0000000000000001 (NEEDED) Shared library: [librt.so.1] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
我知道没有办法recursion地继续这个获得完整列表(如ldd
所做的那样)。 您必须手动重复每个NEEDED
库的过程。
你可以使用bash -x ldd /bin/ls
来理解ldd
在做什么。 ldd
脚本不是那么“神秘”。 它基本上运行
LD_TRACE_LOADED_OBJECTS=1 /lib64/ld-linux-x86-64.so.2 /bin/ls
所以它使用系统的dynamic加载器(因为ldd
的结果取决于你的实际环境和系统!)。 但是你可以用objdump -x /bin/ls
来检查可执行文件的dynamic部分,例如
% 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
同样,实际的依赖依赖于你的二进制运行的系统(例如,因为我可以有一个LD_LIBRARY_PATH
与我自己的libc.so.6
某处,这是一个坏主意)。
所以你需要一个objdump
的交叉变种
而在gdb
, 共享信息类似于ldd
。 它为可执行文件提供完整的人类可读的运行时信息
readelf
会错过path和其他图书馆的信息 。
readelf
是一个非常好的东道主学习工具。 开发者可以select那个作品。
有点迟了这个加法,但有人可能会受益/澄清。 readelf的-A标志不会给出与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
这里唯一缺less的信息似乎是这些库所在的完整path。
另一方面,到目前为止所提到的工具只有在已知安装完成后才有用。 我最常见的问题是:
- 安装程序(主要是通过rpm),然后在启动时无法启动或崩溃。 不知何故,我认为这是与图书馆的不兼容性有关,但我还没有find一个简单的方法来检查这些东西之前安装一个程序(事实上也没有)
- 在试图克服(1)时,有时我已经采取了下载源和编译本地。 典型的configuration脚本是部分有用的,因为它告诉你你错过了哪些库。 但是,它没有告诉你这种库的最低版本是什么
任何人都可以解释一下这些问题? 顺便说一句,我已经尝试阅读安装说明和发行说明,但他们几乎总是远远不够。
一个很好的例子可能会把所有东西都放到上下文中,所以请尝试编译Cinelerra 。
按deviseldd只能在目标上执行。 但是,使用readelf可以模拟ldd行为。 在crosstool-ng项目中开发了一个名为`xldd'的脚本。 这个脚本的独立版本可以在这里find:
https://gist.github.com/jerome-pouiller/c403786c1394f53f44a3b61214489e6f
要列出非本机二进制文件的共享库依赖性,可以尝试以下工具: http : //www.mathembedded.com/component/k2/item/1-cross-ldd.html
我在SH4和MIPS上使用它。 正如在其他答案中所报告的,你可以使用readelf输出和recursion循环来实现相同的function,但是由于cross-ldd的存在,我从来没有自己试过。
对不起,僵尸线程,但我正在为我的OpenWRT路由器的一些东西,并希望这个检查一些依赖关系,看看我的jffs2分区上有足够的空间只是e2fsck
复制。 简短的回答: nope.avi 。
Anyhoo,我做了一个小脚本,使用接受的答案加上一些(可能是过度冗长的) grep
调用和一个小手和一些独angular兽的眼泪(不用担心,他们是幸福的眼泪!)我设法把下面的脚本给你所有的依赖。 我相信有很多改进的空间,特别是RE:循环和recursion,以及所有的时候都是bashisms(即索引数组),但这至less在名义上为我工作:
#!/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. ♥
所以,你去了。 希望它可以帮助别人。 Egads让我花了很长的时间,甚至可以用shell脚本来取得足够的好处,以便能够把这样的东西拉下来,而不是要花费我比预期更长的时间,所以请原谅你可能会动摇你的一些东西脚本大师在那里到你的存在的核心。 🙂
一些依靠白痴刚刚上传这个。 我敢肯定,它显示的东西LDD不,但它还没有很好的testing。 下面显示了一小部分的输出。
http://sourceforge.net/p/dep-trace/
http://sourceforge.net/projects/dep-trace/files/libdeps
应该显示ldconfig(1)将加载(或已经加载)的全部依赖表,并显示哪些库是NOT_FOUND(即没有版本或文件),然后还有什么影响。
尝试一下,享受。 这是非常新的,所以不要说我没有告诉你。 它只是发现了一些事情,我不知道我的lib系统 – 我正要去解决这个问题。
# 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