555

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

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

4

11 回答 11

671

列出符号的标准工具是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
于 2008-08-29T17:21:08.550 回答
91

如果您的.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}';
于 2009-10-25T10:39:36.357 回答
56
objdump -TC /usr/lib/libexample.so
于 2010-01-15T18:25:47.270 回答
44

对于共享库 libNAME.so,需要 -D 开关才能在我的 Linux 中查看符号

nm -D libNAME.so

以及其他人报告的静态库

nm -g libNAME.a
于 2013-02-06T19:54:44.537 回答
37

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

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

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

于 2010-09-07T08:55:02.707 回答
28

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

于 2018-01-06T00:05:35.867 回答
17

对于 Android.so文件,NDK 工具链附带其他答案中提到的所需工具readelfobjdumpnm.

于 2014-11-04T15:33:32.380 回答
12

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

于 2008-08-29T21:22:13.727 回答
11

您可以使用nm -gbinutils 工具链中的工具。但是,它们的来源并不总是很容易获得。而且我什至不确定是否始终可以检索到这些信息。也许objcopy会揭示更多信息。

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

于 2008-08-29T17:07:11.563 回答
7

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

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

纳米——版本

GNU 纳米 2.17.50.0.6-12.el5 20061020

于 2010-11-11T07:00:56.083 回答
2

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

objdump -h /path/to/object

或列出调试信息

objdump -g /path/to/object
于 2019-02-08T11:30:53.907 回答