Dynamic Loader Operation
The following is an annotated and summarized view of the dynamic loader startup:
RTLD_START (sysdep/<arch>/dl-machine.h) _dl_start (elf/rtld.c) ELF_MACHINE_BEFORE_RTLD_RELOC (sysdep/<arch>/dl-machine.h) ELF_DYNAMIC_RELOCATE (sysdep/<arch>/dl-machine.h, Relocate the loader) _dl_start_final (elf/rtld.c, bottom half of _dl_start) entry = _dl_sysdep_start (sysdep/generic/dl-sysdep.c) user_entry = (ElfW(Addr)) ENTRY_POINT; dl_main (elf/rtld.c, main entry point for loader) _dl_init_paths (elf/dl-load.c, fill in RPATH and LD_LIBRARY_PATH information) _dl_debug_initialize (elf/dl-debug.c, initialization of _r_debug and DT_DEBUG) DL_SYSDEP_INIT; DL_PLATFORM_INIT; (sysdeps/<arch>/dl-machine.h) /* Last action of _dl_sysdep_start return the user entry point */ return user_entry; /* Last action of _dl_start returns the user entry point */ ELF_MACHINE_START_ADDRESS (GL(dl_loaded), entry); (sysdep/<arch>/dl-machine.h) _dl_init (elf/dl-init.c, run DSO initializers) call_init (elf/dl-init.c) jump to return of _dl_start (sysdep/<arch>/dl-machine.h) /*User code is now executing*/
Annotations by machine
Machine: hppa
The following is the dynamic loader startup annotated for hppa
ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile) elf_machine_runtime_setup(map,lazy,consider_profile) <- Does all the lazy setup. ELF_DYNAMIC_DO_RELA _ELF_DYNAMIC_DO_RELOC (RELA, rela, map, lazy, _ELF_CHECK_REL) elf_dynamic_do_rel(map,...) <- Does everything else. if(lazy) elf_machine_lazy_rel(map, l_addr, r); else { DO_ELF_MACHINE_RELA_RELATIVE(map, l_addr, relative, l_addr + relative->r_offset); elf_machine_rela_relative(map, l_addr, relative, l_addr + relative->r_offset) { value = l_addr + relative->r_addend; reloc_addr = reloc_addr_arg = l_addr + relative->r_offset; /* Cast */ R_PARISC_DIR32: *reloc_addr = value; /* Unaligned case */ R_PARISC_PLABEL32: break; R_PARISC_IPLT: elf_machine_fixup_plt(NULL,map,relative,reloc_addr,value); reloc_addr[1] = D_PTR ( map, l_info[DT_PLTGOT] ); reloc_addr[0] = value; return reloc_addr; return; R_PARISC_NONE: break; *reloc_addr = value; } elf_machine_rela(...) { sym_map = RESOLVE_MAP(&sym, version, r_type) if ( sym_map ) value = sym ? sym_map->l_addr + sym->st_value + reloc->r_addend : reloc->r_addend; else value = 0; reloc_addr = reloc_addr_arg = ...; refsym = sym; R_PARISC_DIR32: *reloc_addr = value; R_PARISC_PLABEL32: R_PARISC_IPLT: R_PARISC_COPY: R_PARISC_NONE: } }