首页 > 解决方案 > ELF 重定位:有偏移量,但我看不到偏移量的要求

问题描述

我正在尝试了解精灵搬迁,但有几件事我不太了解:

说我有:relamin.c

#include <stdio.h>
#include <stdlib.h>
#include "relafoo.c"

int main() {
    int n;
    scanf("%d",&n);
    printf("\ngot %d, %d!=%d",n,n,factorial(n));

    return 0;
}

和 relafoo.c

int factorial(int n) {
    if (n == 0 || n == 1) {
        return 1;
    }
    return factorial(n-1)*n;
}

现在在 relamain.o readelf -ri 看到:

000000000027  000900000002 R_X86_64_PC32     0000000000000000 factorial - 4
000000000052  000500000002 R_X86_64_PC32     0000000000000000 .rodata - 4
00000000005c  000c00000004 R_X86_64_PLT32    0000000000000000 __isoc99_scanf - 4
000000000066  000900000002 R_X86_64_PC32     0000000000000000 factorial - 4
  1. 为什么我有两个相同函数的偏移量(阶乘)

我 objdump -d relamain.o:

0000000000000031 <main>:
  31:   55                      push   rbp
  32:   48 89 e5                mov    rbp,rsp
  35:   48 83 ec 10             sub    rsp,0x10
  39:   64 48 8b 04 25 28 00    mov    rax,QWORD PTR fs:0x28
  40:   00 00 
  42:   48 89 45 f8             mov    QWORD PTR [rbp-0x8],rax
  46:   31 c0                   xor    eax,eax
  48:   48 8d 45 f4             lea    rax,[rbp-0xc]
  4c:   48 89 c6                mov    rsi,rax
  4f:   48 8d 3d 00 00 00 00    lea    rdi,[rip+0x0]        # 56 <main+0x25>
  56:   b8 00 00 00 00          mov    eax,0x0
  5b:   e8 00 00 00 00          call   60 <main+0x2f>
  60:   8b 45 f4                mov    eax,DWORD PTR [rbp-0xc]
  63:   89 c7                   mov    edi,eax
  65:   e8 00 00 00 00          call   6a <main+0x39>
  6a:   89 c1                   mov    ecx,eax
  6c:   8b 55 f4                mov    edx,DWORD PTR [rbp-0xc]
  6f:   8b 45 f4                mov    eax,DWORD PTR [rbp-0xc]
  72:   89 c6                   mov    esi,eax
  74:   48 8d 3d 00 00 00 00    lea    rdi,[rip+0x0]        # 7b <main+0x4a>
  7b:   b8 00 00 00 00          mov    eax,0x0
  80:   e8 00 00 00 00          call   85 <main+0x54>
  85:   b8 00 00 00 00          mov    eax,0x0
  8a:   48 8b 75 f8             mov    rsi,QWORD PTR [rbp-0x8]
  8e:   64 48 33 34 25 28 00    xor    rsi,QWORD PTR fs:0x28
  95:   00 00 
  97:   74 05                   je     9e <main+0x6d>
  99:   e8 00 00 00 00          call   9e <main+0x6d>
  9e:   c9                      leave  
  9f:   c3                      ret    
  1. 查看生成的代码,我发现所有调用都不是指 66 或 27,它们是我的阶乘函数的偏移量,这是为什么呢?根据 Ryan“elfmaster”O'Neill 的“learning linux binary analysis”,我应该期望至少我应该看到call 66或者call 27,有人可以解释一下吗?

  2. 如果有人可以将我链接到一本好书,该书通过示例(除了 man ofc 之外)详细解释了所有内容动态链接和重定位,那就太好了

标签: linuxelfdynamic-linking

解决方案


1-同一功能没有两个偏移量。当必须应用重定位时,您对两个位置有两个偏移量。在您的示例中,您有两次调用函数阶乘。一个在偏移量 0x26 处,另一个在偏移量 0x66 处,并且链接到这些调用的重定位偏移量在偏移量 0x27 和 0x67 处。偏移量 0x27 和 0x66 处的“00000000”将被链接器计算的值替换。您可以肯定地看到可执行文件的转储。
2-创建目标文件时。汇编器不知道factorialaddress ,因此它放置“00000000”并放置一个重定位以告诉链接器将这些 0 替换为所需的值,factorial因为只有链接器会知道它的确切位置。
3- 可能是 John R. Levine 的 Linkers & Loaders。但是我建议你开始阅读http://www.skyfree.org/linux/references/ELF_Format.pdf。也许它就足够了,这取决于你寻求的理解程度。


推荐阅读