diff options
author | Eric Andersen <andersen@codepoet.org> | 2004-08-26 18:36:23 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2004-08-26 18:36:23 +0000 |
commit | 17415ee0becb11c97e86dfa00c2e503649f952e6 (patch) | |
tree | 6410fbd0a149c06695a0a4a38b7d82ec76de67bd /ldso | |
parent | 9d7a22d351d45808aa88224367cc1dd30e518705 (diff) |
Avoid multiple passes to perform mips GOT relocations, and do
the whole lot in a single pass.
-Erik
Diffstat (limited to 'ldso')
-rw-r--r-- | ldso/ldso/ldso.c | 15 | ||||
-rw-r--r-- | ldso/ldso/mips/elfinterp.c | 85 |
2 files changed, 53 insertions, 47 deletions
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 4c6817e6d..6ce8564bc 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -275,11 +275,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, INIT_GOT(lpnt, _dl_loaded_modules); } -#if defined(__mips__) - /* Relocate any global GOT entries for the application */ - _dl_perform_mips_global_got_relocations(app_tpnt); -#endif - /* OK, fill this in - we did not have this before */ if (ppnt->p_type == PT_INTERP) { int readsize = 0; @@ -667,17 +662,17 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, #endif +#ifdef __SUPPORT_LD_DEBUG_EARLY__ + _dl_dprintf(_dl_debug_file, "Beginning relocation fixups\n"); +#endif + #ifdef __mips__ /* * Relocation of the GOT entries for MIPS have to be done - * after all the libraries have been loaded. - */ + * after all the libraries have been loaded. */ _dl_perform_mips_global_got_relocations(_dl_loaded_modules); #endif -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - _dl_dprintf(_dl_debug_file, "Beginning relocation fixups\n"); -#endif /* * OK, now all of the kids are tucked into bed in their proper addresses. * Now we go through and look for REL and RELA records that indicate fixups diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c index e9c6294ca..d86f60d77 100644 --- a/ldso/ldso/mips/elfinterp.c +++ b/ldso/ldso/mips/elfinterp.c @@ -188,9 +188,6 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt, unsigned long old_val=0; #endif - /* Relocate any global GOT entries for the object */ - _dl_perform_mips_global_got_relocations(tpnt); - /* Now parse the relocation information */ rel_size = rel_size / sizeof(Elf32_Rel); rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr); @@ -260,47 +257,61 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt, /* Relocate the global GOT entries for the object */ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt) { - char *strtab; Elf32_Sym *sym; + char *strtab; unsigned long i; unsigned long *got_entry; - /* Setup the loop variables */ - got_entry = (unsigned long *) (tpnt->loadaddr + - tpnt->dynamic_info[DT_PLTGOT]) + tpnt->mips_local_gotno; - sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + - (unsigned long) tpnt->loadaddr) + tpnt->mips_gotsym; - strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + - (unsigned long) tpnt->loadaddr); - i = tpnt->mips_symtabno - tpnt->mips_gotsym; - - while(i--) { - if (sym->st_shndx == SHN_UNDEF) { - if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && sym->st_value) { - *got_entry = sym->st_value + (unsigned long) tpnt->loadaddr; + + for (; tpnt ; tpnt = tpnt->next) { + + /* We don't touch the dynamic linker */ + if (tpnt->libtype == program_interpreter) + continue; + + /* Setup the loop variables */ + got_entry = (unsigned long *) (tpnt->loadaddr + + tpnt->dynamic_info[DT_PLTGOT]) + tpnt->mips_local_gotno; + sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + + (unsigned long) tpnt->loadaddr) + tpnt->mips_gotsym; + strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + + (unsigned long) tpnt->loadaddr); + i = tpnt->mips_symtabno - tpnt->mips_gotsym; + +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "_dl_perform_mips_global_got_relocations for '%s'\n", tpnt->libname); +#endif + + /* Relocate the global GOT entries for the object */ + while(i--) { + if (sym->st_shndx == SHN_UNDEF) { + if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && sym->st_value) { + *got_entry = sym->st_value + (unsigned long) tpnt->loadaddr; + } + else { + *got_entry = (unsigned long) _dl_find_hash(strtab + + sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + } } - else { + else if (sym->st_shndx == SHN_COMMON) { *got_entry = (unsigned long) _dl_find_hash(strtab + - sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); } - } - else if (sym->st_shndx == SHN_COMMON) { - *got_entry = (unsigned long) _dl_find_hash(strtab + - sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); - } - else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && - *got_entry != sym->st_value) { - *got_entry += (unsigned long) tpnt->loadaddr; - } - else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) { - if (sym->st_other == 0) + else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && + *got_entry != sym->st_value) { *got_entry += (unsigned long) tpnt->loadaddr; - } - else { - *got_entry = (unsigned long) _dl_find_hash(strtab + - sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); - } + } + else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) { + if (sym->st_other == 0) + *got_entry += (unsigned long) tpnt->loadaddr; + } + else { + *got_entry = (unsigned long) _dl_find_hash(strtab + + sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); + } - got_entry++; - sym++; + got_entry++; + sym++; + } } } + |