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

How do I list the symbols in a .so file

提问人:Moe 提问时间:8/30/2008 最后编辑:Andrey NikolovMoe 更新时间:11/26/2019 访问量:550869

问:

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

我正在使用 gcc 4.0.2,如果这有什么不同的话。

C++ C GCC 符号名称 修改

评论

0赞 jww 9/13/2015
该平台有所作为。Apple 提供了 GCC 4.0,但它不响应某些选项,例如 和 (IIRC)。nm-D-g
0赞 IgorGanapolsky 5/10/2016
这在 Mac OS 上不会打印任何内容。
5赞 OrangeDog 8/4/2016
@jww因为那是 BSD ,而不是 GNU 。nmnm

答:

13赞 Konrad Rudolph 8/30/2008 #1

您可以使用 binutils 工具链中的工具。然而,它们的来源并不总是现成的。实际上,我甚至不确定这些信息是否总是可以检索到。也许揭示了进一步的信息。nm -gobjcopy

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

767赞 Steve Gury 8/30/2008 #2

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

nm -gD yourLib.so

如果要查看 C++ 库的符号,请添加“-C”选项来解耦符号(解的可读性要高得多)。

nm -gDC yourLib.so

如果你的 .so 文件是 elf 格式,你有如下两个方法:

任一(对于消除 C++ 也很有用):objdump-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

评论

41赞 Brooks Moses 12/14/2010
但是,这并不总是适用于 .so 文件,因此您可能必须使用另一个答案中提到的“readelf”解决方案。
9赞 fredbaba 6/13/2013
请注意,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
8赞 Andrew B 5/27/2014
请注意,这将显示所有符号,并且仅显示外部可见的符号。如果要检查多个符号文件并开始交换命令,这可能会造成混淆。readelf -Wsnm -g
3赞 Yan Foto 8/5/2015
我也会添加到列表中。与此相反,它不显示被破坏的名称。objectdump -TCreadelf -Ws
2赞 user7610 1/6/2018
@BrooksMoses 对于可能需要添加到命令行的文件。.so--dynamicnm
12赞 Adam Mitz 8/30/2008 #3

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

100赞 P Shved 10/25/2009 #4

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

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}';

评论

24赞 deft_code 3/9/2010
readelf -ws /usr/lib/libstdc++.so.6 |awk '{打印 $8}';正则表达式很棒,但有时有点笨拙会有很长的路要走。
57赞 Pavel Lapin 1/16/2010 #5
objdump -TC /usr/lib/libexample.so
37赞 Peter Remmers 9/7/2010 #6

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

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

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

评论

3赞 Brooks Moses 12/14/2010
谢谢!这就解释了为什么有时“nm”不显示 .so 文件的任何符号。
11赞 pt123 7/29/2013
nm -D - 用于列出动态符号表
7赞 zhaorufei 11/11/2010 #7

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

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

nm --版本

革奴联盟 nm 2.17.50.0.6-12.el5 20061020

44赞 cavila 2/7/2013 #8

对于共享库 libNAME.so -D 开关是在我的 Linux 中查看符号所必需的

nm -D libNAME.so

以及其他人报告的静态库

nm -g libNAME.a
18赞 Adi Shavit 11/4/2014 #9

对于 Android 文件,NDK 工具链附带了其他答案中提到的所需工具:、 和 。.soreadelfobjdumpnm

31赞 user7610 1/6/2018 #10

对于 C++ 文件,最终命令是.sonmnm --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

评论

0赞 Treviño 4/14/2021
不过没有办法看到符号版本,不是吗?
2赞 user7610 8/27/2021
@Treviño在我的系统上有。我尝试过,但无论有没有它,输出都是一样的......需要进一步调查。eidt:我忘了用.有了这个,它就可以工作了。例如,我得到 without 和 with,在输出中。nm--with-symbol-versionsglibc.so--dynamiciswupperiswupper@@GLIBC_2.2.5
2赞 Craig Ringer 2/8/2019 #11

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

objdump -h /path/to/object

或列出调试信息

objdump -g /path/to/object