第四章 符号的链接
链接概述与目标文件格式
一个可执行文件的生成
1.预处理:处理"#"开头的预编译指令
展开"#include”处头文件的内容
处理条件编译指令,如"#if""#ifdef”等
删除"#define’并展开所定义的宏
删除所有注释
添加行号和文件名标识,便于编译器产生调试用行号信息
预处理后预处理文件(*.i)仍为文本文件,但不包含任何“#"开头的预编译指令
2.编译:处理流程
先对源程序进行词法、语法和语义分析
然后根据分析结果进行代码优化和存储分配
最终把C语言源程序翻译成汇编语言程序
编译后,汇编代码文件(*.s)为文本文件,无法直接执行
3.汇编:转换成机器语言代码
汇编指令和机器指令一一对应,前者是后者的符号表示,都属于机器级指令,所构成的程序称为机器级代码
汇编生成的机器语言代码文件(*.o)为可重定位目标文件,还无法直接执行
4.链接:生成可执行文件
可重定位目标文件和可执行目标文件都是机器语言目标文件
可重定位目标文件代码总是从0地址开始
可执行目标文件代码从ABI规范规定的虚拟地址开始
子程序(函数)走起始地址和变量起始地址是符号定义
调用子程序(函数或过程)和使用变量即是符号引用
最终须链接(即合并),合并时须在符号引用处填入定义处的地址
优点:
源文件中无需包含共享库函数源代码,只要直接调用就行
可执行文件和运行时的内存中只需包含所调用函数的代码,而不需要整个共享库
目标文件格式
可重定位目标文件 (.o)
通过汇编生成,其代码和数据可和其他可重定位目标文件合并为可执行文件
每个.o文件由对应的.c文件生成每个.o文件代码和数据的地址都是从0开始
可执行目标文件 (默认为a.out)
包含的代码和数据可以被直接复制到内存并被执行
代码和数据地址为虚拟地址空间中的地址
共享的目标文件 (.so)
特殊的可重定位目标文件,能在装入或运行时被装入到内存并自动被链接,称为共享库文件
Windows 中称其为 Dynamic Link Libraries (DLLs)
标准的几种目标文件格式
COFF格式(Common Object File Format,通用目标文件格式),文件中不仅包含代码和数据,还包含重定位信息、调试信息、符号表等其他信息,由一组严格定义的数据结构序列组成
Windows:PE格式(COFF的变种),称为可移植可执行(PortableExecutable,简称PE)
Linux等类UNIX:ELF格式(COFF的变种),称为可执行可链接(Executable andLinkable Format,简称ELF)
ELF头:ELF魔数、版本、大小端、目标文件类型、机器结构类型、节头表起始位置和长度等
data:已初始化的的全局变量和静态局部变量
bss:未初始化的全局变量和静态局部变量,仅是占位符,不占任何实际磁盘空间空间利用率高
动态局部变量由栈帧动态生成,初值由相应指令赋予
节头表描述每个节的节名、在文件中的偏移、大小、访问属性、对齐方式等,不包含某个节的内容
初始化程序段.init节在可执行目标文件中有,在可重定位目标文件中没有
程序头表描述可执行文件中的节与虚拟空间的存储段之间的映射关系。
符号表与符号解析
三种链接器符号
Global symbols(模块内部定义的全局符号)
例如,非static函数和非static的全局变量
External symbols(外部定义的全局符号)
由其他模块定义并被模块m引用的全局符号
==Local symbols(==本模块的局部符号、本地符号)
例如,在模块m中定义的带static的函数和全局变量
符号的定义与强弱特性
符号的定义
指被分配了存储空间为函数名时,指代码所在区;
为变量名时,指所占的静态数据区。
所有定义符号的值就是其目标所在的首地址
局部(本地)符号在本模块定义并引用其解析较简单,只要与本模块内唯一的定义符号关联即可。
全局符号(外部定义的、内部定义的)的解析涉及多个模块,故较复杂。
符号解析也称为符号绑定。
强弱特性:
函数名和已初始化的全局变量名是强符号
未初始化的全局变量名是弱符号
符号解析时只能有一个确定的定义(即每个符号仅占一处存储空间)
多重定义符号的处理规则
1:强符号不能多次定义,否则链接错误
2:若一个符号被定义为一次强符号和多次弱符号,则按强定义为准,对弱符号的引用被解析为对强符号的引用
3:若有多个弱符号定义,则任选其中一个
使用全局变量时尽量使用本地变量(static)
全局变量要赋初值(强定义编译报错提示)
外部全局变量要使用extern(引用)
符号解析过程
静态库的创建:
.c文件编译成.o文件,通过归档器(Archiver)归档成libc.a (C标准静态库)
ar rcs libc.a proc1.o proc2.o
Archiver允许增量更新
常用库: libc.a libm.a(math库)
链接器中符号解析的全过程:
E将被合并以组成可执行文件的所有目标文件集合
U当前所有未解析的引I用符号的集合
D当前所有定义符号的集合
被链接模块应按调用顺序指定否则会出现链接错误
重定位与动态链接
重定位
IA-32有两种最基本的重定位类型
R_386_32:绝对地址
R_386_PC32:PC相对地址
执行CALL指令时,PC是指CALL指令的下一条指令的地址。
共享库
一种特殊的可重定位目标文件,记录了相应的代码、数据、重定位和符号表信息,可以在装入或运行时被动态加载并链接,称为动态链接
Windows 动态链接库.dll
Linux 动态共享对象.so
动态链接的特性
共享性:在内存中只有一个副本,被所有进程共享调用,节省内存空间;一个共享库目标文件被所有程序共享链接,节省硬盘空间
动态性:共享库只在使用它的程序被加载或执行时才加载到内存;每次加载或执行程序时所链接的共享库都是最新的;共享库可分模块、独立、用不同编程语言进行开发,效率高;第三方开发的共享库可作为程序插件,使程序功能易于扩展
在加载或运行时的链接会带来额外的时间开销
习题解析
考察64位IEEE754转换,小端模式
考察重定位与传送指令