没有链接具有构造函数属性的gcc函数

kan*_*nna 9 attributes gcc constructor static-linking

我有一堆静态库,它们是相互依赖的.由于依赖性,我在为目标链接这些库时遇到了问题.作为一种解决方法,我从所有库中创建了一个归档文件.

其中一个静态库具有构造函数和析构函数,因此组合存档(使用nmobjdump检查存档)但是当我使用组合存档作为目标时,最终二进制文件不包含构造函数和析构函数.

我也尝试过--whole-archive但是这个选项对我来说似乎不起作用(二进制大小没有增加).

什么可能出错的想法.谢谢

Dam*_*mon 7

链接器只加载它必须的模块(即你实际隐式显式引用的内容),除非你强制它.

既是好事,也是不幸的.它使链接过程更快,并防止代码膨胀.它通常也不会引起问题,因为通常您会以某种方式引用所需的所有模块,并且不需要您不引用的模块.一般.
但它也是导致此静默失败的原因:链接器从不加载包含构造函数/析构函数的模块,甚至从不查看它.那是因为你从未真正调用过这些函数.

您可以通过显式链接与包含构造函数/析构函数的源对应的目标文件来强制链接器包含该模块.

换句话说,如果构造函数/析构函数在foo.c,添加-l/path/to/foo.o到链接器的选项,或者只是将foo.o命令行传递给链接器(作为额外的参数).

在任何一种情况下,通过这样做,您明确告诉链接器考虑这个模块,这样做将使它找到构造函数并正确调用它们.

另一种方法(不需要你使用命令行)可能会将一个变量或一个函数(不一定做任何事情)放入与构造函数/析构函数相同的源文件中,并从任何源文件中调用该文件.主程序.
这也将强制链接器加载包含模块(它将在其中找到构造函数).

更新:
我测试了替代方案,它工作正常:

/* libcode.c */
void enable_constructors() { /* do nothing */ }
void __attribute__ ((constructor)) con() { __builtin_puts("construct"); }
void __attribute__ ((destructor))  des() { __builtin_puts("destruct"); }


/* main.c */
extern void enable_constructors();

int main()
{
    enable_constructors();
    __builtin_puts("main");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

construct
main
destruct
Run Code Online (Sandbox Code Playgroud)

它还适用于您从主程序中的源文件触摸的全局变量:

/* libcode.c */
int enable_constructors; /* not used for anything */

void __attribute__ ((constructor)) cons() { __builtin_puts("construct"); }
void __attribute__ ((destructor)) des() { __builtin_puts("destruct"); }


/* main.c */
extern int enable_constructors;

int main()
{
    ++enable_constructors; /* touch the other module */
    __builtin_puts("main");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)