如何使共享库符号强大?

Posted

技术标签:

【中文标题】如何使共享库符号强大?【英文标题】:How can I make a shared library's symbols strong? 【发布时间】:2016-12-07 21:06:38 【问题描述】:

我创建了一个共享库,它引用了很多 C++ 模板函数。这些符号作为弱引用输入到共享库的导出表中(例如,当我使用 nm 查看共享库的符号时,它们显示为类型 W)。这意味着在运行时,这些符号可能会被来自首先加载的不同共享库的副本插入。

我的共享库使用包含在库本身中的这些函数的副本,而不是来自任何其他库,这对我的应用程序很重要。有什么办法可以确保这一点?在我看来,这相当于将所有各种模板实例静态链接到共享库中。

【问题讨论】:

【参考方案1】:

这意味着在运行时,这些符号可能会被插入 通过从首先加载的不同共享库中复制。

请注意,无论弱属性如何,它们都可以插入(请参阅this GCC post,它说动态链接器将弱点视为与强点类似,除非设置了LD_DYNAMIC_WEAK,但通常不会设置)。

我的共享库对我的应用程序很重要 使用包含的这些功能的副本 在图书馆本身内,而不是来自任何其他图书馆。 有什么办法可以确保这一点?

您可以做几件事。

通常推荐的方法是将fvisibility=hidden 添加到您的CFLAGS 以防止从您的库中导出任何符号,然后用__attribute__((visibility("default"))) 标记(希望很少)导出的函数。这也将允许在编译时进行更好的优化并加快启动速度,因为 rtld 将需要处理更少的符号。

穷人的有限解决方案是使用-fvisibility-inlines-hidden,这是-fvisility=hidden 的有限形式。它只会隐藏内联函数(例如来自 STL 模板的函数)。

如果您不想弄乱源代码,请使用-Wl,-Bsymbolic 链接 - 这将强制尽可能在库中解析引用。

-- 编辑--

实际上,即使您启用 -fvisibility=hidden 以防止其他库(或可执行文件本身)动态插入库内对导出函数的引用,您也需要 -Bsymbolic

【讨论】:

谢谢。 -Bsymbolic 和/或 -Bsymbolic-functions 是我的问题的解决方案。不过,我想我可能会采用推荐的方法来严格定义公共 API 并使用-fvisibility=hidden。这似乎是最佳做法。 再想一想,我认为即使使用-fvisibility=hidden,您也需要-Bsymbolic - 没有它,导出的函数可以被其他共享库插入。此外,为了避免与fvisibility=hidden 混淆,您可以使用它更简单的变体-fvisiblity-inlines-hidden - 这将隐藏所有内联函数(包括 STL 模板)。我已经更新了答案。

以上是关于如何使共享库符号强大?的主要内容,如果未能解决你的问题,请参考以下文章

当另一个库具有相同的符号时,gdb 不显示来自共享库的符号

链接共享库时限制符号的可见性

强制链接到未使用的共享库

使用 mpirun 时,如何使分析器(valgrind、perf、pprof)拾取/使用带有调试符号的本地版本库?

共享库如何获得自己的基地址

没有共享系统库的精确调试符号的远程事后分析 coredump 分析