diff options
author | Eric Andersen <andersen@codepoet.org> | 2004-08-26 11:30:48 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2004-08-26 11:30:48 +0000 |
commit | f8666418a90c3e1ebe5fe63d2249a16a1ca3190b (patch) | |
tree | e133a35588e6a99eb510099d620563a9b61c2c24 | |
parent | 2c13012629aeedaa9280909128cc887e3f761eb1 (diff) |
Relocations of the application's global GOT entries were not being run, and
only the global GOT entry relocations for the loaded shared libs were being
handled. This made applications segfault when using un-fixedup symbols. After
many hours debugging to track down the problem, this patch makes the mips port
happy again.
-Erik
-rw-r--r-- | ldso/ldso/ldso.c | 5 | ||||
-rw-r--r-- | ldso/ldso/mips/dl-sysdep.h | 2 | ||||
-rw-r--r-- | ldso/ldso/mips/elfinterp.c | 115 |
3 files changed, 44 insertions, 78 deletions
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 568081acd..5afc4a8f7 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -275,6 +275,11 @@ 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; diff --git a/ldso/ldso/mips/dl-sysdep.h b/ldso/ldso/mips/dl-sysdep.h index 9c4a21580..549bcef9e 100644 --- a/ldso/ldso/mips/dl-sysdep.h +++ b/ldso/ldso/mips/dl-sysdep.h @@ -42,6 +42,8 @@ do { \ unsigned long _dl_linux_resolver(unsigned long sym_index, unsigned long old_gpreg); +struct elf_resolve; +void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt); #define do_rem(result, n, base) result = (n % base) diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c index 3e7672757..e9c6294ca 100644 --- a/ldso/ldso/mips/elfinterp.c +++ b/ldso/ldso/mips/elfinterp.c @@ -178,6 +178,7 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt, Elf32_Sym *symtab; Elf32_Rel *rpnt; char *strtab; + unsigned long i; unsigned long *got; unsigned long *reloc_addr=NULL; unsigned long symbol_addr; @@ -186,47 +187,9 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt, #if defined (__SUPPORT_LD_DEBUG__) unsigned long old_val=0; #endif - Elf32_Sym *sym; - 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; - /* 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 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) - *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++; - } + /* 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); @@ -294,54 +257,50 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt, return 0; } -/* This function should be removed */ +/* Relocate the global GOT entries for the object */ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt) { -#if 0 - Elf32_Sym *sym; char *strtab; + Elf32_Sym *sym; 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; - for (; tpnt ; tpnt = tpnt->next) { - /* 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; - - /* 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 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) - *got_entry += (unsigned long) tpnt->loadaddr; + 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); + sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT); } - - got_entry++; - sym++; } + 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) + *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++; } -#endif } |