本文最后更新于:2020年6月27日 晚上

* 逐个分析各段。。。 *

第三章 目标文件里面有什么

真正了不起的程序员对自己的程序的每一个字节都了如指掌。

//Test.c

int global_init_var = 84;
int global_uninit_var;

void func1(int i)
{
	printf("%d\n", i);
}

int main()
{
	static int static_var = 85;
	static int static_var2;
	int a = 1;
	int b	

	func1(static_var + static_var2 + a + b);

	return 0;
}

示例程序中包括代码段、数据段、BSS段、只读数据段(.rodata)、注释信息段(.comment)。

图3.4 目标文件组成

  1. 代码段

    • .text段中存放的是Test.c中函数func()和main()的指令
  2. 数据段只读数据段

    • .data段保存初始化了的全局变量和局部静态变量(上述代码中的global_init_var和static_var)。
  • .rodata段存放只读数据,一般是程序的只读变量(const修饰的变量)字符串常量(上述代码中”%d\n“是一种只读数据)。单独设立.rodata段从语义上支持C++的const关键字,也在加载时将属性映射成只读,保证安全性。有时编译器会把字符串常量放到.data段,而不会单独放在.rodata段。

    1. BSS段
  • .bss段中存放的是未初始化的全局变量和局部静态变量(上述代码中的global_uninit_var和static_var2),准确的说是.bss段为他们预留了空间

  • 有些编译器将未初始化的全局变量存放在目标文件.bss段,有些不存放只是预留一个未定义的全局变量符号”COMMON 符号“,到最终链接成可执行文件的时候再在.bss段·分配空间。

  • 但编译单元内部可见的静态变量(如·global_uninit_var加上static修饰),是存放在.bss段。

  • static int x1 = 0;

x1被放在.bss段,因为可以认为是未初始化的,所以被优化放在.bss段。

  • static int x2 = 1;

x2被放在.data段,因为初始化值为1,所以放在.data段。

  1. 其他段:
    图3.5 其他段

  2. 自定义段:

    • _attribute_((section("FOO"))) int global = 42;
  • _attribute_((section("BAR"))) void foo()
    在全局变量和函数之前加上_attribute_((section("name")))属性可以把相应的变量或函数放到以”name“作为的段中。

* 以上为主要段,下一次总结ELF文件结构,包括文件头、段表。。。 *