[uClibc] buildroot in an uClibc env

Joakim Tjernlund joakim.tjernlund at lumentis.se
Thu Feb 12 19:07:20 UTC 2004


> Hello!
> 
> I have successfully finished (almost) a buildroot in an uClibc env 
> (minimal: busybox, tinylogin, gcc_3_3_target, 
> binutils_target), only the 
> last step running genext2fs segfaults (nothing changed in the main 
> Makefile, all snapshots and buildroot are from 20040212 (unless the 
> __LIBDL_SHARED__ changes in uClibc)
> 
> Peter

Hi Peter

I have just sent Erik a few fixes for ldso(against current CVS).
You can try and see if it gets better.

I have only tested powerpc, but the arch changes were quite simple.

 Jocke

Index: include/dl-elf.h
===================================================================
RCS file: /var/cvs/uClibc/ldso/include/dl-elf.h,v
retrieving revision 1.9
diff -u -b -B -w -p -r1.9 dl-elf.h
--- include/dl-elf.h	10 Feb 2004 09:26:46 -0000	1.9
+++ include/dl-elf.h	12 Feb 2004 16:30:55 -0000
@@ -92,6 +92,19 @@ extern int _dl_fixup(struct dyn_elf *rpn
 # define UNSUPPORTED_RELOC_STR	"RELA"
 #endif
 
+/* Reloc type classes as returned by elf_machine_type_class().
+   ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by
+   some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be
+   satisfied by any symbol in the executable.  Some architectures do
+   not support copy relocations.  In this case we define the macro to
+   zero so that the code for handling them gets automatically optimized
+   out.  */
+#define ELF_RTYPE_CLASS_PLT 1
+#ifndef DL_NO_COPY_RELOCS
+# define ELF_RTYPE_CLASS_COPY 2
+#else
+# define ELF_RTYPE_CLASS_COPY 0
+#endif
 
 
 /* Convert between the Linux flags for page protections and the
Index: include/dl-hash.h
===================================================================
RCS file: /var/cvs/uClibc/ldso/include/dl-hash.h,v
retrieving revision 1.3
diff -u -b -B -w -p -r1.3 dl-hash.h
--- include/dl-hash.h	10 Feb 2004 11:47:57 -0000	1.3
+++ include/dl-hash.h	12 Feb 2004 16:30:55 -0000
@@ -67,9 +67,8 @@ extern struct elf_resolve * _dl_add_elf_
 	char * loadaddr, unsigned long * dynamic_info, 
 	unsigned long dynamic_addr, unsigned long dynamic_size);
 
-enum caller_type{symbolrel=0,copyrel=1,resolver=2};
 extern char * _dl_find_hash(const char * name, struct dyn_elf * rpnt1, 
-	struct elf_resolve * f_tpnt, enum caller_type);
+			    int type_class);
 
 extern int _dl_linux_dynamic_link(void);
 
Index: ldso/dl-elf.c
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/dl-elf.c,v
retrieving revision 1.65
diff -u -b -B -w -p -r1.65 dl-elf.c
--- ldso/dl-elf.c	10 Feb 2004 06:54:27 -0000	1.65
+++ ldso/dl-elf.c	12 Feb 2004 16:30:56 -0000
@@ -255,12 +255,13 @@ struct elf_resolve *_dl_load_shared_libr
 	if (pnt1) {
 		libname = pnt1 + 1;
 	}
-
+#if 0
 	/* Critical step!  Weed out duplicates early to avoid
 	 * function aliasing, which wastes memory, and causes
 	 * really bad things to happen with weaks and globals. */
 	if ((tpnt1=_dl_check_if_named_library_is_loaded(libname, trace_loaded_objects))!=NULL)
 		return tpnt1;
+#endif
 
 #if defined (__SUPPORT_LD_DEBUG__)
 	if(_dl_debug) _dl_dprintf(_dl_debug_file, "\tfind library='%s'; searching\n", libname);
Index: ldso/dl-hash.c
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/dl-hash.c,v
retrieving revision 1.17
diff -u -b -B -w -p -r1.17 dl-hash.c
--- ldso/dl-hash.c	10 Feb 2004 11:47:57 -0000	1.17
+++ ldso/dl-hash.c	12 Feb 2004 16:30:56 -0000
@@ -154,7 +154,7 @@ struct elf_resolve *_dl_add_elf_hash_tab
  * relocations or when we call an entry in the PLT table for the first time.
  */
 char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,
-	struct elf_resolve *f_tpnt, enum caller_type caller_type)
+		    int type_class)
 {
 	struct elf_resolve *tpnt;
 	int si;
@@ -163,23 +163,12 @@ char *_dl_find_hash(const char *name, st
 	Elf32_Sym *symtab;
 	unsigned long elf_hash_number, hn;
 	char *weak_result;
-	struct dyn_elf *rpnt, first;
+	struct dyn_elf *rpnt;
 	const ElfW(Sym) *sym;
 
 	weak_result = 0;
 	elf_hash_number = _dl_elf_hash(name);
 
-	/* A quick little hack to make sure that any symbol in the executable
-	   will be preferred to one in a shared library.  This is necessary so
-	   that any shared library data symbols referenced in the executable
-	   will be seen at the same address by the executable, shared libraries
-	   and dynamically loaded code. -Rob Ryan (robr at cmu.edu) */
-	if (_dl_symbol_tables && rpnt1) {
-		first = (*_dl_symbol_tables);
-		first.next = rpnt1;
-		rpnt1 = (&first);
-	}
-
 	/*
 	 * The passes are so that we can first search the regular symbols
 	 * for whatever module was specified, and then search anything
@@ -187,39 +176,35 @@ char *_dl_find_hash(const char *name, st
 	 * starting the first dlopened module, and anything above that
 	 * is just the next one in the chain.
 	 */
+	if (rpnt1 == NULL)
+		rpnt1 = _dl_symbol_tables;
+
 	for (pass = 0; (1 == 1); pass++) {
 
 		/*
 		 * If we are just starting to search for RTLD_GLOBAL, setup
 		 * the pointer for the start of the search.
 		 */
-		if (pass == 1) {
+		if (pass == 1)
 			rpnt1 = _dl_handles;
-		}
 
 		/*
 		 * Anything after this, we need to skip to the next module.
 		 */
-		else if (pass >= 2) {
+		else if (pass >= 2)
 			rpnt1 = rpnt1->next_handle;
-		}
 
 		/*
-		 * Make sure we still have a module, and make sure that this
-		 * module was loaded with RTLD_GLOBAL.
+		 * Make sure we still have a module.
 		 */
-		if (pass != 0) {
 			if (rpnt1 == NULL)
 				break;
-			//if ((rpnt1->flags & RTLD_GLOBAL) == 0)
-				//continue;
-		}
 
-		for (rpnt = (rpnt1 ? rpnt1 : _dl_symbol_tables); rpnt; rpnt = rpnt->next) {
+		for (rpnt = rpnt1; rpnt; rpnt = rpnt->next) {
 			tpnt = rpnt->dyn;
 
 			/* Don't search the executable when resolving a copy reloc. */
-			if (tpnt->libtype == elf_executable && caller_type == copyrel)
+			if ((type_class &  ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable)
 				continue;
 
 			/*
@@ -236,19 +221,25 @@ char *_dl_find_hash(const char *name, st
 					continue;
 				if (ELF32_ST_TYPE(sym->st_info) > STT_FUNC)
 					continue;
-				if (sym->st_shndx == SHN_UNDEF && caller_type != copyrel)
+				if (type_class & (sym->st_shndx == SHN_UNDEF))
 					continue;
 				if (_dl_strcmp(strtab + sym->st_name, name) != 0)
 					continue;
 
 				switch (ELF32_ST_BIND(sym->st_info)) {
 					case STB_WEAK:
-//Disable this to match current glibc behavior.  Of course,
-//this doesn't actually work yet and will cause segfaults...
-#if 1
+#ifndef __LIBDL_SHARED__
+/* 
+Due to a special hack in libdl.c, one must handle the _dl_ symbols
+according to the OLD weak symbol scheme. This stuff can be deleted
+once that hack has been fixed.
+*/
+
+						if(_dl_symbol((char *)name)) {
 						if (!weak_result)
 							weak_result = (char *)tpnt->loadaddr + sym->st_value;
 						break;
+						}
 #endif
 					case STB_GLOBAL:
 						return (char*)tpnt->loadaddr + sym->st_value;
Index: ldso/dl-startup.c
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/dl-startup.c,v
retrieving revision 1.5
diff -u -b -B -w -p -r1.5 dl-startup.c
--- ldso/dl-startup.c	10 Feb 2004 13:31:43 -0000	1.5
+++ ldso/dl-startup.c	12 Feb 2004 16:30:56 -0000
@@ -513,11 +513,10 @@ found_got:
 				/* We only do a partial dynamic linking right now.  The user
 				   is not supposed to define any symbols that start with a
 				   '_dl', so we can do this with confidence. */
-				if (!symname || symname[0] != '_' ||
-						symname[1] != 'd' || symname[2] != 'l' || symname[3] != '_')
-				{
+				if (!symname || !_dl_symbol(symname)) {
 					continue;
 				}
+
 				symbol_addr = load_addr + symtab[symtab_index].st_value;
 
 				if (!symbol_addr) {
Index: ldso/ldso.c
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/ldso.c,v
retrieving revision 1.92
diff -u -b -B -w -p -r1.92 ldso.c
--- ldso/ldso.c	10 Feb 2004 13:31:43 -0000	1.92
+++ ldso/ldso.c	12 Feb 2004 16:30:56 -0000
@@ -609,12 +609,12 @@ void _dl_get_ready_to_run(struct elf_res
 	   up each symbol individually. */
 
 
-	_dl_brkp = (unsigned long *) (intptr_t) _dl_find_hash("___brk_addr", NULL, NULL, symbolrel);
+	_dl_brkp = (unsigned long *) (intptr_t) _dl_find_hash("___brk_addr", NULL, 0);
 
 	if (_dl_brkp) {
 		*_dl_brkp = brk_addr;
 	}
-	_dl_envp = (unsigned long *) (intptr_t) _dl_find_hash("__environ", NULL, NULL, symbolrel);
+	_dl_envp = (unsigned long *) (intptr_t) _dl_find_hash("__environ", NULL, 0);
 
 	if (_dl_envp) {
 		*_dl_envp = (unsigned long) envp;
@@ -638,10 +638,10 @@ void _dl_get_ready_to_run(struct elf_res
 
 	}
 #endif
-	_dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", NULL, NULL, symbolrel);
+	_dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", NULL, 0);
 #if defined (__SUPPORT_LD_DEBUG__)
 	_dl_on_exit = (int (*)(void (*)(int, void *),void*))
-		(intptr_t) _dl_find_hash("on_exit", NULL, NULL, symbolrel);
+		(intptr_t) _dl_find_hash("on_exit", NULL, 0);
 #endif
 
 	/* Notify the debugger we have added some objects. */
Index: ldso/arm/dl-sysdep.h
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/arm/dl-sysdep.h,v
retrieving revision 1.7
diff -u -b -B -w -p -r1.7 dl-sysdep.h
--- ldso/arm/dl-sysdep.h	17 Dec 2003 08:05:40 -0000	1.7
+++ ldso/arm/dl-sysdep.h	12 Feb 2004 16:30:56 -0000
@@ -122,3 +122,11 @@ static inline unsigned long arm_modulus(
 #define PAGE_ALIGN 0xfffff000
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+   PLT entries should not be allowed to define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_ARM_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT)	\
+   | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY))
Index: ldso/arm/elfinterp.c
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/arm/elfinterp.c,v
retrieving revision 1.18
diff -u -b -B -w -p -r1.18 elfinterp.c
--- ldso/arm/elfinterp.c	29 Jan 2004 12:18:51 -0000	1.18
+++ ldso/arm/elfinterp.c	12 Feb 2004 16:30:56 -0000
@@ -148,7 +148,7 @@ unsigned long _dl_linux_resolver(struct 
 
 	/* Get the address of the GOT entry */
 	new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
-		tpnt->symbol_scope, tpnt, resolver);
+		tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
 	if (!new_addr) {
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
 			_dl_progname, strtab + symtab[symtab_index].st_name);
@@ -283,7 +283,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,s
 	if (symtab_index) {
 
 		symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
-				scope, (reloc_type == R_ARM_JUMP_SLOT ? tpnt : NULL), symbolrel);
+				scope, elf_machine_type_class(reloc_type));
 
 		/*
 		 * We want to allow undefined references to weak symbols - this might
@@ -424,7 +424,7 @@ _dl_do_copy_reloc (struct elf_resolve *t
 
 		symbol_addr = (unsigned long) _dl_find_hash(strtab +
 			symtab[symtab_index].st_name, scope,
-			NULL, copyrel);
+			ELF_RTYPE_CLASS_COPY);
 		if (!symbol_addr) goof++;
 	}
 	if (!goof) {
Index: ldso/cris/dl-sysdep.h
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/cris/dl-sysdep.h,v
retrieving revision 1.4
diff -u -b -B -w -p -r1.4 dl-sysdep.h
--- ldso/cris/dl-sysdep.h	10 Feb 2004 09:26:48 -0000	1.4
+++ ldso/cris/dl-sysdep.h	12 Feb 2004 16:30:56 -0000
@@ -110,3 +110,19 @@ cris_mod(unsigned long m, unsigned long 
 #define PAGE_ALIGN 0xffffe000
 #define ADDR_ALIGN 0x1fff
 #define OFFS_ALIGN 0xffffe000
+
+/* The union of reloc-type-classes where the reloc TYPE is a member.
+
+   TYPE is in the class ELF_RTYPE_CLASS_PLT if it can describe a
+   relocation for a PLT entry, that is, for which a PLT entry should not
+   be allowed to define the value.  The GNU linker for CRIS can merge a
+   .got.plt entry (R_CRIS_JUMP_SLOT) with a .got entry (R_CRIS_GLOB_DAT),
+   so we need to match both these reloc types.
+
+   TYPE is in the class ELF_RTYPE_CLASS_NOCOPY if it should not be allowed
+   to resolve to one of the main executable's symbols, as for a COPY
+   reloc.  */
+#define elf_machine_type_class(type)				\
+  ((((((type) == R_CRIS_JUMP_SLOT))				\
+     || ((type) == R_CRIS_GLOB_DAT)) * ELF_RTYPE_CLASS_PLT)	\
+   | (((type) == R_CRIS_COPY) * ELF_RTYPE_CLASS_COPY))
Index: ldso/cris/elfinterp.c
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/cris/elfinterp.c,v
retrieving revision 1.7
diff -u -b -B -w -p -r1.7 elfinterp.c
--- ldso/cris/elfinterp.c	29 Jan 2004 12:18:51 -0000	1.7
+++ ldso/cris/elfinterp.c	12 Feb 2004 16:30:56 -0000
@@ -142,10 +142,10 @@ _dl_linux_resolver(struct elf_resolve *t
 	got_addr = (char **) instr_addr;
 
 	/* Fetch the address of the GOT entry. */
-	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, resolver);
+	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
 
 	if (!new_addr) {
-		new_addr = _dl_find_hash(symname, NULL, NULL, resolver);
+		new_addr = _dl_find_hash(symname, NULL, ELF_RTYPE_CLASS_PLT);
 
 		if (new_addr)
 			return (unsigned long) new_addr;
@@ -261,7 +261,7 @@ _dl_do_reloc(struct elf_resolve *tpnt, s
 		}
 		else {
 			symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
-				(reloc_type == R_CRIS_JUMP_SLOT ? tpnt : NULL), symbolrel);
+								    elf_machine_type_class(reloc_type));
 		}
 
 		if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
@@ -366,7 +366,7 @@ _dl_do_copy_reloc(struct elf_resolve *tp
 	goof = 0;
 
 	if (symtab_index) {
-		symbol_addr = (unsigned long) _dl_find_hash(symname, scope, NULL, copyrel);
+		symbol_addr = (unsigned long) _dl_find_hash(symname, scope, ELF_RTYPE_CLASS_COPY);
 
 		if (!symbol_addr)
 			goof++;
Index: ldso/i386/dl-sysdep.h
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/i386/dl-sysdep.h,v
retrieving revision 1.9
diff -u -b -B -w -p -r1.9 dl-sysdep.h
--- ldso/i386/dl-sysdep.h	17 Dec 2003 08:05:41 -0000	1.9
+++ ldso/i386/dl-sysdep.h	12 Feb 2004 16:30:56 -0000
@@ -79,3 +79,12 @@ extern unsigned long _dl_linux_resolver(
 #define PAGE_ALIGN 0xfffff000
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+   TLS variable, so undefined references should not be allowed to
+   define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_386_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)			      \
+   | (((type) == R_386_COPY) * ELF_RTYPE_CLASS_COPY))
Index: ldso/i386/elfinterp.c
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/i386/elfinterp.c,v
retrieving revision 1.29
diff -u -b -B -w -p -r1.29 elfinterp.c
--- ldso/i386/elfinterp.c	7 Feb 2004 10:40:16 -0000	1.29
+++ ldso/i386/elfinterp.c	12 Feb 2004 16:30:56 -0000
@@ -145,9 +145,9 @@ unsigned long _dl_linux_resolver(struct 
 	got_addr = (char **) instr_addr;
 
 	/* Get the address of the GOT entry */
-	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, resolver);
+	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
 	if (!new_addr) {
-		new_addr = _dl_find_hash(symname, NULL, NULL, resolver);
+		new_addr = _dl_find_hash(symname, NULL, ELF_RTYPE_CLASS_PLT);
 		if (new_addr) {
 			return (unsigned long) new_addr;
 		}
@@ -263,7 +263,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,s
 	if (symtab_index) {
 
 		symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
-				(reloc_type == R_386_JMP_SLOT ? tpnt : NULL), symbolrel);
+							    elf_machine_type_class(reloc_type));
 
 		/*
 		 * We want to allow undefined references to weak symbols - this might
@@ -377,7 +377,7 @@ _dl_do_copy_reloc (struct elf_resolve *t
 	symname      = strtab + symtab[symtab_index].st_name;
 
 	if (symtab_index) {
-		symbol_addr = (unsigned long) _dl_find_hash(symname, scope, NULL, copyrel);
+		symbol_addr = (unsigned long) _dl_find_hash(symname, scope, ELF_RTYPE_CLASS_COPY);
 		if (!symbol_addr) goof++;
 	}
 	if (!goof) {
Index: ldso/m68k/dl-sysdep.h
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/m68k/dl-sysdep.h,v
retrieving revision 1.4
diff -u -b -B -w -p -r1.4 dl-sysdep.h
--- ldso/m68k/dl-sysdep.h	17 Dec 2003 08:05:41 -0000	1.4
+++ ldso/m68k/dl-sysdep.h	12 Feb 2004 16:30:56 -0000
@@ -86,3 +86,11 @@ extern unsigned int _dl_linux_resolver (
 #define PAGE_ALIGN 0xfffff000
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+   PLT entries should not be allowed to define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_68K_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)	\
+   | (((type) == R_68K_COPY) * ELF_RTYPE_CLASS_COPY))
Index: ldso/m68k/elfinterp.c
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/m68k/elfinterp.c,v
retrieving revision 1.15
diff -u -b -B -w -p -r1.15 elfinterp.c
--- ldso/m68k/elfinterp.c	29 Jan 2004 12:18:52 -0000	1.15
+++ ldso/m68k/elfinterp.c	12 Feb 2004 16:30:57 -0000
@@ -98,7 +98,7 @@ unsigned int _dl_linux_resolver (int dum
 
   /* Get the address of the GOT entry.  */
   new_addr = _dl_find_hash (strtab + symtab[symtab_index].st_name,
-			    tpnt->symbol_scope, tpnt, resolver);
+			    tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
   if (!new_addr)
     {
       _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
@@ -218,7 +218,7 @@ int _dl_parse_relocation_information(str
 	  symbol_addr = (unsigned int)
 	    _dl_find_hash (strtab + symtab[symtab_index].st_name,
 			   tpnt->symbol_scope,
-			   reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, symbolrel);
+			   elf_machine_type_class(reloc_type));
 
 	  /* We want to allow undefined references to weak symbols -
 	     this might have been intentional.  We should not be
@@ -342,7 +342,7 @@ int _dl_parse_copy_information(struct dy
 	{
 	  symbol_addr = (unsigned int)
 	    _dl_find_hash (strtab + symtab[symtab_index].st_name,
-			   xpnt->next, NULL, copyrel);
+			   xpnt->next, ELF_RTYPE_CLASS_COPY);
 	  if (!symbol_addr)
 	    {
 	      _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
Index: ldso/mips/dl-sysdep.h
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/mips/dl-sysdep.h,v
retrieving revision 1.7
diff -u -b -B -w -p -r1.7 dl-sysdep.h
--- ldso/mips/dl-sysdep.h	17 Dec 2003 08:05:42 -0000	1.7
+++ ldso/mips/dl-sysdep.h	12 Feb 2004 16:30:57 -0000
@@ -134,3 +134,5 @@ unsigned long _dl_linux_resolver(unsigne
 #define PAGE_ALIGN 0xfffff000
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
+
+#define elf_machine_type_class(type)		ELF_RTYPE_CLASS_PLT
Index: ldso/mips/elfinterp.c
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/mips/elfinterp.c,v
retrieving revision 1.9
diff -u -b -B -w -p -r1.9 elfinterp.c
--- ldso/mips/elfinterp.c	5 Feb 2004 01:54:33 -0000	1.9
+++ ldso/mips/elfinterp.c	12 Feb 2004 16:30:57 -0000
@@ -129,7 +129,7 @@ unsigned long _dl_linux_resolver(unsigne
 	symname = strtab + sym->st_name;
 
 	new_addr = (unsigned long) _dl_find_hash(strtab + sym->st_name,
-		 tpnt->symbol_scope, tpnt, resolver);
+		 tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
 
 	/* Address of jump instruction to fix up */
 	instr_addr = (unsigned long) (got + local_gotno + sym_index - gotsym);
@@ -279,12 +279,12 @@ void _dl_perform_mips_global_got_relocat
 					*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, copyrel);
+						sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_COPY);
 				}
 			}
 			else if (sym->st_shndx == SHN_COMMON) {
 				*got_entry = (unsigned long) _dl_find_hash(strtab +
-					sym->st_name, tpnt->symbol_scope, NULL, copyrel);
+					sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_COPY);
 			}
 			else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&
 				*got_entry != sym->st_value)
@@ -295,7 +295,7 @@ void _dl_perform_mips_global_got_relocat
 			}
 			else {
 				*got_entry = (unsigned long) _dl_find_hash(strtab +
-					sym->st_name, tpnt->symbol_scope, NULL, copyrel);
+					sym->st_name, tpnt->symbol_scope, ELF_RTYPE_CLASS_COPY);
 			}
 
 			got_entry++;
