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

时间:2021-03-07 15:06:53

How do I find out which functions of a shared object are used by a program or an other library? In this specific case, I would like to see which functions in /lib/libgcc1_s.so.1 are used by an other dynamic library. Since they are dynamically linked, objdump -d doesn't resolve the function call addresses. Is there a way short of running the program in a debugger or relinking statically? Thanks,

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

Luca

卢卡

Edit:

编辑:

nm and readelf won't do, I don't need to see which symbols are present in a shared object, but which are actually used in an other object that links to it.

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

5 个解决方案

#1


40  

nm will only work if the library wasn't stripped of its symbols. However, nm -D could show you some info:

nm仅在库未被删除其符号时才起作用。但是,nm -D可以显示一些信息:

nm -D /lib/libgcc_s.so.1

But there's another tool which can help you: readelf

但是还有另一种工具可以帮助你:readelf

readelf - Displays information about ELF files.

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

And if you check the man pages, option -s: Displays the entries in symbol table section of the file, if it has one.

如果检查手册页,选项-s:显示文件的符号表部分中的条目(如果有)。

readelf -s /lib/libgcc_s.so.1

EDIT:

编辑:

Well, symbols that are not implemented inside the object you are inspecting with nm will appear with a U flag in front of it, but nm won't tell you which library on your system implements that symbol.

好吧,在你用nm检查的对象中没有实现的符号会在它前面出现一个U标志,但是nm不会告诉你系统上哪个库实现了那个符号。

So what you are looking for can probably be achieved with a mixture of ldd and nm. ldd tells which libraries your application is linked with, and nm tells which symbols are undefined (U flag) or implemented locally (T flag).

所以你想要的东西可能是用ldd和nm的混合物来实现的。 ldd告诉您的应用程序链接了哪些库,nm告诉哪些符号未定义(U标志)或本地实现(T标志)。

After listing all the undefined symbols (with nm) on the target application, you should iterate through all libraries reported by ldd in search of those symbols (using nm again). If you find the symbol and it's preceded by the T flag, you found it.

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

By the way, I just wrote this one-liner for bash to illustrate my idea. It analyses an application named win and tries to find the libraries that implement all the symbols reported as undefined.

顺便说一句,我只是用bash写这个单行来说明我的想法。它分析名为win的应用程序,并尝试查找实现报告为undefined的所有符号的库。

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;

Or, if your terminal supports colors:

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

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;

I'm sure someone will find a performance improvement.

我相信有人会发现性能提升。

Outputs:

输出:

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]

#2


4  

Have you looked at ltrace? It intercepts calls to shared library functions at runtime and prints information about them as they occur.

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

Since this is a dynamic solution, it wouldn't print any information for a library call made in part of your program that never gets executed. But it might still be helpful depending on your needs.

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

#3


1  

I'm not aware of one, even nm is of limited use for what you seem to intend. Also, preloading (of the GNU linker) could invalidate any assumptions you make after using a tool that purportedly could do that. See the ld.so man page. LD_PRELOAD can be used by anyone to override the resolution of symbols as it would occur under normal circumstances.

我不知道一个,即使nm对于你似乎想要的东西也有限。此外,预加载(GNU链接器)可能会使您使用据称可以执行此操作的工具后所做的任何假设无效。请参见ld.so手册页。任何人都可以使用LD_PRELOAD覆盖符号的分辨率,因为它在正常情况下会发生。

However, even without a debugger you can use LD_DEBUG to see which function ultimately is being used.

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

#4


0  

Maybe the nm tool can help you since it displays the symbols' names contained in a binary file.
It is as simple as ABC to use:

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

nm my_binary

#5


-1  

This can be achieved using technique called static analysis in Reverse Engineering

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

You need a Disassembler for this. See http://en.wikipedia.org/wiki/Disassembler

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

IDA PRO is a good disassembler witch answers your question.It is capable of reading ELF file format but unfortunately it is not free.

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

#1


40  

nm will only work if the library wasn't stripped of its symbols. However, nm -D could show you some info:

nm仅在库未被删除其符号时才起作用。但是,nm -D可以显示一些信息:

nm -D /lib/libgcc_s.so.1

But there's another tool which can help you: readelf

但是还有另一种工具可以帮助你:readelf

readelf - Displays information about ELF files.

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

And if you check the man pages, option -s: Displays the entries in symbol table section of the file, if it has one.

如果检查手册页,选项-s:显示文件的符号表部分中的条目(如果有)。

readelf -s /lib/libgcc_s.so.1

EDIT:

编辑:

Well, symbols that are not implemented inside the object you are inspecting with nm will appear with a U flag in front of it, but nm won't tell you which library on your system implements that symbol.

好吧,在你用nm检查的对象中没有实现的符号会在它前面出现一个U标志,但是nm不会告诉你系统上哪个库实现了那个符号。

So what you are looking for can probably be achieved with a mixture of ldd and nm. ldd tells which libraries your application is linked with, and nm tells which symbols are undefined (U flag) or implemented locally (T flag).

所以你想要的东西可能是用ldd和nm的混合物来实现的。 ldd告诉您的应用程序链接了哪些库,nm告诉哪些符号未定义(U标志)或本地实现(T标志)。

After listing all the undefined symbols (with nm) on the target application, you should iterate through all libraries reported by ldd in search of those symbols (using nm again). If you find the symbol and it's preceded by the T flag, you found it.

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

By the way, I just wrote this one-liner for bash to illustrate my idea. It analyses an application named win and tries to find the libraries that implement all the symbols reported as undefined.

顺便说一句,我只是用bash写这个单行来说明我的想法。它分析名为win的应用程序,并尝试查找实现报告为undefined的所有符号的库。

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;

Or, if your terminal supports colors:

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

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;

I'm sure someone will find a performance improvement.

我相信有人会发现性能提升。

Outputs:

输出:

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]

#2


4  

Have you looked at ltrace? It intercepts calls to shared library functions at runtime and prints information about them as they occur.

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

Since this is a dynamic solution, it wouldn't print any information for a library call made in part of your program that never gets executed. But it might still be helpful depending on your needs.

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

#3


1  

I'm not aware of one, even nm is of limited use for what you seem to intend. Also, preloading (of the GNU linker) could invalidate any assumptions you make after using a tool that purportedly could do that. See the ld.so man page. LD_PRELOAD can be used by anyone to override the resolution of symbols as it would occur under normal circumstances.

我不知道一个,即使nm对于你似乎想要的东西也有限。此外,预加载(GNU链接器)可能会使您使用据称可以执行此操作的工具后所做的任何假设无效。请参见ld.so手册页。任何人都可以使用LD_PRELOAD覆盖符号的分辨率,因为它在正常情况下会发生。

However, even without a debugger you can use LD_DEBUG to see which function ultimately is being used.

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

#4


0  

Maybe the nm tool can help you since it displays the symbols' names contained in a binary file.
It is as simple as ABC to use:

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

nm my_binary

#5


-1  

This can be achieved using technique called static analysis in Reverse Engineering

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

You need a Disassembler for this. See http://en.wikipedia.org/wiki/Disassembler

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

IDA PRO is a good disassembler witch answers your question.It is capable of reading ELF file format but unfortunately it is not free.

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