C 从源文件到可执行文件 共经过4个步骤 :预处理(Prepressing)、编译(Compilation)、汇编(Assembly)和链接(Linking)
1. 预处理
首先源代码文件(.c/.cpp)和相关头文件(.h/.hpp)被预处理器cpp预编译成.i文件(C++为.ii)。预处理命令为:
gcc –E hello.c –o hello.i
预编译过程主要处理那些源代码中以#开始的预编译指令,主要处理规则如下:
- 将所有的#define删除,并且展开所有的宏定义;
- 处理所有条件编译指令,如#if,#ifdef等;
- 处理#include预编译指令,将被包含的文件插入到该预编译指令的位置。该过程递归进行,及被包含的文件可能还包含其他文件。
- 删除所有的注释//和 /**/;
- 添加行号和文件标识,如#2 “hello.c” 2,以便于编译时编译器产生调试用的行号信息及用于编译时产生编译错误或警告时能够显示行号信息;
- 保留所有的#pragma编译器指令,因为编译器须要使用它们。
2. 编译
编译过程就是把预处理完的文件进行一系列词法分析,语法分析,语义分析及优化后生成相应的汇编代码文件(.s)。编译的命令为:
gcc –S hello.i –o hello.s
或者从源文件直接输出汇编代码文件:
gcc –S hello.c –o hello.s
现在版本的GCC把预编译和编译两个步骤合并成一个步骤,由程序cc1来完成(C++为cc1plus)。
3. 汇编
汇编就是将汇编代码转变成机器可以执行的命令,生成目标文件(.o),汇编器as根据汇编指令和机器指令的对照表一一翻译即可完成。
汇编的命令为:
gcc –c hello.s –o hello.o
或者从源文件直接输出目标文件:
gcc –c hello.c –o hello.o
4. 链接
链接就是链接器ld将各个目标文件组装在一起,解决符号依赖,库依赖关系,并生成可执行文件。链接的命令为:
ld –static crt1.o crti.o crtbeginT.o hello.o –start-group –lgcc –lgcc_eh –lc-end-group crtend.o crtn.o
一般我们使用一条命令就可以完成上述4个步骤:gcc hello.c
实际上gcc只是一些其它程序的包装,它会根据不同参数去调用预编译编译程序cc1、汇编器as、链接器ld。
目标文件的section说明:
段名 | 说明 |
.text | 存放编译后的机器指令 |
.data | 存放已初始化的全局静态变量和局部静态变量 |
.rodata | 存放只读数据,如全局const变量、字符串常量 |
.bss | 存放未初始化的全局静态变量和局部静态变量 |
.symtab | 符号表,记录符号信息 |
.rel.xxx | 重定位表,记录.xxx段中需要重定位定位符号 |
(静态链接)链接器一般采用一种叫做两步链接的方法:
- 空间与地址分配。链接器扫描所有的输入目标文件,将它们的段进行合并,计算出输出文件中各个段合并后的长度和位置,建立映射关系;并且将输入目标文件的符号表中的所有符号定义和符号引用收集起来,统一放到一个全局的符号表。
- 符号解析和重定位。使用上一步收集到的所有信息,读取输入文件中段的数据、重定位信息,并且进行符号解析与重定位、调整代码中的位置等,这一步是链接过程的核心。
动态链接
动态链接基本上分为3步:
- 动态链接器自举。当操作系统将进程控制权交给动态链接器时,动态链接器的自举代码开始执行。自举代码获得动态链接器本身的重定位表和符号表,将它们重定位后,才可以使用自己的全局变量和静态变量。
- 装载共享对象。完成自举以后,动态链接器将可执行文件和链接器本身的符号表都合并到一个全局符号表。然后链接器开始寻找可执行文件所依赖的共享对象,并将这些共享对象的名字放入到一个装载集合中。链接器开始从集合里取一个所需要的共享对象的名字,打开相应的文件并读取ELF文件头和.dynamic段,然后将它对应的代码段和数据段映射到进程空间。如果这个ELF共享对象还依赖于其他的共享对象,那么将所依赖的共享对象放入到装载集合中。如此循环知道所有依赖的共享对象都被装载进来为止。
- 重定位和初始化。链接器开始重新遍历可执行文件和每个共享对象的重定位表,将他们的GOT中每个需要重定位的位置进行修正。重定位完成之后如果某个共享对象有.init段,那么动态链接器就会执行.init段中的代码,用以实现共享对象特有的初始化过程,比如共享对象中的C++全局/静态对象的构造。
参考:
http://www.cnblogs.com/glacierh/p/4678229.html?utm_source=tuicool&utm_medium=referral
http://blog.csdn.net/zvvzxzko2006/article/details/48519845(section表)
http://www.eetop.cn/blog/html/14/56214-43328.html
http://www.cnblogs.com/kekec/p/3238741.html(编译链接的举例说明)
http://blog.csdn.net/dlfer11/article/details/50351676(链接器的说明)