GCC中初始化函数是怎样被处理的?

GCC中初始化函数是怎样被处理的?

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

本文译至:

http://gcc.gnu.org/onlinedocs/gccint/Initialization.html

如我们所知,在GCC通过给代码追加__attribute__((constructor))和__attribute__((destructor))的方式能够追加初始函数和终止函数,

这篇文章介绍了GCC内部是怎样实现上述处理的。

简单的说,就是在最常常的情况下,初始函数会被追加到.ctor section中,.init会调用相应的函数处理这些初始函数。终止情况类似。

———————————————————-

初始化函数是怎样被处理的?

某些语言被编译后的代码包含构造体(也被称为初始化例程)– 该函数被用于程序启动时初始化程序数据。这些函数须要在程序“開始”前被调用 – 就是说,在main函数被调用。
同一时候,编译一些语言时会生成析构体(也被称为终止例程),它应在程序结束时被调用。
为了支持初始函数和终止函数,编译器必须在汇编代码中生成一些东西来使这些函数在合适的时间点被调用。当你把编译器移植到一个新的系统时,你须要去指定怎么去做。
眼下GCC主要有两种方式支持初始函数和终止函数的运行,每种方式都有两个变体。对这四种变体而言,大部分结构是共通的。
链接器必须为这些函数建立两个列表 —  一个初始化函数的列表,称为 __CTOR_LIST__,和一个终止函数列表,称为 __DTOR_LIST__。
每一个列表总是从一个被忽略的函数指针開始(该函数指针在不同环境下,可能是0, -1 或是其后的函数指针的个数)。该函数指针后面尾随着一系列的0或是很多其它的构造体(析构体)函数指针,最后以一个包括0的函数指针结束。
根据不同OS和它的可运行文件格式,crtstuff.c 或 libgcc2.c 会在启动时和退出时遍历这些列表。构造体按列表的逆序被调用,析构体按顺序被调用。
处理静态构造体的最佳方式仅仅支持提供随意命名Section的目标文件格式。一个Section被用于构造体列表,还有一个用于析构体列表。它们习惯上被叫做‘.ctors’ 和 ‘.dtors’。每一个定义一个初始函数的目标文件在构造体的section里放置一个word来指向初始函数。链接器累积全部的word到一个连续的‘.ctors’ section中。终止函数也按类似的方式处理。
假设 TARGET_ASM_NAMED_SECTION 被定义,这样的方法会被 target-def.h 设为默认方式。假设一个目标板不支持随意命名的section,可是又支持特殊的可指定的构造体和析构体也能够通过定义 CTORS_SECTION_ASM_OP 和 DTORS_SECTION_ASM_OP 来达到相同的效果。
当支持随意命名的section时,依据crtstuff.c代码被调用的差别有两种变体。在支持.init section(在程序启动时运行)的系统上,crtstuff.c的部分内容会被编译到这个section里。程序像这样被链接:
     ld -o output_file crti.o crtbegin.o … -lgcc crtend.o crtn.o
一个函数的prologue (__init) 出如今crti.o的 .init section 中 ;epilogue 出如今crtn.o中. 函数 __fini 在 .fini section的处理也一样. 正常情况下,这些文件由OS或GNU C库来提供,可是一些目标板是由GCC提供。
目标文件crtbegin.o 和crtend.o (大部分的情况下)
由crtstuff.c编译得到. 它们包括,除了别的以外,.init 和 .fini sections中的代码片段,用于跳转到 .text section中函数。链接器会将一个section的全部部分放在一起,来生成一个完整的__init函数来调用我们须要在启动阶段调用的函数。

为了使用这个变体,你必须正确的定义 INIT_SECTION_ASM_OP 宏。

假设init section不能使用,当GCC编译不论什么名为main的函数时(更精确点,不论什么被expand_main_function指定为程序入口点的函数),它在插入一个函数调用__main做为函数prologue后的第一段运行代码. __main 函数在 libgcc2.c 里被定义并运行全局的构造体。

