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

时间:2008-08-29 16:57:48

标签: c++ c gcc symbols name-mangling

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

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

11 个答案:

答案 0 :(得分:496)

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

nm -g yourLib.so

如果要查看C ++库的符号,请添加“-C”选项,该符号对符号进行解码(它的解码性更强)。

nm -gC yourLib.so

如果您的.so文件采用精灵格式,您有两种选择:

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

答案 1 :(得分:74)

如果您的.so文件采用精灵格式,则可以使用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}';

答案 2 :(得分:49)

objdump -TC /usr/lib/libexample.so

答案 3 :(得分:36)

对于共享库libNAME.so,需要使用-D开关来查看Linux中的符号

nm -D libNAME.so

以及其他人报告的静态库

nm -g libNAME.a

答案 4 :(得分:33)

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

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

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

答案 5 :(得分:11)

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

答案 6 :(得分:11)

对于Android .so文件,NDK工具链附带了其他答案中提到的必备工具:readelfobjdumpnm

答案 7 :(得分:10)

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

答案 8 :(得分:9)

您可以使用binutils工具链中的nm -g工具。但是,它们的来源并不总是随时可用。我甚至不确定是否总能检索到这些信息。也许objcopy会显示更多信息。

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

答案 9 :(得分:6)

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

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

nm --version

GNU nm 2.17.50.0.6-12.el5 20061020

答案 10 :(得分:0)

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

objdump -h /path/to/object

或列出调试信息

objdump -g /path/to/object