Linux 如何列出非本机二进制文件的库依赖项?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10052041/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to list library dependencies of a non-native binary?
提问by lvella
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-compiling, I don't know how to get the same information. The ldd
is not a normal binutils utility, like strip
or ar
, that can be built alongside gcc
for cross compiling, but instead, it is a cryptic shell script that apparently can only run on native platform.
在针对本机平台进行开发时,我可以使用 ldd 列出所有共享库(.so 文件),我构建的二进制可执行文件将在启动时尝试加载。但是在交叉编译的时候,我不知道如何获得相同的信息。在ldd
不正常的binutils工具,像strip
或者ar
,可以一起建立gcc
了交叉编译,而是,这是一个神秘的shell脚本,显然只能在本地平台上运行。
So, using the cross-target binutils tools, is there any way to get a list of the dynamically linked dependency for of a foreign binary?
那么,使用跨目标 binutils 工具,有没有办法获取外部二进制文件的动态链接依赖项列表?
采纳答案by Employed Russian
is there any way to get a list of the dynamically linked dependency for of a foreign binary
有什么方法可以获取外部二进制文件的动态链接依赖项列表
You can list directdependencies 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.
我知道没有办法递归地继续这个以获得完整的列表(也是ldd
如此)。您必须NEEDED
手动为每个库重复该过程。
回答by Basile Starynkevitch
You can do bash -x ldd /bin/ls
to understand what ldd
is doing. The ldd
script is not that "cryptic". It basically runs
你可以做bash -x ldd /bin/ls
来了解ldd
正在做什么。该ldd
脚本并不是“神秘”。它基本上运行
LD_TRACE_LOADED_OBJECTS=1 /lib64/ld-linux-x86-64.so.2 /bin/ls
so it uses the dynamic loader of the system (because the result of ldd
depends upon your actual environment and system!). But you could examine with objdump -x /bin/ls
the dynamic section of an executable, e.g.
所以它使用系统的动态加载器(因为结果ldd
取决于你的实际环境和系统!)。但是您可以使用objdump -x /bin/ls
可执行文件的动态部分进行检查,例如
% 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
Again, the actual dependency depends upon the system where your binary is run (e.g. because I could have an LD_LIBRARY_PATH
with my own libc.so.6
somewhere, which would be a bad idea).
同样,实际相关性取决于其中二进制运行系统(例如,因为我有LD_LIBRARY_PATH
我自己的libc.so.6
地方,这将是一个坏主意)。
So you need a cross variant of objdump
所以你需要一个交叉变体 objdump
回答by Patrice Tisserand
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
要列出非本地二进制文件的共享库依赖项,您可以尝试以下工具: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.
我在 SH4 和 MIPS 上使用它。正如其他答案中所报告的那样,您可以使用 readelf 输出和递归循环来实现相同的效果,但是自从存在 cross-ldd 以来,我从未自己尝试过。
回答by AjayKumarBasuthkar
while in gdb
, info sharedis 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.
而在 中gdb
,信息共享类似于ldd
。它提供了可执行文件的完整的人类可读的运行时信息。readelf
会错过路径和其他库信息。readelf
是一个非常好的主机学习工具。开发者可以选择那个作品。
回答by shelleybutterfly
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.
很抱歉创建了一个僵尸线程,但我正在为我的 OpenWRT 路由器做一些事情,并希望它检查一些依赖项,看看我的 jffs2 分区上是否有足够的空间来复制e2fsck
. 简短回答:nope.avi。
Anyhoo, I made a little script that uses the accepted answerplus 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:
Anyhoo,我制作了一个小脚本,使用已接受的答案加上一些(可能过于冗长)grep
调用,并挥舞着小手和一些独角兽的眼泪(不用担心,他们是快乐的眼泪!)我设法将以下脚本放在一起你所有的依赖。我确信有很多改进的空间,尤其是 RE:循环和递归,以及它一直都是 bashisms(即索引数组)的事实,但这至少在名义上对我有用:
#!/bin/bash
declare -a search_path
declare -a found_deps
find_dependencies() {
local file=""
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 $ 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
)"
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=""
shift 1
show_header=true
if [ "" = "--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:
# [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. ?
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. :)
所以,你去。希望它可以帮助某人。Egads 我花了很长时间才学会使用 shell 脚本来完成这样的事情,别介意我花了比它应该有的时间长得多的事实,所以请原谅可能让你们中的一些人动摇的事情脚本大师到你的核心。:)
回答by quiet-ranger
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 的 -A 标志不会给出与 ldd 相同的结果吗?
# 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
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:
另一方面,到目前为止提到的工具只有在您安装了可以工作的安装后才有用。我最常见的问题是:
- 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)
- 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
- 安装一个程序(主要通过 rpm),然后在启动过程中无法启动或崩溃。不知何故,我认为这与库不兼容有关,但我还没有找到一种在安装程序之前(也确实在之后)检查这些东西的简单方法
- 为了克服 (1),有时我不得不下载源代码并在本地编译。典型的配置脚本部分有用,因为它会告诉您缺少哪些库。但是,它无法告诉您需要什么最低版本的此类库
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.
一个强大的示例可能会将所有内容置于上下文中,因此请尝试编译Cinelerra。
回答by slackguy
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.
有些依赖白痴刚刚上传了这个。我确信它显示了 LDD 没有的东西,但它还没有经过很好的测试。下面显示了一小部分输出。
http://sourceforge.net/p/dep-trace/
http://sourceforge.net/p/dep-trace/
http://sourceforge.net/projects/dep-trace/files/libdeps
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.
应该显示 ldconfig(1) 将加载(或已经加载)什么的总依赖表,并显示哪些库是 NOT_FOUND(即,没有版本或文件),然后还有影响的内容。
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.
试试看,享受。这是很新的所以不要说我没有告诉你。它确实在下面找到了一些我不知道的关于我的 lib 系统的东西——我正准备去解决这个问题。
objdump -p /path/to/program | grep NEEDED
回答by Jér?me Pouiller
By design ldd can only been executed on target. However, it is possible to mimic ldd behavior using readelf. A script called `xldd' was developed in crosstool-ng project. An independent version of this script is available here:
按照设计,ldd 只能在目标上执行。但是,可以使用 readelf 模拟 ldd 行为。在 crosstool-ng 项目中开发了一个名为“xldd”的脚本。此脚本的独立版本可在此处获得:
https://gist.github.com/jerome-pouiller/c403786c1394f53f44a3b61214489e6f
https://gist.github.com/jerome-pouiller/c403786c1394f53f44a3b61214489e6f
回答by captainchhala
this helped me
这对我有帮助
##代码##