فهرست منبع

Joakim Tjernlund writes:

> Not there yet, but the interfaces are much closer now...
> Heading to bed though, since its 5:30am.  :-)

This works, but I discovered something "funny". For all
relocs but COPY you can use scope instead of scope->dyn->symbol_scope
and it is much faster to do that. Search for "Funny" in the patch
to see what I mean. Probably I probably broke something, please let me
know if it works for you too.

I think I am done with ldso now. Has been fun and I hope to
actually use uClibc/busybox soon in a project.

Ohh, there is one thing left, double sized PLT entries, but maybe these
aren't needed in uClibc?

 Sweet dreams
              Jocke
Eric Andersen 22 سال پیش
والد
کامیت
de2873b9c6
1فایلهای تغییر یافته به همراه87 افزوده شده و 117 حذف شده
  1. 87 117
      ldso/ldso/powerpc/elfinterp.c

+ 87 - 117
ldso/ldso/powerpc/elfinterp.c

@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2001-2002 David A. Schleef
  * Copyright (C) 2003-2004 Erik Andersen
+ * Copyright (C) 2004 Joakim Tjernlund
  *
  * All rights reserved.
  *
@@ -251,72 +252,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 	return finaladdr;
 }
 
-static int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
-	  unsigned long rel_addr, unsigned long rel_size,
-	  int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
-			    ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
-{
-	unsigned int i;
-	char *strtab;
-	Elf32_Sym *symtab;
-	ELF_RELOC *rpnt;
-	int symtab_index;
-
-	/* Now parse the relocation information */
-	rpnt = (ELF_RELOC *)(intptr_t) (rel_addr + tpnt->loadaddr);
-	rel_size = rel_size / sizeof(ELF_RELOC);
-
-	symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
-	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
-
-	  for (i = 0; i < rel_size; i++, rpnt++) {
-	        int res;
-
-		symtab_index = ELF32_R_SYM(rpnt->r_info);
-
-		/* When the dynamic linker bootstrapped itself, it resolved some symbols.
-		   Make sure we do not do them again */
-		if (!symtab_index && tpnt->libtype == program_interpreter)
-			continue;
-		if (symtab_index && tpnt->libtype == program_interpreter &&
-		    _dl_symbol(strtab + symtab[symtab_index].st_name))
-			continue;
-
-#if defined (__SUPPORT_LD_DEBUG__)
-		debug_sym(symtab,strtab,symtab_index);
-		debug_reloc(symtab,strtab,rpnt);
-#endif
-
-		res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
-
-		if (res==0) continue;
-
-		_dl_dprintf(2, "\n%s: ",_dl_progname);
-
-		if (symtab_index)
-		  _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
-
-		if (res <0)
-		{
-		        int reloc_type = ELF32_R_TYPE(rpnt->r_info);
-#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(-res);
-		}
-		else if (res >0)
-		{
-			_dl_dprintf(2, "can't resolve symbol\n");
-			return res;
-		}
-	  }
-	  return 0;
-}
-
-static int
+static inline int
 _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 	      ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
@@ -325,6 +261,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 	char *symname;
 	Elf32_Addr *reloc_addr;
 	Elf32_Addr finaladdr;
+	struct dyn_elf *sym_scope;
 
 	unsigned long symbol_addr;
 #if defined (__SUPPORT_LD_DEBUG__)
@@ -336,13 +273,22 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 		*reloc_addr = tpnt->loadaddr + rpnt->r_addend;
 		return 0;
 	}
-	if (reloc_type == R_PPC_NONE || reloc_type == R_PPC_COPY) /*  R_PPC_COPY is handled later */
+	if (reloc_type == R_PPC_NONE)
 		return 0;
 	symtab_index = ELF32_R_SYM(rpnt->r_info);
 	symname      = strtab + symtab[symtab_index].st_name;
