基本上,我想获得二进制文件可能加载的库列表。
我提出的不可靠的方式似乎有效(可能存在误报):
comm -13 <(ldd elf_file | sed 's|\s*\([^ ]*\)\s.*|\1|'| sort -u) <(strings -a elf_file | egrep '^(|.*/)lib[^:/]*\.so(|\.[0-9]+)$' | sort -u)
这不可靠。但它提供了有用的信息,即使二进制文件被剥离了。
是否有可靠的方法来获取此信息而没有可能的误报?
编辑:更多背景信息。
Firefox正在使用gstreamer
转换为使用ffmpeg
。
我想知道libavcodec.so
的哪个版本会起作用。
libxul.so
使用dlopen()
表示许多可选功能。
库名称是硬编码的。所以,上面的命令有帮助
在这种情况下。
我对包管理和二进制依赖关系也有一般兴趣。
我知道你可以通过readelf -d
获得直接的依赖关系
与ldd
的依赖关系。我想知道可选的依赖关系,因此问题。
答案 0 :(得分:8)
ldd
告诉您二进制文件链接的库。这些不是程序可以<{1}} 打开的那些。
dlopen
的签名是
dlopen
所以你可以,仍然不可靠,在二进制文件上运行void *dlopen(const char *filename, int flag);
,但是如果库名不是静态字符串,但是在程序期间从某个地方构建或读取,这仍然可能会失败执行 - 这最后一种情况意味着你的问题的答案是&#34;没有&#34; ......不可靠。 (例如,可以从网络中读取库文件的名称,从Unix套接字中读取,或者甚至可以在运行中解压缩。一切皆有可能! - 尽管我自己也不会推荐任何这些想法。 。)
编辑:另外,正如John Bollinger所提到的,可以从配置文件中读取库名。
编辑:您也可以尝试使用其中一个strings
系统调用替换{这是由Boehm垃圾收集器dlopen
完成的,例如),所以它会打开库,但也会在某处记录它的名字。但是如果程序在执行期间没有打开特定的库,你仍然不会知道它。
答案 1 :(得分:3)
(我专注于Linux;我想我的大部分答案都适用于每个POSIX系统;但是在MacOSX上dlopen
需要.dylib
dynamic library个文件,而不是{{ 1}}共享对象)
程序甚至可以在某些临时文件.so
,/tmp/foo1234.c
中将fork
的一些C代码发送到共享库/tmp/foo1234.c
中,由某些/tmp/foo1234.so
命令 - 在程序运行时生成并执行 - 可能会删除gcc -O -shared -fPIC /tmp/foo1234.c -o /tmp/foo1234.so
文件 - 因为它不再需要 - 和/tmp/foo1234.c
dlopen
(甚至可能删除{在/tmp/foo1234.so
之后{1}},在同一过程中的所有内容。我/tmp/foo1234.so
的{{3}}插件就是这样做的,GCC MELT也是如此,而Bigloo库正在做一些接近的事情。
所以一般来说,你的任务是不可能的,甚至没有意义。
是否有可靠的方法来获取此信息而没有可能的误报?
不,没有可靠的方法来获取此类信息而没有误报(您可以证明这等同于GCCJIT或其他halting problem)。另请参阅undecidable problem。
实际上,大多数dlopen
都发生在某些配置提供的插件上。在配置文件中可能没有确切命名(例如,某些gcc
程序可能具有类似dlopen
配置文件中名为Foo
的插件的约定由{{1}提供插件)。
但是,您可能会发现一些启发式近似值。执行某些bar
的大多数程序都有一些插件约定请求插件中的某些特定符号名称。您可以搜索定义这些名称的共享对象。当然,你会得到误报。
例如,Rice's theorem shell接受名为zsh的插件。 zsh modules模块显示foo.conf
,
foo-bar.so
,dlopen
等...函数在zsh模块中是预期的。您可以使用enables_
查找提供这些文件的boot_
文件(因此features_
可以>> / p>
(我不相信这样的方法是值得的;实际上你通常应该知道哪些插件对你的系统应用程序有用)
顺便说一句,您可以在执行某些命令时使用example来理解它正在执行的系统调用,因此它正在加载插件。您也可以使用strace(1)或ltrace(1)(在某些特定流程上),或者只是使用pmap(1) 1234-使用nm -D
来了解其process,因此它已经加载的插件。请参阅virtual address space。
请注意,Linux上存在*.so
,zsh
,cat /proc/1234/maps
,但许多POSIX系统都有类似的程序。
此外,程序可以在运行时生成一些机器代码并执行它(proc(5)在每次 SBCL交互时执行此操作!)。您的程序还可以使用一些REPL技术(例如,使用JIT,libjit,llvm,asmjit或手写代码......)同样。因此,在没有strace
的情况下可能会发生类似插件的行为(您可能会使用ltrace
调用和GCCJIT重定位处理来模仿pmap
。
如果你从其打包版本安装firefox(例如Debian上的dlopen
包),它的包可能会处理依赖项