collect2

本以为gcc会调用cc1asld来完成一系列编译、汇编和链接的工作,实际上,gcc是通过collect2间接调用ld的。

collect2主要实现了两个额外的功能,都是为C++程序准备的。其一是生成代码调用全局静态对象的构造函数和析构函数;其二是支持Cfront方式生成模板代码。

C++程序的全局静态对象,需要在main函数运行前构造好,在main函数执行完成后析构掉。构造函数和析构函数是由程序员编写的,那么该由谁负责调用呢?通常来讲,调用这些函数的工作由初始化代码完成,比如,GNU ld就可以生成这些代码。如果这些代码不能由linker自动生成,就需要collect2的帮助。

collect2调用ld生成一个执行程序,然后调用nm程序,根据命名规则,查找所有的调用全局静态对象构造函数和析构函数的函数,并将这些函数保存为一张表,再生成一段代码遍历每个表项,调用对应的函数。所有这些信息被保存为一个C程序,然后编译、汇编为目标文件,在链接时作为第一个目标文件传给linker,做第二次链接。此功能实现在gcc/collect2.c文件内。通过在config.gcc文件里查找use_collect2=yes来确定哪些系统使用了该功能,PC上默认是关闭的。

Cfront支持代码实现在gcc/tlink.c文件里,这里的调用关系就更复杂了。gcc在编译C++程序时不生成任何模板代码,而是使用-frepo生成一个辅助文件,collect2调用ld做链接后,分析错误信息,提取未定义的符号,然后通过分析所有的repo文件,判断要生成哪些模板代码,并调用gcc重新编译特定文件,然后再链接,如果还有未定义的符号,则重复上述过程。如此反复,最多17次。如果还不能正确链接,则报错。

查看collect2的手册

info gccint 'collect2'

查看Cfront模型

info gcc 'C++ Extensions' 'Template Instantiation'

 

One thought on “collect2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据