summaryrefslogtreecommitdiff
path: root/ldso/ldso/mips/elfinterp.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldso/ldso/mips/elfinterp.c')
-rw-r--r--ldso/ldso/mips/elfinterp.c59
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++;
+ }
+ }
+}