ELF文件格式

1.目标文件

  • 可重定位目标文件(main.o例如):包含二进制代码和数据,其形式可以在编译时与其他可重定位目标文件合并,创建一个可执行目标文件
  • 可执行目标文件(.exe/a.out):包含二进制代码和数据,其形式可以被直接拷贝到存储器并执行
  • 共享目标文件(.dll/.so):一种特殊类型的重定位目标文件,可以在加载或运行时被动态的加载到存储器并连接。
编译器和汇编器生成可重定位目标文件(包括共享目标文件)。链接器生成可执行目标文件。

2.可重定位目标文件和可执行目标文件的格式
可重定位目标文件格式:

可执行目标文件格式:

3.下面我们开始分析上面图片

  • ELF header: 用来描述整个目标文件的组织结构,包括节的数目、节的大小、程序的入口地址。使用linux的readelf工具就可查看目标文件的ELF文件结构,命令如下:gcc -c xxx.c;readelf -a xxx.o


  • 段头部表:描述分节和地址空间的映射关系,格式如下图,和上面可执行目标文件对照起来看。



  • 节头部表:描述目标文件节的信息。
  • text:代码段
  • rodata:只读数据
  • data:已经初始化的全局c变量(包括static变量),注:局部变量只会出现在调用堆栈当中。
  • bss:未初始化的全局c变量。在目标文件当中这个节实际不占用空间,仅仅是占位符。未初始化的变量不需要占据任何的实际磁盘空间。
而对于未被初始化的全局变量和静态局部变量,编译的时候并未被分配空间,而是仅仅在.bss段中标记它们,当程序运行的时候才为它们在内存中分配空间,并把它们初始化为零。

4.未初始化的全局变量和static局部变量


gcc -c main.c
readelf -a main.o


上图是目标文件main.o中的符号表。i的Ndx值是COM:代表未被分配空间的未初始化的数据目标;j的Ndx是3,我们查看到这是.bss段的索引,所以j在.bss段有占位符(并不是空间)。 像i这种未初始化内置类型的变量,他并没有分配空间,是没法设置断点的。

下面我们分析i、j最终分配空间时,属于线性地址空间的哪部分?
这里我们需要使用cat /proc/processid/maps命令这里是要查看进程的ID,可以使用ps -aux |grep a.out获取进程的ID。

根据我的测试,像目标文件的.data,.bss段的内容都会在地址空间的数据段分配空间(bss段内容在第一次使用才才在数据段分配内存),像const int k=0和字符串常量是在代码代码段中分配内存的。这点也可以从深入理解操作系统的P466页得到验证。



参考文章:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值