细说编译性语言的编译四大阶段
编译的四个阶段:预处理(扩展各个宏与文件)、编译(得到汇编代码)、汇编(得到机器码)、链接(得到可执行文件)
一. 编译时达到的每一个阶段
可以使用 gcc 一个 -save-temps 参数编译源代码,会把编译整个过程的中间文件保存下来,不删除。
- 预处理阶段
# 预处理阶段:gcc -E Hello.c
* 得到一个 *.i 后缀的文件。
* 源代码里以 “#” 开头的命令是“预处理命令”,例如:“#define”,"#include","ifndef"等。
- 编译阶段
# 编译阶段:gcc -S Hello.c
* 得到一个 *.s 后缀的汇编语言的汇编代码文件。
* 在此编译阶段中编译器会依次进行:词法分析、语法分析、代码优化、存储分配、代码生成 这五个步骤。
* 进行的方式是“多次扫描的方式”:编译器每次扫描源代码只完成一个上面五个步骤,依次扫描进行完成上面的五个步骤。
- 汇编阶段
# 汇编阶段:gcc -c Hello.c
* 得到一个 *.o 后缀的目的文件。
* 汇编阶段就是汇编器 ar 把汇编代码翻译成机器码。
- 链接阶段
# 链接阶段:gcc Hello.c
* 得到一个 *.o 后缀的可执行文件。
* 链接阶段就是连接器 ld 把汇编生成的 .o 目的文件,与其他 .o 目的文件、库文件链接起来,生成可执行 .o 文件。
二. ELF文件
- ELF(Executable and Linkable Format)Linux平台特有的文件,是一种对象文件的格式。
- ELF的三种类型
- 可执行文件(Executable File)
- 可重定位文件(Relocatable File 后缀为 .o)
- 共享目标文件(Shared Object File 后缀 .so)
- ELF文件的作用
-
ELF文件参与程序的链接和程序的执行,所以可以从不同的角度来看 elf 格式的各文件。
-
用于编译、链接的可重定位文件:编译器和连接器会把 elf 文件看做节头表描述的节的集合,程序表头可选。
- 用于加载执行的可执行文件:加载器将把 elf 文件看做是程序头表描述的段的集合,一个段可能包含多个节,节头表可选。
- 可以使用 readelf 工具查看 ELF 文件结构细节(工具使用细节:man readelf)。