如何找出程序或其他库使用共享对象的哪些功能? 在这种特定情况下,我想看看/lib/libgcc1_s.so.1中的哪些函数被其他动态库使用。 由于它们是动态链接的,因此objdump -d不解析函数调用地址。 有没有办法在调试器中运行程序或静态重新链接? 谢谢,
卢卡
编辑:
nm和readelf将不会这样做,我不需要查看共享对象中存在哪些符号,但实际上在链接到它的其他对象中使用了哪些符号。
答案 0 :(得分:41)
nm 仅在图书馆未删除其符号时才有效。但是,nm -D
可以向您显示一些信息:
nm -D /lib/libgcc_s.so.1
但还有另一种可以帮助你的工具: readelf
readelf - 显示有关的信息 ELF文件。
如果您查看手册页,请选择 -s :Displays the entries in symbol table section of the file, if it has one.
readelf -s /lib/libgcc_s.so.1
修改强>
嗯,在您使用nm检查的对象中未实现的符号将在其前面显示 U 标记,但nm不会告诉您系统上的哪个库实现了该标记符号
所以你想要的东西可以通过 ldd 和 nm 的混合来实现。 ldd告诉您的应用程序链接了哪些库,nm告诉哪些符号未定义( U 标志)或本地实现( T 标志)。
在目标应用程序上列出所有未定义的符号(带有nm)后,您应该遍历ldd报告的所有库以搜索这些符号(再次使用nm)。如果你找到符号并且它前面有T标志,你就找到了它。
顺便说一句,我刚刚为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]
答案 1 :(得分:4)
你看过ltrace了吗?它在运行时拦截对共享库函数的调用,并在它们发生时打印有关它们的信息。
由于这是一个动态解决方案,因此它不会打印任何部分程序中永远不会执行的库调用的信息。但根据您的需要,它可能仍然有用。
答案 2 :(得分:1)
我不知道一个,即使nm
对你想要的东西的用处有限。此外,预加载(GNU链接器)可能会使您使用据称可以执行此操作的工具后所做的任何假设无效。请参阅ld.so man page。任何人都可以使用LD_PRELOAD
来覆盖正常情况下符号的解析。
但是,即使没有调试器,您也可以使用LD_DEBUG
查看最终使用的函数。
答案 3 :(得分:0)
也许nm
工具可以帮助您,因为它显示二进制文件中包含的符号名称
它就像ABC一样简单:
nm my_binary
答案 4 :(得分:0)
这可以使用逆向工程中的静态分析技术来实现
你需要一个反汇编程序。见http://en.wikipedia.org/wiki/Disassembler
IDA PRO是一个很好的反汇编程序,可以回答你的问题。它能够读取ELF文件格式,但不幸的是它不是免费的。