-
-	symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
-						    (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), symbolrel);
+#if 0
+	sym_scope = scope->dyn->symbol_scope;
+#else
+	sym_scope = scope;/* Funny, this works too and appears to be much faster. */
+#endif
+	if (reloc_type == R_PPC_COPY) {
+		sym_scope = scope->next;
+		tpnt = NULL; /* To be or not to be ...*/
+	}
+	symbol_addr = (unsigned long) _dl_find_hash(symname, sym_scope,
+						    (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL),
+						    (reloc_type == R_PPC_COPY ? copyrel : symbolrel));
 	/*
 	 * We want to allow undefined references to weak symbols - this might
 	 * have been intentional.  We should not be linking local symbols
@@ -398,7 +344,6 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 		break;
 	}
 	case R_PPC_COPY:
-		/* This does not work yet, R_PPC_COPY is handled later, see if statemet above */
 		if (symbol_addr) {
 #if defined (__SUPPORT_LD_DEBUG__)
 			if(_dl_debug_move)
@@ -423,7 +368,8 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 	{
 		Elf32_Sword delta = finaladdr - (Elf32_Word)reloc_addr;
 		if(delta<<6>>6 != delta){
-			_dl_dprintf(2, "%s: symbol '%s' R_PPC_REL24 is out of range.\n\tCompile shared libraries with -fPIC!\n",
+			_dl_dprintf(2, "%s: symbol '%s' R_PPC_REL24 is out of range.\n\t"
+					"Compile shared libraries with -fPIC!\n",
 				    _dl_progname, symname);
 			_dl_exit(1);
 		}
@@ -452,48 +398,6 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 	return 0;
 }
 
-/* This is done as a separate step, because there are cases where
-   information is first copied and later initialized.  This results in
-   the wrong information being copied.  Someone at Sun was complaining about
-   a bug in the handling of _COPY by SVr4, and this may in fact be what he
-   was talking about.  Sigh. */
-static int
-_dl_do_copy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
-	     ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
-{
-	int reloc_type;
-	int symtab_index;
-	unsigned long *reloc_addr;
-	unsigned long symbol_addr;
-	int goof = 0;
-	char *symname;
-
-	reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-	reloc_type = ELF32_R_TYPE(rpnt->r_info);
-	if (reloc_type != R_PPC_COPY)
-		return 0;
-	symtab_index = ELF32_R_SYM(rpnt->r_info);
-	symbol_addr = 0;
-	symname      = strtab + symtab[symtab_index].st_name;
-
-	if (symtab_index) {
-		symbol_addr = (unsigned long) _dl_find_hash(symname, scope, NULL, copyrel);
-		if (!symbol_addr) goof++;
-	}
-	if (!goof) {
-#if defined (__SUPPORT_LD_DEBUG__)
-	        if(_dl_debug_move)
-		  _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x",
-			     symname, symtab[symtab_index].st_size,
-			     symbol_addr, symtab[symtab_index].st_value);
-#endif
-			_dl_memcpy((char *) reloc_addr,
-					(char *) (symbol_addr + (unsigned long)rpnt->r_addend), symtab[symtab_index].st_size);
-	}
-
-	return goof;
-}
-
 void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
 	unsigned long rel_addr, unsigned long rel_size, int type)
 {
@@ -538,16 +442,82 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
 	PPC_ISYNC;
 }
 
+static inline int
+_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+	  unsigned long rel_addr, unsigned long rel_size,
+	  int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
+			    ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
+{
+	unsigned int i;
+	char *strtab;
+	Elf32_Sym *symtab;
+	ELF_RELOC *rpnt;
+	int symtab_index;
+
+	/* Now parse the relocation information */
+	rpnt = (ELF_RELOC *)(intptr_t) (rel_addr + tpnt->loadaddr);
+	rel_size = rel_size / sizeof(ELF_RELOC);
+
+	symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
+	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+
+	  for (i = 0; i < rel_size; i++, rpnt++) {
+	        int res;
+
+		symtab_index = ELF32_R_SYM(rpnt->r_info);
+
+		/* When the dynamic linker bootstrapped itself, it resolved some symbols.
+		   Make sure we do not do them again */
+		if (!symtab_index && tpnt->libtype == program_interpreter)
+			continue;
+		if (symtab_index && tpnt->libtype == program_interpreter &&
+		    _dl_symbol(strtab + symtab[symtab_index].st_name))
+			continue;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+		debug_sym(symtab,strtab,symtab_index);
+		debug_reloc(symtab,strtab,rpnt);
+#endif
+
+		res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
+
+		if (res==0) continue;
+
+		_dl_dprintf(2, "\n%s: ",_dl_progname);
+
+		if (symtab_index)
+		  _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
+
+		if (res <0)
+		{
+		        int reloc_type = ELF32_R_TYPE(rpnt->r_info);
+#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(-res);
+		}
+		else if (res >0)
+		{
+			_dl_dprintf(2, "can't resolve symbol\n");
+			return res;
+		}
+	  }
+	  return 0;
+}
+
 int _dl_parse_relocation_information(struct dyn_elf *rpnt,
 	unsigned long rel_addr, unsigned long rel_size, int type)
 {
-	return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+	return _dl_parse(rpnt->dyn, rpnt, rel_addr, rel_size, _dl_do_reloc);
 }
 
+/* Should be a static inline instead, but that conflicts with ld_elf.h */
 int _dl_parse_copy_information(struct dyn_elf *rpnt,
 	unsigned long rel_addr, unsigned long rel_size, int type)
 {
-	return _dl_parse(rpnt->dyn, rpnt->next, rel_addr, rel_size, _dl_do_copy_reloc);
+	/* Not used! */
+	return 0;
 }
 
-