静态链接(具体)

静态链接

地址空间分配

​ 两个或者多个不同的目标文件如何组成一个可执行文件,需要进行链接(linking)。链接由链接器(linker)完成,根据发生的时间不同,可分为编译时链接(compile time)、加载时链接(load time)和运行时链接(run time)。

下面由两个c语言文件main.c和func.c

main.cfunc.c
extern int shared;
extern void func(int *a,int *b);
int main()
{
int a=100;
func(&a,&shared);
return 0;
}
int shared=1;
int tmp=0;
void func(int *a,int *b)
{
tmp = *a;
*a = *b;
*b = tmp;
}
在这里插入图片描述

执行此命令,结果如下:

在这里插入图片描述

​ 在将main.o和func.o这两个文件链接成一个exec文件,按序叠加
在这里插入图片描述

另一种是相似节合并,将不同目标文件相同属性的节合并为一个节

在这里插入图片描述

静态链接的详细过程

​ 为了构造可执行文件,链接器必须完成两个重要工作:符号解析(symbol resolution)和重定位(relocation)。

符号解析是将每个符号(函数、全局变量、静态变量)的引用与其定义进行关联。

重定位是将每个符号的定义与一个内存地址进行关联,然后修改这些符号的引用,使其指向这个内存地址。

先查看静态链接前后文件的区别,这里以func.ELF和main.o两者进行比较
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

VMA(virtual memory address)是虚拟地址,LMA(load memory address)是加载地址

观察上述,得出未经链接的main.o文件的VMA和LMA的值都是0,而链接以后的文件中,完成了虚拟地址的分配

在查看两个文件的反汇编代码

在这里插入图片描述

​ 可以看到main()函数的地址从0开始。其中,对func()函数的调用在偏移0x22处,0xe8是CALL指令的操作码,后四个字节是被调用函数相对于调用指令的下一条指令的偏移量。

在这里插入图片描述

​ 可以看到,调用func函数的指令CALL位于0x400b8a,其下一条指令MOV位于0x400b8f,call行操作码中的偏移量位0x07,也就是相对于MOV的偏移量为0x07,:0x400b8f+0x07=0x400b96。正好是func函数的地址。同时,shared的地址也变成了6b90f0。

​ 可重定位文件中最重要的就是要包括重定位表,用于告诉链接器如何修改节的内容。

静态链接库

​ 后缀名为.a的文件是静态链接库文件,如常见的libc.a。一个动态链接库可以视为一组目标文件经过压缩打包后形成的集合。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值