I build a position-independent executable (puppet
below), dynamically load via dlopen
, get its main
via dlsym
, and call it. This works fine, as long as this PIE doesn't use iostream
, specifically cout
. If it does, the code segfaults with the stack trace below.
If I do roughly the same thing, but compile the puppet as a shared library, not a PIE (renaming main to something else), everything works fine.
What could be causing this problem? It exists only on Linux; on a Mac this works fine.
puppet.cpp
:
#include <iostream>
int main(int argc, char** argv)
{
std::cout << "Hello from puppet" << std::endl;
}
main.cpp
:
#include <iostream>
#include <unistd.h>
#include <errno.h>
#include <dlfcn.h>
int main()
{
std::cout << "Hello from main" << std::endl;
typedef int (*MainType)(int argc, char *argv[]);
void* lib = dlopen("./puppet", RTLD_LAZY);
if (lib == NULL)
{
std::cerr << "Unable to open the library" << std::endl;
return 1;
}
MainType f = (MainType) dlsym(lib, "main");
if (f == NULL)
{
std::cerr << "Unable to get the function" << std::endl;
return 1;
}
int argc = 0; char** argv = 0;
f(argc, argv);
}
Makefile
:
all: main puppet
puppet: puppet.cpp
g++ puppet.cpp -o puppet -fPIE -Wl,-pie -Wl,--export-dynamic
main: main.cpp
g++ main.cpp -o main -ldl
Backtrace from the segfault:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff795da56 in std::ostream::sentry::sentry (this=0x7fffffffe080, __os=...) at /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/ostream.tcc:46
46 /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/ostream.tcc: No such file or directory.
(gdb) back
#0 0x00007ffff795da56 in std::ostream::sentry::sentry (this=0x7fffffffe080, __os=...) at /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/ostream.tcc:46
#1 0x00007ffff795e109 in std::__ostream_insert<char, std::char_traits<char> > (__out=..., __s=__s@entry=0x7ffff6ce0b95 "Hello from puppet", __n=17) at /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/lib
stdc++-v3/include/bits/ostream_insert.h:76
#2 0x00007ffff795e5a9 in std::operator<< <std::char_traits<char> > (__out=..., __s=0x7ffff6ce0b95 "Hello from puppet") at /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/char_t
raits.h:320
#3 0x00007ffff6ce0a87 in main () from ./puppet
#4 0x0000555555554a7e in main ()