nm和"readelf -s"的区别

36

假设我们有一个名为libtest.so的共享库,它里面有一个名为"foo"的函数。

使用strip命令来丢弃libtest.so中所有的符号。

$strip libtest.so

所以,现在如果我们使用:

$nm libtest.so

它将打印出:

nm: libtest.so: no symbols

但是如果我们使用:

$readelf -s libtest.so 

从它的结果中仍然可以看到foo函数:

...

10: 000005dc 5 FUNC GLOBAL DEFAULT 12 _Z3foov

...

我们也可以使用命令字符串来检查它:

$strings libtest.so

_Z3foov

...

我有一个问题,为什么使用nm命令在剥离了符号表的libtest.so上没有结果?

谢谢

1个回答

66
为什么strip后的libtest.so在使用nm命令时无法显示结果?
原始的libtest.so中有两个符号表:一个是“常规”符号表(在.symtab和.strtab部分),另一个是动态符号表(在.dynsym和.dynstr部分)。
如果strip移除了两个符号表,那么库将完全无用:动态加载器无法解析其中的任何符号。因此strip只会删除“常规”符号表,保留动态符号表。
你可以使用命令nm -Dreadelf -s来查看动态符号表中的符号。
“常规”符号表仅对调试有用(例如,它包含静态函数的条目,这些函数不会被库导出,并且不会出现在动态符号表中)。
但动态加载器从不查看“常规”符号表(该格式不适合快速符号查找);它只查看动态符号表。因此,“常规”符号表对于正确的程序操作并不需要,但动态符号表是必需的。

2
你的用户名很棒。所以,基本上,如果我在编译时将静态库链接到二进制文件中,那么该库的符号将显示在nm中,但如果我进行动态链接,则符号将显示在readelf -S和nm -D中,对吗? - acib708
@AlejandroCárdenas 我认为你的理解不太正确。此外,readelf -sreadelf -S之间有区别。最好单独提出一个问题来问。 - Employed Russian
是的,抱歉,我指的是readelf -s。好吧,核心问题仍然存在,我不明白nm和readelf -s之间的区别,因为您告诉我我所理解的是不正确的。您能否再详细解释一下呢?谢谢。 - acib708

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接