Linux ELF重新定位:有偏移量,但我看不到需要偏移量

Linux ELF重新定位:有偏移量,但我看不到需要偏移量,linux,elf,dynamic-linking,Linux,Elf,Dynamic Linking,我试图理解elf的迁移,但有两件事我并不真正理解: 说我有: relamain.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)); ret

我试图理解elf的迁移,但有两件事我并不真正理解:

说我有: relamain.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;
}
现在在relamain.o readelf-r中,我看到:

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
  • 为什么同一个函数有两个偏移量(阶乘)
  • i 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    
    
    00000000000000 31:
    31:55推动rbp
    32:48 89 e5 mov rbp,rsp
    35:48 83 ec 10子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移动rsi,rax
    4f:48 8d 3d 00 lea rdi,[rip+0x0]#56
    56:B800 mov eax,0x0
    5b:e8 00 00呼叫60
    60:8b 45 f4 mov eax,DWORD PTR[rbp-0xc]
    63:89 c7移动电子数据交换,eax
    65:e8 00呼叫6a
    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电影esi,eax
    74:48 8d 3d 00 lea rdi,[rip+0x0]#7b
    7b:b800 mov eax,0x0
    80:E800呼叫85
    85:B800 mov eax,0x0
    8a:48 8b 75 f8移动rsi,QWORD PTR[rbp-0x8]
    8e:64 48 33 34 25 28 00异或rsi,QWORD PTR fs:0x28
    95:   00 00 
    97:74 05日本脑炎9e
    99:e8 00呼叫9e
    9e:c9离开
    9f:c3 ret
    
  • 查看生成的代码,我发现所有调用都不是指66或27,这是我的阶乘函数的偏移量,为什么?根据Ryan“elfmaster”O'Neill的“learning linux binary analysis”,我至少应该看到
    call 66
    call 27
    ,有人能解释一下吗

  • 如果有人能把我和一本好书联系起来,这本书用例子详细解释了一切(超越了MANOFC),动态链接和重新定位,那就太好了


  • 1-同一函数没有两个偏移量。当必须应用重定位时,有两个偏移到两个位置。在您的示例中,有两个对factorial函数的调用。一个位于偏移量0x26,另一个位于偏移量0x66,与这些调用链接的重定位的偏移量位于偏移量0x27和0x67。偏移量0x27和0x66处的“00000000”将由链接器计算的值替换。您可以肯定地看到可执行文件的转储。
    2-创建对象文件时。汇编程序不知道
    factorial
    地址,因此它会放置“00000000”并放置一个重新定位,以告诉链接器用获取
    factorial
    所需的值替换这些0,因为只有链接器才知道它的确切位置。
    3-可能是John R.Levine的链接器和加载程序。然而,我建议你,开始阅读。也许这就足够了,这取决于你所寻求的理解水平

    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