I have recently been looking into ELF binaries and how functions are called using GOT and PLT in an ELF file.
When a function is called this is what occurs as far as i know:
- function is called
- a jump is a made to PLT specifically the functions plt stub (
function@plt
) - inside
function@plt
a jump is made to GOT to check if the functions address is present, if not it is loaded into GOT - next time the function is called the PLT stub (
function@plt
) will jump directly to the function address via the GOT
This makes sense but when doing further research into this i wondered how and why libraries that contain functions are loaded randomly. Specifically here is an example with a ELF dynamically linked binary called x
:
user1@ubuntu:~$ ldd x
linux-vdso.so.1 (0x00007ffeff6f6000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd65aa52000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd65ac94000)
user1@ubuntu:~$ ldd x
linux-vdso.so.1 (0x00007ffdda5ee000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f10242a0000)
/lib64/ld-linux-x86-64.so.2 (0x00007f10244e2000)
Calling lld
on the executable reveals that my executable uses libc.so
where many C standard library functions are located like printf
for example. However you may also notice that the address changes on each call from 0x00007ffeff6f6000
to 0x00007ffdda5ee000
and upon calling lld x
multiple times the address always changes.
Why does the address keep changing and how does the computer know where the new address of libc will be?