summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2004-08-26 18:36:23 +0000
committerEric Andersen <andersen@codepoet.org>2004-08-26 18:36:23 +0000
commit17415ee0becb11c97e86dfa00c2e503649f952e6 (patch)
tree6410fbd0a149c06695a0a4a38b7d82ec76de67bd
parent9d7a22d351d45808aa88224367cc1dd30e518705 (diff)
Avoid multiple passes to perform mips GOT relocations, and do
the whole lot in a single pass. -Erik
-rw-r--r--ldso/ldso/ldso.c15
-rw-r--r--ldso/ldso/mips/elfinterp.c85
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++;
+ }
}
}
+