有时当我对 .so 文件(例如 libstdc++.so.6)执行 nm 时,它显示没有符号,我需要使用 nm --dynamic。但是对于其他一些 .so 文件,我可以看到没有 --dynamic 的符号。
医生说:
显示动态符号而不是普通符号。这仅对动态对象有意义,例如某些类型的共享库。
但这令人困惑……共享库需要哪些“类型”--dynamic?这是如何确定的?在编译库期间?我认为所有共享库都是动态的(我的意思是,可以在运行时动态加载),但似乎我的理解不太正确。
有时当我对 .so 文件(例如 libstdc++.so.6)执行 nm 时,它显示没有符号,我需要使用 nm --dynamic。但是对于其他一些 .so 文件,我可以看到没有 --dynamic 的符号。
医生说:
显示动态符号而不是普通符号。这仅对动态对象有意义,例如某些类型的共享库。
但这令人困惑……共享库需要哪些“类型”--dynamic?这是如何确定的?在编译库期间?我认为所有共享库都是动态的(我的意思是,可以在运行时动态加载),但似乎我的理解不太正确。
如果您的符号没有从您的共享库中导出,很有可能它会以.normal symbol table
而不是dynamic symbol table
.
ELF 文件中有多种类型的符号。
的符号部分Normal Symbol table
。这是仅仅nm libabc.so
or的输出objdump --syms libabc.so
。这些符号仅在静态链接期间使用。
的符号部分Dynamic Symbol table
。这是nm --dynamic libabc.so
or的输出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 图像唯一可用的符号时。
如果共享库被剥离并因此仅包含动态符号表,则需要在共享库上使用--dynamic
or选项。-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