如何在 Linux 上追加到 __preinit_array_start ?

pts*_*pts 3 c linux gcc initialization

如果我定义的话,在带有 GCC 的 Linux 上

__attribute__((constructor)) static void myfunc(void) {}
Run Code Online (Sandbox Code Playgroud)

,那么 的地址myfunc将被附加到__init_array_start.ctors部分中。但是我怎样才能附加一个函数指针呢__preinit_array_start

__preinit_array_start与静态链接的二进制文件相关吗?

Pet*_*esh 5

由于没有__attribute__((preconstructor)),您可以使用一些部分属性将代码混入相关部分,例如

#include <stdio.h>

int v;
int w;
int x;

__attribute__((constructor)) static void
foo(void)
{
    printf("Foo %d %d %d\n", v, w, x);
}

static void
bar(void)
{
    v = 3;
}

static void
bar1(void)
{
    w = 2;
}

static void
bar2(void)
{
    x = 1;
}

__attribute__((section(".preinit_array"))) static void (*y[])(void) = { &bar, &bar1, &bar2 };

int
main(int argc, char **argv)
{
    printf("Hello World\n");
}
Run Code Online (Sandbox Code Playgroud)

文件转储到foo.c,使用: 进行编译gcc -o foo foo.c,然后运行会产生以下输出:

Foo 3 2 1
Hello World
Run Code Online (Sandbox Code Playgroud)

使用 编译的文件gcc -static -o foo foo.c,然后运行会产生相同的输出,因此它似乎可以与静态链接的二进制文件一起使用。

但它不适用于文件;.so链接器抱怨:

/usr/bin/ld: /tmp/ccI0lMgd.o: .preinit_array section is not allowed in DSO
/usr/bin/ld: failed to set dynamic section sizes: Nonrepresentable section on output
Run Code Online (Sandbox Code Playgroud)

我倾向于避免它,因为该部分中的代码运行先于所有其他初始化例程。如果您尝试执行一些“这应该首先运行”初始化,那么这确实不是一个好主意 - 您只是在与应该通过其他机制解决的竞争条件作斗争。

  • 真正详细解释它的唯一参考文献是 [System V ABI](http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#init_fini)。它用于可执行文件的独立初始化代码。该代码在可能的启动最早点运行(即在所有内容都已映射之后,但在调用构造函数之前)。无法保证任何库代码在这种情况下都能正常工作,例如 const 对象此时不可用。 (2认同)