2014-01-20 66 views
0

在Linux上使用GCC如果我定义如何在Linux上追加到__preinit_array_start?

__attribute__((constructor)) static void myfunc(void) {} 

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

__preinit_array_start相关的静态链接二进制?

回答

2

由于没有__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"); 
} 

文件倒入foo.c,编译使用:gcc -o foo foo.c,然后运行产生一个的输出:使用

Foo 3 2 1 
Hello World 

文件编译,然后运行产生相同的输出,所以也出现与静态链接的二进制文件一起工作。

它会不是.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 

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

+0

你有关于'__preinit_array_start'预期用途的任何信息吗?它看起来非常没有证件。 – pts

+1

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