X86 ELF-了解R_386_PC32迁移
我试图理解ELF中的重新定位,但我在这方面的文档中遇到了一些问题,这是相当神秘的。例如,重定位方程描述了3个参数,S,A和P。现在我知道A只是一个加数,它是用来帮助重定位计算的数字,S是索引位于重定位项中的符号的“值”(与函数名相同,对吗?),但是P呢?手册将其描述为“重新安置存储单元的位置”,但这到底意味着什么 我刚刚找到了一个例子来说明这一点:假设我们有两个对象文件,obj1.o和obj2.o。第一个引用了一个名为foo()的函数,该函数位于obj2.o内部 objdump-d obj1.o产生:X86 ELF-了解R_386_PC32迁移,x86,elf,X86,Elf,我试图理解ELF中的重新定位,但我在这方面的文档中遇到了一些问题,这是相当神秘的。例如,重定位方程描述了3个参数,S,A和P。现在我知道A只是一个加数,它是用来帮助重定位计算的数字,S是索引位于重定位项中的符号的“值”(与函数名相同,对吗?),但是P呢?手册将其描述为“重新安置存储单元的位置”,但这到底意味着什么 我刚刚找到了一个例子来说明这一点:假设我们有两个对象文件,obj1.o和obj2.o。第一个引用了一个名为foo()的函数,该函数位于obj2.o内部 objdump-d obj1.o
Disassembly of section .text:
00000000 <func>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 08 sub $0x8,%esp
6: e8 fc ff ff ff call 7 <func+0x7>
b: c9 leave
c: c3 ret
节的反汇编。文本:
00000000 :
0:55推力%ebp
1:89 e5 mov%esp,%ebp
3:83 ec 08子$0x8,%esp
6:e8 fc ff呼叫7
b:c9请假
c:c3 ret
现在,readelf显示这是一个R_386_PC32重定位,其方程为:S+a-p
在组合这两个文件以生成一个完全成熟的可执行文件后,重新定位,重新定位条目显然已修补:
objdump -d relocated
test: file format elf32-i386
Disassembly of section .text:
080480d8 <func>:
80480d8: 55 push %ebp
80480d9: 89 e5 mov %esp,%ebp
80480db: 83 ec 08 sub $0x8,%esp
80480de: e8 05 00 00 00 call 80480e8 <foo>
80480e3: c9 leave
80480e4: c3 ret
80480e5: 90 nop
80480e6: 90 nop
80480e7: 90 nop
080480e8 <foo>:
80480e8: 55 push %ebp
80480e9: 89 e5 mov %esp,%ebp
80480eb: 5d pop %ebp
80480ec: c3 ret
objdump-d
测试:文件格式elf32-i386
第节的分解。正文:
080480d8:
80480d8:55推力%ebp
80480d9:89 e5 mov%esp,%ebp
80480db:83 ec 08子$0x8,%esp
80480de:e8 05 00 00呼叫80480e8
80480e3:c9离开
80480e4:c3 ret
80480e5:90无
80480e6:90无
80480e7:90无
080480e8:
80480e8:55推力%ebp
80480e9:89 e5 mov%esp,%ebp
80480eb:5d pop%ebp
80480ec:c3 ret
因此,链接器似乎执行了以下计算:S+A–p:0x80480e8+0xfffffc–0x80480df
我的问题是:
- P的值从哪里来
- 有加数有什么意义
调用rel32
中的fc ff=-4
判断,这可能是4字节移位的开始。在机器代码中,以指令结尾(即下一条指令的开始)为基础的相对跳跃,因此可以解释4字节的偏移量
这是加数的一个用例
另一种是PC机对静态数据进行相对寻址,以生成位置无关的代码。您的PC引用可能就在附近,但甚至不在使用它的指令内,或者您希望为全局数组编制索引
所以你可能会有
call get_eip_into_ebx
mov $table - this_instruction + 40(%ebx), %ecx
或者,对于一个真实的示例,为
-m32-PIE
加载一个全局文件。(但是全局偏移量表符号名称得到特殊处理,因此我不打算重现编译器asm输出。)S=0x80480e8是符号的起始地址(foo()的入口地址)
P=0x80480df是其值需要修改(重新定位)的地址
所以S-p是这两个地址之间的距离(字节)
然而,call rel32指令计算从下一条指令开始的距离(rel32),距离p有4个字节的偏移量,因此a-4。这个答案是错误的,还是因为我没有尝试使它值得赏金而被否决?在我看来,这不值得投反对票。不是我,彼得(你可以查一下我上次登录的时间是昨天),但我真的很感谢你的回答,因为always@Trey字体别担心,我并没有假设你是落选的选民。有一种真实的可能性,我从代码中推断出的一些东西不是100%正确的,所以我不得不问它是否真的错了:P。我认为这对于理解它如何工作的原理来说已经足够接近了,但是如果我真的实现了我自己的链接器,我不会完全相信这个答案。我猜你对理解引擎盖下的东西更感兴趣,我很确定这是准确的。