目录
前言:在阅读《程序员的自我修养》——链接、装载与库,为了更好记录,就把自己认为重要的内容摘抄细看,文章的目录是按照书本的目录结构来的,如有侵权,立即删掉。
一、温故而知新
二、编译和链接
我们很少关注编译和链接的过程,因为通常开发环境都是流行的集成开发环境(IDE),例如Visual Studio、Delphi等。
编译的过程大致能分解4个步骤:
(1)预处理(Prepressing);
(2)编译(Compilation);
(3)汇编(Assembly);
(4)链接(Linking)。
1、预处理(Prepressing)
- 生成.ii文件
- 主要处理“#”开头的预编译指令,#include、#define
- 删除所有#define,并且展开所有的宏定义
- 处理所有条件预编译指令,#include等
2、编译(Compilation)
- 生成.s文件
- 对预处理完的文件,进行一系列词法分析、语法分析、语义分析及优化后生产相应的汇编代码文件。
- 现在版本的GCC将预编译和编译合并一个步骤
- 编译分6步
- 扫描
- 源代码程序被输入扫描器(Scaner),进行词法分析,将源代码的字符序列分割成一系列的记号(Token)
- 语法分析
- Grammar Parser:将对扫描器产生的记号进行语法分析,从而产生语法树(Syntax Tree)
- 整个分析过程采用了:上下无关语法(Context-free Grammar)的分析手段
- Grammar Parser:将对扫描器产生的记号进行语法分析,从而产生语法树(Syntax Tree)
- 语义分析
- 语义分析器:Semantic Analyzer来完成,仅仅是完成了对表达式的语法层面的分析,但是它并不了解这个语句是否真正有意义。
- 源代码优化
- 源码级优化器在源代码级别进行优化
- 简单的表达式,可以进行优化,直接取结果
- 源码级优化器在源代码级别进行优化
- 代码生成
- 源码级优化器产生中间代码标志着下面的过程都属于编辑器后端。
- 属于编辑器后端。
- 目标代码优化
- 属于编辑器后端。
- 扫描
3、汇编(Assembly)
- 生成.o文件(目标文件Object File)
- 将汇编代码转变成机器可以执行的指令
4、链接(Linking)
- 生成 .out 可执行文件
- 调用ld生成
- 一个复杂的项目会划分为小模块,每个模块独立编译完后,然后按照需要将它们“组装”起来。这个组装的过程就是链接。
- 主要过程
- 地址和空间分配(Address and Storage Allocation)
- 符号决议(Symbol Resolution)
- 重定位(Relocation)
- 编译时候可能不知道变量的地址,等链接时候才知道正确地址,进行地址修正,这个过程叫重定位。
- 重定位所作的就是给程序中每个这样的绝对地址引用的位置“打补丁”,是它们指向正确的地址。
- 静态链接
- 每个模块的源代码(如.c文件)经过编译器编译成目标文件(Object File,一般为.o或.obj),目标文件和库(Library)一起链接形成最终可执行文件。
- 最常见的库就是运行时库(RunTime Library,简称CRT)
- 支持程序运行的基本函数的集合
- 库其实是一组目标文件的包
- 一些最常用的代码编译成目标文件后打包存放
三、目标文件里有什么
1、目标文件的格式
-
目标文件就是源代码编译后但未进行链接的中间文件;
-
目标文件的后缀:Windows的.obj,Linux的.o;
-
可执行文件:Windows的.exe,Linux的ELF可执行文件;
-
动态链接库:Windows的.dll,Linux的.so;
-
静态链接库:Windows的.lib,Linux的.a;
2、目标文件是什么样的
-
目标文件里面有:机器指令代码、数据、符号表、调试信息、字符串等;
-
文件头File Header:描述整个文件的文件属性,如是否执行,静态还是动态,及入口信息、目标硬件、目标操作系统等信息;
-
机器指令放在代码段(Code Section),为.code或.text;
-
全局变量和局部静态变量数据,放在数据段(Data Section),为.data;
-
静态变量放在.bss section,.bss段只是为未初始化的全局变量和局部静态变量(都为0)预留位置而已。
3、挖掘 SimpleSection.o
-
(1)代码段.text;
-
(2)数据段和只读数据段.data:初始化的全局静态变量和局部静态变量;
-
(3).bss:未初始化的全局变量和局部静态变量;
4、ELF 文件结构描述
-
ELF(Executable and Linkable Format):可执行与可链接格式,文件是UNIX和类UNIX操作系统的标准二进制格式文件。
-
里面包括:文件头、段表、重定位表、字符串表
5、链接的接口----符号
-
ELF符号表结构:
-
extern "C":C++编译器将括号内的当作C语言代码处理;
6、调试信息
-
目标文件里可能保存调试信息,支持源代码级别的调试。
四、静态链接
主要讲解:
1、空间与地址分配
2、符号解析与重定位
3、COMMON块
4、C++相关问题
5、静态库链接
6、链接过程控制
7、BFD库
(1)对于连接器来说,整个链接过程中,它就是将几个输入目标文件加工后合并成一个输出文件。
(2)静态链接中的第一个步骤,即目标文件在被链接或最终可执行文件时,输入目标文件中的各个段是如何被合并到输出文件中的,链接器如何为它们分配在输出文件中的空间和地址。一旦输入段的最终地址被确定,接下来就可以进行符号的解析与重定位,链接器会把各个输入目标文件中对于外部符号的引用进行解析,把每个段中须重定位的指令和数据进行“修补”,使它们都指向正确的位置。
五、Windows PE/COFF
主要讲解:
1、Windows 的二进制文件格式 PE/COFF
2、PE 的前身----COFF
3、链接指示信息
4、调试信息
5、Windows 下的 ELF----PE
6、PE 数据目录