静态链接详解

简介: 静态链接详解

引言

上篇文章,我们详细介绍了从源码到可执行程序的全过程,并详细介绍了目标文件的存储格式,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服务期高级架构,及书籍(程序员的自我修养)。

相关文章
|
编译器 C++ 开发者
【C/ C++链接】深入C/C++链接:从基础到高级应用(一)
【C/ C++链接】深入C/C++链接:从基础到高级应用
316 0
|
数据采集 机器学习/深度学习 数据挖掘
处理异常值:详细教程与实例分析
处理异常值:详细教程与实例分析
1346 0
|
3月前
|
搜索推荐 安全 API
电商API接口开放平台的生态构建与运营策略
本文探讨了电商API接口开放平台在推动电商行业发展中的重要作用,涵盖用户体验提升、业务创新促进、运营效率提高及销售渠道拓展等方面。同时,文章分析了生态构建的关键要素,如明确目标受众、制定吸引政策和强化支持体系,并提出数据共享、个性化服务与安全合规等运营策略。最后展望未来,指出跨平台支持、个性化服务与生态共赢将成为主要发展趋势,为电商行业的持续创新提供参考。
165 2
|
人工智能 计算机视觉
Dataset之BDD100K:BDD100K数据集的简介、下载、使用方法之详细攻略
Dataset之BDD100K:BDD100K数据集的简介、下载、使用方法之详细攻略
Dataset之BDD100K:BDD100K数据集的简介、下载、使用方法之详细攻略
|
Linux Shell 数据安全/隐私保护
Linux修改密码是提示“passwd: 鉴定令牌操作错误”问题的处理办法
今早忽然想修改一下一个普通用户的密码,root登录进去之后键入修改密码命令之后发现提示“passwd: 鉴定令牌操作错误”。
7637 0
|
10月前
|
缓存 运维 监控
【运维必备知识】Linux系统平均负载与top、uptime命令详解
系统平均负载是衡量Linux服务器性能的关键指标之一。通过使用 `top`和 `uptime`命令,可以实时监控系统的负载情况,帮助运维人员及时发现并解决潜在问题。理解这些工具的输出和意义是确保系统稳定运行的基础。希望本文对Linux系统平均负载及相关命令的详细解析能帮助您更好地进行系统运维和性能优化。
620 3
|
10月前
|
Java easyexcel 大数据
震撼!通过双重异步,Excel 10万行数据导入从191秒优化到2秒!
通过合理设计线程池和利用异步编程模型,本文展示了如何将 Excel 10万行数据的导入时间从191秒优化到2秒。文章详细介绍了使用 Spring Boot 的 `@Async` 注解、自定义线程池和 EasyExcel 进行大数据量的 Excel 解析和异步写入数据库的方法。通过分而治之的策略,减少了系统的响应时间,提高了并发处理能力。同时,还分析了如何根据 CPU 和 IO 密集型任务的特性,合理设置线程池的参数,以充分发挥硬件资源的性能。
使用QMovie类来实现在QT中的动态加载效果。
使用QMovie类来实现在QT中的动态加载效果。
601 0
|
JavaScript
vue3筛选功能
vue3筛选功能
436 0
|
缓存 NoSQL JavaScript
从入门到精通:.gitlab-ci.yml文件的完整指南
从入门到精通:.gitlab-ci.yml文件的完整指南
1140 2