gpt4 book ai didi

linux - 加载可执行文件或执行库

转载 作者:行者123 更新时间:2023-12-03 09:58:54 26 4
gpt4 key购买 nike

有一个large numberquestions关于如何执行库或动态加载可执行文件。据我所知,所有答案都归结为:将可执行文件编译为与位置无关的代码并使用 dlopen 加载它。 .这很好用 --- 并且在 macOS 上仍然很好用 --- 直到 recent change in glibc ,明确禁用 dlopen在 PIE 中。例如,此更改现在在 ArchLinux 上的当前版本的 glibc (2.30) 中,并尝试 dlopen与位置无关的可执行文件会出现错误:“无法动态加载与位置无关的可执行文件”。

很难猜测是什么促使了如此彻底的改变,破坏了如此多的代码和有用的用例。 (关于 Patchwork 和 Bugzilla 的解释对我来说没有多大意义。)但现在有一个问题:如果你想创建一个也是动态库的可执行文件,反之亦然,该怎么办?

A solution从其中一条评论链接。在此复制以供后人使用:

#include <stdio.h>
#include <unistd.h>

const char service_interp[] __attribute__((section(".interp"))) = "/lib/ld-linux-x86-64.so.2";

extern "C" {

void lib_entry(void)
{
printf("Entry point of the service library\n");
_exit(0);
}

}

编译 g++ -shared test-no-pie.cpp -o test-no-pie -Wl,-e,lib_entry生成一个也可以在 Linux 上执行的共享对象(动态库)。

我有两个问题:
  • 如果我想传递命令行参数怎么办?如何修改此解决方案以使其接受 arc,argv ?
  • 还有其他选择吗?
  • 最佳答案

    It's difficult to guess what prompted such a radical change



    不是真的:它从来没有正常工作过。

    that breaks so much code



    该代码已经以微妙的方式被破坏了。现在你得到一个明确的迹象,它不会工作。

    Are there other alternatives?



    不要那样做?
    dlopen有什么问题ing 一个可执行文件解决?

    如果这是一个真正的问题,请打开 GLIBC bugzilla 功能请求,解释该问题并请求支持的机制以实现所需的结果。

    更新:

    at least say why "it never worked correctly". Is it some triviality like potentially clashing globals between the executables, or something real?



    线程局部变量是一个不能正常工作的例子。你是否认为它们是“真实的”,我不知道。

    这是代码:
    // foo.c
    #include <stdio.h>

    __thread int var;

    __attribute__((constructor))
    static void init()
    {
    var = 42;
    printf("foo.c init: %d %p\n", var, &var);
    }

    int bar() {
    printf("foo.c bar: %d %p\n", var, &var);
    return var;
    }

    int main()
    {
    printf("foo.c main: %d %p bar()=%d\n", var, &var, bar());
    return 0;
    }
    gcc -g foo.c -o foo -Wl,-E -fpie -pie && ./foo
    foo.c init: 42 0x7fb5dfd7d4fc
    foo.c bar: 42 0x7fb5dfd7d4fc
    foo.c main: 42 0x7fb5dfd7d4fc bar()=42
    // main.c
    // Error checking omitted for brevity
    #include <dlfcn.h>
    #include <stdio.h>

    int main()
    {
    void *h1 = dlopen("./foo", RTLD_LOCAL|RTLD_LAZY);
    int (*bar)(void) = dlsym(h1, "bar");

    printf("main.c: %d\n", bar());
    return 0;
    }
    gcc -g main.c -ldl && ./a.out
    foo.c init: 42 0x7fb7305da73c
    foo.c bar: 0 0x7fb7305da73c <<< what?
    main.c: 0 <<< what?

    这是使用 GNU C Library (Debian GLIBC 2.28-10) stable release version 2.28.
    底线:这从来没有被设计为有效的,你只是碰巧没有踩到许多地雷,所以你认为它有效,而实际上你正在行使未定义的行为。

    关于linux - 加载可执行文件或执行库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59074126/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com