Browse Source

Make the mips ld.so debug noise somewhat useful, and less gratuitously
different than all other arches.
-Erik

Eric Andersen 21 years ago
parent
commit
88352870e9
1 changed files with 129 additions and 35 deletions
  1. 129 35
      ldso/ldso/mips/elfinterp.c

+ 129 - 35
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++;
 		}