第四章:成为Elf领主
这篇文章是关于ELF(可执行和链接格式)文件如何在Linux系统中被执行的详细解析。
1. ELF文件格式:
- ELF是最常用的Linux程序文件格式。
- ELF文件由四个部分组成:ELF头部、程序头部表(PHT)、节头部表(SHT)和数据部分。
2. ELF头部:
- 包含关于二进制文件的基本信息,如目标处理器架构、是否为可执行文件、程序入口点等。
- 指定PHT和SHT的位置。
3. 程序头部表(PHT):
- 描述如何以及在何处将ELF文件的数据加载到内存中。
- 常见的PHT类型包括
PT_LOAD
(要加载到内存的数据)、PT_NOTE
(版权声明等自由格式文本)、PT_DYNAMIC
(动态链接信息)和PT_INTERP
(ELF解释器的路径)。
4. 节头部表(SHT):
- 可选的“地图”,帮助调试器理解ELF文件中数据的预期用途。
- 包含节的名称、类型和标志。
5. 数据:
- PHT和SHT指向的数据块,包含程序的机器代码、初始化数据、BSS段、只读数据等。
6. 动态链接:
- 与静态链接相比,动态链接只包含对库函数的引用,而不是库代码本身。
- 运行时,操作系统需要确定所需的库,加载它们,替换所有命名指针为实际的跳转指令,然后启动程序代码。
7. ELF解释器:
- 动态链接的程序需要通过ELF解释器来运行,它负责加载所需的库并初始化程序。
8. 执行过程:
- 内核读取ELF头部和PHT,设置新程序的内存结构。
- 加载所有
PT_LOAD
段到内存,填充程序的静态数据、BSS空间和机器代码。 - 如果程序是动态链接的,内核还需要执行ELF解释器。
- 设置CPU的指令指针,如果是动态链接,指向ELF解释器的代码;否则指向可执行文件的开始。
- 内核将
argc
、argv
和环境变量推送到栈上,供程序开始时读取。 - 清空寄存器,准备返回用户空间。
- 系统调用结束,内核返回用户空间,恢复寄存器,并跳转到存储的指令指针,这将是新程序(或ELF解释器)的起始点。
文章深入探讨了ELF文件的结构和执行过程,解释了静态链接和动态链接的区别,以及Linux内核如何处理和执行ELF文件。这些信息对于理解Linux系统上的程序执行机制非常有用。