本文的demo是在linux环境下编译解析的,cpu是x86-64
首先我们先写一个功能简单的demo-SimpleSection.c。这个demo中有一个func1函数用来打印数据,一个已经初始化的全局变量global_init_var和未初始化的全局变量global_uninit_var,一个已初始化的局部静态变量static_var和一个未初始化的局部静态变量static_var2。
int printf(const char* format, ...);
int global_init_var = 84;
int global_uninit_var;
void func1(int i)
{
	printf("%d\n", i);
}
int main(void)
{
	static int static_var = 85;
	static int static_var2;
	int a = 1;
	int b;
	
	func1(static_var + static_var2 + a + b);
	return a;
}
 
下一步我们把代码文件编译成目标文件: gcc -c SimpleSection.c
 接着使用使用objdump工具查看目标文件:objdump -h SImpleSection.o

从上述截图中可以看出,objdump得到的 目标文件信息共有8项,前六项0~5分别是:
- 代码段
 - 数据段
 - BSS段
 - 只读数据段
 - 注释信息段
 - 堆栈提示段
 
信息项共有5列,分别为Size、VMA、LMA、File off 和 Algn。其中Size为段的长度,File off为段的偏移也就是段的位置。
 下面我们用一张图来标识这几个段的相对位置。

 从图中可以清晰的看到各个段在目标文件中的分布。值得注意的是.bss段并不存在,我们在上一张截图中就可以看到Size一列中.bss显示的是ALLOC而不是CONTENTS。这表示在ELF文件中不存在内容。因此.bss段中只记录需要分配的空间大小,而不是真正存在于ELF文件的空间大小。还有就是.text段的起始地址是0x 0000 0040,段size为0x5f,但是奇怪的是0x40+0x5f=0x9f而不是0xa0,这是因为对齐的缘故。
为了更加清晰的查看.text段的信息,我们使用objdump -s -d SimpleSection.o命令去反汇编ELF文件,从而与上面的表述向印证。
 
 如上述截图所示,.text段的最后一个字节的偏移量,也就是位置是0x5f。这与前面我们看到的.text段的大小一致。

对于.data段,一共有8个字节,对应了代码中的int global_init_var和static int static_var变量。前4个字节为0x 54 00 00 00 00,其中第一个字节为0x54,相应的十进制为84,对应了代码中int global_init_var变量。但是需要注意的是这里使用了小端字节序,所以0x54字节才会在第一个。类比一下就知道后4个字节表示的是static int static_var变量。
通常编译器会把字符串常量和其他的一些常量(在c++中用const修饰)放在.rodata段中,这样有一下几个好处:
- 在语义上支持c++的const关键字
 - 可以在操作系统加载程序的时候将
.rodata段的属性映射成只读,保证程序的安全性 - 在某些嵌入式平台下,有些存储区采用只读存储器,如ROM,保证了程序访问存储器的正确性
但是需要注意的是,某些编译器会把字符串常量放到.data段,如MSVC编译器。 














![[附源码]Python计算机毕业设计Django酒店在线预约咨询小程序](https://img-blog.csdnimg.cn/dec0b4b7c1af4702ba958b452cf1e651.png)




