如何列出从.so文件导出的符号?如果可能的话,我也想知道它们的来源(例如,如果它们是从静态库中引入的).
我正在使用gcc 4.0.2,如果这有所不同.
用于列出符号的标准工具是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
如果您的.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
对于共享库libNAME.so,在我的Linux中查看符号需要-D开关
nm -D libNAME.so
以及其他人报告的静态库
nm -g libNAME.a
我一直想知道为什么-fvisibility =隐藏和的#pragma GCC的知名度似乎没有产生任何影响,因为所有的符号总是与可见的纳米 -直到我发现这个职位,指出我readelf和objdump的,这让我认识到,有似乎实际上是两个符号表:
你可以用nm列出的那个
你可以用readelf和objdump列出的那个
我认为前者包含可以使用strip剥离的调试符号或者可以为链接器或install命令提供的-s开关.即使nm不再列出任何内容,导出的符号仍会被导出,因为它们位于ELF"动态符号表"中,后者就是后者.
对于C++ .so
文件,最终的nm
命令是nm --demangle --dynamic --defined-only --extern-only
# 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
尝试将-l添加到nm标志以获取每个符号的来源.如果使用调试信息(gcc -g)编译库,则应该是源文件和行号.正如Konrad所说,此时对象文件/静态库可能是未知的.
对于Android的.so
文件时,NDK工具链附带有其他的答案中提到的所需的工具:readelf
,objdump
和nm
.
您可以使用nm -g
binutils工具链中的工具.但是,它们的来源并不总是随时可用.我甚至不确定是否总能检索到这些信息.或许可以objcopy
揭示更多信息
/编辑:工具的名称当然是nm
.该标志-g
用于仅显示导出的符号.
nm -g列出extern变量,这不是必需的导出符号.任何非静态文件范围变量(在C中)都是外部变量.
nm -D将列出动态表中的符号,您可以通过dlsym找到它的地址.
nm --version
GNU nm 2.17.50.0.6-12.el5 20061020