无法解决的`R_X86_64_NONE`搬迁

zau*_*ufi 8 c++ elf unresolved-external binutils

我在CentOS 7上使用Devtoolset-7并且已经构建了Boost 1.65.1 w/it.但是当我链接我的应用程序时,我有以下内容:

/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
Run Code Online (Sandbox Code Playgroud)

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

所以我的问题是:

  • 这个错误究竟意味着什么?
  • 是什么R_X86_64_NONE和为什么"没有任何重新定位"(根据bintils来源)ELF标题中存在的符号类型?

附录:

  • 链接单元测试可执行文件时出错,链接到我的静态库和Boosts的静态库(单元测试框架)
  • 所有静态库(Boost和我的一个)都内置了-fPIC选项

PS.我真的希望这个问题能够一次又一次地解决(已经打过几次,但这次更新到最新的binutils并没有帮助).(将对此问题的任何活动开始赏金)

Flo*_*mer 8

发布到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
Run Code Online (Sandbox Code Playgroud)

请注意/usr/bin/strip,不是/opt/rh/devtoolset-7/root/usr/bin/strip.因此使用系统strip命令.42对应于R_X86_64_REX_GOTPCRELX重定位,其由DTS binutils作为优化生成.

重现这一点的简单方法是使用此C++文件:

#include <iostream>

void
dot ()
{
  std::cout << '.';
}
Run Code Online (Sandbox Code Playgroud)

如果编译-O2 -fpic,它将产生一个X86_64_REX_GOTPCRELX重定位_ZNSt8ios_base4InitD1Ev./usr/bin/strip -g在那上面运行会把它变成R_X86_64_NONE.这可以使用验证eu-readelf -r.

您可以使用RPM来告诉使用DTS strip使用

%if 0%{?scl:1}
%define __strip %{_bindir}/strip
%endif
Run Code Online (Sandbox Code Playgroud)

在RPM spec文件中,或者您可以添加

%undefine __brp_strip_static_archive
Run Code Online (Sandbox Code Playgroud)

跳过完全剥离静态库(这可能是正确的事情).