【问题标题】:How to check why some symbol is required for linkage?如何检查为什么链接需要一些符号?
【发布时间】:2020-10-08 12:19:36
【问题描述】:

这个问题比较麻烦,让我们试试简短的版本: 通常,当您使用unresolved symbol reference 失败时,它会非常困难,在这里您调用链接器找不到的东西。您只需为您的链接器提供库,它就可以工作。有时,当您将头撞到墙上并且不明白为什么链接器需要这个符号时,它不会被调用,至少不会被直接调用。是否有一个工具/链接器开关可以解释为什么它认为“这里”需要该符号?

原来的问题: 这都是关于静态链接的。我有一个小实用程序,几行代码,几个包含。该实用程序与名为lib1 的库静态链接。假设lib1 依赖于另一个库lib2,因为lib1 使用来自lib2 的符号sym1。然而,没有使用/调用来自lib2sym1 的任何内容,也没有来自lib1 的任何可能依赖于lib2 的内容。然而,上述微小的实用程序因sym1 的未解析符号而失败。第一个问题是为什么?因为,在实用程序中,任何地方都不需要sym1,甚至没有使用实用程序中使用sym1lib1 的符号,为什么链接器首先要费心寻找这个符号?第二个问题,包含链有可能将符号sym1 引入我的实用程序,然后它回答“为什么”但它不应该引入它(至少没有明显的原因),所以第二个问题我如何找到链接器认为实用程序需要来自lib2sym1 的原因?

什么/何时/为什么:Linux、C/C++、GCC-9/Clang-9

【问题讨论】:

  • 原因是没有正确链接库,没有链接到依赖库。至于“为什么链接器认为实用程序需要来自barbaz”,看来您自己已经回答了这个问题:“foo 使用该库中的符号”。你还在你的叙述中交换了barbaz,几次,这让人困惑。您应该使用真实的符号名称,而不是虚假的符号名称,以避免这种混淆。
  • 大声笑,会修复它
  • 重写了 5 次,我认为它变得更糟了......
  • @kreuzerkrieg 您是否使用函数部分和/或数据部分编译了 lib1 和 lib2?你做部分垃圾收集吗?顺带一提-fdata-sections -ffunction-sections -fipa-pta main.cpp -Wl,--gc-sections -Wl,-O1 -Wl,--as-needed
  • @kreuzerkrieg 您可能想看看 gc-sections here 的另一种用法。基本上,有了这样的脚本(Eric 可能会给你),你可以了解使用什么和丢弃什么、代码大小、rodata 大小等

标签: c++ gcc linker clang++


【解决方案1】:

好吧,显然我设法回答了没有看到代码和错误消息的问题。是时候打开我的 psi 咨询了。

关于 Linux/ELF 目标上的链接,重要的是要记住,链接器在尝试满足/解析符号时,正在合并(并复制到最终可执行文件)部分(又名段)。通常应用程序具有 .text(代码段)、.rodata(只读数据)段、.data(r/w 初始化数据)段、.bss(未初始化数据)等。因此,如果需要符号位于三个函数之间在一个编译文件中,将选取文件的整个 .text 部分。如果未使用但出现在节函数中调用了其他东西,链接器将开始搜索那个“其他东西”来满足,即使它与应用程序无关。

另外,还有一些 C++ 特定的东西:对于具有虚函数的类,编译器生成 vtable,带有指向每个虚函数的指针,并将该表移动到 .rodata 部分。注意,那是什么 我们认为代码实际上是在(只读)DATA 部分中结束的。

如果你只定义了一个虚函数,链接器很可能会抱怨类似的错误消息

/tmp/cc5YTcBb.o:(.rodata._ZTV3CL1[_ZTV3CL1]+0x18): undefined reference to `CL1::fnc2()

您可以看到问题在于 .rodata,而不是 .text。

故事的寓意:将您的代码和数据切成大量最小的可能部分/段,即您的链接原子。理想情况下,每个函数都进入自己的部分,以及一段初始化或 r/o 数据。

最后一步是指示链接器(通过 -Wl 选项)丢弃(垃圾收集)所有未使用的部分。

一般来说,链接器会使用更多的 RAM,链接阶段可能会更慢,但应用程序会更小更快。

命令行使用,看看GCC手册wrt options的含义。

g++ -fdata-sections -ffunction-sections -fipa-pta main.cpp -Wl,--gc-sections -Wl,-O1 -Wl,--as-needed

【讨论】:

    猜你喜欢
    • 2012-12-14
    • 1970-01-01
    • 1970-01-01
    • 2023-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    相关资源
    最近更新 更多