问题描述
基于 building a .so that is also an executable,我正在尝试使用 C++ 进行重现,但在主程序执行时出现分段错误。
/* pie.cpp */
#include <cstdio>
int foo()
{
printf("in %s %s:%d\n",__func__,__FILE__,__LINE__);
return 42;
}
int main()
{
printf("in %s %s:%d\n",__LINE__);
return foo();
}
/* pie.h */
#ifndef PIE_H
#define PIE_H
int foo();
#endif
/* main.cpp */
#include <cstdio>
#include <string>
#include "pie.h"
std::string data;
int main()
{
data="TEST";
printf("in %s %s:%d [%s]\n",__LINE__,data.c_str());
return foo();
}
$ g++ -fPIC -pie -o pie.so pie.cpp -Wl,-E
$ g++ main.cpp ./pie.so
$ ./pie.so
in main pie.cpp:10
in foo pie.cpp:5
$ ./a.out
Segmentation fault (core dumped)
$
我将“数据”的定义从全局移动到它运行的本地。 似乎全局变量没有被初始化。
有人能解释一下会发生什么以及应该怎么做才能让它运行吗?
Program terminated with signal SIGSEGV,Segmentation fault.
#0 std::string::size (this=0x404080 <data>) at /usr/src/debug/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.h:716
716 { return _M_rep()->_M_length; }
(gdb) bt
#0 std::string::size (this=0x404080 <data>) at /usr/src/debug/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.h:716
#1 std::string::assign (this=0x404080 <data>,__s=0x402010 "TEST",__n=4) at /usr/src/debug/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.tcc:262
#2 0x00000000004011c5 in main () at main.cpp:9
谢谢!
解决方法
我刚刚尝试了旧 answer 中的代码;它不再使用最近的 GLIBC(我有 2.31-9+build1
):
$ gcc -fPIC -pie -o pie.so pie.c -Wl,-E
$ gcc main.c ./pie.so
$ ./pie.so
in main pie.c:10
in foo pie.c:5
$ ./a.out
./a.out: error while loading shared libraries: ./pie.so: cannot dynamically load position-independent executable
使用您的 C++
示例,我无法使用您的命令构建它:
$ g++ -fPIC -pie -o pie.so pie.cc -Wl,-E
$ gcc main.cc ./pie.so
/usr/bin/ld: /tmp/ccaXra73.o: in function `main':
main.cc:(.text+0x13): undefined reference to `std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char> >::operator=(char const*)'
/usr/bin/ld: main.cc:(.text+0x1f): undefined reference to `std::__cxx11::basic_string<char,std::allocator<char> >::c_str() const'
/usr/bin/ld: /tmp/ccaXra73.o: in function `__static_initialization_and_destruction_0(int,int)':
main.cc:(.text+0x77): undefined reference to `std::__cxx11::basic_string<char,std::allocator<char> >::basic_string()'
/usr/bin/ld: main.cc:(.text+0x8c): undefined reference to `std::__cxx11::basic_string<char,std::allocator<char> >::~basic_string()'
collect2: error: ld returned 1 exit status
如果我用 g++
链接(当你有 C++
代码时应该这样做),那么它链接正常,但失败的方式与 C
代码相同:
$ g++ main.cc ./pie.so
$ ./pie.so
in main pie.cc:9
in foo pie.cc:4
$ ./a.out
./a.out: error while loading shared libraries: ./pie.so: cannot dynamically load position-independent executable
所以我想答案是:它本不打算以这种方式工作(并且过去“偶然”工作),现在 GLIBC 检测并拒绝了它。