一、相比 .o 的 ELF 格式,有哪些变化?

1. .rel.text和.rel.data消失了

链接器将各.o中同名的.text.data节整合到一起时,会对整合后的.text.data进行重定位

其实重定位时主要针对就是.text.data节,不过这.text.data节重定位时,
需要依赖.rel.text.rel.data中的信息,一旦重定位结束后,这两个节的使命就完成了,自然也就会消失

2. 多出了两个节

(a)init
作用:这个节会提供_init等函数,专门用于实现程序的一些初始化

程序入口为_start,从_start开始执行后,在正式调用main函数之前,
会先调用_init等函数进行程序的初始化(比如建立函数栈等等)

(b)init节怎么来的
回顾gcc链接的过程,

collect2                                     # 链接程序
-dynamic-linker  /lib64/ld-linux-x86-64.so.2 # 动态链接器
crt1.o  crti.o  crtbegin.o                   # 启动代码
ccyIcm4A.o                                   # 自己程序的.o
-lc //libc                                   # 常用c函数库——c标准库的子库
crtend.o  crtn.o                             # 扫尾代码

init节就是由gcc提供的crt1.o、crti.o、crtbegin.o.o构建而来的

(c) “段头部表” 节
重定位时,链接器根据“链接脚本文件”所给的运行地址,给.text/.data中指令和变量重定位运行地址时,
这些“运行地址”只是链接时理论上安排的

当加载程序到内存中运行时,就需要将硬盘上所存放的程序,搬到“运行地址”所指定的内存位置,
段头部表中的内容,就是用来辅助加载程序的


三、“可执行目标文件”的ELF头总结归类

可执行目标文件”的各个节,可以进行进一步的归类。

总结:
1)程序最终运行时,需要搬到内存上的节有:ELF头/.init/.text/.rodata/.data/.bss
搬到内存上什么位置呢?搬到重定位的“运行地址”所指定的位置

2)ELF/.init/.text/.rodata:只读的存储段(代码段)

3).data/.bss:可读可写存储段(静态数据段)
之所以称为静态数据段,是因为.data/.bss的空间规划,是在编译时就进行了理论安排,
并不是程序运行起来才安排的,所以被称为静态数据段