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

时间:2020-03-05 18:45:05  来源:igfitidea点击:

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

我正在使用gcc 4.0.2,如果有所不同

解决方案

回答

我们可以使用binutils工具链中的" nm -g"工具。但是,它们的来源并不总是容易获得。而且我什至不确定该信息是否总是可以检索到。也许objcopy揭示了更多信息。

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

回答

列出符号的标准工具是" 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 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

回答

尝试将-l添加到nm标志中,以获取每个符号的来源。如果该库是使用调试信息(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 }';

回答

objdump -TC /usr/lib/libexample.so

回答

我一直想知道为什么-fvisibility = hidden和#pragma GCC可见性似乎没有任何影响,因为所有符号始终在nm中可见,直到我发现这篇文章将我指向readelf和objdump,这使我意识到实际上是两个符号表:

  • 我们可以用nm列出的那个
  • 我们可以使用readelf和objdump列出的一个

我认为前者包含调试符号,可以使用strip或者-s开关将其删除,然后将其提供给链接器或者install命令。即使nm不再列出任何内容,我们导出的符号仍会被导出,因为它们位于ELF"动态符号表"中,后者是后者。

回答

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

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

nm-版本

GNU nm 2.17.50.0.6-12.el5 20061020