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


485

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

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


该平台有所作为。苹果提供了GCC 4.0,但它nm不响应某些选项,例如-D-g(IIRC)。
jww

这在Mac OS上不打印任何内容。
IgorGanapolsky '16

3
@jww因为这是BSD nm,而不是GNU nm
OrangeDog

Answers:


575

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

35
但是,这并不总是适用于.so文件,因此您可能必须使用另一个答案中提到的“ readelf”解决方案。
Brooks Moses 2010年

9
请注意,OS X版本的nm缺少用于拆分符号的'-C'选项。可以使用c ++ filt。此处的示例脚本:v8.googlecode.com/svn/branches/bleeding_edge/tools/mac-nm nm -g /usr/lib/libstdc++.6.dylib | c ++ filt -p -i
fredbaba

5
请注意,这readelf -Ws将显示所有符号,并且nm -g仅显示外部可见的符号。如果要检查多个符号文件并开始交换命令,这可能会造成混淆。
安德鲁B

3
我也将添加objectdump -TC到列表中。与相反readelf -Ws,它不显示名称混乱的名称。
Yan Foto

2
@BrooksMoses对于.so文件,您可能需要添加--dynamicnm命令行。
user7610

84

如果.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}';

19
readelf -Ws /usr/lib/libstdc++.so.6 | awk'{print $ 8}'; 正则表达式很棒,但是有时候有点awk可以帮上大忙。
deft_code 2010年


42

对于共享库libNAME.so,必须使用-D开关才能在Linux中查看符号

nm -D libNAME.so

以及其他人报告的静态库

nm -g libNAME.a

35

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

  • 您可以用nm列出的那个
  • 您可以使用readelfobjdump列出的一个

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


3
谢谢!这解释了为什么有时“ nm”不显示.so文件的任何符号的原因。
Brooks Moses

10
nm -D-让您列出动态符号表
pt123

19

对于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


11

尝试将-l添加到nm标志中,以获取每个符号的来源。如果该库是使用调试信息(gcc -g)编译的,则该库应该是源文件和行号。正如Konrad所说的,此时目标文件/静态库可能是未知的。



9

您可以使用nm -gbinutils工具链中的工具。但是,它们的来源并不总是随时可用。而且我什至不确定该信息是否总是可以检索到。也许objcopy揭示更多信息。

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


6

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

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

nm-版本

GNU nm 2.17.50.0.6-12.el5 20061020


1

如果您只是想知道是否存在符号可以使用

objdump -h /path/to/object

或列出调试信息

objdump -g /path/to/object
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.