Reputation: 129
I assumed a procedure call in the same object module wouldn't require relocation in the link stage. e.g. following code
void callee()
{
printf("Should I be relocated\n");
}
void caller()
{
callee();
}
After compile/assemble, I got following
Relocation section '.rel.text' at offset 0x438 contains 3 entries:
Offset Info Type Sym.Value Sym. Name
00000009 00000501 R_386_32 00000000 .rodata
0000000e 00000a02 R_386_PC32 00000000 puts
0000001b 00000902 R_386_PC32 00000000 callee
And the result of disassembly:
Disassembly of section .text:
00000000 <callee>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 18 sub $0x18,%esp
6: c7 04 24 00 00 00 00 movl $0x0,(%esp)
d: e8 fc ff ff ff call e <callee+0xe>
12: c9 leave
13: c3 ret
00000014 <caller>:
14: 55 push %ebp
15: 89 e5 mov %esp,%ebp
17: 83 ec 08 sub $0x8,%esp
1a: e8 fc ff ff ff call 1b <caller+0x7>
1f: c9 leave
20: c3 ret
Why does the procedure call in a same object module (1a: e8 fc ff ff ff call 1b ) need relocation? Does it depend on my toolchain? Does the PC-relative address (the address offset between the caller and callee) ever have chance to change when calling the procedure within a same object module? If not, why not just fix the code at 0x1a to "e8 e1 ff ff ff"
Upvotes: 3
Views: 84
Reputation: 51264
Relocation tables have to be stored inside each module, for that actual module, to allow load-time relocation of shared libs.
Since the dynamic linker in (most) Unix distributions can override functions in shared libraries, this means that the function can be relocated, even if the call happens inside a single module. Tools like Valgrind benefit from such features for instrumentation and leak detection.
So, as noted in comments, if you mark the function static
, then the compiler can skip this part altogether and hardcode the jump.
Upvotes: 2