静态链接详解

简介: 静态链接详解

引言

上篇文章,我们详细介绍了从源码到可执行程序的全过程,并详细介绍了目标文件的存储格式,ELF格式。这篇文章我们介绍静态链接的全过程,

一、多个目标文件如何合并

多个目标文件在链接过程中,采用相似段合并的方法。比如将所有目标文件的“.text”段合并到输出文件的“.text”段。

二、链接步骤

  1. 扫描所有的输入目标文件,拿到它们各个段的位置、长度和属性;将各个目标文件中的符号表中的符号定义和符号引用统一放到一个全局符号表中。将所有的段合并,重新计算各个段的位置和长度,并建立映射关系。
  2. 进行符号解析与重定位、调整代码中的地址。

三、举例说明链接的全过程

准备a.c 和 b.c 两个文件

a.c

#include <stdio.h>
extern int shared;
int main()
{
    int a = 100;
    swap(&a, &shared);
    return 0;
}

b.c

int shared = 1;
void swap(int* a ,int* b){
    *a ^= *b ^= *a ^= *b;
}
gcc -c a.c b.c  // 只编译不链接,生成a.o b.o
gcc a.o b.o -o ab // 链接生成可执行文件 ab

图中的VMA就是虚拟地址,我们关注VMA和Size。可以看到在链接前,目标文件中的VMA都是0,因为还没有分配虚拟空间,默认为0。在链接后,我们使用objdump -h查看ab文件,“.text”段被分配到0x004000e8,大小是0x77字节,“.data”段被分配到0x00601000,大小是0x04字节。链接后的文件及程序虚拟地址如下图所示:

3.1 符号地址如何确定

经过上一步,输入目标文件的各个段在链接后的虚拟地址就确定了,“.text”段的起始地址为0x004000e8。有了起始地址,各个符号的虚拟地址通过偏移可以计算出来。

四、符号解析与重定位

因为a.c的中变量shared和函数swap都不在本文件中,所以这两个符号就需要重定位。在编译a.o目标文件的时候,因为编译器不知道这两个符号的地址,会先用一个虚假值代替,在链接的时候通过重定位进行地址修正。

重定位表

链接器就通过重定位表知道哪些符号需要重定位。每个需要重定位的段,都会有一个对应的重定位表。比如: “rela.text” 就是针对 “.text”段的重定位表,这是因为“.text”段中的“swap” 函数的调用和shared变量的引用;

可以通过:objdump -r 查看目标文件的重定位表。

每个需要重定位的地方都有一个重定位入口,从图中我们可以看到a.o有两个重定位的入口。“RELOCATION RECORDS FOR [.text]” 表示这个重定位表是代码段的重定位表。图中的OFFSET 0x14 和 0x21 分别对应通过a.o的反汇编结果中需要重定位的地方。

符号解析

如果只连接a.o,链接器就会找不到shared和sawp的定义而报错:undefined reference to “shared”和“swap”。就是链接时符号未定义。

链接时,链接器通过查找重定位表发现shared和swap符号需要重定位,就会查找所有目标文件建立的全局符号表,若是没找到就报未定义错误。

文章参考于<零声教育>的C/C++linux服务期高级架构,及书籍(程序员的自我修养)。

相关文章
|
2月前
|
Linux Windows
静态库和动态库
本文详细介绍了静态库和动态库的概念及使用方法。在 Linux 系统中,静态库以 `libxxx.a` 形式存在,而动态库则为 `libxxx.so`。文章分别讲解了如何创建和使用这两种库,并提供了具体的命令示例。此外,还介绍了将库文件添加到系统目录的方法,包括直接复制到默认库路径、修改环境变量以及编辑系统配置文件等方案。适合初学者了解库文件的基本操作。
|
开发者
静态链接与动态链接
空间链接使得不同的程序开发者和部门能够相对独立地开发和测试自己的程序模块,从某种意义上来将大大促进了程序开发的效率,原先限制程序的规模也随之扩大。但是慢慢地静态链接的诸多缺点也逐步暴露出来,比如浪费内存和磁盘空间、模块更新苦难你等问题,使得人们不得不寻找一种更好的方式来组织程序的模块。本文简单介绍静态链接与动态链接。
|
存储 Cloud Native Linux
C++ 动态库与静态库的区别?
C++ 动态库与静态库的区别?
|
存储 Linux 编译器
什么是链接库 | 动态库与静态库
什么是链接库 | 动态库与静态库
159 0
|
Shell 开发工具 iOS开发
动态库下(5)
动态库下(5)
374 0
动态库下(5)
|
编译器 Windows
静态库和动态库的特点和关系
库是一段可以复用的二进制代码的有序集合。
76 0
|
Linux 编译器 Shell
【Linux系统编程】静态库和共享库
【Linux系统编程】静态库和共享库
148 0
|
vr&ar C语言 索引
静态链接和静态库
静态链接和静态库
173 0
|
开发者
动态链接和动态库
动态链接和动态库
115 0
vs2019使用动态库
vs2019使用动态库
210 0