G -WL,-Z,Nocopyloc重定位误差
g++ -Wl,-z,nocopyreloc relocation error
当我尝试编译以下程序
时#include <iostream>
#include <memory>
#include <thread>
#include <vector>
// This function will be called from a thread
void call_from_thread()
{
std::cout << "Threaded: Hello, World" << std::endl;
}
int main()
{
std::cout << "Hello World" << std::endl;
std::thread t1(call_from_thread);
t1.join();
std::cout << "Goodbye World" << std::endl;
}
使用此调用
pi@raspberrypi:/tmp $ arm -linux -linux -gnueaeabihf -g -g -wall -o0 -o0 -ggdb -wl,-z,-z,nocopylelec segfault_check.cpp-cpp -ogv_test -o segv_test -segv_test -lpthRad>
它将在没有警告的情况下进行编译。在这种情况下,目标机是Raspberry Compute模块3运行Rapbian Stretch和GCC 6.3.0。试图运行它将导致立即发生的segfault,甚至在达到主入口点之前。
GNU gdb (Raspbian 7.12-6) 7.12.0.20161007-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "arm-linux-gnueabihf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from segv_test...done.
(gdb) run
Starting program: /tmp/segv_test
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x00000000 in ?? ()
(gdb) bt
#0 0x00000000 in ?? ()
#1 0x76e99148 in __dynamic_cast () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
#2 0x76f105f4 in bool std::has_facet<std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > > >(std::locale const&) () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
#3 0x76f02f94 in std::basic_ios<char, std::char_traits<char> >::_M_cache_locale(std::locale const&) () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
#4 0x76f030c0 in std::basic_ios<char, std::char_traits<char> >::init(std::basic_streambuf<char, std::char_traits<char> >*) () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
#5 0x76eab684 in std::ios_base::Init::Init() () from /usr/lib/arm-linux-gnueabihf/libstdc++.so.6
#6 0x00010de8 in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /usr/include/c++/6/iostream:74
#7 0x00010e28 in _GLOBAL__sub_I__Z16call_from_threadv () at segfault_check.cpp:44
#8 0x00011db4 in __libc_csu_init ()
#9 0x76c5460c in __libc_start_main (main=0x7efff214, argc=1993838592, argv=0x76c5460c <__libc_start_main+168>, init=0x11d68 <__libc_csu_init>, fini=0x11dc8 <__libc_csu_fini>, rtld_fini=0x76fdf9b8 <_dl_fini>, stack_end=0x7efff214)
at libc-start.c:247
#10 0x00010a78 in _start ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb)
但是,如果我放下nocopyreloc
指令,一切似乎都起作用:
pi@raspberrypi:/tmp $ arm -linux -linux -gnueabihf -g -g -wall -o0 -o0 -ggdb segfault_check.cpp -o segv_test -lpthread
pi@raspberrypi:/tmp $ ./segv_test
Hello World
Threaded: Hello, World
Goodbye World
直到今天,我都不知道nocopyreloc
选项。它通过cmake 滑入默认的cmake_exe_linker_flags设置工具链文件,我们用于交叉汇编。Binutils文档指出:
nocopyloc禁用副本重新定位的生产。
没有太多解释。
当我用G 7.2.0在Dev Machine(Linux X86_64(上编译程序时,我会收到以下错误消息
./segv_test: Symbol `_ZSt4cout' causes overflow in R_X86_64_PC32 relocation
./segv_test: Symbol `_ZSt4cout' causes overflow in R_X86_64_PC32 relocation
./segv_test: Symbol `_ZSt4cout' causes overflow in R_X86_64_PC32 relocation
./segv_test: Symbol `_ZTVNSt6thread6_StateE' causes overflow in R_X86_64_PC32 relocation
Segmentation fault (core dumped)
似乎暗示了问题的原因。显然,装载机无法执行必要的重新定位,但我真的不太了解该过程的细节。
我想知道我可以安全地丢弃nocopyreloc
选项,还是我需要以不同的或两者的方式构建我的Libs?或什么?
nocopyloc是为i386 ABI设计的,其中从动态库中的recrocs也被复制为主要可执行文件中的relocs。当时,这是唯一这样做的ABI。标志Nocopylocs抑制了这种行为。我不确定它在非I386 ABIS上做什么,但是掉落此标志似乎是安全的。
- 为什么在浮点中从大到小会引入更多的误差
- 重新定位图像时如何前进到下一个内存块
- 流填充字符的默认定位
- 通过Python Distutils(用于Python C扩展)使用可重定位的设备代码编译CUDA代码
- 为什么gmp会在这里与"invalid next size"重新定位一起崩溃?
- NS3 - python.h 文件无法定位编译错误
- 设置我的应用程序 API 感知并防止系统使其模糊和错误定位
- 基于相邻元素 c++ 的分段误差范围的循环
- QImage::p ixel 和 QImage::setPixel 坐标超出范围误差
- GLEW 未在 MSYS2 上定位 OpenGL 函数
- c++ 链接器错误"针对'.rodata.str1.1'的重新定位R_X86_64_32"链接 CXX 共享库 libsrt.so
- 将误差线添加到 VTK 二维散点图
- 动态矩阵特征分解过程中的误差
- 如何忽略32位整数中的特定位
- 如何在C++中使用光标定位
- 转换为非标量误差是什么意思?我该如何解决?
- 使用 stdio.h 重新定位和重命名文件C++
- R 包安装错误:重新定位 0 具有无效的符号索引 11
- G -WL,-Z,Nocopyloc重定位误差
- 定位由于整数除法引起的数值误差