如何找出共享对象的哪些函数被程序或其他库使用?

Posted

技术标签:

【中文标题】如何找出共享对象的哪些函数被程序或其他库使用?【英文标题】:How do I find out which functions of a shared object are used by a program or an other library? 【发布时间】:2011-07-03 17:53:31 【问题描述】:

在这种特定情况下,我想查看 /lib/libgcc1_s.so.1 中的哪些函数被其他动态库使用。 由于它们是动态链接的,因此 objdump -d 不会解析函数调用地址。 有没有办法在调试器中运行程序或静态重新链接? 谢谢,

卢卡

编辑:

nm 和 readelf 不行,我不需要查看共享对象中存在哪些符号,但实际上哪些符号在链接到它的其他对象中使用。

【问题讨论】:

【参考方案1】:

这可以使用逆向工程中称为静态分析的技术来实现

为此,您需要一个反汇编程序。见http://en.wikipedia.org/wiki/Disassembler

IDA PRO 是一个很好的反汇编程序,可以回答你的问题。它能够读取 ELF 文件格式,但不幸的是它不是免费的。

【讨论】:

每个经验丰富的逆向工程师都会对分析什么(以及分析多少)非常挑剔。您的建议需要全面分析。它适用于某些软件,但很少见,因为它需要大量工作。对于提问者想要达到的目标,静态分析是一个不好的建议。【参考方案2】:

你看过ltrace吗?它在运行时拦截对共享库函数的调用,并在它们发生时打印有关它们的信息。

由于这是一个动态解决方案,因此它不会为您的程序中从未执行的部分库调用打印任何信息。但根据您的需要,它可能仍然会有所帮助。

【讨论】:

【参考方案3】:

nm 仅在库未删除其符号时才有效。但是,nm -D 可以向您显示一些信息:

nm -D /lib/libgcc_s.so.1

但还有另一个工具可以帮助您:readelf

readelf - 显示有关信息 ELF 文件。

如果您查看手册页,选项 -sDisplays the entries in symbol table section of the file, if it has one.

readelf -s /lib/libgcc_s.so.1

编辑:

好吧,没有在您使用 nm 检查的对象内部实现的符号将在其前面显示一个 U 标志,但 nm 不会告诉您系统上的哪个库实现了该标志符号。

所以您正在寻找的可能可以通过 lddnm 的混合来实现。 ldd 告诉您的应用程序与哪些库链接,nm 告诉哪些符号未定义(U 标志)或本地实现(T 标志)。

在列出目标应用程序上的所有未定义符号(使用 nm)后,您应该遍历 ldd 报告的所有库以搜索这些符号(再次使用 nm)。如果您找到该符号并且它前面有 T 标志,那么您就找到了。

顺便说一句,我刚刚写了这个 one-liner for bash 来说明我的想法。它分析一个名为 win 的应用程序并尝试找到实现所有报告为未定义符号的库。

target="win"; for symbol in $(nm -D $target | grep "U " | cut -b12-); do for library in $(ldd $target | cut -d ' ' -f3- | cut -d' ' -f1); do for lib_symbol in $(nm -D $library | grep "T " | cut -b12-); do if [ $symbol == $lib_symbol ]; then echo "Found symbol: $symbol at [$library]"; fi ; done; done; done;

或者,如果您的终端支持颜色:

target="win"; for symbol in $(nm -D $target | grep "U " | cut -b12-); do for library in $(ldd $target | cut -d ' ' -f3- | cut -d' ' -f1); do for lib_symbol in $(nm -D $library | grep "T " | cut -b12-); do if [ $symbol == $lib_symbol ]; then echo -e "Found symbol: \e[1;36m$symbol\033[0m at \e[1;34m$library\033[0m"; fi ; done; done; done;

我相信有人会发现性能改进。

输出:

Found symbol: XCreateColormap at [/usr/lib/libX11.so.6]
Found symbol: XCreateWindow at [/usr/lib/libX11.so.6]
Found symbol: XIfEvent at [/usr/lib/libX11.so.6]
Found symbol: XMapWindow at [/usr/lib/libX11.so.6]
Found symbol: XOpenDisplay at [/usr/lib/libX11.so.6]
Found symbol: __libc_start_main at [/lib/tls/i686/cmov/libc.so.6]
Found symbol: __stack_chk_fail at [/lib/tls/i686/cmov/libc.so.6]
Found symbol: glClear at [/usr/lib/mesa/libGL.so.1]
Found symbol: glClearColor at [/usr/lib/mesa/libGL.so.1]
Found symbol: glFlush at [/usr/lib/mesa/libGL.so.1]
Found symbol: glXChooseFBConfig at [/usr/lib/mesa/libGL.so.1]
Found symbol: glXChooseVisual at [/usr/lib/mesa/libGL.so.1]
Found symbol: glXCreateContext at [/usr/lib/mesa/libGL.so.1]
Found symbol: glXCreateNewContext at [/usr/lib/mesa/libGL.so.1]
Found symbol: glXCreateWindow at [/usr/lib/mesa/libGL.so.1]
Found symbol: glXGetVisualFromFBConfig at [/usr/lib/mesa/libGL.so.1]
Found symbol: glXMakeContextCurrent at [/usr/lib/mesa/libGL.so.1]
Found symbol: glXMakeCurrent at [/usr/lib/mesa/libGL.so.1]
Found symbol: glXQueryVersion at [/usr/lib/mesa/libGL.so.1]

【讨论】:

@lultimouomo 更新了我的答案,并为 bash 添加了一条线来帮助您入门。 我也使用readelf-W (Allow output width to exceed 80 characters)。 请参阅gist.github.com/toojays/dffd9b806692a10649c1fcd146ee7866 以获得更快的实现,该实现遵循大致相似的方法。【参考方案4】:

也许nm 工具可以帮助您,因为它会显示二进制文件中包含的符号名称。 使用起来就像ABC一样简单:

nm my_binary

【讨论】:

【参考方案5】:

我不知道有一个,即使nm 对于您似乎打算的用途也有限。此外,(GNU 链接器的)预加载可能会使您在使用据称可以做到这一点的工具后所做的任何假设无效。请参阅ld.so man page。任何人都可以使用LD_PRELOAD 来覆盖符号的分辨率,就像在正常情况下一样。

但是,即使没有调试器,您也可以使用LD_DEBUG 查看最终使用的是哪个函数。

【讨论】:

以上是关于如何找出共享对象的哪些函数被程序或其他库使用?的主要内容,如果未能解决你的问题,请参考以下文章

常用动态链接库的DLL都有哪些?

如何找出特定 Boost 库需要哪些依赖项(即其他 Boost 库)?

如何使共享库符号强大?

如何找出从共享对象导出的所有符号?

如何使用 GDB 调试共享对象库中的函数?

Linux,共享库使用主程序中的函数而不是其他共享库