9

我有一些带有非空构造函数的全局实例的简单声明。这些构造函数在启动期间自动调用。我在 Linux 上将 C++ 交叉编译到不同的微控制器目标。


至于

  • arm-none-eabi-gcc-4.8.4
  • rx-elf-gcc-4.8-GNURX_v14.03 (GCC 4.8.3)

对构造函数的调用被放入该.init_array部分。地图文件如下所示:

.init_array 0x00007cb8 0x4 libmotor.o

.init_array 0x00007cbc 0x4 libaudio.o


至于

  • mips-elf-gcc-4.8.2
  • avr-gcc-4.8.1
  • msp430-gcc-4.6.3

这些调用进入该.ctors部分:

.ctors 0x000000009d011508 0x4 libmotor.o

.ctors 0x000000009d01150c 0x4 libaudio.o


编译完成-ffunction-sections -fdata-sections,链接器得到--gc-sections.

所有二进制文件都有效,但我想将所有调用放在同一部分(以简化链接器脚本的维护)。

  • 为什么有不同的目标部分?
  • 是否可以使用命令行选项更改默认部分?
  • 如果命令行选项不退出:是否可以在 GCC 编译时定义默认部分?
4

1 回答 1

8

错误 46770 - Replace .ctors/.dtors with .init_array/.fini_array 在支持它们的目标上进行了长时间的讨论

我提取了一些解释情况的项目:

为什么.init_array出现了?

  • 我们添加了.init_array/.fini_array以便将包含实际代码的 SVR4 版本.init与包含函数指针并使用DT_INIT_SZ动态数组中的条目而不是来自 crt*.o 文件的序言和结尾片段的 HP-UX 版本混合。HP-UX 版本被视为改进,但不兼容,因此我们重命名了部分和动态表条目,以便两个版本可以并存,实现可以从一个缓慢过渡到另一个.

  • 在 HP-UX 上,我们将.init/.init_array用于静态构造函数,它们在特殊atexit列表中注册了相应的静态析构函数,而不是在 中添加析构函数.fini_array,以便我们可以dlclose()正确处理事件的析构函数(取决于您对“正确”的解释)语境)

执行顺序在.ctors和之间不同.init_array

.ctors节的倒序

一些程序可能隐含地依赖于稍后链接的档案中的全局构造函数在与这些档案链接的对象中的构造函数之前运行的事实。也就是说,给定

g++ foo.o -lbar

其中 bar 是静态存档,而不是共享库,那么目前从 libbar.c 中提取的对象中的全局构造函数将在 foo.o 中的全局构造函数之前执行。这是一个有意的选择,因为它比相反的情况更有可能是正确的。但是,C++ 标准并不能保证这一点,因此任何依赖此顺序的程序在技术上都是无效的。

倒序问题.ctors

ld在 GNU和gold将构造函数从 迁移.ctors到中都做了很多工作.init_array,所有这些都是为了改善 Firefox 的启动延迟

使用.init_array/.fini_array代替.ctors/.dtors消除了对相关(相对)重定位的需要,并避免了启动时的向后磁盘寻道(因为.ctors向后处理,.init_array所以向前处理)。

从 过渡.ctors.init_array

ldGNU和gold现在的主线版本都将.ctors部分放入.init_array部分中,并将.dtors部分放入.fini_array部分中。

评论:可能是在 GCC 4.7 中引入的。

手臂

ARM EABI 从一开始就一直在使用.init_array

注释:尽管如此,默认链接描述文件包含一个.ctors输出部分。

GCC 配置

您可以选择使用 --disable-initfini-array 配置 gcc。

注释:此选项不会出现在mips-elf-gcc -v-v显示“配置为:...”)的输出中。

于 2015-03-11T08:42:01.177 回答