diff options
Diffstat (limited to 'ldso/ldso/mips/elfinterp.c')
-rw-r--r-- | ldso/ldso/mips/elfinterp.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c index e6c3781b8..5b1192169 100644 --- a/ldso/ldso/mips/elfinterp.c +++ b/ldso/ldso/mips/elfinterp.c @@ -142,3 +142,62 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt, }; return 0; } + +void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt) +{ + Elf32_Sym *sym; + char *strtab; + unsigned long i; + unsigned long *got_entry; + + 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; + + /* 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, NULL, 1); + } + } + else if (sym->st_shndx == SHN_COMMON) { + *got_entry = (unsigned long) _dl_find_hash(strtab + + sym->st_name, tpnt->symbol_scope, NULL, 1); + } + 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, NULL, 1); + } + +#ifdef DL_DEBUG + if (*got_entry == 0) + _dl_dprintf(2,"ZERO: %s\n", strtab + sym->st_name); +#endif + + got_entry++; + sym++; + } + } +} |