summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldso/ldso/mips/elfinterp.c164
1 files changed, 129 insertions, 35 deletions
diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c
index 182a79fc0..a73a89a60 100644
--- a/ldso/ldso/mips/elfinterp.c
+++ b/ldso/ldso/mips/elfinterp.c
@@ -27,6 +27,81 @@
* SUCH DAMAGE.
*/
+#if defined (__SUPPORT_LD_DEBUG__)
+static const char *_dl_reltypes_tab[] =
+{
+ [0] "R_MIPS_NONE", "R_MIPS_16", "R_MIPS_32",
+ [3] "R_MIPS_REL32", "R_MIPS_26", "R_MIPS_HI16",
+ [6] "R_MIPS_LO16", "R_MIPS_GPREL16", "R_MIPS_LITERAL",
+ [9] "R_MIPS_GOT16", "R_MIPS_PC16", "R_MIPS_CALL16",
+ [12] "R_MIPS_GPREL32",
+ [16] "R_MIPS_SHIFT5", "R_MIPS_SHIFT6", "R_MIPS_64",
+ [19] "R_MIPS_GOT_DISP", "R_MIPS_GOT_PAGE", "R_MIPS_GOT_OFST",
+ [22] "R_MIPS_GOT_HI16", "R_MIPS_GOT_LO16", "R_MIPS_SUB",
+ [25] "R_MIPS_INSERT_A", "R_MIPS_INSERT_B", "R_MIPS_DELETE",
+ [28] "R_MIPS_HIGHER", "R_MIPS_HIGHEST", "R_MIPS_CALL_HI16",
+ [31] "R_MIPS_CALL_LO16", "R_MIPS_SCN_DISP", "R_MIPS_REL16",
+ [34] "R_MIPS_ADD_IMMEDIATE", "R_MIPS_PJUMP", "R_MIPS_RELGOT",
+ [37] "R_MIPS_JALR",
+};
+
+static const char *
+_dl_reltypes(int type)
+{
+ static char buf[22];
+ const char *str;
+
+ if (type >= (int)(sizeof (_dl_reltypes_tab)/sizeof(_dl_reltypes_tab[0])) ||
+ NULL == (str = _dl_reltypes_tab[type]))
+ {
+ str =_dl_simple_ltoa( buf, (unsigned long)(type));
+ }
+ return str;
+}
+
+static
+void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index)
+{
+ if(_dl_debug_symbols)
+ {
+ if(symtab_index){
+ _dl_dprintf(_dl_debug_file, "\n%s\n\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x",
+ strtab + symtab[symtab_index].st_name,
+ symtab[symtab_index].st_value,
+ symtab[symtab_index].st_size,
+ symtab[symtab_index].st_info,
+ symtab[symtab_index].st_other,
+ symtab[symtab_index].st_shndx);
+ }
+ }
+}
+
+static void debug_reloc(Elf32_Sym *symtab,char *strtab, ELF_RELOC *rpnt)
+{
+ if(_dl_debug_reloc)
+ {
+ int symtab_index;
+ const char *sym;
+ symtab_index = ELF32_R_SYM(rpnt->r_info);
+ sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0";
+
+ if(_dl_debug_symbols)
+ _dl_dprintf(_dl_debug_file, "\n\t");
+ else
+ _dl_dprintf(_dl_debug_file, "\n%s\n\t", sym);
+#ifdef ELF_USES_RELOCA
+ _dl_dprintf(_dl_debug_file, "%s\toffset=%x\taddend=%x",
+ _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
+ rpnt->r_offset,
+ rpnt->r_addend);
+#else
+ _dl_dprintf(_dl_debug_file, "%s\toffset=%x\n",
+ _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
+ rpnt->r_offset);
+#endif
+ }
+}
+#endif
extern int _dl_linux_resolve(void);
@@ -41,47 +116,57 @@ unsigned long _dl_linux_resolver(unsigned long sym_index,
char *strtab;
unsigned long local_gotno;
unsigned long gotsym;
- unsigned long value;
+ unsigned long new_addr;
+ unsigned long instr_addr;
+ char **got_addr;
+ char *symname;
gotsym = tpnt->mips_gotsym;
local_gotno = tpnt->mips_local_gotno;
- sym = ((Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr)) +
- sym_index;
-
+ sym = ((Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr)) + sym_index;
strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+ symname = strtab + sym->st_name;
- value = (unsigned long) _dl_find_hash(strtab + sym->st_name,
+ new_addr = (unsigned long) _dl_find_hash(strtab + sym->st_name,
tpnt->symbol_scope, tpnt, resolver);
-
- *(got + local_gotno + sym_index - gotsym) = value;
-
+
+ /* Address of jump instruction to fix up */
+ instr_addr = (unsigned long) (got + local_gotno + sym_index - gotsym);
+ got_addr = (char **) instr_addr;
+
#if defined (__SUPPORT_LD_DEBUG__)
- _dl_dprintf(2, "---RESOLVER---\n");
- _dl_dprintf(2, "SYMTAB INDEX: %i\n", sym_index);
- _dl_dprintf(2, " GOTSYM: %i\n", gotsym);
- _dl_dprintf(2, " LOCAL GOTNO: %i\n", local_gotno);
- _dl_dprintf(2, " VALUE: %x\n", value);
- _dl_dprintf(2, " SYMBOL: %s\n\n", strtab + sym->st_name);
+ if (_dl_debug_bindings)
+ {
+ _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+ if(_dl_debug_detail) _dl_dprintf(_dl_debug_file,
+ "\n\tpatched %x ==> %x @ %x\n", *got_addr, new_addr, got_addr);
+ }
+ if (!_dl_debug_nofixups) {
+ *got_addr = (char*)new_addr;
+ }
+#else
+ *got_addr = (char*)new_addr;
#endif
- return value;
+ return new_addr;
}
-void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
+void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
unsigned long rel_addr, unsigned long rel_size, int type)
{
/* Nothing to do */
return;
}
-int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
+int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
unsigned long rel_size, int type)
{
/* Nothing to do */
return 0;
}
-
+
+
int _dl_parse_relocation_information(struct elf_resolve *tpnt,
unsigned long rel_addr, unsigned long rel_size, int type)
{
@@ -89,7 +174,7 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt,
Elf32_Rel *rpnt;
char *strtab;
unsigned long *got;
- unsigned long *reloc_addr;
+ unsigned long *reloc_addr=NULL, old_val=0;
unsigned long symbol_addr;
int i, reloc_type, symtab_index;
@@ -111,6 +196,12 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt,
if (!symtab_index && tpnt->libtype == program_interpreter)
continue;
+#if defined (__SUPPORT_LD_DEBUG__)
+ debug_sym(symtab,strtab,symtab_index);
+ debug_reloc(symtab,strtab,rpnt);
+ old_val = *reloc_addr;
+#endif
+
switch (reloc_type) {
case R_MIPS_REL32:
if (symtab_index) {
@@ -130,13 +221,28 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt,
case R_MIPS_NONE:
break;
default:
- _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
- if (symtab_index)
- _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
- _dl_exit(1);
+ {
+ int reloc_type = ELF32_R_TYPE(rpnt->r_info);
+ _dl_dprintf(2, "\n%s: ",_dl_progname);
+
+ if (symtab_index)
+ _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
+#else
+ _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
+#endif
+ _dl_exit(1);
+ }
};
};
+#if defined (__SUPPORT_LD_DEBUG__)
+ if(_dl_debug_reloc && _dl_debug_detail)
+ _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, *reloc_addr, reloc_addr);
+#endif
+
return 0;
}
@@ -164,10 +270,6 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
/* Relocate the global GOT entries for the object */
while(i--) {
-#if defined (__SUPPORT_LD_DEBUG__)
- _dl_dprintf(2,"BEFORE: %s=%x\n", strtab + sym->st_name,
- *got_entry);
-#endif
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;
@@ -192,14 +294,6 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
sym->st_name, tpnt->symbol_scope, NULL, copyrel);
}
-#if defined (__SUPPORT_LD_DEBUG__)
- if (*got_entry == 0)
- _dl_dprintf(2,"ZERO: %s\n", strtab + sym->st_name);
- else
- _dl_dprintf(2," AFTER: %s=%x\n", strtab + sym->st_name,
- *got_entry);
-#endif
-
got_entry++;
sym++;
}