首页 > 解决方案 > 动态加载的与位置无关的可执行文件中的段错误

问题描述

我构建了一个与位置无关的可执行文件(puppet如下),动态加载 via dlopen,获取它的mainviadlsym并调用它。这很好用,只要这个 PIE 不使用iostream, 特别是cout. 如果是这样,则代码会在下面的堆栈跟踪中出现段错误。

如果我做大致相同的事情,但将 puppet 编译为共享库,而不是 PIE(将 main 重命名为其他内容),一切正常。

什么可能导致这个问题?它只存在于 Linux 上;在 Mac 上这工作正常。

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

段错误的回溯:

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 ()

标签: c++linuxgccsegmentation-fault

解决方案


推荐阅读