如何列出从.so文件导出的符号?如果可能的话,我也想知道它们的来源(例如,如果它们是从静态库中提取的)。
我正在使用gcc 4.0.2,如果有区别的话。
nm
,而不是GNU nm
。
如何列出从.so文件导出的符号?如果可能的话,我也想知道它们的来源(例如,如果它们是从静态库中提取的)。
我正在使用gcc 4.0.2,如果有区别的话。
nm
,而不是GNU nm
。
Answers:
列出符号的标准工具是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
readelf -Ws
将显示所有符号,并且nm -g
仅显示外部可见的符号。如果要检查多个符号文件并开始交换命令,这可能会造成混淆。
objectdump -TC
到列表中。与相反readelf -Ws
,它不显示名称混乱的名称。
.so
文件,您可能需要添加--dynamic
到nm
命令行。
如果.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}';
objdump -TC /usr/lib/libexample.so
我一直想知道为什么-fvisibility = hidden和#pragma GCC可见性似乎没有任何影响,因为所有符号始终在nm中可见-直到我发现这篇文章将我指向readelf和objdump,这使我意识到那里似乎实际上是两个符号表:
我认为前者包含调试符号,可以使用strip或-s开关将其删除,然后将其提供给链接器或install命令。即使nm不再列出任何内容,您导出的符号仍会被导出,因为它们位于ELF“动态符号表”中,后者是后者。
对于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)
尝试将-l添加到nm标志中,以获取每个符号的来源。如果该库是使用调试信息(gcc -g)编译的,则该库应该是源文件和行号。正如Konrad所说的,此时目标文件/静态库可能是未知的。
对于Android的.so
文件时,NDK工具链附带有其他的答案中提到的所需的工具:readelf
,objdump
和nm
。
nm
不响应某些选项,例如-D
和-g
(IIRC)。