为什么GCC将对全局实例的构造函数的调用放入不同的部分(取决于目标)? [英] Why does GCC put calls to constructors of global instances into different sections (depending on the target)?

查看:186
本文介绍了为什么GCC将对全局实例的构造函数的调用放入不同的部分(取决于目标)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些非空的构造函数的全局实例的简单声明。这些构造函数在启动期间自动调用。我在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编译时定义默认部分? li>

解决方案

Bug 46770 - 在支持它们的目标上用.init_array / .fini_array替换.ctors / .dtors



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



.init_array turn up?



  • 我们添加了 .init_array .init 的SVR4版本,其中包含实际的 / / 代码,包含函数指针并在动态数组中使用 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 ld gold 中移动构造函数从 .ctors 到 .init_array ,以提高Firefox的启动延迟



code> .init_array / .fini_array 而不是 .ctors / .dtors 不需要关联(相对)重定位,并且避免了启动时的向后磁盘寻找(因为while .ctors .init_array 被向前处理。)


.ctors 转换到 .init_array



< blockquote>

GNU ld gold 的主线版本现在将 .ctors 节放入 .init_array 节中,并将 .dtors code> .fini_array 节。


注释:可能用GCC 4.7引入。 >

ARM


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



$ b

$ b


一个选项是使用--disable-initfini-array配置gcc。


注释:此选项不会出现在 mips-elf-gcc -v -v 显示已配置:...)。


I have some simple declarations of a global instances with non-empty constructors. These constructors are called during startup automatically. I am cross-compiling C++ on Linux to different microcontroller targets.


As for

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

calls to constructors are put into the .init_array section. The map file looks like this:

.init_array 0x00007cb8 0x4 libmotor.o

.init_array 0x00007cbc 0x4 libaudio.o


As for

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

these calls get into the .ctors section:

.ctors 0x000000009d011508 0x4 libmotor.o

.ctors 0x000000009d01150c 0x4 libaudio.o


Compiling was done with -ffunction-sections -fdata-sections, the linker got --gc-sections.

All binaries work, but I'd like to put all calls into the same section (to simplify maintenance of linker scripts).

  • Why are there different target sections?
  • Is it possible to change the default section using a command line option?
  • If a command line option does not exit: Is it possible to define the default section at GCC compile-time?

解决方案

There is a long discussion in Bug 46770 - Replace .ctors/.dtors with .init_array/.fini_array on targets supporting them

I have extracted some items which explain the situation:

Why did .init_array turn up?

  • We added .init_array/.fini_array in order to blend the SVR4 version of .init, which contained actual code, with the HP-UX version, which contained function pointers and used a DT_INIT_SZ entry in the dynamic array rather than prologue and epilogue pieces contributed from crt*.o files. The HP-UX version was seen as an improvement, but it wasn't compatible, so we renamed the sections and the dynamic table entries so that the two versions could live side-by-side and implementations could transition slowly from one to the other.

  • On HP-UX, we used .init/.init_array for static constructors, and they registered the corresponding static destructors on a special atexit list, rather than adding destructors to .fini_array, so that we could handle destructors on dlclose() events properly (subject to your interpretation of "properly" in that context)

The order of execution differs between .ctors and .init_array

Backwarding order of .ctors section

Some programs may implicitly rely on the fact that global constructors in archives linked later are run before constructors in the object linked against those archives. That is, given

g++ foo.o -lbar

where bar is a static archive, not a shared library, then currently the global constructors in objects pulled in from libbar.c will be executed before the global constructors in foo.o. That was an intentional choice because it is more likely to be correct than the reverse. However, the C++ standard does not guarantee it, so any programs which relies on this ordering is technically invalid.

Problem of backwarding order of .ctors

A lot of work was done in both GNU ld and gold to move constructors from .ctors to .init_array, all to improve startup latency for Firefox

Using .init_array/.fini_array instead of .ctors/.dtors removes the need for the associated (relative) relocations, and avoids the backwards disk seeks on startup (since while .ctors are processed backwards, .init_array is processed forward).

Transition from .ctors to .init_array

The mainline versions of both GNU ld and gold now put .ctors sections into .init_array sections, and put .dtors sections into .fini_array sections.

Comment: Probably introduced with GCC 4.7.

ARM

ARM EABI has been using .init_array from day one.

Comment: Nevertheless the default linker script contains a .ctors output section.

GCC configuration

One option you have is to configure gcc with --disable-initfini-array.

Comment: This option does not turn up in the output of mips-elf-gcc -v (-v shows "Configured with: ...").

这篇关于为什么GCC将对全局实例的构造函数的调用放入不同的部分(取决于目标)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