19

有时当我对 .so 文件(例如 libstdc++.so.6)执行 nm 时,它显示没有符号,我需要使用 nm --dynamic。但是对于其他一些 .so 文件,我可以看到没有 --dynamic 的符号。

医生说:

显示动态符号而不是普通符号。这仅对动态对象有意义,例如某些类型的共享库。

但这令人困惑……共享库需要哪些“类型”--dynamic?这是如何确定的?在编译库期间?我认为所有共享库都是动态的(我的意思是,可以在运行时动态加载),但似乎我的理解不太正确。

4

2 回答 2

18

如果您的符号没有从您的共享库中导出,很有可能它会以.normal symbol table而不是dynamic symbol table.

ELF 文件中有多种类型的符号。

  • 的符号部分Normal Symbol table。这是仅仅nm libabc.soor的输出objdump --syms libabc.so。这些符号仅在静态链接期间使用。

  • 的符号部分Dynamic Symbol table。这是nm --dynamic libabc.soor的输出objdump --dynamic-syms libabc.so。动态符号表是运行时链接器/加载器使用的表,它将符号绑定在引用它们的 ELF 文件和定义它们的 ELF 文件之间。也使用它static linker,同时将共享库与需要它的应用程序链接起来。这是有助于在undefined symbol errors链接期间显示所有内容的组件。

  • Hidden symbols- 这些是使用 标记的符号_attribute_ ((visibility("hidden")))。这些符号不会导出到外部,只能在库中使用。在链接步骤期间检查可见性,因此仅对共享库强制执行。默认可见性是public,即符号被导出,除非另有说明。可以使用 修改行为-fvisibility=default|internal|hidden|protected

将默认的 ELF 图像符号可见性设置为指定的选项——除非在代码中被覆盖,否则所有符号都将被标记。使用此功能可以极大地改善共享对象库的链接和加载时间,生成更优化的代码,提供近乎完美的 API 导出并防止符号冲突。强烈建议您在分发的任何共享对象中使用它。尽管有命名法,但默认总是意味着公开,即;可从共享对象外部链接。protected 和 internal 在实际使用中毫无用处,因此唯一的其他常用选项将被隐藏。如果未指定 -fvisibility,则默认为 default,即公开每个符号——这会导致与 GCC 先前版本相同的行为。

在http://gcc.gnu.org/wiki/Visibility中概述了这些技术、它们的好处以及如何使用它们。

要回答您的问题,您何时会使用--dynamic选项nm,这将是您想要列出共享库导出的所有符号以及引用它们的 ELF 图像唯一可用的符号时。

于 2013-03-11T19:40:14.240 回答
2

如果共享库被剥离并因此仅包含动态符号表,则需要在共享库上使用--dynamicor选项。-D

您可能希望将此选项用于其他共享库以显式显示动态符号表,因为这是动态链接器查询的表。

file实用程序指示共享库是否被剥离。例子:

$ file /usr/lib64/libcrypt-nss-2.26.so
[..] ELF 64-bit LSB shared object, x86-64 [..], not stripped
$ file /usr/lib64/libxml2.so.2.9.7
[..] ELF 64-bit LSB shared object, x86-64 [..], stripped

不同符号表如何包含不同符号的示例:

$ nm -D /usr/lib64/libcrypt-nss-2.26.so | wc -l
39
$ nm /usr/lib64/libcrypt-nss-2.26.so | wc -l 
112
于 2018-05-23T15:41:36.257 回答