无法解析的`R_X86_64_NONE`重定位

11

我正在CentOS 7上使用Devtoolset-7,已经用它构建了Boost 1.65.1。但是当我链接我的应用程序时,出现了以下错误:

/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: /opt/rh/devtoolset-7/root/usr/lib64/libboost_unit_test_framework.a(compiler_log_formatter.o)(.text._ZN5boost9unit_test5utils11string_castINS0_13basic_cstringIKcEEEESsRKT_[_ZN5boost9unit_test5utils11string_castINS0_13basic_cstringIKcEEEESsRKT_]+0x3c): unresolvable R_X86_64_NONE relocation against symbol `_ZTVSt9basic_iosIcSt11char_traitsIcEE@@GLIBCXX_3.4'
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status

搜索有关 R_X86_64_NONE 的更多信息没有给出任何有价值的结果:大多数是没有回答或精确解释这是什么以及如何解决它的类似问题

所以我的问题是:

  • 这个错误实际上是什么意思?
  • R_X86_64_NONE 是什么,为什么 ELF 头中会存在“无需重定位”(根据 bintils 源)类型的符号?

补充说明:

  • 错误发生在链接单元测试可执行文件时,该可执行文件链接到我的静态库和 Boost 的静态库(单元测试框架)
  • 所有静态库(Boost 和我的静态库)都使用 -fPIC 选项构建

PS. 我真的希望这个问题能够一劳永逸地得到解决(已经遇到过几次了,但这次更新到最新的 binutils 也没有帮助)。 (将对此问题上的任何活动开始赏金)


你可能会在最近的基于LLVM的编译器中,例如clang(https://reviews.llvm.org/rL288485),获得更好的运气。 - OMGtechy
不幸的是,我需要 GCC 7.x %) - zaufi
@zaufi能否在某个地方发布一组最小的对象文件,以触发此问题?例如,您可以在Bugzilla中打开一个错误报告。我从未见过任何可以触发此问题的对象文件,并且似乎也没有人提交正确的错误报告。 - Florian Weimer
@zaufi,我需要精确的链接器调用(如 g++ -v 所示)和一个包含所有输入文件的 tar 压缩包(至少包括那些不是分发/软件集合的一部分的文件)。 - Florian Weimer
@FlorianWeimer,请告诉我缺陷跟踪器的URL以便发布(我认为SO不是正确的地方%) - zaufi
显示剩余4条评论
1个回答

10

从发布到Red Hat Bugzilla bug的构建日志中提取:

[19:15:01]W:     [Step 8/12] + /usr/lib/rpm/check-buildroot
[19:15:01]W:     [Step 8/12] + /usr/lib/rpm/brp-scl-compress /opt/rh/devtoolset-7/root
[19:15:01]W:     [Step 8/12] + /usr/lib/rpm/brp-strip-static-archive /usr/bin/strip
[19:16:40]W:     [Step 8/12] /usr/bin/strip: /work/build/BUILDROOT/devtoolset-7-boost-1.65.1-4.el7.centos.x86_64/opt/rh/devtoolset-7/root/usr/lib64/libboost_container.a(global_resource.o): invalid relocation type 42
[19:16:40]W:     [Step 8/12] /usr/bin/strip: BFD version 2.25.1-32.base.el7_4.2  assertion fail elf64-x86-64.c:341

注意使用 /usr/bin/strip 而非 /opt/rh/devtoolset-7/root/usr/bin/strip。因此,将使用系统的 strip 命令。数字 42 对应于由 DTS binutils 作为优化生成的 R_X86_64_REX_GOTPCRELX 重定位。
用以下 C++ 文件可以简单地复制此问题:
#include <iostream>

void
dot ()
{
  std::cout << '.';
}

如果使用-O2 -fpic编译,它将为_ZNSt8ios_base4InitD1Ev产生一个X86_64_REX_GOTPCRELX重定位。对其运行/usr/bin/strip -g会将其转换为R_X86_64_NONE。可以使用eu-readelf -r验证这一点。 您可以使用RPM告诉系统使用DTS strip
%if 0%{?scl:1}
%define __strip %{_bindir}/strip
%endif

在RPM规范文件中,或者你可以添加。
%undefine __brp_strip_static_archive

可以完全跳过剥离静态库的步骤(这也可能是正确的做法)。


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