LiorA
LiorA

Reputation: 441

ELF relocation: offsets are there but i see no call for the offset

I'm trying to understand elf relocation and there're couple of things that I don't really understand:

say I've got: 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;
}

and relafoo.c

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

now in relamain.o readelf -r i see:

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. how come i have two offsets for the same function(factorial)

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    
  1. Looking at the produced code i see that all the calls are not referring to 66 nor 27 which are the offsets for my factorial function, why is that? according to "learning linux binary analysis" by Ryan "elfmaster" O'Neill, I should expect that at least i should see call 66 or call 27, can anyone explain this?

  2. if anyone can link me to a good book that explains everything in details with examples(beyond man ofc) dynamic linking and relocations it would be great

Upvotes: 0

Views: 255

Answers (1)

yflelion
yflelion

Reputation: 1746

1- You don't have two offset for the same function. you have two offset to two locations when the relocations must be applied. In your example you have two call to the function factorial. One at offset 0x26 and the other at offset 0x66 and the offset to the relocation linked to these calls are at offset 0x27 and 0x67. The "00000000" at the offsets 0x27 and 0x66 will be replaced by a value calculated by the linker. you can see the dump of the executable to be sure.
2- When creating the object file. The assembler don't know factorial address , so it places "00000000" and place a relocation to tell the linker to replace these 0 by the value needed to get factorial since only the linker will know it exact location.
3- May be Linkers & Loaders by John R. Levine. however what i suggest you, is to start reading http://www.skyfree.org/linux/references/ELF_Format.pdf. Maybe it can be enough, depending on the level of understanding you seek.

Upvotes: 1

Related Questions