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:
          }
      }