有时当我在.so文件上执行nm(例如,libstdc ++。so.6)时,它没有说明符号,我需要使用nm --dynamic。但对于其他一些.so文件,我可以看到没有--dynamic的符号。
医生说:
显示动态符号而不是普通符号。这仅对动态对象有意义,例如某些类型的共享库。
但令人困惑的是......共享库的“类型”需要什么 - 动态?这是如何确定的?在编译图书馆期间?我认为所有共享库都是动态的(我的意思是,可以在运行时动态加载),但似乎我的理解不太正确。
答案 0 :(得分:13)
如果您的符号未从共享库导出,很可能最终会导致normal symbol table
而不是dynamic symbol table
。
ELF文件中有许多类型的符号。
符号是Normal Symbol table
的一部分。这是nm libabc.so
或objdump --syms libabc.so
的输出。这些符号仅在静态链接期间使用。
符号是Dynamic Symbol table
的一部分。这是nm --dynamic libabc.so
或objdump --dynamic-syms libabc.so
的输出。动态符号表是运行时链接器/加载器使用的表,它绑定引用它们的ELF文件和定义它们的ELF文件之间的符号。它也被static linker
使用,同时将共享库与需要它的应用程序链接起来。这是有助于在链接期间显示所有undefined symbol errors
的组件。
Hidden symbols
- 这些是使用_attribute_ ((visibility("hidden")))
标记的符号。这些符号不会导出到外部,只能在库中使用。在链接步骤期间检查可见性,因此仅对共享库强制执行。默认可见性为public
,即除非另有说明,否则将导出符号。可以使用-fvisibility=default|internal|hidden|protected
修改行为。
将默认的ELF图像符号可见性设置为指定的 option-all符号将被标记为this,除非在其中被覆盖 代码。使用此功能可以非常显着地改善链接 和共享对象库的加载时间,产生更多优化 代码,提供近乎完美的API导出并防止符号冲突。它 强烈建议您在任何共享对象中使用它 分发。尽管有命名法,但默认总是意味着公共,即; 可以从共享对象外部链接。 受保护和内部在实际使用中相当无用,所以 只会隐藏其他常用选项。默认为 -fvisibility未指定为默认值,即将每个符号设为公共 - 这会导致与以前版本的GCC相同的行为。
这些技术的概述,它们的好处以及如何使用它们 在http://gcc.gnu.org/wiki/Visibility。
要回答您的问题,您何时会使用--dynamic
的{{1}}选项,那么您希望列出共享库导出的所有符号,以及唯一可用的符号。参考它们的ELF图像。
答案 1 :(得分:0)
如果共享库被剥离,则需要在共享库中使用--dynamic
或-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