How Linux executes binaries: ELF and dynamic linking explained