Reputation: 2160
I want to know, how the linker determines that printf is called @ 0xd1: If I look into the symbol table for the address of _printf I see it's 0x0, because this function is not already relocated. But how does the linker and objdump know that at address 1e relocation should be done? Objdump says DISP32 _printf, but I can't find an entry in the objfile that says at address 1e relocation should be done.
objdump -d -r -t test.obj
Output:
test.obj: file format pe-i386
SYMBOL TABLE:
[ 0](sec -2)(fl 0x00)(ty 0)(scl 103) (nx 1) 0x00000000 test.c
File
[ 2](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _main
[ 3](sec 1)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .text
AUX scnlen 0x29 nreloc 3 nlnno 0
[ 5](sec 2)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .data
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 7](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .bss
AUX scnlen 0x0 nreloc 0 nlnno 0
[ 9](sec 4)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .rdata
AUX scnlen 0x3 nreloc 0 nlnno 0
[ 11](sec 5)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000 .eh_frame
AUX scnlen 0x38 nreloc 1 nlnno 0
[ 13](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 1) 0x00000000 ___main
AUX tagndx 0 ttlsiz 0x0 lnnos 0 next 0
[ 15](sec 0)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000 _printf
Disassembly of section .text:
00000000 <_main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: 83 ec 10 sub $0x10,%esp
9: e8 00 00 00 00 call e <_main+0xe>
a: DISP32 ___main
e: c7 44 24 04 05 00 00 movl $0x5,0x4(%esp)
15: 00
16: c7 04 24 00 00 00 00 movl $0x0,(%esp)
19: dir32 .rdata
1d: e8 00 00 00 00 call 22 <_main+0x22>
1e: DISP32 _printf
22: b8 00 00 00 00 mov $0x0,%eax
27: c9 leave
28: c3 ret
29: 90 nop
2a: 90 nop
2b: 90 nop
Upvotes: 1
Views: 439
Reputation: 2160
After I studied the PE / COFF - Format and looked into the OBJ-Code I've found a table for the relocation entries:
0x160:14 00 19 00 00 00 09 00 00 00 06 00 1E 00 00 00 ................
0x170:0F 00 00 00 14 00 2D 00 00 00 09 00 00 00 06 00 ......-.........
@ 0x16C is the entry for _printf. 0x1E is the address of the address part of the call instruction. The linker inserts the relocated symbol at this position. It's a 32 Bit Word. At 0x174 you find the type of the relocation. The type id is 14 and says the linker should replace this part with the relative address of printf:
IMAGE_REL_I386_REL32 0x0014 The 32-bit relative displacement of the target. This supports the x86 relative branch and call instructions.
Upvotes: 1
Reputation: 13189
When I last looked at dynamic linking in Windows, system calls were compiled as calls to a "thunk", a 2-line subroutine that did a far call. So all calls to printf will call this same thunk. The symbol table gives the location of the thunk, and the linker only has to replace the one address in the thunk to link all calls to the correct far address when the library containing printf is loaded. I can't imagine that has changed much.
Upvotes: 0