Index: ldso/powerpc/dl-sysdep.h
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/powerpc/dl-sysdep.h,v
retrieving revision 1.9
diff -u -b -B -w -p -r1.9 dl-sysdep.h
--- ldso/powerpc/dl-sysdep.h	29 Jan 2004 08:20:11 -0000	1.9
+++ ldso/powerpc/dl-sysdep.h	12 Feb 2004 16:30:57 -0000
@@ -125,3 +125,16 @@ void _dl_init_got(unsigned long *lpnt,st
 #define PAGE_ALIGN 0xfffff000
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+   PLT entries should not be allowed to define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+/* We never want to use a PLT entry as the destination of a
+   reloc, when what is being relocated is a branch. This is
+   partly for efficiency, but mostly so we avoid loops.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_PPC_JMP_SLOT				\
+    || (type) == R_PPC_REL24				\
+    || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT)	\
+   | (((type) == R_PPC_COPY) * ELF_RTYPE_CLASS_COPY))
Index: ldso/powerpc/elfinterp.c
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/powerpc/elfinterp.c,v
retrieving revision 1.36
diff -u -b -B -w -p -r1.36 elfinterp.c
--- ldso/powerpc/elfinterp.c	31 Jan 2004 03:15:07 -0000	1.36
+++ ldso/powerpc/elfinterp.c	12 Feb 2004 16:30:57 -0000
@@ -210,7 +210,7 @@ unsigned long _dl_linux_resolver(struct 
 
 	/* Get the address of the GOT entry */
 	finaladdr = (Elf32_Addr) _dl_find_hash(strtab + symtab[symtab_index].st_name,
-						tpnt->symbol_scope, tpnt, resolver);
+					       tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
 	if (!finaladdr) {
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
 		_dl_exit(1);
@@ -223,11 +223,8 @@ unsigned long _dl_linux_resolver(struct 
 	delta = finaladdr - (Elf32_Word)reloc_addr;
 	if (delta<<6>>6 == delta) {
 		*reloc_addr = OPCODE_B(delta);
-#if 0
-	/* this will almost never be true */
-	} else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000) {
+	} else if (finaladdr <= 0x01fffffc) {
 		*reloc_addr = OPCODE_BA (finaladdr);
-#endif
 	} else {
 		/* Warning: we don't handle double-sized PLT entries */
 		Elf32_Word *plt, *data_words, index, offset;
@@ -261,7 +258,6 @@ _dl_do_reloc (struct elf_resolve *tpnt,s
 	char *symname;
 	Elf32_Addr *reloc_addr;
 	Elf32_Addr finaladdr;
-	struct dyn_elf *sym_scope;
 
 	unsigned long symbol_addr;
 #if defined (__SUPPORT_LD_DEBUG__)
@@ -278,19 +274,8 @@ _dl_do_reloc (struct elf_resolve *tpnt,s
 	symtab_index = ELF32_R_SYM(rpnt->r_info);
 	symname      = strtab + symtab[symtab_index].st_name;
 
-#if 1
-	sym_scope = scope->dyn->symbol_scope;
-#else
-	/* Funny, this works too and appears to be much faster. */
-	sym_scope = scope;
-#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));
+	symbol_addr = (unsigned long) _dl_find_hash(symname, scope->dyn->symbol_scope,
+						    elf_machine_type_class(reloc_type));
 	/*
 	 * We want to allow undefined references to weak symbols - this might
 	 * have been intentional.  We should not be linking local symbols
@@ -320,11 +305,8 @@ _dl_do_reloc (struct elf_resolve *tpnt,s
 
 		if (delta<<6>>6 == delta) {
 			*reloc_addr = OPCODE_B(delta);
-#if 0
-		/* this will almost never be true */
-		} else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000) {
+		} else if (finaladdr <= 0x01fffffc) {
 			*reloc_addr = OPCODE_BA (finaladdr);
-#endif
 		} else {
 			/* Warning: we don't handle double-sized PLT entries */
 			Elf32_Word *plt, *data_words, index, offset;
Index: ldso/sh/dl-sysdep.h
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/sh/dl-sysdep.h,v
retrieving revision 1.8
diff -u -b -B -w -p -r1.8 dl-sysdep.h
--- ldso/sh/dl-sysdep.h	17 Dec 2003 08:05:43 -0000	1.8
+++ ldso/sh/dl-sysdep.h	12 Feb 2004 16:30:57 -0000
@@ -142,3 +142,12 @@ _dl_urem(unsigned int n, unsigned int ba
 #define PAGE_ALIGN 0xfffff000
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+   TLS variable, so undefined references should not be allowed to
+   define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_SH_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)	\
+   | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY))
Index: ldso/sh/elfinterp.c
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/sh/elfinterp.c,v
retrieving revision 1.8
diff -u -b -B -w -p -r1.8 elfinterp.c
--- ldso/sh/elfinterp.c	29 Jan 2004 12:18:55 -0000	1.8
+++ ldso/sh/elfinterp.c	12 Feb 2004 16:30:57 -0000
@@ -149,9 +149,9 @@ unsigned long _dl_linux_resolver(struct 
 
 
 	/* Get the address of the GOT entry */
-	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, resolver);
+	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
 	if (!new_addr) {
-		new_addr = _dl_find_hash(symname, NULL, NULL, resolver);
+		new_addr = _dl_find_hash(symname, NULL, ELF_RTYPE_CLASS_PLT);
 		if (new_addr) {
 			return (unsigned long) new_addr;
 		}
@@ -270,7 +270,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,s
 
 
 		symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
-				(reloc_type == R_SH_JMP_SLOT ? tpnt : NULL), symbolrel);
+							    elf_machine_type_class(reloc_type));
 
 		/*
 		 * We want to allow undefined references to weak symbols - this might
@@ -385,7 +385,7 @@ _dl_do_copy_reloc (struct elf_resolve *t
 
 	if (symtab_index) {
 
-		symbol_addr = (unsigned long) _dl_find_hash(symname, scope, NULL, copyrel);
+		symbol_addr = (unsigned long) _dl_find_hash(symname, scope, ELF_RTYPE_CLASS_COPY);
 		if (!symbol_addr) goof++;
 	}
 	if (!goof) {
Index: ldso/sh64/dl-sysdep.h
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/sh64/dl-sysdep.h,v
retrieving revision 1.1
diff -u -b -B -w -p -r1.1 dl-sysdep.h
--- ldso/sh64/dl-sysdep.h	17 Dec 2003 08:07:14 -0000	1.1
+++ ldso/sh64/dl-sysdep.h	12 Feb 2004 16:30:57 -0000
@@ -168,3 +168,11 @@ extern unsigned long _dl_linux_resolver(
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
 
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+   TLS variable, so undefined references should not be allowed to
+   define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_SH_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)	\
+   | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY))
Index: ldso/sh64/elfinterp.c
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/sh64/elfinterp.c,v
retrieving revision 1.2
diff -u -b -B -w -p -r1.2 elfinterp.c
--- ldso/sh64/elfinterp.c	29 Jan 2004 12:18:56 -0000	1.2
+++ ldso/sh64/elfinterp.c	12 Feb 2004 16:30:57 -0000
@@ -190,9 +190,9 @@ unsigned long _dl_linux_resolver(struct 
 
 
 	/* Get the address of the GOT entry */
-	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, resolver);
+	new_addr = _dl_find_hash(symname, tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
 	if (!new_addr) {
-		new_addr = _dl_find_hash(symname, NULL, NULL, resolver);
+		new_addr = _dl_find_hash(symname, NULL, ELF_RTYPE_CLASS_PLT);
 
 		if (new_addr)
 			return (unsigned long)new_addr;
@@ -319,8 +319,7 @@ static int _dl_do_reloc(struct elf_resol
 		int stb;
 
 		symbol_addr = (unsigned long)_dl_find_hash(symname, scope,
-				(reloc_type == R_SH_JMP_SLOT ? tpnt : NULL),
-				 symbolrel);
+							   elf_machine_type_class(reloc_type));
 
 		/*
 		 * We want to allow undefined references to weak symbols - this
@@ -492,7 +491,7 @@ static int _dl_do_copy_reloc(struct elf_
 
 	if (symtab_index) {
 		symbol_addr = (unsigned long)
-			_dl_find_hash(symname, scope, NULL, copyrel);
+			_dl_find_hash(symname, scope, ELF_RTYPE_CLASS_COPY);
 
 		if (!symbol_addr)
 			goof++;
Index: ldso/sparc/dl-sysdep.h
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/sparc/dl-sysdep.h,v
retrieving revision 1.5
diff -u -b -B -w -p -r1.5 dl-sysdep.h
--- ldso/sparc/dl-sysdep.h	17 Dec 2003 08:05:44 -0000	1.5
+++ ldso/sparc/dl-sysdep.h	12 Feb 2004 16:30:57 -0000
@@ -110,3 +110,11 @@ extern unsigned int _dl_linux_resolver(u
 #define PAGE_ALIGN 0xfffff000
 #define ADDR_ALIGN 0xfff
 #define OFFS_ALIGN 0x7ffff000
+
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
+   PLT entries should not be allowed to define the value.
+   ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
+   of the main executable's symbols, as for a COPY reloc.  */
+#define elf_machine_type_class(type) \
+  ((((type) == R_SPARC_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)			      \
+   | (((type) == R_SPARC_COPY) * ELF_RTYPE_CLASS_COPY))
Index: ldso/sparc/elfinterp.c
===================================================================
RCS file: /var/cvs/uClibc/ldso/ldso/sparc/elfinterp.c,v
retrieving revision 1.14
diff -u -b -B -w -p -r1.14 elfinterp.c
--- ldso/sparc/elfinterp.c	29 Jan 2004 12:18:58 -0000	1.14
+++ ldso/sparc/elfinterp.c	12 Feb 2004 16:30:57 -0000
@@ -109,7 +109,7 @@ unsigned int _dl_linux_resolver(unsigned
 
   /* Get the address of the GOT entry */
   new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
-  			tpnt->symbol_scope, tpnt, resolver);
+  			tpnt->symbol_scope, ELF_RTYPE_CLASS_PLT);
   if(!new_addr) {
     _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
 	       _dl_progname, strtab + symtab[symtab_index].st_name);
@@ -225,8 +225,7 @@ int _dl_parse_relocation_information(str
 
       symbol_addr = (unsigned int)
 	_dl_find_hash(strtab + symtab[symtab_index].st_name,
-			      tpnt->symbol_scope,
-		      (reloc_type == R_SPARC_JMP_SLOT ? tpnt : NULL), symbolrel);
+		      tpnt->symbol_scope, elf_machine_type_class(reloc_type);
 
       if(!symbol_addr &&
 	 ELF32_ST_BIND(symtab [symtab_index].st_info) == STB_GLOBAL) {
@@ -343,7 +342,7 @@ int _dl_parse_copy_information(struct dy
 
       symbol_addr = (unsigned int)
 	_dl_find_hash(strtab + symtab[symtab_index].st_name,
-			      xpnt->next, NULL, copyrel);
+		      xpnt->next,  ELF_RTYPE_CLASS_COPY);
       if(!symbol_addr) {
 	_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
 		   _dl_progname, strtab + symtab[symtab_index].st_name);
Index: libdl/libdl.c
===================================================================
RCS file: /var/cvs/uClibc/ldso/libdl/libdl.c,v
retrieving revision 1.38
diff -u -b -B -w -p -r1.38 libdl.c
--- libdl/libdl.c	12 Feb 2004 08:51:21 -0000	1.38
+++ libdl/libdl.c	12 Feb 2004 16:30:57 -0000
@@ -30,7 +30,7 @@ static void __attribute__ ((unused)) foo
 
 static int __attribute__ ((unused)) foobar1 = (int) foobar;	/* Use as pointer */
 extern void _dl_dprintf(int, const char *, ...) __attribute__ ((__weak__, __alias__ ("foobar")));
-extern char *_dl_find_hash(const char *, struct dyn_elf *, struct elf_resolve *, enum caller_type)
+extern char *_dl_find_hash(const char *, struct dyn_elf *, int)
 	__attribute__ ((__weak__, __alias__ ("foobar")));
 extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **, struct elf_resolve *, char *, int)
 	__attribute__ ((__weak__, __alias__ ("foobar")));
@@ -179,6 +179,7 @@ void *_dlopen(const char *libname, int f
 	if(_dl_debug) 
 	_dl_dprintf(_dl_debug_file, "Trying to dlopen '%s'\n", (char*)libname);
 #endif
+	if (!(tpnt = _dl_check_if_named_library_is_loaded((char *)libname, 0)))
 	tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname, 0);
 	if (tpnt == NULL) {
 		_dl_unmap_cache();
@@ -220,6 +221,9 @@ void *_dlopen(const char *libname, int f
 					dpnt->d_un.d_val);
 				name = _dl_get_last_path_component(lpntstr);
 
+				if ((tpnt1 = _dl_check_if_named_library_is_loaded(name, 0)))
+					continue;
+
 #ifdef __SUPPORT_LD_DEBUG__
 				if(_dl_debug) 
 				_dl_dprintf(_dl_debug_file, "Trying to load '%s', needed by '%s'\n", 
@@ -381,7 +385,7 @@ void *_dlsym(void *vhandle, const char *
 		}
 	}
 
-	ret = _dl_find_hash((char*)name, handle, NULL, copyrel);
+	ret = _dl_find_hash((char*)name, handle, 0);
 
 	/*
 	 * Nothing found.




More information about the uClibc mailing list