操作系统课程2










下面是将 GCC 编译流程拆解到较细粒度后的表格版,便于查阅和排障。
| 阶段 | 子步骤 | 组件 | 输入 | 输出 | 核心工作 |
|---|---|---|---|---|---|
| 1 | 参数解析 | gcc Driver | 命令行 | 内部配置 | 识别语言类型、目标架构、优化等级 |
| 2 | 编译任务调度 | gcc Driver | 参数配置 | cc1/as/ld调用链 | 决定调用哪些后端程序 |
| 3 | 预处理 | cpp | C源码 | 预处理源码(.i) | 展开宏、处理#include、条件编译 |
| 4 | 词法分析(Lexer) | cc1 | 字符流 | Token流 | 关键字、标识符、常量识别 |
| 5 | 语法分析(Parser) | cc1 | Token流 | AST | 构建抽象语法树 |
| 6 | 语义分析 | cc1 | AST | Annotated AST | 类型检查、作用域检查 |
| 7 | AST Lowering | cc1 | AST | GENERIC Tree | GCC内部树结构转换 |
| 8 | GIMPLE生成 | cc1 | GENERIC | GIMPLE SSA | 转换为三地址码 |
| 9 | SSA构建 | cc1 | GIMPLE | SSA GIMPLE | 插入PHI节点 |
| 10 | 常量传播 | Optimizer | SSA | 优化SSA | 编译期计算常量 |
| 11 | Copy Propagation | Optimizer | SSA | 优化SSA | 变量替换 |
| 12 | Dead Code Elimination | Optimizer | SSA | 优化SSA | 删除无用代码 |
| 13 | Value Range Analysis | Optimizer | SSA | 优化SSA | 推断变量范围 |
| 14 | Function Inline | Optimizer | SSA | 优化SSA | 函数内联 |
| 15 | Loop Optimization | Optimizer | SSA | 优化SSA | 循环展开、融合 |
| 16 | Vectorization | Optimizer | SSA | SIMD代码 | 自动SIMD化 |
| 17 | RTL生成 | Backend | SSA | RTL | 面向目标架构 |
| 18 | 指令选择 | Backend | RTL | RTL | 选择CPU指令 |
| 19 | 寄存器活跃分析 | Backend | RTL | 活跃区间 | 构建干涉图 |
| 20 | 寄存器分配 | Backend | RTL | RTL | Graph Coloring |
| 21 | Spill处理 | Backend | RTL | RTL | 溢出到栈 |
| 22 | 指令调度 | Backend | RTL | RTL | 优化流水线 |
| 23 | Peephole优化 | Backend | RTL | RTL | 局部替换 |
| 24 | 汇编生成 | Backend | RTL | .s | 输出汇编代码 |
| 25 | 汇编解析 | as | .s | AST | 解析助记符 |
| 26 | 指令编码 | as | 汇编指令 | 机器码 | Opcode编码 |
| 27 | 符号生成 | as | 汇编 | Symbol Table | 记录符号 |
| 28 | 重定位生成 | as | 外部引用 | Relocation | 生成.rela节 |
| 29 | ELF目标文件封装 | as | 机器码 | .o | 生成ELF |
| 30 | 读取目标文件 | ld | .o/.a | 内存映像 | 加载所有输入 |
| 31 | Section合并 | ld | 多个.o | 合并节区 | .text/.data合并 |
| 32 | Symbol Resolution | ld | 符号表 | 全局符号表 | 解析引用 |
| 33 | 地址分配 | ld | 节区 | 虚拟地址 | 分配最终地址 |
| 34 | Relocation Fixup | ld | 重定位表 | 已修正机器码 | 地址回填 |
| 35 | GOT生成 | ld | 动态符号 | .got | 全局偏移表 |
| 36 | PLT生成 | ld | 动态函数 | .plt | 延迟绑定 |
| 37 | crt对象链接 | ld | crt1.o等 | 启动代码 | _start入口 |
| 38 | Segment布局 | ld | Sections | Segments | ELF Program Header |
| 39 | ELF Header生成 | ld | 所有数据 | ELF Header | 文件头 |
| 40 | 输出可执行文件 | ld | ELF映像 | a.out | 最终程序 |
Linux ELF视角
最终形成的 ELF 大致如下:
ELF
├── ELF Header
├── Program Header Table
│
├── LOAD Segment(R-X)
│ ├── .text
│ ├── .plt
│ └── .rodata
│
├── LOAD Segment(RW-)
│ ├── .data
│ ├── .got
│ ├── .got.plt
│ └── .bss
│
├── .symtab
├── .strtab
├── .rela.text
├── .rela.plt
└── Section Header Table
GCC 实际调用链
执行:
gcc -O2 main.c -o main
实际近似于:
cpp main.c > main.i
cc1 main.i -O2 -o main.s
as main.s -o main.o
collect2 \
crt1.o crti.o crtbegin.o \
main.o \
-lc \
crtend.o crtn.o \
-o main
其中:
gcc
├── cpp
├── cc1
├── as
└── collect2
└── ld
SRE/内核排障最常关注的位置
| 问题类型 | 关注阶段 |
|---|---|
| 宏展开异常 | cpp |
| 编译报语法错误 | Lexer/Parser |
| 类型错误 | Semantic Analysis |
| O0正常 O2异常 | GIMPLE优化 |
| CPU指令异常 | RTL/Instruction Selection |
| 符号找不到 | Symbol Resolution |
| multiple definition | Symbol Resolution |
| relocation truncated | Relocation |
| undefined reference | Relocation |
| 动态库加载失败 | GOT/PLT |
| 程序入口异常 | crt/_start |
| 段错误 | Segment Layout |
| ASLR相关问题 | ELF Loader |
对于做内核、Ceph、Kubernetes、存储或网络方向的 SRE,最值得深入的是:
-
GIMPLE SSA 优化机制(为什么 O2/O3 会引入诡异 Bug)
-
ELF 重定位机制(Relocation)
-
GOT/PLT 动态链接原理
-
_start → __libc_start_main → main启动链路 -
Linux Loader 如何 mmap ELF 到进程地址空间
这五部分直接对应生产环境中最常见的 coredump、符号解析、动态库和性能问题。
浙公网安备 33010602011771号