关于DSO引用隐藏符号的警告是什么意思?

49

我在使用g++连接某些共享库时遇到了问题。它会给出警告:

hidden symbol XXX in YYY is referenced by DSO /usr/lib/...

我已经阅读了一些关于特定问题的相关问题,但我希望全面了解 - 这个警告意味着什么,以及它的原因是什么:

  1. DSO是什么?
  2. 什么是隐藏符号?
  3. 如果它是隐藏的,如何引用它?

DSO = 动态共享对象 - Marco A.
2个回答

53

什么是DSO?

DSO是动态共享对象,或者更不正式地说是共享库

什么是隐藏符号?

隐藏符号是已编译为隐藏链接的符号(即函数或数据对象名称),例如按照(GCC特定的)声明:

int x __attribute__ ((visibility ("hidden")));

如果一个动态共享目标库(DSO)中定义了变量x,则从另一个DSO中无法动态引用它。链接器可以看到x(它不是静态的),但无法在动态链接时使用。文档here

如果它被隐藏了,如何引用它?

无法引用它,这就是您收到警告的原因。例如,链接时的警告:

在/usr/lib/libc_nonshared.a(stat.oS)中,隐藏的符号`stat'被DSO引用

告诉您链接中的DSO引用了符号stat,链接器可以在/usr/lib/libc_nonshared.a中找到stat的定义, 但很显然,该定义不在引用它的DSO中并且无法从该DSO中引用,因为它被隐藏了。

如果问题DSO没有正确构建为DSO,则会出现此问题。请参见此示例并按照后续操作进行解决。

继续为OP的后续操作

如果隐藏符号已被某个DSO引用,那么为什么问题出在DSO上?

链接器说:

DSO X 包含对符号 S 的引用。我可以在另一个链接模块 Y 中找到符号 S 的定义, 但该定义将无法动态(即在运行时)满足 X 中的引用,因为 SY 中具有隐藏链接。

我可以确认问题出现在非共享对象上[...][但]我没有明确隐藏我的非共享对象中的这些符号。

你可能没有明确标记任何隐藏在非共享对象中的符号。根据其构建方式,除非明确标记为“否”,否则符号可能默认情况下会被隐藏。
比如说,非共享对象是libnonshared.a,而所谓的隐藏符号是foo。那么运行以下命令:
objdump -t libnonshared.a

获取有关libnonshared.a中符号的信息。在输出中,查找foo的条目。它是否包含标记.hidden? - 例如。

0000000000000000 g     F .text  000000000000000b .hidden foo

这篇文章说foo是一个全局符号(标记为g - 这就是链接器能够看到它的原因),但对于动态链接来说,它被隐藏了。

如果情况确实如此,那么您需要去修复libnonshared.a的构建过程,以便它不再隐藏foo。 否则,我就束手无策了。


我不理解你回答的最后一部分。如果隐藏符号已经被某个DSO引用,那么为什么问题会出现在DSO上?实际上,我可以确认问题出现在一个非共享对象上,它定义了一些可能与DSO知道的外部符号同名的符号 - 它们在另一个地方提供。此外,我没有明确地隐藏我的非共享对象中的这些符号。 - abyss.7
有帮助,但我仍然难以理解在所有这些假设的例子中,是只有一个共享或静态库,还是有两个库,一个是静态的,一个是动态的...? - Welgriv

1
这篇文章是关于编程的,以下是翻译内容:

距离Mike的出色回答已经过去了将近十年,我想提供一个更简短的答案,希望能帮助未来的读者:

当出现此错误时会发生什么:

  1. 您正在链接到一个包含由另一个库解析的符号的动态库
  2. 如果解析符号的库是静态的(.a),则会出现此错误
  3. 尝试将解析库重新创建为动态库(.so)

我遇到此问题的一个具体示例:

  1. 我创建了一个使用一些OpenCV函数并因此具有一些OpenCV符号的动态库
  2. 我正在链接OpenCV库以解析动态库中的符号,但我的OpenCV库是静态的,这导致了原始帖子中描述的错误。
  3. 我重新编译了OpenCV,这次创建了动态库
  4. 我尝试使用我的动态库和新创建的OpenCV动态库重新编译程序
  5. 嘿,错误不再出现了。

祝你好运!


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