使用 C++ 构建一个 .so 这也是一个可执行文件

building a .so that is also an executable with C++

基于 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", __func__, __FILE__, __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", __func__, __FILE__, __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)
$

我将“数据”的定义从全局移动到本地 运行s。 好像没有初始化全局变量。

谁能解释一下发生了什么以及应该怎么做才能做到这一点 运行?

代码文件结果的 gdb 回溯:

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::char_traits<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::char_traits<char>, std::allocator<char> >::basic_string()'
/usr/bin/ld: main.cc:(.text+0x8c): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
collect2: error: ld returned 1 exit status

如果我 link 和 g++(当你有 C++ 代码时你应该这样做),那么它 link 没问题,但失败的方式与 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 检测并拒绝它。