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

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

我使用的是gcc 4.0.2,如果有区别的话。

500834 次浏览

您可以使用binutils工具链中的nm -g工具。然而,它们的来源并不总是现成的。我甚至不确定这些信息是否总能被检索到。也许objcopy揭示了更多的信息。

/EDIT:这个工具的名字当然是nm。标志-g仅用于显示导出的符号。

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

nm -gD yourLib.so

如果你想看到c++库的符号,添加“-C”选项,它需要这些符号(它的可读性要强得多)。

nm -gDC 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 free@GLIBC_2.2.5 (14)
3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __errno_location@GLIBC_2.2.5 (14)
4: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable

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

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

readelf -Ws /usr/lib/libexample.so

您应该只提取在这个.so文件中定义的内容,而不是在它引用的库中。在本例中,第七列应该包含一个数字。你可以使用一个简单的正则表达式来提取它:

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可见性似乎没有任何影响,因为所有的符号都是在纳米中可见的-直到我发现了这篇文章,它指向了readelfobjdump,这让我意识到似乎实际上有两个符号表:

  • 你可以用纳米列出
  • 你可以用readelfobjdump列出

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

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

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

nm -版本

GNU nm 2.17.50.0.6-12。el5 20061020

对于共享库libNAME。所以-D开关是必要的,以查看符号在我的Linux

nm -D libNAME.so

并为静态库如别人所报道

nm -g libNAME.a

对于Android .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)

来源:# EYZ0

如果你只是想知道是否有符号现在,你可以使用

objdump -h /path/to/object

或者列出调试信息

objdump -g /path/to/object