失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 符号引用重定位 重定位PC相对引用 简单讲解

符号引用重定位 重定位PC相对引用 简单讲解

时间:2018-11-17 02:42:27

相关推荐

符号引用重定位 重定位PC相对引用 简单讲解

目录

链接符号引用重定位简介例子重定位条目简介offsettypesymboladdend重定位PC相对引用重定位PC绝对引用

链接符号引用重定位

简介

我们知道一个.c文件可以被编译为.o文件,即目标文件,而假如一个.c中引用了别的.c中的函数或者是变量,这时候的.o其实是不知道引用函数实际的内存位置的,也就无法跳转,这就需要【重定位】的操作了,而针对函数名(也是符号)的重定位

例子

我们编写两个.c文件,分别是main.c和func.c,main.c引用了func.c中的func函数

// main.cint func(int x, int y);int main(){int c = func(1, 2);return 0;}

// func.cint func(int x, int y){return 2*x + y;}

我们使用gcc来编译出两个.o文件,使用如下命令将会生成main.o与func.o

gcc -c main.c func.c

然后我们对main.o与func.o反汇编,使用如下命令可以生成main_dump.txt与func_dump.txt的反汇编文件

objdump -d main.o > main_dump.txtobjdump -d func.o > func_dump.txt

因为main.c调用func.c而func.c并未调用其他函数,所以我们查看main.o反汇编结果,如下图蓝色区域,因为在链接之前每个.c相对是独立的,并不知道如何跳转到其他文件的函数,所以无法正确的写成跳转指令

但是我们将两个.o文件进一步编译成可执行文件,并查看其反汇编。执行以下命令做进一步的编译,将main.o和func.o链接进而生成exe可执行的二进制文件

gcc -o exe main.o func.o

如图

我们对exe反汇编,得到exe的汇编代码

objdump -d exe > exe_dump.txt

发现可以正确的跳转到func所指定的地址,这是我们想要的,也是链接中重定位所做的功劳

重定位条目

简介

----引用自《深入理解计算机系统》

但是书上讲的很抽象,而且没有例子,接下来简单解释以下这些条目中各个符号的意义

offset

因为在链接之前,每个.c相当于一个独立的部分,我们称之为【节】,而offset表明这个符号引用相对于【节】起始处的偏移(其实就是相对地址)

值得注意的是,这个offset指向的是callq指令中需要被修改的操作数,而不是callq指令本身

如图 main.c 的节

type

是何种重定位方式,因为编译的时候可以有很多种重定位方式,但是接下来只讨论书上描述的比较难懂的【重定位PC相对引用】

symbol

即这个引用指向的是哪个符号,比如main.c引用func函数那么就指向func函数

addend

在PC+偏移跳转计算实际地址时用到的计算偏移,待会会讲解

重定位PC相对引用

这里是书上讲的比较晦涩的地方,书上直接给出了公式

这个公式很难懂,但是我们可以翻译一下。仍然以main.c引用func.c为例子

结合exe可执行文件的反汇编代码,我们进一步理解:

现在再来看这个公式,其中offset为0x13,根据上面offset定义推得

refaddr = ADDR(s) + r.offset要修改的引用的实际地址 = main函数实际地址 + 要修改的引用的相对地址0x60d= 0x5fa + 0x13

addend是由命令查看精灵ELFreadelf -r main.o查询得的

*refptr = ADDR(r.symbol) + r.addend - refaddr修改后的内容x= func函数实际地址 + 计算偏移 - 要修改的引用的实际地址0xa= 0x61b + -0x4- 0x60d注:因为是【PC+偏移】寻址,修改后的内容x就是call的操作数要想使跳转到func函数,就需要【PC+x = func函数实际地址】PC + 0xa = 0x611 + 0xa = 0x61b 确实是func函数的地址,达到效果

注:此处r.addend=-4,是因为要修改的操作数地址(refaddr)和该操作数所在指令的下一条指令地址(即PC)相差4字节。因为操作数是4字节的,填充操作数之后,才是下一条指令的地址(PC),所以做差之后,要补偿操作数占用的4字节地址回去。

换句话说,call的操作数有 x 字节,r.addend的就等于 -x

可以看到编译后的结果,也就是链接的时候修改后的结果,确实是0xa(小端表示牢记于心)

附:图解,以main函数调用sum函数为例

现在再看书上的公式是否变简单了?

重定位PC绝对引用

这个简单,没有那么多做差和偏移,直接将实际的func函数的地址赋值给操作数,但是一般用于外部变量数据的引用中

如果觉得《符号引用重定位 重定位PC相对引用 简单讲解》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。