不支持随意section的文件格式,相同也有两种变体。在最简单的变体里必须用到GNU 链接器(GNU ld)和’a.out’ 格式。这样的情况下,TARGET_ASM_CONSTRUCTOR 被定义来生成一个类型为’N_SETT’的.stabs入口,參照__CTOR_LIST__, .stabs入口把指向初始化函数代码的void函数地址做为它的值。GNU链接器觉得这是一个把值加到集合的请求;这些值会累积,终于放在可运行文件中做为一个向量,格式如前所述,有一个前导(被忽略)的count和一个末尾的0元素。TARGET_ASM_DESTRUCTOR 处理也类似。既然没有init section可用,缺省的 INIT_SECTION_ASM_OP 使 main 的编译过程会去调用上述的__main函数,開始初始化处理。

最后的变体既不使用随意section也不用GNU 链接器。这在你想要动态链接且文件格式不被 GNU 链接器支持(如 ECOFF )的情况下推荐使用。在这样的情况下,TARGET_HAVE_CTORS_DTORS 是错误的,初始和终止函数简单地通过它们的名称被识别。这个要求在链接阶段的使用一个叫 collect2 的额外程序。这个程序会假扮为链接器被 GCC 使用;它的工作是执行正常的链接器,也管理追加初始函数和终止函数的向量,这些函数通过上述的 __main 被调用。为了使用这种方法,必须在 config.gcc 里的 target 定义use_collect2。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/118236.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Oracle优化[通俗易懂]

    个人理解,数据库性能最关键的因素在于IO,因为操作内存是快速的,但是读写磁盘是速度很慢的,优化数据库最关键的问题在于减少磁盘的IO,就个人理解应该分为物理的和逻辑的优化,物理的是指oracle产品本身的一些优化,逻辑优化是指应用程序级别的优化物理优化的一些原则:1).Oracle的运行环境(网络,硬件等)2).使用合适的优化器3).合理配置oracle实例参数4).建…

  • oracle存储过程捕捉异常后回滚_Oracle存储过程异常

    oracle存储过程捕捉异常后回滚_Oracle存储过程异常由三种方式抛出异常1.通过PL/SQL运行时引擎2.使用RAISE语句3.调用RAISE_APPLICATION_ERROR存储过程当数据库或PL/SQL在运行时发生错误时,一个异常被PL/SQL运行时引擎自动抛出。异常也可以通过RAISE语句抛出RAISEexception_name;显式抛出异常是程序员处理声明的异常的习惯用法,但RAISE不限于声明了的异常,它可以抛出任何任何异常。例…

  • 选择排序、插入排序、冒泡排序python实现

    选择排序、插入排序、冒泡排序python实现

    2021年11月24日
  • influx数据同步「建议收藏」

    influx数据同步「建议收藏」经过测试,通过设置influxdb可以将多个influx数据库实时汇总到一台服务器的同一个数据库里。1、test_A数据库创建保留策略influx-execute“CREATESUBSCRIPTION“momServices_sub”ON“test_A”.“autogen”DESTINATIONSANY‘http://192.168.50.50:8086’”-database“Test_All”momServices_sub:同步规则名mom_services:要做数据同步的

    2022年10月25日
  • kettle使用教程(超详细)

    kettle使用教程(超详细)今天详细详细说一下kettle的安装,安装的版本:jdk:jdk-8u152-windows–x64kettle:KETTLE-5.4一、环境部署1、安装JDK,按默认值安装即可2、设置环境变量,如图下图具体步骤:1.右击我的电脑-属性-高级系统设置-环境变量-系统变量-新建2.变量名:JAVA_HOME3.变量值:JDK安装目录3、…

  • C++之内存管理建议收藏

    内存分配方式在C++中,内存分为内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。(1)堆就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,

    2021年12月19日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号