void _dl_relocate_static_pie (void) { struct link_map *main_map = _dl_get_dl_main_map (); # define STATIC_PIE_BOOTSTRAP # define BOOTSTRAP_MAP (main_map) # define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP # include "dynamic-link.h" /* Figure out the run-time load address of static PIE. */ main_map->l_addr = elf_machine_load_address (); /* Read our own dynamic section and fill in the info array. */ main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ()); elf_get_dynamic_info (main_map, NULL); # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC ELF_MACHINE_BEFORE_RTLD_RELOC (main_map->l_info); # endif /* Relocate ourselves so we can do normal function calls and data access using the global offset table. */ ELF_DYNAMIC_RELOCATE (main_map, 0, 0, 0); main_map->l_relocated = 1; /* Initialize _r_debug. */ struct r_debug *r = _dl_debug_initialize (0, LM_ID_BASE); r->r_state = RT_CONSISTENT; /* Set up debugging before the debugger is notified for the first time. */ # ifdef ELF_MACHINE_DEBUG_SETUP /* Some machines (e.g. MIPS) don't use DT_DEBUG in this way. */ ELF_MACHINE_DEBUG_SETUP (main_map, r); # else if (main_map->l_info[DT_DEBUG] != NULL) /* There is a DT_DEBUG entry in the dynamic section. Fill it in with the run-time address of the r_debug structure */ main_map->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r; # endif }
void _dl_relocate_object (struct link_map *l, struct link_map *scope[], int lazy) { if (l->l_relocated) return; if (l->l_info[DT_TEXTREL]) { /* Bletch. We must make read-only segments writable long enough to relocate them. */ const ElfW(Phdr) *ph; for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph) if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0) { caddr_t mapstart = ((caddr_t) l->l_addr + (ph->p_vaddr & ~(_dl_pagesize - 1))); caddr_t mapend = ((caddr_t) l->l_addr + ((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1) & ~(_dl_pagesize - 1))); if (__mprotect (mapstart, mapend - mapstart, PROT_READ|PROT_WRITE) < 0) _dl_signal_error (errno, l->l_name, "cannot make segment writable for relocation"); } } { /* Do the actual relocation of the object's GOT and other data. */ const char *strtab /* String table object symbols. */ = ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr); /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */ #define RESOLVE(ref, flags) \ (_dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope, \ l->l_name, flags)) #include "dynamic-link.h" ELF_DYNAMIC_RELOCATE (l, lazy); } /* Set up the PLT so its unrelocated entries will jump to _dl_runtime_resolve (dl-runtime.c), which will relocate them. */ elf_machine_runtime_setup (l, lazy); /* Mark the object so we know ths work has been done. */ l->l_relocated = 1; if (l->l_info[DT_TEXTREL]) { /* Undo the protection change we made before relocating. */ const ElfW(Phdr) *ph; for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph) if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0) { caddr_t mapstart = ((caddr_t) l->l_addr + (ph->p_vaddr & ~(_dl_pagesize - 1))); caddr_t mapend = ((caddr_t) l->l_addr + ((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1) & ~(_dl_pagesize - 1))); int prot = 0; if (ph->p_flags & PF_R) prot |= PROT_READ; if (ph->p_flags & PF_X) prot |= PROT_EXEC; if (__mprotect (mapstart, mapend - mapstart, prot) < 0) _dl_signal_error (errno, l->l_name, "can't restore segment prot after reloc"); } } }