1.gcc test.c 经历了什么?
// test.cc
#include <stdio.h>
int main(){
printf("gcc compilation link process.");
return 0;
}
有 预编译、编译、汇编、链接 四个步骤,下面逐一分析:
预编译
也叫预处理阶段,主要操作有这几个:
- 展开所以 #define 宏定义 ,进行文本替换
- 删除所有的注释
- 处理条件编译 #ifdef #endif 等
- 处理#include指令,把这些头文件的内容都复制到当前源文件中
- 添加行号和文件名标识,方便编译器产生警告及调试信息
- 保留 #pragma 编译器指令,因为编译器会用到
编译
做语法分析、语义分析、代码的优化(g++ -o 来指定代码的优化级别)、汇总所有的符号。 **在编译这个过程中,符号是不分配虚拟地址的,所以当前所有引用符号的地方都写成0.
汇编
根据当前系统的架构,来生成相应的汇编指令,即将汇编码转成机器码 ==> *.o文件,是二进制可重定位文件。
*.o文件都是由不同的段组成的(elf文件头、.text、.bss、.data、符号表等)
objdunp 可以查看 *.o 文件和可执行文件的一些详细信息:
链接
链接分为两步:
- 所有的*.o文件 段的合并(因为 *.o 文件都是由不同的段组成的,合并时,将不同的.text段合并、.data段合并、.bss段合并、还有段表以及符号表的合并),符号表合并后,进行符号的解析。
- 符号的重定位:给所有的符号分配虚拟地址,这里的重定位指的是把之前指令中所有引用符号的地方都可以填上相应的虚拟地址了。
链接完成后,生成的是可执行文件(*.exe *.out),可执行文件也都是由各种段组成,每个段都是由 *.o 文件相应的段合并而来。