Unix 编程 -- 静态链接 & 重定位

本文详细介绍了Unix系统中静态链接的过程,包括重定位节的聚合、符号定义的确定,以及重定位节中符号引用的处理。通过分析main.c和func.c的汇编代码,解释了重定位条目的作用,例如R_X86_64_PC32和R_X86_64_32类型的重定向,并展示了如何计算修正值。文章还探讨了静态链接时如何处理标准库的引用。

静态链接·重定位

静态链接过程会将汇编器生成的可重定位文件(*.o)合并到一个可执行文件中。当链接器完成符号解析后,就会执行重定位过程。重定位过程分为两步:

  • 重定位节及符号定义。相同类型的节会被聚合到可执行文件的同一类型的节中,如下图的步骤一。符号解析过程已经确定了符号被定义的模块及节位置,所以重定位节后,每个符号的运行时地址也已经确定了。
  • 重定位节中的符号引用。如下图的步骤二,在编译main.o时,引用的符号func是由其它模块定义的,编译器无法确定该符号的运时地址,此时编译器所做的是为每个引用的位置记录一个重定位条目信息。链接器根据此信息进行符号引用重定位。

程序代码

main.c

#include <stdio.h>

const static char *s_str = "a static string";
extern int g_num;

int func();

static int func_st()
{
	return --g_num;
}

int main()
{
    int ret = func();
	int ret2 = func_st();

	printf("str: %s, ret: %d, ret2: %d\n", s_str, ret, ret2);	

	return 0;
}

func.c

static int s_num = 200;
int g_num = 200;

int func()
{
	s_num++;
    return s_num;
}

链接示意

       main.o中引用了三个外部符号,其中g_num、func由func.o定义,使用静态的链接方式。printf是标准库定义的函数,如果其它模块都没定义,链接器会默认从标准库libc.so中查找。可以使用-static选项表明要生成一个完全的可执行文件,这样链接器会选择从libc.a库静态链接相应模块到可执行文件里。

 

汇编代码及重定位条目

main.o 汇编代码

[guest@linux ~]$ objdump -D main.o

main.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 &l
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值