为什么GCC将对全局实例的构造函数的调用放入不同的部分(取决于目标)?

时间:2015-02-17 14:47:37

标签: c++ gcc microcontroller ld linker-scripts

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


至于

  • 臂-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编译时定义默认部分?

1 个答案:

答案 0 :(得分:4)

Bug 46770 - Replace .ctors/.dtors with .init_array/.fini_array on targets supporting them

进行了长时间的讨论

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

为什么.init_array出现了?

  
      
  • 我们添加了.init_array / .fini_array,以便将包含实际代码的.init的SVR4版本与包含函数指针的HP-UX版本混合在一起在动态数组中使用DT_INIT_SZ条目,而不是使用crt * .o文件提供的序言和结尾片段。 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

的反向订单问题
  

在GNU ldgold中完成了大量工作,将构造函数从.ctors移到.init_array,所有这些都是为了改善Firefox的启动延迟

     

使用.init_array / .fini_array代替.ctors / .dtors可以消除对相关(相对)重定位的需求,并避免在启动时向后搜索磁盘(因为向后处理.ctors,向前处理.init_array

.ctors过渡到.init_array

  

GNU ldgold的主要版本现在将.ctors个部分放入.init_array部分,并将.dtors部分放入.fini_array部分部分。

评论:可能与GCC 4.7一起推出。

<强> ARM

  

ARM EABI从第一天开始就使用.init_array

注释:然而,默认链接描述文件包含.ctors输出部分。

GCC配置

  

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

评论:此选项未显示在mips-elf-gcc -v的输出中(-v显示“已配置:...”)。