>Linux linker does not seem to be a lead actor in play of application. But it work like the script which is essential to success of the play. Linker(ldd) is a piece of software that is primarily responsible for address patching a.k.a. relocation. Object files bear absolute and relative addresses.

// test.c
int main()
{
foo();
}

Disassembly of section .text:

00000000 :
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 08 sub $0x8,%esp
6: 83 e4 f0 and $0xfffffff0,%esp
9: b8 00 00 00 00 mov $0x0,%eax
e: 29 c4 sub %eax,%esp
10: e8 fc ff ff ff call 11
15: c9 leave
16: c3 ret

# An object file always starts on address 0x0000.

You can see that addresses are relative to the module and called function is completely unknown to foo. Linker take these object files, relocate their addresses to loading addresses(virtual addresses) and resolve calls to function by a function offset table.

To get a function offset table:
$objdump -x ./test.o

RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
00000011 R_386_PC32 foo

All functions called from a file are listed in this table and here foo() has got 0x11 offset. Once all object files are there linker patches the offset with virtual address. Though call to foo() has been patched with correct virtual address, offset of the instruction is still the same(main+0x11).

08048344 :
8048344: 55 push %ebp
8048345: 89 e5 mov %esp,%ebp
8048347: 83 ec 08 sub $0x8,%esp
804834a: 83 e4 f0 and $0xfffffff0,%esp
804834d: b8 00 00 00 00 mov $0x0,%eax
8048352: 29 c4 sub %eax,%esp
8048354: e8 03 00 00 00 call 804835c
8048359: c9 leave
804835a: c3 ret
804835b: 90 nop

0804835c :
804835c: 55 push %ebp
804835d: 89 e5 mov %esp,%ebp
804835f: 5d pop %ebp
8048360: c3 ret

Advertisements