I am struggling in understanding how a linker perform relocation. According on the ELF manual (Relocation section, pag 27) a relocation of type R_386_PC32 is performed by calculating the quantity S + A - P (see ELF manual at page 29).
Now, consider the following ELF header:
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 560 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 13
Section header string table index: 10
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000038 00 AX 0 0 1
[ 2] .rel.text REL 00000000 0001b8 000010 08 I 11 1 4
[ 3] .data PROGBITS 00000000 00006c 000000 00 WA 0 0 1
[ 4] .bss NOBITS 00000000 00006c 000000 00 WA 0 0 1
[ 5] .rodata PROGBITS 00000000 00006c 00000f 00 A 0 0 1
[ 6] .comment PROGBITS 00000000 00007b 000035 01 MS 0 0 1
[ 7] .note.GNU-stack PROGBITS 00000000 0000b0 000000 00 0 0 1
[ 8] .eh_frame PROGBITS 00000000 0000b0 000044 00 A 0 0 4
[ 9] .rel.eh_frame REL 00000000 0001c8 000008 08 I 11 8 4
[10] .shstrtab STRTAB 00000000 0001d0 00005f 00 0 0 1
[11] .symtab SYMTAB 00000000 0000f4 0000b0 10 12 9 4
[12] .strtab STRTAB 00000000 0001a4 000013 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no section groups in this file.
There are no program headers in this file.
Relocation section '.rel.text' at offset 0x1b8 contains 2 entries:
Offset Info Type Sym.Value Sym. Name
0000001f 00000501 R_386_32 00000000 .rodata
00000024 00000a02 R_386_PC32 00000000 printf
Relocation section '.rel.eh_frame' at offset 0x1c8 contains 1 entries:
Offset Info Type Sym.Value Sym. Name
00000020 00000202 R_386_PC32 00000000 .text
The decoding of unwind sections for machine type Intel 80386 is not currently supported.
Symbol table '.symtab' contains 11 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS asd.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 5
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 0 SECTION LOCAL DEFAULT 8
8: 00000000 0 SECTION LOCAL DEFAULT 6
9: 00000000 56 FUNC GLOBAL DEFAULT 1 main
10: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf
No version information found in this file.
and the relative relocatable file:
asd.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 14 sub $0x14,%esp
11: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp)
18: 83 ec 08 sub $0x8,%esp
1b: ff 75 f4 pushl -0xc(%ebp)
1e: 68 00 00 00 00 push $0x0
23: e8 fc ff ff ff call 24 <main+0x24>
28: 83 c4 10 add $0x10,%esp
2b: b8 00 00 00 00 mov $0x0,%eax
30: 8b 4d fc mov -0x4(%ebp),%ecx
33: c9 leave
34: 8d 61 fc lea -0x4(%ecx),%esp
37: c3 ret
Given that the symbol printf has type R_386_PC32, the new offset has to be calculated as S + A - P. According the sym table S is equal to 0. The quantity A, according the ELF manual, is implicit in the location to be modified, therefore should be equal to 0xfffffffc (little endianess) and finally P should be r_offset, thus 0x24. It follows that the new offset should be equal to 0xffffffD8.
Instead, after linking the above program, I obtain:
0804840b <main>:
804840b: 8d 4c 24 04 lea 0x4(%esp),%ecx
804840f: 83 e4 f0 and $0xfffffff0,%esp
8048412: ff 71 fc pushl -0x4(%ecx)
8048415: 55 push %ebp
8048416: 89 e5 mov %esp,%ebp
8048418: 51 push %ecx
8048419: 83 ec 14 sub $0x14,%esp
804841c: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp)
8048423: 83 ec 08 sub $0x8,%esp
8048426: ff 75 f4 pushl -0xc(%ebp)
8048429: 68 d0 84 04 08 push $0x80484d0
804842e: e8 ad fe ff ff call 80482e0 <printf@plt>
8048433: 83 c4 10 add $0x10,%esp
8048436: b8 00 00 00 00 mov $0x0,%eax
804843b: 8b 4d fc mov -0x4(%ebp),%ecx
804843e: c9 leave
804843f: 8d 61 fc lea -0x4(%ecx),%esp
8048442: c3 ret
8048443: 66 90 xchg %ax,%ax
8048445: 66 90 xchg %ax,%ax
8048447: 66 90 xchg %ax,%ax
8048449: 66 90 xchg %ax,%ax
804844b: 66 90 xchg %ax,%ax
804844d: 66 90 xchg %ax,%ax
804844f: 90 nop
My question is: how is calculated the value actually stored in the final executable file as argument of the printf call(i.e., 0xfffffead)?
S
is not0
, it's whatever the address ofprintf
in theplt
is going to be. – Jesterprintf
isn't in your object file, it's undefined. So yes, the specification is correct, it is going to be that address, but from your dump that address is not yet known. PS: also applies to your.rodata
relocation. – Jester