如何列出.so文件中的符号

问题描述:

如何列出从.so文件导出的符号。如果可能的话,我也想知道它们的来源(例如,如果它们是从静态库中提取的)。如何列出.so文件中的符号

我用gcc 4.0.2,如果有差别

+0

该平台有差别。 Apple提供了GCC 4.0,但是它的`nm`不响应某些选项,如`-D`和`-g`(IIRC)。 – jww 2015-09-13 08:50:37

+0

这在Mac OS上不打印任何东西。 – 2016-05-10 14:05:14

+3

@jww因为那是BSD`nm`,而不是GNU`nm`。 – OrangeDog 2016-08-03 17:00:16

上市符号的标准工具是nm,你可以简单地使用它像这样:

nm -g yourLib.so 

如果你想看到一个C++库的符号,添加“-C”选项,还原函数符号(它的可读性更强)。

nm -gC yourLib.so 

如果你的.so文件是ELF格式,你有两个选择:

要么objdump-C也还原C有用++):

$ objdump -TC libz.so 

libz.so:  file format elf64-x86-64 

DYNAMIC SYMBOL TABLE: 
0000000000002010 l d .init 0000000000000000    .init 
0000000000000000  DF *UND* 0000000000000000 GLIBC_2.2.5 free 
0000000000000000  DF *UND* 0000000000000000 GLIBC_2.2.5 __errno_location 
0000000000000000 w D *UND* 0000000000000000    _ITM_deregisterTMCloneTable 

或者使用readelf

$ readelf -Ws libz.so 
Symbol table '.dynsym' contains 112 entries: 
    Num: Value   Size Type Bind Vis  Ndx Name 
    0: 0000000000000000  0 NOTYPE LOCAL DEFAULT UND 
    1: 0000000000002010  0 SECTION LOCAL DEFAULT 10 
    2: 0000000000000000  0 FUNC GLOBAL DEFAULT UND [email protected]_2.2.5 (14) 
    3: 0000000000000000  0 FUNC GLOBAL DEFAULT UND [email protected]_2.2.5 (14) 
    4: 0000000000000000  0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTable 
+23

但是,这并不总是适用于.so文件,因此您可能不得不使用另一个答案中提到的“readelf”解决方案。 – 2010-12-13 23:53:22

+0

好的答案 - 但我没有从nm,objdump或readelf获取函数签名。你知道我如何获得函数签名(参数)吗? – 2012-06-20 22:07:59

+7

请注意,nm的OS X版本缺少将符号解映射的'-C'选项。可以用C++ filt代替。示例脚本:http://v8.googlecode.com/svn/branches/bleeding_edge/tools/mac-nm nm -g /usr/lib/libstdc++.6.dylib | C++ filt -p -i – fredbaba 2013-06-12 21:13:34

您可以使用从binutils的工具链的nm -g工具。但是,它们的来源并不总是可用。而且我实际上并不确定这些信息总是可以被检索到。也许objcopy显示进一步的信息。

/编辑:该工具的名称当然是nm。标志-g用于仅显示导出的符号。

尝试添加-l到nm标志以g et每个符号的来源。如果库是用调试信息(gcc -g)编译的,这应该是源文件和行号。正如康拉德所说,目标文件/静态库在这一点上可能是未知的。

如果您的.so文件为elf格式,则可以使用readelf程序从二进制文件中提取符号信息。这个命令会给你的符号表:

readelf -Ws /usr/lib/libexample.so 

你应该只提取那些在此.so文件中定义的,而不是由它引用的库。在这种情况下,第七列应该包含一个数字。您可以通过使用一个简单的regex提取它:

readelf -Ws /usr/lib/libstdc++.so.6 | grep '^\([[:space:]]\+[^[:space:]]\+\)\{6\}[[:space:]]\+[[:digit:]]\+' 

或建议,由Caspin,:

readelf -Ws /usr/lib/libstdc++.so.6 | awk '{print $8}'; 

objdump -TC /usr/lib/libexample.so 

我一直在想,为什么-fvisibility =隐藏的#pragma GCC能见度似乎没有任何影响,因为所有的符号总是可见的nm - 直到我发现这篇文章,指出我readelfobjdump的,这让我认识到,似乎实际上是符号表:

  • 一个你可以用纳米
  • 的一个列表,你可以用readelf名单objdump的

我认为前者包含debuggi ng符号,可用剥离或-s开关,您可以给连接器或安装命令。即使nm不再列出任何东西,导出的符号仍然会被导出,因为它们位于ELF的“动态符号表”中,后者是后者。

nm -g列出extern变量,这不是必需的导出符号。 任何非静态文件范围变量(在C中)都是extern变量。

nm -D将在动态表中列出该符号,您可以通过dlsym找到它的地址。

纳米--version

GNU纳米2.17.50.0.6-12.el5 20061020

对于共享库以libname.so -D开关必要看到在我的Linux

nm -D libNAME.so 
符号

和静态库所报告的其他

nm -g libNAME.a 

对于安卓.so文件,NDK工具链随附其他答案中提到的所需工具:readelfobjdumpnm

对于C++ .so文件,最终nm命令是nm --demangle --dynamic --defined-only --extern-only <my.so>

# nm --demangle --dynamic --defined-only --extern-only /usr/lib64/libqpid-proton-cpp.so | grep work | grep add 
0000000000049500 T proton::work_queue::add(proton::internal::v03::work) 
0000000000049580 T proton::work_queue::add(proton::void_function0&) 
000000000002e7b0 W proton::work_queue::impl::add_void(proton::internal::v03::work) 
000000000002b1f0 T proton::container::impl::add_work_queue() 
000000000002dc50 T proton::container::impl::container_work_queue::add(proton::internal::v03::work) 
000000000002db60 T proton::container::impl::connection_work_queue::add(proton::internal::v03::work) 

源:https://stackoverflow.com/a/43257338