Skip to content

Latest commit

 

History

History
63 lines (47 loc) · 3.7 KB

CSAPP-7-链接.md

File metadata and controls

63 lines (47 loc) · 3.7 KB

CH7 链接

7.1 链接器

链接器需要完成2个任务,以便来生成可执行文件:

解析符号(symbol resolution)。每个符号对应一个函数、一个全局变量或一个静态变量。符号解析的目的,是为将每个符号引用和符号定义关联起来。
重定位(relocation)。编译器和汇编器生成的代码和数据节都是从地址为0开始的。链接器通过把每个符号定义与一个内存位置关联起来,从而重定位这些节,然后修改所有对这些符号的引用,使得它们指向这个内存位置。

7.2 目标文件

有三种目标文件:

(1) 可重定位目标文件,包含二进制的代码和数据。可以在编译时与其它目标文件合并起来,创建一个可执行的目标文件。
(2) 可执行目标文件,包含二进制代码和数据,可以直接执行。
(3) 共享目标文件,一种特殊的可重定位目标文件,可以在加载或运行时被动态地加载进内存并链接。

ELF可重定位目标文件格式

名称 含义
ELF头 描述字节序、机器类型等信息
.text 代码段
.rodata 只读数据
.data 已初始化的全局和静态变量
.bss 未初始化的/或被初始化为0的全局和静态变量
.symtab 符号表,存放程序中定义和引用的函数和全局变量的信息
.rel.text 一个.text段中位置的列表。当链接器把这个目标文件和其它文件组合时,需要修改这些位置信息
.rel.data 被模块引用或定义的所有全局变量的重定位信息
.debug 调试符号表. 包含程序中定义的局部变量和类型. 需-g选项来编译
.line 原始C源程序的行号和.text段中机器指令间的映射. 需-g选项来编译
.strtab 一个字符串从表,包含.symtab和.debug段中的符号表
节头部表

每个可重定位模块都有一个符号表,包含本模块中定义和引用的符号信息。

全局符号: 本模块定义的,能被其它模块引用的全局函数和全局变量. (全局、非静态的函数和变量)
外部符号: 其它模块定义的,被本模块引用的全局函数和全局变量.
内部符号: 本模块定义的,只被本模块引用的。带static属性的全局函数和全局变量. (全局的、static的函数和变量)

函数内部定义的非static局部变量,运行时在栈中被管理,链接器忽略这些符号。

readelf查看目标文件详细信息

名称 含义
ABS 不被重定位的符号
COMMON 未分配位置的未初始化的数据目标
UNDEF 未定义的符号(在本模块引用的,但在其它模块定义的符号)

value: 字段对其要求
size : 最小的大小

7.3 链接器

编译器的输出,便是链接器的输入。
编译器输出的全局符号,要么强(strong)要么弱(weak),汇编器把这些信息隐含的编码在可重定位目标文件的符号表里。函数和已初始化的全局变量是强符号,未初始化的全局变量是弱符号。有以下规则:

不允许有多个同名的强符号, 否则链接器会提示: "multiple definition of 'xx'".
若有一个强符号和一个若符号同名,选择强符号.
若有多个同名的弱符号,则从这些弱符号中任意选择一个.

若有多个弱符号,链接器会随机的选择一个,会带来潜在的error。 可用使用 -fno-common标志,该选项告诉链接器,在遇到多重定义的全局符号时,触发错误。

在符号解析阶段,链接器会根据编译命令行中库的顺序(从左到右),来重定位目标文件和.a/.so文件。