《深入理解计算机系统》第7章:重定位PC相对引用的理解

在第七章《链接》中的静态链接有对符号进行重定位PC相对引用的处理,书上对应的还有公式,但不是很好理解。现做实验对公式进行理解(公式内容如有兴趣可以参考原文)

我们的目的是根据.text节起点和目标函数地址(如下面的0x8048420),重新计算引用偏移量

现创建2个文件

代码语言:javascript
复制
//main.c
void swap();
int buf[2]={1,2};
int main()
{
        swap();
        return 0;
}

//swap.c
extern int buf[];
int *bufp0 = &buf[0];
int *bufp1;
void swap()
{
int temp;
bufp1 = &buf[1];
temp = *bufp0;
*bufp0 = *bufp1;
*bufp1 = temp;
}

可以看到main.c引用了swap.c的函数,编译main.c为main.o,反汇编有如下结果

代码语言:javascript
复制
# objdump -d main.o

main.o: file format elf32-i386
Disassembly of section .text:

00000000 <main>:
0: 8d 4c 24 04        lea 0x4(%esp),%ecx
4: 83 e4 f0          and $0xfffffff0,%esp
7: ff 71 fc          pushl -0x4(%ecx)
a: 55              push %ebp
b: 89 e5            mov %esp,%ebp
d: 51              push %ecx
e: 83 ec 04 sub $0x4,%esp
11: e8 fc ff ff ff call 12 <main+0x12> --对swap引用的地址偏移量为12(call命令占一个字节)
16: b8 00 00 00 00       mov $0x0,%eax
1b: 83 c4 04          add $0x4,%esp
1e: 59              pop %ecx
1f: 5d              pop %ebp
20: 8d 61 fc           lea -0x4(%ecx),%esp
23: c3              ret

将swap.o和main.o编译为可执行文件p,查看p的.text节信息(截取部分如下)

[15] .text PROGBITS 08048330 000330 0001bc 00 AX 0 0 16 --节起始地址为红色部分

反汇编p,(截取部分如下)

代码语言:javascript
复制
080483f0 <main>:
80483f0: 8d 4c 24 04        lea 0x4(%esp),%ecx
80483f4: 83 e4 f0          and $0xfffffff0,%esp
80483f7: ff 71 fc          pushl -0x4(%ecx)
80483fa: 55              push %ebp
80483fb: 89 e5            mov %esp,%ebp
80483fd: 51              push %ecx
80483fe: 83 ec 04          sub $0x4,%esp
8048401: e8 1a 00 00 00       call 8048420 <swap>
8048406: 83 c4 04 add $0x4,%esp
8048409: 31 c0 xor %eax,%eax
804840b: 59 pop %ecx
804840c: 5d pop %ebp
804840d: 8d 61 fc lea -0x4(%ecx),%esp

由于不知道swap相对与.text起始地址的偏移量,我们采用main函数的地址,它相对于main函数的偏移量为0x12。

那么新的引用量为0x8048420-(0x080483f0+0x12)-4 = 1A

实际上0x080483f0+0x12+4的地址就是PC的值,0x8048420-PC就是偏移值

可见公式害死人。。。