Browse Source

Patch from Stefan Allius and Edie C. Dost to add SuperH
shared library support. This also adds some cleaner error
handling, which I (Erik) then ported over to x86 and arm.
In addition Stefan added the following fixes:

- in hash.c was the lvalue handling of global library functions wrong.
To fix this I had to change the prototype of _dl_find_hash. (==> TIS and
ELF spec. Vers. 1.2)

- in ldso.c was the order of the .init sections calls wrong. Before we call
the initialization code of a library we have to check that all dependend
libraries are already initialized. This can easily made by calling it in the
revers loading order. For this I added a previous pointer chain.

- in ldso.c the ELF magics wasn't checked fo PPC, MIPS and SH architecture

Eric Andersen 22 years ago
parent
commit
9cba52f0ae

+ 28 - 6
ldso/ldso/Makefile

@@ -31,13 +31,35 @@ LDSO_FULLNAME=ld-uClibc-$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL).so
 # (i.e. where the shared library loader does all the heavy lifting)
 # Since this currently only saves about 300 bytes, I'm going to leave 
 # it enabled...
-XXFLAGS+= -DDL_TRACE
+XXFLAGS+= -DLD_TRACE
 
-# Enable this to enable debugging output from ld.so
-#XXFLAGS+= -DDL_DEBUG
-#XXFLAGS+= -DDL_DEBUG_SYMBOLS
-#Enable this to never actually fixup symbols so you can watch each call...
-#XXFLAGS+= -DDL_NEVER_FIXUP_SYMBOLS
+# Enable this to enable all the code needed for debugging the runtime 
+# linking of an application using the LD_DEBUG environment variable:
+#   LD_DEBUG=token1,token2,..  prog
+# enables diagnostics to the stderr.
+# For now there are these tokens possible:
+#    bindings      displays the resolve processing (function calls); detail shows the relocation patch
+#    detail        provide more information for some options
+#    move          display copy processings
+#    reloc         display relocation processing; detail shows the relocation patch
+#    symbols       display symbol table processing
+#
+# The additional environment variable:
+#    LD_DEBUG_OUTPUT=file
+# redirects the diagnostics to an output file created using
+# the specified name and the process id as a suffix.
+#
+# try this
+# $ LD_DEBUG=binding,move,symbols,reloc,detail LD_DEBUG_OUTPUT=appname ./appname
+#
+#XXFLAGS+= -DSUPPORT_LD_DEBUG
+
+# Enable this for the very very early debugging.  Really only useful
+# for people porting to new architectures.
+#XXFLAGS+= -DLD_DEBUG
+
+# Enable this to never actually fixup symbols...
+#XXFLAGS+= -DLD_NEVER_FIXUP_SYMBOLS
 
 XXFLAGS+=-DUCLIBC_TARGET_PREFIX=\"$(TARGET_PREFIX)\" \
 	-DUCLIBC_DEVEL_PREFIX=\"$(DEVEL_PREFIX)\" \

+ 1 - 1
ldso/ldso/arm/boot1_arch.h

@@ -20,7 +20,7 @@ _dl_boot:
 ");
 
 #define _dl_boot _dl_boot2
-#define DL_BOOT(X)   static void *  __attribute__ ((unused)) _dl_boot (X)
+#define LD_BOOT(X)   static void *  __attribute__ ((unused)) _dl_boot (X)
 
 
  /* It seems ARM needs an offset here */

+ 1 - 1
ldso/ldso/arm/dl-startup.h

@@ -20,7 +20,7 @@ _dl_boot:
 ");
 
 #define _dl_boot _dl_boot2
-#define DL_BOOT(X)   static void *  __attribute__ ((unused)) _dl_boot (X)
+#define LD_BOOT(X)   static void *  __attribute__ ((unused)) _dl_boot (X)
 
 
  /* It seems ARM needs an offset here */

+ 283 - 185
ldso/ldso/arm/elfinterp.c

@@ -1,39 +1,102 @@
-/* Run an ELF binary on a linux system.
-
-   Copyright (C) 1993, Eric Youngdale.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-#ifndef VERBOSE_DLINKER
-#define VERBOSE_DLINKER
-#endif
-#ifdef VERBOSE_DLINKER
-static const char *_dl_reltypes[] =
-	{ "R_ARM_NONE", "R_ARM_PC24", "R_ARM_ABS32", "R_ARM_REL32",
-	"R_ARM_PC13", "R_ARM_ABS16", "R_ARM_ABS12", "R_ARM_THM_ABS5",
-	"R_ARM_ABS8", "R_ARM_SBREL32", "R_ARM_THM_PC22", "R_ARM_THM_PC8",
-	"R_ARM_AMP_VCALL9", "R_ARM_SWI24", "R_ARM_THM_SWI8", "R_ARM_XPC25",
-	"R_ARM_THM_XPC22", "R_ARM_COPY", "R_ARM_GLOB_DAT", "R_ARM_JUMP_SLOT",
-	"R_ARM_RELATIVE", "R_ARM_GOTOFF", "R_ARM_GOTPC", "R_ARM_GOT32",
-	"R_ARM_PLT32", "R_ARM_ALU_PCREL_7_0", "R_ARM_ALU_PCREL_15_8",
-	"R_ARM_ALU_PCREL_23_15", "R_ARM_LDR_SBREL_11_0", "R_ARM_ALU_SBREL_19_12",
-	"R_ARM_ALU_SBREL_27_20", "R_ARM_GNU_VTENTRY", "R_ARM_GNU_VTINHERIT",
-	"R_ARM_THM_PC11", "R_ARM_THM_PC9", "R_ARM_RXPC25", "R_ARM_RSBREL32",
-	"R_ARM_THM_RPC22", "R_ARM_RREL32", "R_ARM_RABS22", "R_ARM_RPC24",
-	"R_ARM_RBASE", "R_ARM_NUM"
+/* vi: set sw=4 ts=4: */
+/* ARM ELF shared library loader suppport
+ *
+ * Copyright (C) 2001-2002, Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_DEBUG_SYMBOLS)
+static const char *_dl_reltypes_tab[] =
+  [0]	"R_ARM_NONE",	    "R_ARM_PC24",	"R_ARM_ABS32",		"R_ARM_REL32",
+  [4]	"R_ARM_PC13",	    "R_ARM_ABS16",	"R_ARM_ABS12",		"R_ARM_THM_ABS5",
+  [8]	"R_ARM_ABS8",		"R_ARM_SBREL32","R_ARM_THM_PC22",	"R_ARM_THM_PC8",
+  [12]	"R_ARM_AMP_VCALL9",	"R_ARM_SWI24",	"R_ARM_THM_SWI8",	"R_ARM_XPC25",
+  [16]	"R_ARM_THM_XPC22",
+  [20]	"R_ARM_COPY",		"R_ARM_GLOB_DAT","R_ARM_JUMP_SLOT",	"R_ARM_RELATIVE",
+  [24]	"R_ARM_GOTOFF",		"R_ARM_GOTPC",	 "R_ARM_GOT32",		"R_ARM_PLT32",
+  [32]	"R_ARM_ALU_PCREL_7_0","R_ARM_ALU_PCREL_15_8","R_ARM_ALU_PCREL_23_15","R_ARM_LDR_SBREL_11_0",
+  [36]	"R_ARM_ALU_SBREL_19_12","R_ARM_ALU_SBREL_27_20",
+  [100]	"R_ARM_GNU_VTENTRY","R_ARM_GNU_VTINHERIT","R_ARM_THM_PC11","R_ARM_THM_PC9",
+  [249] "R_ARM_RXPC25", "R_ARM_RSBREL32", "R_ARM_THM_RPC22", "R_ARM_RREL32",
+  [253] "R_ARM_RABS22", "R_ARM_RPC24", "R_ARM_RBASE",
 };
+
+static const char *
+_dl_reltypes(int type)
+{
+  static char buf[22];  
+  const char *str;
+  
+  if (type >= (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\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";
+    
+#ifdef ELF_USES_RELOCA
+    _dl_dprintf(_dl_debug_file, "\n%s\toffset=%x\taddend=%x %s",
+		_dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
+		rpnt->r_offset,
+		rpnt->r_addend,
+		sym);
+#else
+    _dl_dprintf(_dl_debug_file, "\n%s\toffset=%x %s",
+		_dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
+		rpnt->r_offset,
+		sym);
+#endif
+  }
+}
 #endif
 
 /* Program to load an ELF binary on a linux system, and run it.
@@ -47,22 +110,21 @@ static const char *_dl_reltypes[] =
    a more than adequate job of explaining everything required to get this
    working. */
 
-
 extern int _dl_linux_resolve(void);
 
 unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 {
 	int reloc_type;
-	Elf32_Rel *this_reloc;
+	ELF_RELOC *this_reloc;
 	char *strtab;
 	Elf32_Sym *symtab;
-	Elf32_Rel *rel_addr;
+	ELF_RELOC *rel_addr;
 	int symtab_index;
 	char *new_addr;
 	char **got_addr;
 	unsigned long instr_addr;
 
-	rel_addr = (Elf32_Rel *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
+	rel_addr = (ELF_RELOC *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
 
 	this_reloc = rel_addr + (reloc_entry >> 3);
 	reloc_type = ELF32_R_TYPE(this_reloc->r_info);
@@ -71,92 +133,114 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 	symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
 	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
 
+
 	if (reloc_type != R_ARM_JUMP_SLOT) {
-	  _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", 
-		       _dl_progname);
-	  _dl_exit(1);
+		_dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", 
+			_dl_progname);
+		_dl_exit(1);
 	};
-	
+
 	/* Address of jump instruction to fix up */
 	instr_addr = ((unsigned long) this_reloc->r_offset + 
-			(unsigned long) tpnt->loadaddr);
+		(unsigned long) tpnt->loadaddr);
 	got_addr = (char **) instr_addr;
 
-#ifdef DL_DEBUG_SYMBOLS
-	_dl_dprintf(2, "Resolving symbol %s\n", 
-		strtab + symtab[symtab_index].st_name);
-#endif
-
 	/* Get the address of the GOT entry */
 	new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-		tpnt->symbol_scope, tpnt, 0);
+		tpnt->symbol_scope, tpnt, resolver);
 	if (!new_addr) {
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 			_dl_progname, strtab + symtab[symtab_index].st_name);
 		_dl_exit(1);
 	};
-#ifdef DL_NEVER_FIXUP_SYMBOLS
-	if ((unsigned long) got_addr < 0x40000000) {
-		_dl_dprintf(2, "Calling library function: %s\n", 
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_NEVER_FIXUP_SYMBOLS)
+	if ((unsigned long) got_addr < 0x40000000)
+	{
+#ifndef SUPPORT_LD_DEBUG
+          if (_dl_debug_bindings)
+	  {
+	    _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
 			strtab + symtab[symtab_index].st_name);
+	    if(_dl_debug_detail) _dl_dprintf(_dl_debug_file, "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
+	  }
+#endif	  
+#ifndef LD_NEVER_FIXUP_SYMBOLS
+	  *got_addr = new_addr;
+#endif		
 	} else {
-		*got_addr = new_addr;
+	  *got_addr = new_addr;
 	}
 #else
 	*got_addr = new_addr;
 #endif
+
 	return (unsigned long) new_addr;
 }
 
-void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, 
-	unsigned long rel_addr, unsigned long rel_size, int type)
+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))
 {
 	int i;
 	char *strtab;
-	int reloc_type;
-	int symtab_index;
+	int goof = 0;
 	Elf32_Sym *symtab;
-	Elf32_Rel *rpnt;
-	unsigned long *reloc_addr;
-
+	ELF_RELOC *rpnt;
+	int symtab_index;
 	/* Now parse the relocation information */
-	rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
-	rel_size = rel_size / sizeof(Elf32_Rel);
 
-	symtab =
-		(Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
+	rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
+	rel_size = rel_size / sizeof(ELF_RELOC);
+
+	symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
 	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
 
-	for (i = 0; i < rel_size; i++, rpnt++) {
-		reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-		reloc_type = ELF32_R_TYPE(rpnt->r_info);
+	  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))
+		    _dl_symbol(strtab + symtab[symtab_index].st_name))
 			continue;
 
-		switch (reloc_type) {
-		case R_ARM_NONE:
-			break;
-		case R_ARM_JUMP_SLOT:
-			*reloc_addr += (unsigned long) tpnt->loadaddr;
-			break;
-		default:
-			_dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", 
-				_dl_progname);
-#ifdef VERBOSE_DLINKER
-			_dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_DEBUG_SYMBOLS)
+		debug_sym(symtab,strtab,symtab_index);
+		debug_reloc(symtab,strtab,rpnt);
 #endif
-			if (symtab_index)
-				_dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
-			_dl_exit(1);
-		};
-	};
+
+		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 '%s'\n");
+			goof += res;
+		}
+	  }
+	  return goof;
 }
 
 static unsigned long
@@ -183,58 +267,40 @@ fix_bad_pc24 (unsigned long *const reloc_addr, unsigned long value)
   return (unsigned long)fix_address;
 }
 
-
-int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
-	unsigned long rel_addr, unsigned long rel_size, int type)
+static int
+_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
+	      ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
-	int i;
-	char *strtab;
 	int reloc_type;
-	int goof = 0;
-	Elf32_Sym *symtab;
-	Elf32_Rel *rpnt;
+	int symtab_index;
 	unsigned long *reloc_addr;
 	unsigned long symbol_addr;
-	int symtab_index;
-
-	/* Now parse the relocation information */
+	int goof = 0;
 
-	rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
-	rel_size = rel_size / sizeof(Elf32_Rel);
+	reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+	reloc_type = ELF32_R_TYPE(rpnt->r_info);
+	symtab_index = ELF32_R_SYM(rpnt->r_info);
+	symbol_addr = 0;
 
-	symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
-	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+	if (symtab_index) {
 
-	for (i = 0; i < rel_size; i++, rpnt++) {
-		reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-		reloc_type = ELF32_R_TYPE(rpnt->r_info);
-		symtab_index = ELF32_R_SYM(rpnt->r_info);
-		symbol_addr = 0;
+		symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
+				scope, (reloc_type == R_ARM_JUMP_SLOT ? tpnt : NULL), symbolrel);
 
-		if (!symtab_index && tpnt->libtype == program_interpreter)
-			continue;
-
-		if (symtab_index) {
-
-			if (tpnt->libtype == program_interpreter &&
-					_dl_symbol(strtab + symtab[symtab_index].st_name))
-				continue;
-
-			symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-					tpnt->symbol_scope,
-					(reloc_type == R_ARM_JUMP_SLOT ? tpnt : NULL), 0);
-
-			/*
-			 * We want to allow undefined references to weak symbols - this might
-			 * have been intentional.  We should not be linking local symbols
-			 * here, so all bases should be covered.
-			 */
-			if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
-				_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
-						_dl_progname, strtab + symtab[symtab_index].st_name);
-				goof++;
-			}
+		/*
+		 * We want to allow undefined references to weak symbols - this might
+		 * have been intentional.  We should not be linking local symbols
+		 * here, so all bases should be covered.
+		 */
+		if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
+			goof++;
 		}
+	}
+
+#if defined (SUPPORT_LD_DEBUG)
+	{
+		unsigned long old_val = *reloc_addr;
+#endif
 		switch (reloc_type) {
 			case R_ARM_NONE:
 				break;
@@ -286,19 +352,50 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt,
 #endif
 				break;
 			default:
-				_dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
-#ifdef VERBOSE_DLINKER
-				_dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
+				return -1; /*call _dl_exit(1) */
+		}
+#if defined (SUPPORT_LD_DEBUG)
+		if(_dl_debug_reloc && _dl_debug_detail)
+			_dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
+	}
+
 #endif
-				if (symtab_index)
-					_dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
-				_dl_exit(1);
-		};
 
-	};
 	return goof;
 }
 
+static int
+_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
+		   ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
+{
+	int reloc_type;
+	unsigned long *reloc_addr;
+
+	reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+	reloc_type = ELF32_R_TYPE(rpnt->r_info);
+
+#if defined (SUPPORT_LD_DEBUG)
+	{
+		unsigned long old_val = *reloc_addr;
+#endif
+		switch (reloc_type) {
+			case R_ARM_NONE:
+				break;
+			case R_ARM_JUMP_SLOT:
+				*reloc_addr += (unsigned long) tpnt->loadaddr;
+				break;
+			default:
+				return -1; /*call _dl_exit(1) */
+		}
+#if defined (SUPPORT_LD_DEBUG)
+		if(_dl_debug_reloc && _dl_debug_detail)
+			_dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
+	}
+
+#endif
+	return 0;
+
+}
 
 /* This is done as a separate step, because there are cases where
    information is first copied and later initialized.  This results in
@@ -308,59 +405,60 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt,
 
 /* No, there are cases where the SVr4 linker fails to emit COPY relocs
    at all */
-
-int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr, 
-	unsigned long rel_size, int type)
+static int
+_dl_do_copy (struct elf_resolve *tpnt, struct dyn_elf *scope,
+	     ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
-	int i;
-	char *strtab;
-	int reloc_type;
-	int goof = 0;
-	Elf32_Sym *symtab;
-	Elf32_Rel *rpnt;
+        int reloc_type;
+	int symtab_index;
 	unsigned long *reloc_addr;
 	unsigned long symbol_addr;
-	struct elf_resolve *tpnt;
-	int symtab_index;
-
-	/* Now parse the relocation information */
+	int goof = 0;
+	  
+	reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+	reloc_type = ELF32_R_TYPE(rpnt->r_info);
+	if (reloc_type != R_ARM_COPY) 
+		return 0;
+	symtab_index = ELF32_R_SYM(rpnt->r_info);
+	symbol_addr = 0;
+		
+	if (symtab_index) {
+
+		symbol_addr = (unsigned long) _dl_find_hash(strtab + 
+			symtab[symtab_index].st_name, 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",
+			     strtab + symtab[symtab_index].st_name,
+			     symtab[symtab_index].st_size,
+			     symbol_addr, symtab[symtab_index].st_value);
+#endif
+		_dl_memcpy((char *) symtab[symtab_index].st_value, 
+			(char *) symbol_addr, symtab[symtab_index].st_size);
+	}
 
-	tpnt = xpnt->dyn;
+	return goof;
+}
 
-	rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
-	rel_size = rel_size / sizeof(Elf32_Rel);
+void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, 
+	unsigned long rel_addr, unsigned long rel_size, int type)
+{
+  (void)_dl_parse(tpnt, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
 
-	symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
-	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
+	unsigned long rel_addr, unsigned long rel_size, int type)
+{
+  return _dl_parse(tpnt, tpnt->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+}
 
-	for (i = 0; i < rel_size; i++, rpnt++) {
-		reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-		reloc_type = ELF32_R_TYPE(rpnt->r_info);
-		if (reloc_type != R_ARM_COPY)
-			continue;
-		symtab_index = ELF32_R_SYM(rpnt->r_info);
-		symbol_addr = 0;
-		if (!symtab_index && tpnt->libtype == program_interpreter)
-			continue;
-		if (symtab_index) {
-
-			if (tpnt->libtype == program_interpreter &&
-				_dl_symbol(strtab + symtab[symtab_index].st_name))
-				continue;
-
-			symbol_addr = (unsigned long) _dl_find_hash(strtab + 
-				symtab[symtab_index].st_name, xpnt->next, 
-				NULL, 1);
-			if (!symbol_addr) {
-				_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
-					_dl_progname, strtab + symtab[symtab_index].st_name);
-				goof++;
-			};
-		};
-		if (!goof) {
-			_dl_memcpy((char *) symtab[symtab_index].st_value, 
-				(char *) symbol_addr, symtab[symtab_index].st_size);
-		}
-	};
-	return goof;
+int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr, 
+	unsigned long rel_size, int type)
+{
+  return _dl_parse(xpnt->dyn, xpnt->next, rel_addr, rel_size, _dl_do_copy);
 }
+

+ 59 - 37
ldso/ldso/dl-elf.c

@@ -1,21 +1,34 @@
-/* Load an ELF sharable library into memory.
-
-   Copyright (C) 1993-1996, Eric Youngdale.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
+/* vi: set sw=4 ts=4: */
+/* Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
+ *				David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2002, Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
 
 
 /* This file contains the helper routines to load an ELF sharable
@@ -180,8 +193,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 		pnt++;
 	}
 
-#ifdef DL_DEBUG
-	    _dl_dprintf(2, "searching for library: '%s'\n", libname);
+#ifdef LD_DEBUG
+	    _dl_dprintf(_dl_debug_file, "searching for library: '%s'\n", libname);
 #endif
 	/* If the filename has any '/', try it straight and leave it at that.
 	   For IBCS2 compatibility under linux, we substitute the string 
@@ -204,8 +217,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 			if (pnt) {
 				pnt += (unsigned long) tpnt->loadaddr +
 					tpnt->dynamic_info[DT_STRTAB];
-#ifdef DL_DEBUG
-				_dl_dprintf(2, "searching RPATH: '%s'\n", pnt);
+#ifdef LD_DEBUG
+				_dl_dprintf(_dl_debug_file, "searching RPATH: '%s'\n", pnt);
 #endif
 				if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) 
 				{
@@ -217,8 +230,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 
 	/* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
 	if (_dl_library_path) {
-#ifdef DL_DEBUG
-	    _dl_dprintf(2, "searching _dl_library_path: '%s'\n", _dl_library_path);
+#ifdef LD_DEBUG
+	    _dl_dprintf(_dl_debug_file, "searching _dl_library_path: '%s'\n", _dl_library_path);
 #endif
 	    if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL) 
 	    {
@@ -251,8 +264,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 
 	/* Look for libraries wherever the shared library loader
 	 * was installed */
-#ifdef DL_DEBUG
-	_dl_dprintf(2, "searching in ldso dir: %s\n", _dl_ldsopath);
+#ifdef LD_DEBUG
+	_dl_dprintf(_dl_debug_file, "searching in ldso dir: %s\n", _dl_ldsopath);
 #endif
 	if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt)) != NULL) 
 	{
@@ -262,8 +275,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 
 	/* Lastly, search the standard list of paths for the library.
 	   This list must exactly match the list in uClibc/ldso/util/ldd.c */
-#ifdef DL_DEBUG
-	    _dl_dprintf(2, "searching full lib path list\n");
+#ifdef LD_DEBUG
+	    _dl_dprintf(_dl_debug_file, "searching full lib path list\n");
 #endif
 	if ((tpnt1 = search_for_named_library(libname, secure, 
 			UCLIBC_TARGET_PREFIX "/usr/lib:"
@@ -282,8 +295,8 @@ goof:
 	if (_dl_internal_error_number)
 		_dl_error_number = _dl_internal_error_number;
 	else
-		_dl_error_number = DL_ERROR_NOFILE;
-#ifdef DL_DEBUG
+		_dl_error_number = LD_ERROR_NOFILE;
+#ifdef LD_DEBUG
 	    _dl_dprintf(2, "Bummer: could not find '%s'!\n", libname);
 #endif
 	return NULL;
@@ -323,6 +336,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 			(*rpnt)->next = (struct dyn_elf *)
 				_dl_malloc(sizeof(struct dyn_elf));
 			_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+			(*rpnt)->next->prev = (*rpnt);
 			*rpnt = (*rpnt)->next;
 			(*rpnt)->dyn = tpnt;
 			tpnt->symbol_scope = _dl_symbol_tables;
@@ -352,7 +366,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 		 */
 		_dl_dprintf(2, "%s: can't open '%s'\n", _dl_progname, libname);
 #endif
-		_dl_internal_error_number = DL_ERROR_NOFILE;
+		_dl_internal_error_number = LD_ERROR_NOFILE;
 		return NULL;
 	}
 
@@ -365,7 +379,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	{
 		_dl_dprintf(2, "%s: '%s' is not an ELF file\n", _dl_progname,
 					 libname);
-		_dl_internal_error_number = DL_ERROR_NOTELF;
+		_dl_internal_error_number = LD_ERROR_NOTELF;
 		_dl_close(infile);
 		return NULL;
 	};
@@ -377,7 +391,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 		)) 
 	{
 		_dl_internal_error_number = 
-		    (epnt->e_type != ET_DYN ? DL_ERROR_NOTDYN : DL_ERROR_NOTMAGIC);
+		    (epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC);
 		_dl_dprintf(2, "%s: '%s' is not an ELF executable for " ELF_TARGET 
 			"\n", _dl_progname, libname);
 		_dl_close(infile);
@@ -424,7 +438,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 		maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
 	if (_dl_mmap_check_error(status)) {
 		_dl_dprintf(2, "%s: can't map %s\n", _dl_progname, libname);
-		_dl_internal_error_number = DL_ERROR_MMAP_FAILED;
+		_dl_internal_error_number = LD_ERROR_MMAP_FAILED;
 		_dl_close(infile);
 		return NULL;
 	};
@@ -457,7 +471,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 				if (_dl_mmap_check_error(status)) {
 					_dl_dprintf(2, "%s: can't map '%s'\n", 
 						_dl_progname, libname);
-					_dl_internal_error_number = DL_ERROR_MMAP_FAILED;
+					_dl_internal_error_number = LD_ERROR_MMAP_FAILED;
 					_dl_munmap((char *) libaddr, maxvma - minvma);
 					_dl_close(infile);
 					return NULL;
@@ -488,7 +502,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 					infile, ppnt->p_offset & OFFS_ALIGN);
 			if (_dl_mmap_check_error(status)) {
 				_dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname);
-				_dl_internal_error_number = DL_ERROR_MMAP_FAILED;
+				_dl_internal_error_number = LD_ERROR_MMAP_FAILED;
 				_dl_munmap((char *) libaddr, maxvma - minvma);
 				_dl_close(infile);
 				return NULL;
@@ -516,7 +530,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	/* Start by scanning the dynamic section to get all of the pointers */
 
 	if (!dynamic_addr) {
-		_dl_internal_error_number = DL_ERROR_NODYNAMIC;
+		_dl_internal_error_number = LD_ERROR_NODYNAMIC;
 		_dl_dprintf(2, "%s: '%s' is missing a dynamic section\n", 
 			_dl_progname, libname);
 		return NULL;
@@ -580,6 +594,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 		(*rpnt)->next = (struct dyn_elf *)
 			_dl_malloc(sizeof(struct dyn_elf));
 		_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+		(*rpnt)->next->prev = (*rpnt);
 		*rpnt = (*rpnt)->next;
 		(*rpnt)->dyn = tpnt;
 		tpnt->symbol_scope = _dl_symbol_tables;
@@ -626,6 +641,10 @@ int _dl_copy_fixups(struct dyn_elf *rpnt)
 		return goof;
 	tpnt->init_flag |= COPY_RELOCS_DONE;
 
+#if defined (SUPPORT_LD_DEBUG)
+	if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation copy fixups: %s", tpnt->libname);	
+#endif    
+
 #ifdef ELF_USES_RELOCA
 	goof += _dl_parse_copy_information(rpnt, 
 		tpnt->dynamic_info[DT_RELA], tpnt->dynamic_info[DT_RELASZ], 0);
@@ -635,5 +654,8 @@ int _dl_copy_fixups(struct dyn_elf *rpnt)
 		tpnt->dynamic_info[DT_RELSZ], 0);
 
 #endif
+#if defined (SUPPORT_LD_DEBUG)
+	if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation copy fixups: %s; finished\n\n", tpnt->libname);	
+#endif    
 	return goof;
 }

+ 57 - 25
ldso/ldso/dl-hash.c

@@ -1,21 +1,34 @@
-/* Run an ELF binary on a linux system.
-
-   Copyright (C) 1993-1996, Eric Youngdale.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
+/* vi: set sw=4 ts=4: */
+/* Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
+ *				David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2002, Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
 
 
 /* Various symbol table handling functions, including symbol lookup */
@@ -150,7 +163,7 @@ struct elf_resolve *_dl_add_elf_hash_table(char *libname,
  */
 
 char *_dl_find_hash(char *name, struct dyn_elf *rpnt1, 
-	struct elf_resolve *f_tpnt, int copyrel)
+	struct elf_resolve *f_tpnt, enum caller_type caller_type)
 {
 	struct elf_resolve *tpnt;
 	int si;
@@ -172,7 +185,7 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
 	   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@cmu.edu) */
-	if (!copyrel && rpnt1) {
+	if (copyrel!=caller_type && rpnt1) {
 		first = (*_dl_symbol_tables);
 		first.next = rpnt1;
 		rpnt1 = (&first);
@@ -247,11 +260,12 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
 				pnt = strtab + symtab[si].st_name;
 
 				if (_dl_strcmp(pnt, name) == 0 &&
-					(ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
-					 ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
-					 ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
-					symtab[si].st_value != 0 &&
-					symtab[si].st_shndx != 0) {
+				    symtab[si].st_value != 0)
+				{
+				  if ((ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
+				       ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
+				       ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
+				      symtab[si].st_shndx != SHN_UNDEF) {
 
 					/* Here we make sure that we find a module where the symbol is
 					 * actually defined.
@@ -284,6 +298,24 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
 					default:	/* Do local symbols need to be examined? */
 						break;
 					}
+				  }
+				  /*
+				   * References to the address of a function from an executable file and
+				   * the shared objects associated with it might not resolve to the same
+				   * value. To allow comparisons of function addresses we must resolve
+				   * to the address of the plt entry of the executable instead of the
+				   * real function address.
+				   * see "TIS ELF Specification Version 1.2, Book 3, A-11 (Function
+				   * Adresses) 
+				   */				 
+				  if (resolver != caller_type &&
+				      NULL==f_tpnt && /*trick: don't  handle R_??_JMP_SLOT reloc type*/
+				      tpnt->libtype == elf_executable &&
+				      ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC &&
+				      symtab[si].st_shndx == SHN_UNDEF)
+				  {
+				      return (char*)symtab[si].st_value;
+				  }
 				}
 			}
 		}

+ 57 - 25
ldso/ldso/hash.c

@@ -1,21 +1,34 @@
-/* Run an ELF binary on a linux system.
-
-   Copyright (C) 1993-1996, Eric Youngdale.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
+/* vi: set sw=4 ts=4: */
+/* Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
+ *				David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2002, Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
 
 
 /* Various symbol table handling functions, including symbol lookup */
@@ -150,7 +163,7 @@ struct elf_resolve *_dl_add_elf_hash_table(char *libname,
  */
 
 char *_dl_find_hash(char *name, struct dyn_elf *rpnt1, 
-	struct elf_resolve *f_tpnt, int copyrel)
+	struct elf_resolve *f_tpnt, enum caller_type caller_type)
 {
 	struct elf_resolve *tpnt;
 	int si;
@@ -172,7 +185,7 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
 	   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@cmu.edu) */
-	if (!copyrel && rpnt1) {
+	if (copyrel!=caller_type && rpnt1) {
 		first = (*_dl_symbol_tables);
 		first.next = rpnt1;
 		rpnt1 = (&first);
@@ -247,11 +260,12 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
 				pnt = strtab + symtab[si].st_name;
 
 				if (_dl_strcmp(pnt, name) == 0 &&
-					(ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
-					 ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
-					 ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
-					symtab[si].st_value != 0 &&
-					symtab[si].st_shndx != 0) {
+				    symtab[si].st_value != 0)
+				{
+				  if ((ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
+				       ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
+				       ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
+				      symtab[si].st_shndx != SHN_UNDEF) {
 
 					/* Here we make sure that we find a module where the symbol is
 					 * actually defined.
@@ -284,6 +298,24 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
 					default:	/* Do local symbols need to be examined? */
 						break;
 					}
+				  }
+				  /*
+				   * References to the address of a function from an executable file and
+				   * the shared objects associated with it might not resolve to the same
+				   * value. To allow comparisons of function addresses we must resolve
+				   * to the address of the plt entry of the executable instead of the
+				   * real function address.
+				   * see "TIS ELF Specification Version 1.2, Book 3, A-11 (Function
+				   * Adresses) 
+				   */				 
+				  if (resolver != caller_type &&
+				      NULL==f_tpnt && /*trick: don't  handle R_??_JMP_SLOT reloc type*/
+				      tpnt->libtype == elf_executable &&
+				      ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC &&
+				      symtab[si].st_shndx == SHN_UNDEF)
+				  {
+				      return (char*)symtab[si].st_value;
+				  }
 				}
 			}
 		}

+ 1 - 1
ldso/ldso/i386/boot1_arch.h

@@ -4,4 +4,4 @@
  * can be done.
  */
 
-#define DL_BOOT(X)   void _dl_boot (X)
+#define LD_BOOT(X)   void _dl_boot (X)

+ 1 - 1
ldso/ldso/i386/dl-startup.h

@@ -4,4 +4,4 @@
  * can be done.
  */
 
-#define DL_BOOT(X)   void _dl_boot (X)
+#define LD_BOOT(X)   void _dl_boot (X)

+ 298 - 196
ldso/ldso/i386/elfinterp.c

@@ -1,31 +1,96 @@
-/* Run an ELF binary on a linux system.
-
-   Copyright (C) 1993, Eric Youngdale.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-#ifndef VERBOSE_DLINKER
-#define VERBOSE_DLINKER
-#endif
-#ifdef VERBOSE_DLINKER
-static const char *_dl_reltypes[] =
-	{ "R_386_NONE", "R_386_32", "R_386_PC32", "R_386_GOT32",
-	"R_386_PLT32", "R_386_COPY", "R_386_GLOB_DAT",
-	"R_386_JMP_SLOT", "R_386_RELATIVE", "R_386_GOTOFF",
-	"R_386_GOTPC", "R_386_NUM"
+/* vi: set sw=4 ts=4: */
+/* i386 ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
+ *				David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2002, Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_DEBUG_SYMBOLS)
+static const char *_dl_reltypes_tab[] =
+{
+  [0]	"R_386_NONE",	    "R_386_32",	    "R_386_PC32",	"R_386_GOT32",
+  [4]	"R_386_PLT32",	    "R_386_COPY",   "R_386_GLOB_DAT",	"R_386_JMP_SLOT",
+  [8]	"R_386_RELATIVE",   "R_386_GOTOFF", "R_386_GOTPC",
 };
+
+static const char *
+_dl_reltypes(int type)
+{
+  static char buf[22];  
+  const char *str;
+  
+  if (type >= (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\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";
+    
+#ifdef ELF_USES_RELOCA
+    _dl_dprintf(_dl_debug_file, "\n%s\toffset=%x\taddend=%x %s",
+		_dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
+		rpnt->r_offset,
+		rpnt->r_addend,
+		sym);
+#else
+    _dl_dprintf(_dl_debug_file, "\n%s\toffset=%x %s",
+		_dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
+		rpnt->r_offset,
+		sym);
+#endif
+  }
+}
 #endif
 
 /* Program to load an ELF binary on a linux system, and run it.
@@ -44,16 +109,16 @@ extern int _dl_linux_resolve(void);
 unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 {
 	int reloc_type;
-	Elf32_Rel *this_reloc;
+	ELF_RELOC *this_reloc;
 	char *strtab;
 	Elf32_Sym *symtab;
-	Elf32_Rel *rel_addr;
+	ELF_RELOC *rel_addr;
 	int symtab_index;
 	char *new_addr;
 	char **got_addr;
 	unsigned long instr_addr;
 
-	rel_addr = (Elf32_Rel *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
+	rel_addr = (ELF_RELOC *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
 
 	this_reloc = rel_addr + (reloc_entry >> 3);
 	reloc_type = ELF32_R_TYPE(this_reloc->r_info);
@@ -74,175 +139,211 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 		(unsigned long) tpnt->loadaddr);
 	got_addr = (char **) instr_addr;
 
-#ifdef DL_DEBUG_SYMBOLS
-	_dl_dprintf(2, "Resolving symbol %s\n", 
-		strtab + symtab[symtab_index].st_name);
-#endif
-
 	/* Get the address of the GOT entry */
 	new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-		tpnt->symbol_scope, tpnt, 0);
+		tpnt->symbol_scope, tpnt, resolver);
 	if (!new_addr) {
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 			_dl_progname, strtab + symtab[symtab_index].st_name);
 		_dl_exit(1);
 	};
-#ifdef DL_NEVER_FIXUP_SYMBOLS
-	if ((unsigned long) got_addr < 0x40000000) {
-		_dl_dprintf(2, "Calling library function: %s\n", 
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_NEVER_FIXUP_SYMBOLS)
+	if ((unsigned long) got_addr < 0x40000000)
+	{
+#ifndef SUPPORT_LD_DEBUG
+          if (_dl_debug_bindings)
+	  {
+	    _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
 			strtab + symtab[symtab_index].st_name);
+	    if(_dl_debug_detail) _dl_dprintf(_dl_debug_file, "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
+	  }
+#endif	  
+#ifndef LD_NEVER_FIXUP_SYMBOLS
+	  *got_addr = new_addr;
+#endif		
 	} else {
-		*got_addr = new_addr;
+	  *got_addr = new_addr;
 	}
 #else
 	*got_addr = new_addr;
 #endif
+
 	return (unsigned long) new_addr;
 }
 
-void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, 
-	unsigned long rel_addr, unsigned long rel_size, int type)
+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))
 {
 	int i;
 	char *strtab;
-	int reloc_type;
-	int symtab_index;
+	int goof = 0;
 	Elf32_Sym *symtab;
-	Elf32_Rel *rpnt;
-	unsigned long *reloc_addr;
-
+	ELF_RELOC *rpnt;
+	int symtab_index;
 	/* Now parse the relocation information */
-	rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
-	rel_size = rel_size / sizeof(Elf32_Rel);
 
-	symtab =
-		(Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
+	rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
+	rel_size = rel_size / sizeof(ELF_RELOC);
+
+	symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
 	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
 
-	for (i = 0; i < rel_size; i++, rpnt++) {
-		reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-		reloc_type = ELF32_R_TYPE(rpnt->r_info);
+	  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))
+		    _dl_symbol(strtab + symtab[symtab_index].st_name))
 			continue;
 
-		switch (reloc_type) {
-		case R_386_NONE:
-			break;
-		case R_386_JMP_SLOT:
-			*reloc_addr += (unsigned long) tpnt->loadaddr;
-			break;
-		default:
-			_dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", 
-				_dl_progname);
-#ifdef VERBOSE_DLINKER
-			_dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_DEBUG_SYMBOLS)
+		debug_sym(symtab,strtab,symtab_index);
+		debug_reloc(symtab,strtab,rpnt);
 #endif
-			if (symtab_index)
-				_dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
-			_dl_exit(1);
-		};
-	};
+
+		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 '%s'\n");
+			goof += res;
+		}
+	  }
+	  return goof;
 }
 
-int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
-	unsigned long rel_addr, unsigned long rel_size, int type)
+static int
+_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
+	      ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
-	int i;
-	char *strtab;
 	int reloc_type;
-	int goof = 0;
-	Elf32_Sym *symtab;
-	Elf32_Rel *rpnt;
+	int symtab_index;
 	unsigned long *reloc_addr;
 	unsigned long symbol_addr;
-	int symtab_index;
-
-	/* Now parse the relocation information */
-
-	rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
-	rel_size = rel_size / sizeof(Elf32_Rel);
+	int goof = 0;
 
-	symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
-	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+	reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+	reloc_type = ELF32_R_TYPE(rpnt->r_info);
+	symtab_index = ELF32_R_SYM(rpnt->r_info);
+	symbol_addr = 0;
 
-	for (i = 0; i < rel_size; i++, rpnt++) {
-		reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-		reloc_type = ELF32_R_TYPE(rpnt->r_info);
-		symtab_index = ELF32_R_SYM(rpnt->r_info);
-		symbol_addr = 0;
+	if (symtab_index) {
 
-		if (!symtab_index && tpnt->libtype == program_interpreter)
-			continue;
+		symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
+				scope, (reloc_type == R_386_JMP_SLOT ? tpnt : NULL), symbolrel);
 
-		if (symtab_index) {
-
-			if (tpnt->libtype == program_interpreter &&
-				_dl_symbol(strtab + symtab[symtab_index].st_name))
-				continue;
-
-			symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-					tpnt->symbol_scope,
-					(reloc_type == R_386_JMP_SLOT ? tpnt : NULL), 0);
-
-			/*
-			 * We want to allow undefined references to weak symbols - this might
-			 * have been intentional.  We should not be linking local symbols
-			 * here, so all bases should be covered.
-			 */
-			if (!symbol_addr &&
-				ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
-				_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
-					_dl_progname, strtab + symtab[symtab_index].st_name);
-				goof++;
-			}
+		/*
+		 * We want to allow undefined references to weak symbols - this might
+		 * have been intentional.  We should not be linking local symbols
+		 * here, so all bases should be covered.
+		 */
+		if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
+			goof++;
 		}
+	}
+
+#if defined (SUPPORT_LD_DEBUG)
+	{
+		unsigned long old_val = *reloc_addr;
+#endif
 		switch (reloc_type) {
-		case R_386_NONE:
-			break;
-		case R_386_32:
-			*reloc_addr += symbol_addr;
-			break;
-		case R_386_PC32:
-			*reloc_addr += symbol_addr - (unsigned long) reloc_addr;
-			break;
-		case R_386_GLOB_DAT:
-		case R_386_JMP_SLOT:
-			*reloc_addr = symbol_addr;
-			break;
-		case R_386_RELATIVE:
-			*reloc_addr += (unsigned long) tpnt->loadaddr;
-			break;
-		case R_386_COPY:
-#if 0							
-			/* Do this later */
-			_dl_dprintf(2, "Doing copy for symbol ");
-			if (symtab_index) _dl_dprintf(2, strtab + symtab[symtab_index].st_name);
-			_dl_dprintf(2, "\n");
-			_dl_memcpy((void *) symtab[symtab_index].st_value, 
-				(void *) symbol_addr, symtab[symtab_index].st_size);
+			case R_386_NONE:
+				break;
+			case R_386_32:
+				*reloc_addr += symbol_addr;
+				break;
+			case R_386_PC32:
+				*reloc_addr += symbol_addr - (unsigned long) reloc_addr;
+				break;
+			case R_386_GLOB_DAT:
+			case R_386_JMP_SLOT:
+				*reloc_addr = symbol_addr;
+				break;
+			case R_386_RELATIVE:
+				*reloc_addr += (unsigned long) tpnt->loadaddr;
+				break;
+			case R_386_COPY:
+#if 0
+				/* Do this later */
+				_dl_dprintf(2, "Doing copy for symbol ");
+				if (symtab_index) _dl_dprintf(2, strtab + symtab[symtab_index].st_name);
+				_dl_dprintf(2, "\n");
+				_dl_memcpy((void *) symtab[symtab_index].st_value, 
+						(void *) symbol_addr, symtab[symtab_index].st_size);
 #endif
-			break;
-		default:
-			_dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
-#ifdef VERBOSE_DLINKER
-			_dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
+				break;
+
+			default:
+				return -1; /*call _dl_exit(1) */
+		}
+#if defined (SUPPORT_LD_DEBUG)
+		if(_dl_debug_reloc && _dl_debug_detail)
+			_dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
+	}
+
 #endif
-			if (symtab_index)
-				_dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
-			_dl_exit(1);
-		};
 
-	};
 	return goof;
 }
 
+static int
+_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
+		   ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
+{
+	int reloc_type;
+	unsigned long *reloc_addr;
+
+	reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+	reloc_type = ELF32_R_TYPE(rpnt->r_info);
+
+#if defined (SUPPORT_LD_DEBUG)
+	{
+		unsigned long old_val = *reloc_addr;
+#endif
+		switch (reloc_type) {
+			case R_386_NONE:
+				break;
+			case R_386_JMP_SLOT:
+				*reloc_addr += (unsigned long) tpnt->loadaddr;
+				break;
+
+			default:
+				return -1; /*call _dl_exit(1) */
+		}
+#if defined (SUPPORT_LD_DEBUG)
+		if(_dl_debug_reloc && _dl_debug_detail)
+			_dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
+	}
+
+#endif
+	return 0;
+
+}
 
 /* This is done as a separate step, because there are cases where
    information is first copied and later initialized.  This results in
@@ -252,59 +353,60 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt,
 
 /* No, there are cases where the SVr4 linker fails to emit COPY relocs
    at all */
-
-int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr, 
-	unsigned long rel_size, int type)
+static int
+_dl_do_copy (struct elf_resolve *tpnt, struct dyn_elf *scope,
+	     ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
-	int i;
-	char *strtab;
-	int reloc_type;
-	int goof = 0;
-	Elf32_Sym *symtab;
-	Elf32_Rel *rpnt;
+        int reloc_type;
+	int symtab_index;
 	unsigned long *reloc_addr;
 	unsigned long symbol_addr;
-	struct elf_resolve *tpnt;
-	int symtab_index;
-
-	/* Now parse the relocation information */
+	int goof = 0;
+	  
+	reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+	reloc_type = ELF32_R_TYPE(rpnt->r_info);
+	if (reloc_type != R_386_COPY) 
+		return 0;
+	symtab_index = ELF32_R_SYM(rpnt->r_info);
+	symbol_addr = 0;
+		
+	if (symtab_index) {
+
+		symbol_addr = (unsigned long) _dl_find_hash(strtab + 
+			symtab[symtab_index].st_name, 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",
+			     strtab + symtab[symtab_index].st_name,
+			     symtab[symtab_index].st_size,
+			     symbol_addr, symtab[symtab_index].st_value);
+#endif
+		_dl_memcpy((char *) symtab[symtab_index].st_value, 
+			(char *) symbol_addr, symtab[symtab_index].st_size);
+	}
 
-	tpnt = xpnt->dyn;
+	return goof;
+}
 
-	rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
-	rel_size = rel_size / sizeof(Elf32_Rel);
+void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, 
+	unsigned long rel_addr, unsigned long rel_size, int type)
+{
+  (void)_dl_parse(tpnt, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
 
-	symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
-	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
+	unsigned long rel_addr, unsigned long rel_size, int type)
+{
+  return _dl_parse(tpnt, tpnt->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+}
 
-	for (i = 0; i < rel_size; i++, rpnt++) {
-		reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-		reloc_type = ELF32_R_TYPE(rpnt->r_info);
-		if (reloc_type != R_386_COPY)
-			continue;
-		symtab_index = ELF32_R_SYM(rpnt->r_info);
-		symbol_addr = 0;
-		if (!symtab_index && tpnt->libtype == program_interpreter)
-			continue;
-		if (symtab_index) {
-
-			if (tpnt->libtype == program_interpreter &&
-				_dl_symbol(strtab + symtab[symtab_index].st_name))
-				continue;
-
-			symbol_addr = (unsigned long) _dl_find_hash(strtab + 
-				symtab[symtab_index].st_name, xpnt->next, 
-				NULL, 1);
-			if (!symbol_addr) {
-				_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
-					_dl_progname, strtab + symtab[symtab_index].st_name);
-				goof++;
-			};
-		};
-		if (!goof) {
-			_dl_memcpy((char *) symtab[symtab_index].st_value, 
-				(char *) symbol_addr, symtab[symtab_index].st_size);
-		}
-	};
-	return goof;
+int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr, 
+	unsigned long rel_size, int type)
+{
+  return _dl_parse(xpnt->dyn, xpnt->next, rel_addr, rel_size, _dl_do_copy);
 }
+

+ 15 - 11
ldso/ldso/ld_hash.h

@@ -43,6 +43,7 @@ struct dyn_elf{
   struct elf_resolve * dyn;
   struct dyn_elf * next_handle;  /* Used by dlopen et al. */
   struct dyn_elf * next;
+  struct dyn_elf * prev;
 };
  
 struct elf_resolve{
@@ -113,8 +114,11 @@ extern struct elf_resolve * _dl_check_hashed_files(char * libname);
 extern struct elf_resolve * _dl_add_elf_hash_table(char * libname, 
 	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(char * name, struct dyn_elf * rpnt1, 
-	struct elf_resolve * f_tpnt, int copyrel);
+	struct elf_resolve * f_tpnt, enum caller_type);
+
 extern int _dl_linux_dynamic_link(void);
 
 extern char * _dl_library_path;
@@ -129,16 +133,16 @@ static inline int _dl_symbol(char * name)
 }
 
 
-#define DL_ERROR_NOFILE 1
-#define DL_ERROR_NOZERO 2
-#define DL_ERROR_NOTELF 3
-#define DL_ERROR_NOTMAGIC 4
-#define DL_ERROR_NOTDYN 5
-#define DL_ERROR_MMAP_FAILED 6
-#define DL_ERROR_NODYNAMIC 7
-#define DL_WRONG_RELOCS 8
-#define DL_BAD_HANDLE 9
-#define DL_NO_SYMBOL 10
+#define LD_ERROR_NOFILE 1
+#define LD_ERROR_NOZERO 2
+#define LD_ERROR_NOTELF 3
+#define LD_ERROR_NOTMAGIC 4
+#define LD_ERROR_NOTDYN 5
+#define LD_ERROR_MMAP_FAILED 6
+#define LD_ERROR_NODYNAMIC 7
+#define LD_WRONG_RELOCS 8
+#define LD_BAD_HANDLE 9
+#define LD_NO_SYMBOL 10
 
 
 

+ 25 - 1
ldso/ldso/ld_string.h

@@ -17,6 +17,7 @@ static int _dl_strcmp(const char * s1,const char * s2);
 static int _dl_strncmp(const char * s1,const char * s2,size_t len);
 static char * _dl_strchr(const char * str,int c);
 static char *_dl_strrchr(const char *str, int c);
+static char *_dl_strstr(const char *s1, const char *s2);
 static void * _dl_memcpy(void * dst, const void * src, size_t len);
 static int _dl_memcmp(const void * s1,const void * s2,size_t len);
 static void *_dl_memset(void * str,int c,size_t len);
@@ -122,6 +123,29 @@ static inline char *_dl_strrchr(const char *str, int c)
     return(prev);
 }
 
+
+static inline char *_dl_strstr(const char *s1, const char *s2)
+{
+    register const char *s = s1;
+    register const char *p = s2;
+    
+    do {
+        if (!*p) {
+	    return (char *) s1;;
+	}
+	if (*p == *s) {
+	    ++p;
+	    ++s;
+	} else {
+	    p = s2;
+	    if (!*s) {
+	      return NULL;
+	    }
+	    s = ++s1;
+	}
+    } while (1);
+}
+
 static inline void * _dl_memcpy(void * dst, const void * src, size_t len)
 {
 	register char *a = dst;
@@ -221,7 +245,7 @@ static inline char *_dl_simple_ltoahex(char * local, unsigned long i)
 }
 
 
-#if defined mc68000 || defined __arm__ || defined __mips__
+#if defined mc68000 || defined __arm__ || defined __mips__ || defined __sh__
 /* On some arches constant strings are referenced through the GOT. */
 /* XXX Requires load_addr to be defined. */
 #define SEND_STDERR(X)				\

+ 8 - 2
ldso/ldso/ld_syscall.h

@@ -51,8 +51,8 @@ static inline _syscall1(void, _dl_exit, int, status);
 static inline _syscall1(int, _dl_close, int, fd);
 
 
-#if defined(__powerpc) || defined(__mips__)
-/* PowerPC and MIPS have a different calling convention for mmap(). */
+#if defined(__powerpc) || defined(__mips__) || defined(__sh__)
+/* PowerPC, MIPS and SuperH have a different calling convention for mmap(). */
 #define __NR__dl_mmap __NR_mmap
 static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
 		int, prot, int, flags, int, fd, off_t, offset);
@@ -91,6 +91,9 @@ static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
 
 #define __NR__dl_open __NR_open
 #define O_RDONLY        0x0000
+#define O_WRONLY	     01
+#define O_RDWR		     02
+#define O_CREAT		   0100	/* not fcntl */
 static inline _syscall2(int, _dl_open, const char *, fn, int, flags);
 
 #define __NR__dl_write __NR_write
@@ -126,6 +129,9 @@ static inline _syscall0(gid_t, _dl_getgid);
 #define __NR__dl_getegid __NR_getegid
 static inline _syscall0(gid_t, _dl_getegid);
 
+#define __NR__dl_getpid __NR_getpid
+static inline _syscall0(gid_t, _dl_getpid);
+
 /*
  * Not an actual syscall, but we need something in assembly to say whether
  * this is OK or not.

+ 194 - 94
ldso/ldso/ldso.c

@@ -1,23 +1,33 @@
 /* vi: set sw=4 ts=4: */
 /* Program to load an ELF binary on a linux system, and run it
  * after resolving ELF shared library symbols
- * 
- * Copyright (C) 1993-1996, Eric Youngdale.
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
+ *				David Engel, Hongjiu Lu and Mitch D'Souza
  * Copyright (C) 2001-2002, Erik Andersen
  *
- * This program is free software; you can redistribute it and/or modify 
- * it under the terms of the GNU General Public License as published by 
- * the Free Software Foundation; either version 2, or (at your option) 
- * any later version.  
- * 
- * This program is distributed in the hope that it will be useful, 
- * but WITHOUT ANY WARRANTY; without even the implied warranty of 
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
- * GNU General Public License for more details.  
- * 
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 /* Enable mprotect protection munging.  ARM and MIPS Linux needs this
@@ -27,21 +37,6 @@
 // Support a list of library preloads in /etc/ld.so.preload
 //#define SUPPORT_LDSO_PRELOAD_FILE
 
-/* Enable ldd library tracing.  Just set LD_TRACE_LOADED_OBJECTS=1 in
- * the environment and run the app to do the ldd thing.  With this
- * enabled you can make a simple /usr/bin/ldd shell script as:
- *		#!/bin/sh
- *		LD_TRACE_LOADED_OBJECTS=1 $1
- * so you can do stuff like:
- *		$ ldd ./appname
- *				libc.so.0 => /lib/libc.so.0 (0x0x40006000) 
- *				ld-uClibc.so.0 => /home/andersen/CVS/uClibc/lib/ld-uClibc.so.0 (0x0x40000000)
- * This is off by default since it doesn't work when cross compiling,
- * so uClibc provides an ELF header reading ldd instead...
- */
-//#define DL_TRACE
-
-
 
 /* Disclaimer:  I have never seen any AT&T source code for SVr4, nor have
    I ever taken any courses on internals.  This program was developed using
@@ -113,6 +108,12 @@
  * housekeeping chores and we can transfer control to the user's
  * application.
  */
+#ifdef LD_DEBUG_SYMBOLS
+#ifdef SUPPORT_LD_DEBUG
+#undef SUPPORT_LD_DEBUG
+#endif
+#define SUPPORT_LD_DEBUG
+#endif
 
 #include "ld_syscall.h"
 #include "linuxelf.h"
@@ -127,11 +128,11 @@
 #define	    ELFMAGIC	ELFMAG
 
 /* This is a poor man's malloc, used prior to resolving our internal poor man's malloc */
-#define DL_MALLOC(SIZE) ((void *) (malloc_buffer += SIZE, malloc_buffer - SIZE)) ;  REALIGN();
+#define LD_MALLOC(SIZE) ((void *) (malloc_buffer += SIZE, malloc_buffer - SIZE)) ;  REALIGN();
 /*
  * Make sure that the malloc buffer is aligned on 4 byte boundary.  For 64 bit
  * platforms we may need to increase this to 8, but this is good enough for
- * now.  This is typically called after DL_MALLOC.
+ * now.  This is typically called after LD_MALLOC.
  */
 #define REALIGN() malloc_buffer = (char *) (((unsigned long) malloc_buffer + 3) & ~(3))
 
@@ -139,6 +140,17 @@ char *_dl_library_path = 0;		/* Where we look for libraries */
 char *_dl_preload = 0;			/* Things to be loaded before the libs. */
 char *_dl_ldsopath = 0;
 static char *_dl_not_lazy = 0;
+#ifdef SUPPORT_LD_DEBUG
+static char *_dl_debug  = 0;
+static char *_dl_debug_symbols = 0;
+static char *_dl_debug_move    = 0;
+static char *_dl_debug_reloc   = 0;
+static char *_dl_debug_detail  = 0;
+static char *_dl_debug_bindings  = 0;
+static int   _dl_debug_file = 2;
+#else
+#define _dl_debug_file 2
+#endif
 static char *_dl_malloc_addr, *_dl_mmap_zero;
 
 static char *_dl_trace_loaded_objects = 0;
@@ -171,7 +183,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 		auxvt[0...N]   Auxiliary Vector Table elements (mixed types)
 */
 
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 /* Debugging is especially tricky on PowerPC, since string literals
  * require relocations.  Thus, you can't use _dl_dprintf() for
  * anything until the bootstrap relocations are finished. */
@@ -192,7 +204,7 @@ static inline void hexprint(unsigned long x)
 }
 #endif
 
-DL_BOOT(unsigned long args)
+LD_BOOT(unsigned long args)
 {
 	unsigned int argc;
 	char **argv, **envp;
@@ -257,14 +269,19 @@ DL_BOOT(unsigned long args)
 	/* Check the ELF header to make sure everything looks ok.  */
 	if (!header || header->e_ident[EI_CLASS] != ELFCLASS32 ||
 		header->e_ident[EI_VERSION] != EV_CURRENT
-#if !defined(__powerpc__) && !defined(__mips__)
+#if !defined(__powerpc__) && !defined(__mips__) && !defined(__sh__)
 		|| _dl_strncmp((void *) header, ELFMAGIC, SELFMAG) != 0
+#else
+	        || header->e_ident[EI_MAG0] != ELFMAG0
+	        || header->e_ident[EI_MAG1] != ELFMAG1
+	        || header->e_ident[EI_MAG2] != ELFMAG2
+	        || header->e_ident[EI_MAG3] != ELFMAG3
 #endif
 		) {
 		SEND_STDERR("Invalid ELF header\n");
 		_dl_exit(0);
 	}
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 	SEND_STDERR("ELF header=");
 	SEND_ADDRESS_STDERR(load_addr, 1);
 #endif
@@ -286,6 +303,16 @@ DL_BOOT(unsigned long args)
   __asm__("\tbl _GLOBAL_OFFSET_TABLE_-4@local\n\t":"=l"(got));
 #elif defined(__mips__)
   __asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got));
+#elif defined(__sh__)
+  __asm__("
+	   mov.l    1f, %0
+	   mova     1f, r0
+	   bra      2f
+	   add r0,  %0
+	   .balign  4
+1:	   .long    _GLOBAL_OFFSET_TABLE_
+2:
+"  : "=r" (got) : : "r0");
 #else
 	/* Do things the slow way in C */
 	{
@@ -294,7 +321,7 @@ DL_BOOT(unsigned long args)
 		Elf32_Shdr *shdr;
 		Elf32_Phdr *pt_load;
 
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 		SEND_STDERR("Finding the GOT using C code to read the ELF file\n");
 #endif
 		/* Find where the dynamic linking information section is hiding */
@@ -339,7 +366,7 @@ DL_BOOT(unsigned long args)
 
 	/* Now, finally, fix up the location of the dynamic stuff */
 	dpnt = (Elf32_Dyn *) (*got + load_addr);
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 	SEND_STDERR("First Dynamic section entry=");
 	SEND_ADDRESS_STDERR(dpnt, 1);
 #endif
@@ -354,15 +381,15 @@ DL_BOOT(unsigned long args)
 		_dl_exit(13);
 	}
 
-	tpnt = DL_MALLOC(sizeof(struct elf_resolve));
+	tpnt = LD_MALLOC(sizeof(struct elf_resolve));
 	_dl_memset(tpnt, 0, sizeof(*tpnt));
-	app_tpnt = DL_MALLOC(sizeof(struct elf_resolve));
+	app_tpnt = LD_MALLOC(sizeof(struct elf_resolve));
 	_dl_memset(app_tpnt, 0, sizeof(*app_tpnt));
 
 	/*
 	 * This is used by gdb to locate the chain of shared libraries that are currently loaded.
 	 */
-	debug_addr = DL_MALLOC(sizeof(struct r_debug));
+	debug_addr = LD_MALLOC(sizeof(struct r_debug));
 	_dl_memset(debug_addr, 0, sizeof(*debug_addr));
 
 	/* OK, that was easy.  Next scan the DYNAMIC section of the image.
@@ -483,7 +510,7 @@ DL_BOOT(unsigned long args)
 
 	/* OK, now do the relocations.  We do not do a lazy binding here, so
 	   that once we are done, we have considerably more flexibility. */
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 	SEND_STDERR("About to do library loader relocations.\n");
 #endif
 
@@ -541,7 +568,7 @@ DL_BOOT(unsigned long args)
 					SEND_STDERR(" undefined.\n");
 					goof++;
 				}
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_DEBUG_SYMBOLS
 				SEND_STDERR("About to fixup symbol: ");
 				SEND_STDERR(strtab + symtab[symtab_index].st_name);
 				SEND_STDERR("\n");
@@ -557,9 +584,9 @@ DL_BOOT(unsigned long args)
 	if (goof) {
 		_dl_exit(14);
 	}
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 	/* Wahoo!!! */
-	_dl_dprintf(2, "Done relocating library loader, so we can now\n\tuse globals and make function calls!\n");
+	_dl_dprintf(_dl_debug_file, "Done relocating library loader, so we can now\n\tuse globals and make function calls!\n");
 #endif
 
 	if (argv[0]) {
@@ -594,9 +621,12 @@ DL_BOOT(unsigned long args)
 	 * Transfer control to the application.
 	 */
 	status = 0;					/* Used on x86, but not on other arches */
-#ifdef DL_DEBUG
-	_dl_dprintf(2, "Calling application main()\n");
+#ifdef LD_DEBUG
+	_dl_dprintf(_dl_debug_file, "Calling application main()\n");
 #endif
+#if defined (SUPPORT_LD_DEBUG)
+	if(_dl_debug) _dl_dprintf(_dl_debug_file,"\ntransfering control: %s\n\n", _dl_progname);	
+#endif    
 	START();
 }
 
@@ -628,8 +658,8 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 	tpnt->loadaddr = (char *) load_addr;
 
 	INIT_GOT(lpnt, tpnt);
-#ifdef DL_DEBUG
-	_dl_dprintf(2, "GOT found at %x\n", tpnt);
+#ifdef LD_DEBUG
+	_dl_dprintf(_dl_debug_file, "GOT found at %x\n", lpnt);
 #endif
 	/* OK, this was a big step, now we need to scan all of the user images
 	   and load them properly. */
@@ -728,8 +758,8 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 			if (readsize > 0 && readsize < sizeof(buf)-1) {
 				pnt1 = _dl_strrchr(buf, '/');
 				if (pnt1 && buf != pnt1) {
-#ifdef DL_DEBUG
-					_dl_dprintf(2, "changing tpnt->libname from '%s' to '%s'\n", tpnt->libname, buf);
+#ifdef LD_DEBUG
+					_dl_dprintf(_dl_debug_file, "changing tpnt->libname from '%s' to '%s'\n", tpnt->libname, buf);
 #endif
 					tpnt->libname = _dl_strdup(buf);
 				}
@@ -745,8 +775,8 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 			} else {
 				_dl_ldsopath = tpnt->libname;
 			}
-#ifdef DL_DEBUG
-			_dl_dprintf(2, "Lib Loader:\t(%x) %s\n", tpnt->loadaddr, tpnt->libname);
+#ifdef LD_DEBUG
+			_dl_dprintf(_dl_debug_file, "Lib Loader:\t(%x) %s\n", tpnt->loadaddr, tpnt->libname);
 #endif
 		}
 	}
@@ -774,10 +804,56 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 		}
 	}
 
+#ifdef SUPPORT_LD_DEBUG
+	_dl_debug    = _dl_getenv("LD_DEBUG", envp);
+	if (_dl_debug)
+	{
+	  _dl_debug_detail   = _dl_strstr(_dl_debug, "detail");
+	  _dl_debug_move     = _dl_strstr(_dl_debug, "move");
+	  _dl_debug_symbols  = _dl_strstr(_dl_debug, "sym");
+	  _dl_debug_reloc    = _dl_strstr(_dl_debug, "reloc");
+	  _dl_debug_bindings = _dl_strstr(_dl_debug, "bind");
+	}
+	{
+	  const char *dl_debug_output;
+	  
+	  dl_debug_output = _dl_getenv("LD_DEBUG_OUTPUT", envp);
+
+	  if (dl_debug_output)
+	  {
+	    char tmp[22], *tmp1, *filename;
+	    int len1, len2;
+	    
+	    _dl_memset(tmp, 0, sizeof(tmp));
+	    tmp1=_dl_simple_ltoa( tmp, (unsigned long)_dl_getpid());
+
+	    len1 = _dl_strlen(dl_debug_output);
+	    len2 = _dl_strlen(tmp1);
+
+	    filename = _dl_malloc(len1+len2+2);
+
+	    if (filename)
+	    {
+	      _dl_strcpy (filename, dl_debug_output);
+	      filename[len1] = '.';
+	      _dl_strcpy (&filename[len1+1], tmp1);
+
+	      _dl_debug_file= _dl_open (filename, O_WRONLY|O_CREAT);
+	      if (_dl_debug_file<0)
+	      {
+		_dl_debug_file = 2;
+		_dl_dprintf (2, "can't open file: '%s'\n",filename);
+	      }
+	    }
+	  }
+	}
+	
+	
+#endif	
 	_dl_trace_loaded_objects = _dl_getenv("LD_TRACE_LOADED_OBJECTS", envp);
-#ifndef DL_TRACE
+#ifndef LD_TRACE
 	if (_dl_trace_loaded_objects) {
-		_dl_dprintf(2, "Use the ldd provided by uClibc\n");
+		_dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n");
 		_dl_exit(1);
 	}
 #endif
@@ -809,7 +885,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 			{
 				tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str);
 				if (!tpnt1) {
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 					if (_dl_trace_loaded_objects)
 						_dl_dprintf(1, "\t%s => not found\n", str);
 					else {
@@ -817,14 +893,14 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 						_dl_dprintf(2, "%s: can't load "
 								"library '%s'\n", _dl_progname, str);
 						_dl_exit(15);
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 					}
 #endif
 				} else {
-#ifdef DL_DEBUG
-					_dl_dprintf(2, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
+#ifdef LD_DEBUG
+					_dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
 #endif
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 					if (_dl_trace_loaded_objects
 							&& tpnt1->usage_count==1) {
 						/* this is a real hack to make ldd not print 
@@ -888,7 +964,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 
 						tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2);
 						if (!tpnt1) {
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 							if (_dl_trace_loaded_objects)
 								_dl_dprintf(1, "\t%s => not found\n", cp2);
 							else {
@@ -896,14 +972,14 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 								_dl_dprintf(2, "%s: can't load library '%s'\n", 
 										_dl_progname, cp2);
 								_dl_exit(15);
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 							}
 #endif
 						} else {
-#ifdef DL_DEBUG
-							_dl_dprintf(2, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
+#ifdef LD_DEBUG
+							_dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
 #endif
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 							if (_dl_trace_loaded_objects
 									&& tpnt1->usage_count==1) {
 								_dl_dprintf(1, "\t%s => %s (0x%x)\n", cp2, 
@@ -939,7 +1015,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 				if (tpnt && _dl_strcmp(lpntstr, _dl_get_last_path_component(tpnt->libname)) == 0) {
 					struct elf_resolve *ttmp;
 
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 					if (_dl_trace_loaded_objects && tpnt->usage_count==1) {
 						_dl_dprintf(1, "\t%s => %s (0x%x)\n", 
 								lpntstr, tpnt->libname, (unsigned) tpnt->loadaddr);
@@ -954,6 +1030,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 					rpnt->next = (struct dyn_elf *)
 						_dl_malloc(sizeof(struct dyn_elf));
 					_dl_memset(rpnt->next, 0, sizeof(*(rpnt->next)));
+					rpnt->next->prev = rpnt;
 					rpnt = rpnt->next;
 					rpnt->dyn = tpnt;
 					tpnt->usage_count++;
@@ -963,7 +1040,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 				}
 				if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr)))
 				{
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 					if (_dl_trace_loaded_objects)
 						_dl_dprintf(1, "\t%s => not found\n", lpntstr);
 					else {
@@ -971,14 +1048,14 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 						_dl_dprintf(2, "%s: can't load library '%s'\n", 
 								_dl_progname, lpntstr);
 						_dl_exit(16);
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 					}
 #endif
 				} else {
-#ifdef DL_DEBUG
-					_dl_dprintf(2, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
+#ifdef LD_DEBUG
+					_dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
 #endif
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 					if (_dl_trace_loaded_objects && tpnt1->usage_count==1)
 						_dl_dprintf(1, "\t%s => %s (0x%x)\n", lpntstr, tpnt1->libname, 
 								(unsigned) tpnt1->loadaddr);
@@ -993,7 +1070,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 	_dl_unmap_cache();
 #endif
 	/* ldd uses uses this.  I am not sure how you pick up the other flags */
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 	if (_dl_trace_loaded_objects) {
 		char *_dl_warn = 0;
 		_dl_warn = _dl_getenv("LD_WARN", envp);
@@ -1026,6 +1103,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 			rpnt->next =
 				(struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
 			_dl_memset(rpnt->next, 0, sizeof(*(rpnt->next)));
+			rpnt->next->prev = rpnt;
 			rpnt = rpnt->next;
 		} else {
 			rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
@@ -1034,7 +1112,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 		rpnt->dyn = tpnt;
 		tpnt = NULL;
 	}
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 	if (_dl_trace_loaded_objects) {
 		_dl_dprintf(1, "\t%s => %s (0x%x)\n", rpnt->dyn->libname + (_dl_strlen(_dl_ldsopath)) + 1, 
 				rpnt->dyn->libname, rpnt->dyn->loadaddr);  
@@ -1050,8 +1128,8 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 	_dl_perform_mips_global_got_relocations(_dl_loaded_modules);
 #endif
 
-#ifdef DL_DEBUG
-	_dl_dprintf(2, "Beginning relocation fixups\n");
+#ifdef LD_DEBUG
+	_dl_dprintf(_dl_debug_file, "Beginning relocation fixups\n");
 #endif
 	/*
 	 * OK, now all of the kids are tucked into bed in their proper addresses.
@@ -1065,12 +1143,12 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 	   and we have to manually search for entries that require fixups. 
 	   Solaris gets this one right, from what I understand.  */
 
-#ifdef DL_DEBUG
-	_dl_dprintf(2, "Beginning copy fixups\n");
+#ifdef LD_DEBUG
+	_dl_dprintf(_dl_debug_file, "Beginning copy fixups\n");
 #endif
 	if (_dl_symbol_tables)
 		goof += _dl_copy_fixups(_dl_symbol_tables);
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 	if (goof || _dl_trace_loaded_objects)
 		_dl_exit(0);
 #endif
@@ -1083,13 +1161,13 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 	   up each symbol individually. */
 
 
-	_dl_brkp = (unsigned long *) _dl_find_hash("___brk_addr", NULL, NULL, 0);
+	_dl_brkp = (unsigned long *) _dl_find_hash("___brk_addr", NULL, NULL, symbolrel);
 	
 	if (_dl_brkp) {
 		*_dl_brkp = brk_addr;
 	}
 	_dl_envp =
-		(unsigned long *) _dl_find_hash("__environ", NULL, NULL, 0);
+		(unsigned long *) _dl_find_hash("__environ", NULL, NULL, symbolrel);
 
 	if (_dl_envp) {
 		*_dl_envp = (unsigned long) envp;
@@ -1113,7 +1191,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 
 	}
 #endif
-	_dl_atexit = (int (*)(void *)) _dl_find_hash("atexit", NULL, NULL, 0);
+	_dl_atexit = (int (*)(void *)) _dl_find_hash("atexit", NULL, NULL, symbolrel);
 
 	/*
 	 * OK, fix one more thing - set up the debug_addr structure to point
@@ -1130,33 +1208,48 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 	   function call. */
 	((void (*)(void)) debug_addr->r_brk) ();
 
-#ifdef DL_DEBUG
-	_dl_dprintf(2, "Calling init/fini for shared libraries\n");
+#ifdef LD_DEBUG
+ 	_dl_dprintf(_dl_debug_file, "Calling init/fini for shared libraries\n");
 #endif
-	for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
-		/* Apparently crt1 for the application is responsible for handling this.
+
+	for (rpnt = _dl_symbol_tables; rpnt!=NULL&& rpnt->next!=NULL; rpnt=rpnt->next)
+	  ;
+	  
+	for (;rpnt!=NULL; rpnt=rpnt->prev)
+	{
+  	        tpnt = rpnt->dyn;
+
+	        if (tpnt->libtype == program_interpreter)
+			continue;
+
+		/* Apparently crt0/1 for the application is responsible for handling this.
 		 * We only need to run the init/fini for shared libraries
 		 */
-		if (tpnt->libtype == program_interpreter || tpnt->libtype == elf_executable)
-			continue;
+	        if (tpnt->libtype == elf_executable)
+			break;      /* at this point all shared libs are initialized !! */
+
 		if (tpnt->init_flag & INIT_FUNCS_CALLED)
 			continue;
 		tpnt->init_flag |= INIT_FUNCS_CALLED;
 
 		if (tpnt->dynamic_info[DT_INIT]) {
 			_dl_elf_init = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
+			  
+#if defined (SUPPORT_LD_DEBUG)
+			if(_dl_debug) _dl_dprintf(_dl_debug_file,"\ncalling init: %s\n\n", tpnt->libname);	
+#endif    
 			(*_dl_elf_init) ();
 		}
 		if (_dl_atexit && tpnt->dynamic_info[DT_FINI]) {
 			(*_dl_atexit) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
 		}
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 		else {
 			if (!_dl_atexit)
-				_dl_dprintf(2, "%s: The address of atexit () is 0x0.\n", tpnt->libname);
+				_dl_dprintf(_dl_debug_file, "%s: The address of atexit () is 0x0.\n", tpnt->libname);
 #if 0
 			if (!tpnt->dynamic_info[DT_FINI])
-				_dl_dprintf(2, "%s: Invalid .fini section.\n", tpnt->libname);
+				_dl_dprintf(_dl_debug_file, "%s: Invalid .fini section.\n", tpnt->libname);
 #endif
 		}
 #endif
@@ -1179,6 +1272,10 @@ int _dl_fixup(struct elf_resolve *tpnt)
 
 	if (tpnt->next)
 		goof += _dl_fixup(tpnt->next);
+#if defined (SUPPORT_LD_DEBUG)
+	if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation processing: %s", tpnt->libname);	
+#endif    
+	
 	if (tpnt->dynamic_info[DT_REL]) {
 #ifdef ELF_USES_RELOCA
 		_dl_dprintf(2, "%s: can't handle REL relocation records\n",
@@ -1216,6 +1313,9 @@ int _dl_fixup(struct elf_resolve *tpnt)
 			goof += _dl_parse_relocation_information(tpnt, tpnt->dynamic_info[DT_JMPREL], 
 					tpnt->dynamic_info[DT_PLTRELSZ], 0);
 	}
+#if defined (SUPPORT_LD_DEBUG)
+	if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation processing: %s; finished\n\n", tpnt->libname);	
+#endif    
 	return goof;
 }
 
@@ -1224,8 +1324,8 @@ void *_dl_malloc(int size)
 	void *retval;
 
 #if 0
-#ifdef DL_DEBUG
-	_dl_dprintf(2, "malloc: request for %d bytes\n", size);
+#ifdef LD_DEBUG
+	_dl_dprintf(_dl_debug_file, "malloc: request for %d bytes\n", size);
 #endif
 #endif
 
@@ -1233,8 +1333,8 @@ void *_dl_malloc(int size)
 		return (*_dl_malloc_function) (size);
 
 	if (_dl_malloc_addr - _dl_mmap_zero + size > 4096) {
-#ifdef DL_DEBUG
-		_dl_dprintf(2, "malloc: mmapping more memory\n");
+#ifdef LD_DEBUG
+		_dl_dprintf(_dl_debug_file, "malloc: mmapping more memory\n");
 #endif
 		_dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, size, 
 				PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);

+ 1 - 1
ldso/ldso/m68k/boot1_arch.h

@@ -4,4 +4,4 @@
  * can be done.
  */
 
-#define DL_BOOT(X)   void _dl_boot (X)
+#define LD_BOOT(X)   void _dl_boot (X)

+ 1 - 1
ldso/ldso/m68k/dl-startup.h

@@ -4,4 +4,4 @@
  * can be done.
  */
 
-#define DL_BOOT(X)   void _dl_boot (X)
+#define LD_BOOT(X)   void _dl_boot (X)

+ 35 - 25
ldso/ldso/m68k/elfinterp.c

@@ -1,23 +1,33 @@
-/* Run an ELF binary on a linux system.
-
-   Copyright (C) 1993, Eric Youngdale.
-   Copyright (C) 1995, Andreas Schwab.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-/* Adapted to ELF/68k by Andreas Schwab.  */
+/* vi: set sw=4 ts=4: */
+/* m68k ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
+ *				David Engel, Hongjiu Lu and Mitch D'Souza
+ * Adapted to ELF/68k by Andreas Schwab.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
 
 #ifndef VERBOSE_DLINKER
 #define VERBOSE_DLINKER
@@ -83,21 +93,21 @@ unsigned int _dl_linux_resolver (int dummy1, int dummy2,
   instr_addr = (int) this_reloc->r_offset + (int) tpnt->loadaddr;
   got_addr = (char **) instr_addr;
 
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_DEBUG_SYMBOLS
   _dl_dprintf (2, "Resolving symbol %s\n",
 		strtab + symtab[symtab_index].st_name);
 #endif
 
   /* Get the address of the GOT entry.  */
   new_addr = _dl_find_hash (strtab + symtab[symtab_index].st_name,
-			    tpnt->symbol_scope, tpnt, 0);
+			    tpnt->symbol_scope, tpnt, resolver);
   if (!new_addr)
     {
       _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
 		    _dl_progname, strtab + symtab[symtab_index].st_name);
       _dl_exit (1);
     }
-#ifdef DL_NEVER_FIXUP_SYMBOLS
+#ifdef LD_NEVER_FIXUP_SYMBOLS
   if ((unsigned int) got_addr < 0x40000000) {
       _dl_dprintf (2, "Calling library function: %s\n",
 	      strtab + symtab[symtab_index].st_name);
@@ -202,7 +212,7 @@ _dl_parse_relocation_information (struct elf_resolve *tpnt,
 	  symbol_addr = (unsigned int)
 	    _dl_find_hash (strtab + symtab[symtab_index].st_name,
 			   tpnt->symbol_scope,
-			   reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, 0);
+			   reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, symbolrel);
 
 	  /* We want to allow undefined references to weak symbols -
 	     this might have been intentional.  We should not be
@@ -327,7 +337,7 @@ _dl_parse_copy_information (struct dyn_elf *xpnt, unsigned long rel_addr,
 	{
 	  symbol_addr = (unsigned int)
 	    _dl_find_hash (strtab + symtab[symtab_index].st_name,
-			   xpnt->next, NULL, 1);
+			   xpnt->next, NULL, copyrel);
 	  if (!symbol_addr)
 	    {
 	      _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",

+ 1 - 1
ldso/ldso/mips/boot1_arch.h

@@ -35,4 +35,4 @@ coff:	subu $8, $31, $8
 ");
 
 #define _dl_boot _dl_boot2
-#define DL_BOOT(X)   static void __attribute__ ((unused)) _dl_boot (X)
+#define LD_BOOT(X)   static void __attribute__ ((unused)) _dl_boot (X)

+ 1 - 1
ldso/ldso/mips/dl-startup.h

@@ -35,4 +35,4 @@ coff:	subu $8, $31, $8
 ");
 
 #define _dl_boot _dl_boot2
-#define DL_BOOT(X)   static void __attribute__ ((unused)) _dl_boot (X)
+#define LD_BOOT(X)   static void __attribute__ ((unused)) _dl_boot (X)

+ 33 - 36
ldso/ldso/mips/elfinterp.c

@@ -1,34 +1,31 @@
 /* vi: set sw=4 ts=4: */
-
-/* Run an ELF binary on a linux system.
-
+/* mips/mipsel ELF shared library loader suppport
+ *
    Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com)
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-
-/* Program to load an ELF binary on a linux system, and run it.
-   References to symbols in sharable libraries can be resolved by either
-   an ELF sharable library or a linux style of shared library. */
-
-/* Disclaimer:  I have never seen any AT&T source code for SVr4, nor have
-   I ever taken any courses on internals.  This program was developed using
-   information available through the book "UNIX SYSTEM V RELEASE 4,
-   Programmers guide: Ansi C and Programming Support Tools", which did
-   a more than adequate job of explaining everything required to get this
-   working. */
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
 
 
 extern int _dl_linux_resolve(void);
@@ -55,11 +52,11 @@ unsigned long _dl_linux_resolver(unsigned long sym_index,
 	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
 
 	value = (unsigned long) _dl_find_hash(strtab + sym->st_name,
-		 tpnt->symbol_scope, tpnt, 1);
+		 tpnt->symbol_scope, tpnt, resolver);
 
 	*(got + local_gotno + sym_index - gotsym) = value;
 
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 	_dl_dprintf(2, "---RESOLVER---\n");
 	_dl_dprintf(2, "SYMTAB INDEX: %i\n", sym_index);
 	_dl_dprintf(2, "      GOTSYM: %i\n", gotsym);
@@ -167,7 +164,7 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
 
 		/* Relocate the global GOT entries for the object */
 		while(i--) {
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 			_dl_dprintf(2,"BEFORE: %s=%x\n", strtab + sym->st_name,
 				*got_entry);
 #endif
@@ -176,12 +173,12 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
 					*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, 1);
+						sym->st_name, tpnt->symbol_scope, NULL, copyrel);
 				}
 			}
 			else if (sym->st_shndx == SHN_COMMON) {
 				*got_entry = (unsigned long) _dl_find_hash(strtab +
-					sym->st_name, tpnt->symbol_scope, NULL, 1);
+					sym->st_name, tpnt->symbol_scope, NULL, copyrel);
 			}
 			else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&
 				*got_entry != sym->st_value)
@@ -192,10 +189,10 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
 			}
 			else {
 				*got_entry = (unsigned long) _dl_find_hash(strtab +
-					sym->st_name, tpnt->symbol_scope, NULL, 1);
+					sym->st_name, tpnt->symbol_scope, NULL, copyrel);
 			}
 
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 			if (*got_entry == 0)
 				_dl_dprintf(2,"ZERO: %s\n", strtab + sym->st_name);
 			else

+ 1 - 1
ldso/ldso/powerpc/boot1_arch.h

@@ -17,5 +17,5 @@ _dl_boot:
 ");
 
 #define _dl_boot _dl_boot2
-#define DL_BOOT(X)   static void *  __attribute__ ((unused)) _dl_boot (X)
+#define LD_BOOT(X)   static void *  __attribute__ ((unused)) _dl_boot (X)
 

+ 1 - 1
ldso/ldso/powerpc/dl-startup.h

@@ -17,5 +17,5 @@ _dl_boot:
 ");
 
 #define _dl_boot _dl_boot2
-#define DL_BOOT(X)   static void *  __attribute__ ((unused)) _dl_boot (X)
+#define LD_BOOT(X)   static void *  __attribute__ ((unused)) _dl_boot (X)
 

+ 33 - 23
ldso/ldso/powerpc/elfinterp.c

@@ -1,22 +1,32 @@
-//#define DL_DEBUG
-/* Run an ELF binary on a linux system.
+/* vi: set sw=4 ts=4: */
+/* i386 ELF shared library loader suppport
+ *
+ * Copyright (C) 2001-2002,  David A. Schleef
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
 
-   Copyright (C) 1993, Eric Youngdale.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
 #ifndef VERBOSE_DLINKER
 #define VERBOSE_DLINKER
 #endif
@@ -49,7 +59,7 @@ static const char *_dl_reltypes[] =
    working. */
 
 
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_DEBUG_SYMBOLS
 static void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index);
 static void debug_reloc(ELF_RELOC *rpnt);
 #define DPRINTF(fmt,args...) _dl_dprintf(2,fmt,args)
@@ -161,7 +171,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 	/* Get the address of the GOT entry */
 	targ_addr = (unsigned long) _dl_find_hash(
 		strtab + symtab[symtab_index].st_name, 
-		tpnt->symbol_scope, tpnt, 0);
+		tpnt->symbol_scope, tpnt, resolver);
 	if (!targ_addr) {
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 			_dl_progname, strtab + symtab[symtab_index].st_name);
@@ -338,7 +348,7 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt,
 
 			symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
 					tpnt->symbol_scope,
-					(reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), 0);
+					(reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), symbolrel);
 
 			/*
 			 * We want to allow undefined references to weak symbols - this might
@@ -499,7 +509,7 @@ int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
 
 			symbol_addr = (unsigned long) _dl_find_hash(strtab + 
 				symtab[symtab_index].st_name, xpnt->next, 
-				NULL, 1);
+				NULL, copyrel);
 			if (!symbol_addr) {
 				_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 					_dl_progname, strtab + symtab[symtab_index].st_name);
@@ -551,7 +561,7 @@ static void fixup_jmpslot(unsigned long reloc_addr, unsigned long targ_addr)
 #endif
 
 
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_DEBUG_SYMBOLS
 static void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index)
 {
 	if(symtab_index){

+ 59 - 37
ldso/ldso/readelflib1.c

@@ -1,21 +1,34 @@
-/* Load an ELF sharable library into memory.
-
-   Copyright (C) 1993-1996, Eric Youngdale.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
+/* vi: set sw=4 ts=4: */
+/* Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
+ *				David Engel, Hongjiu Lu and Mitch D'Souza
+ * Copyright (C) 2001-2002, Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
 
 
 /* This file contains the helper routines to load an ELF sharable
@@ -180,8 +193,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 		pnt++;
 	}
 
-#ifdef DL_DEBUG
-	    _dl_dprintf(2, "searching for library: '%s'\n", libname);
+#ifdef LD_DEBUG
+	    _dl_dprintf(_dl_debug_file, "searching for library: '%s'\n", libname);
 #endif
 	/* If the filename has any '/', try it straight and leave it at that.
 	   For IBCS2 compatibility under linux, we substitute the string 
@@ -204,8 +217,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 			if (pnt) {
 				pnt += (unsigned long) tpnt->loadaddr +
 					tpnt->dynamic_info[DT_STRTAB];
-#ifdef DL_DEBUG
-				_dl_dprintf(2, "searching RPATH: '%s'\n", pnt);
+#ifdef LD_DEBUG
+				_dl_dprintf(_dl_debug_file, "searching RPATH: '%s'\n", pnt);
 #endif
 				if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) 
 				{
@@ -217,8 +230,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 
 	/* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
 	if (_dl_library_path) {
-#ifdef DL_DEBUG
-	    _dl_dprintf(2, "searching _dl_library_path: '%s'\n", _dl_library_path);
+#ifdef LD_DEBUG
+	    _dl_dprintf(_dl_debug_file, "searching _dl_library_path: '%s'\n", _dl_library_path);
 #endif
 	    if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL) 
 	    {
@@ -251,8 +264,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 
 	/* Look for libraries wherever the shared library loader
 	 * was installed */
-#ifdef DL_DEBUG
-	_dl_dprintf(2, "searching in ldso dir: %s\n", _dl_ldsopath);
+#ifdef LD_DEBUG
+	_dl_dprintf(_dl_debug_file, "searching in ldso dir: %s\n", _dl_ldsopath);
 #endif
 	if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt)) != NULL) 
 	{
@@ -262,8 +275,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 
 	/* Lastly, search the standard list of paths for the library.
 	   This list must exactly match the list in uClibc/ldso/util/ldd.c */
-#ifdef DL_DEBUG
-	    _dl_dprintf(2, "searching full lib path list\n");
+#ifdef LD_DEBUG
+	    _dl_dprintf(_dl_debug_file, "searching full lib path list\n");
 #endif
 	if ((tpnt1 = search_for_named_library(libname, secure, 
 			UCLIBC_TARGET_PREFIX "/usr/lib:"
@@ -282,8 +295,8 @@ goof:
 	if (_dl_internal_error_number)
 		_dl_error_number = _dl_internal_error_number;
 	else
-		_dl_error_number = DL_ERROR_NOFILE;
-#ifdef DL_DEBUG
+		_dl_error_number = LD_ERROR_NOFILE;
+#ifdef LD_DEBUG
 	    _dl_dprintf(2, "Bummer: could not find '%s'!\n", libname);
 #endif
 	return NULL;
@@ -323,6 +336,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 			(*rpnt)->next = (struct dyn_elf *)
 				_dl_malloc(sizeof(struct dyn_elf));
 			_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+			(*rpnt)->next->prev = (*rpnt);
 			*rpnt = (*rpnt)->next;
 			(*rpnt)->dyn = tpnt;
 			tpnt->symbol_scope = _dl_symbol_tables;
@@ -352,7 +366,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 		 */
 		_dl_dprintf(2, "%s: can't open '%s'\n", _dl_progname, libname);
 #endif
-		_dl_internal_error_number = DL_ERROR_NOFILE;
+		_dl_internal_error_number = LD_ERROR_NOFILE;
 		return NULL;
 	}
 
@@ -365,7 +379,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	{
 		_dl_dprintf(2, "%s: '%s' is not an ELF file\n", _dl_progname,
 					 libname);
-		_dl_internal_error_number = DL_ERROR_NOTELF;
+		_dl_internal_error_number = LD_ERROR_NOTELF;
 		_dl_close(infile);
 		return NULL;
 	};
@@ -377,7 +391,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 		)) 
 	{
 		_dl_internal_error_number = 
-		    (epnt->e_type != ET_DYN ? DL_ERROR_NOTDYN : DL_ERROR_NOTMAGIC);
+		    (epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC);
 		_dl_dprintf(2, "%s: '%s' is not an ELF executable for " ELF_TARGET 
 			"\n", _dl_progname, libname);
 		_dl_close(infile);
@@ -424,7 +438,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 		maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
 	if (_dl_mmap_check_error(status)) {
 		_dl_dprintf(2, "%s: can't map %s\n", _dl_progname, libname);
-		_dl_internal_error_number = DL_ERROR_MMAP_FAILED;
+		_dl_internal_error_number = LD_ERROR_MMAP_FAILED;
 		_dl_close(infile);
 		return NULL;
 	};
@@ -457,7 +471,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 				if (_dl_mmap_check_error(status)) {
 					_dl_dprintf(2, "%s: can't map '%s'\n", 
 						_dl_progname, libname);
-					_dl_internal_error_number = DL_ERROR_MMAP_FAILED;
+					_dl_internal_error_number = LD_ERROR_MMAP_FAILED;
 					_dl_munmap((char *) libaddr, maxvma - minvma);
 					_dl_close(infile);
 					return NULL;
@@ -488,7 +502,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 					infile, ppnt->p_offset & OFFS_ALIGN);
 			if (_dl_mmap_check_error(status)) {
 				_dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname);
-				_dl_internal_error_number = DL_ERROR_MMAP_FAILED;
+				_dl_internal_error_number = LD_ERROR_MMAP_FAILED;
 				_dl_munmap((char *) libaddr, maxvma - minvma);
 				_dl_close(infile);
 				return NULL;
@@ -516,7 +530,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	/* Start by scanning the dynamic section to get all of the pointers */
 
 	if (!dynamic_addr) {
-		_dl_internal_error_number = DL_ERROR_NODYNAMIC;
+		_dl_internal_error_number = LD_ERROR_NODYNAMIC;
 		_dl_dprintf(2, "%s: '%s' is missing a dynamic section\n", 
 			_dl_progname, libname);
 		return NULL;
@@ -580,6 +594,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 		(*rpnt)->next = (struct dyn_elf *)
 			_dl_malloc(sizeof(struct dyn_elf));
 		_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+		(*rpnt)->next->prev = (*rpnt);
 		*rpnt = (*rpnt)->next;
 		(*rpnt)->dyn = tpnt;
 		tpnt->symbol_scope = _dl_symbol_tables;
@@ -626,6 +641,10 @@ int _dl_copy_fixups(struct dyn_elf *rpnt)
 		return goof;
 	tpnt->init_flag |= COPY_RELOCS_DONE;
 
+#if defined (SUPPORT_LD_DEBUG)
+	if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation copy fixups: %s", tpnt->libname);	
+#endif    
+
 #ifdef ELF_USES_RELOCA
 	goof += _dl_parse_copy_information(rpnt, 
 		tpnt->dynamic_info[DT_RELA], tpnt->dynamic_info[DT_RELASZ], 0);
@@ -635,5 +654,8 @@ int _dl_copy_fixups(struct dyn_elf *rpnt)
 		tpnt->dynamic_info[DT_RELSZ], 0);
 
 #endif
+#if defined (SUPPORT_LD_DEBUG)
+	if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation copy fixups: %s; finished\n\n", tpnt->libname);	
+#endif    
 	return goof;
 }

+ 23 - 0
ldso/ldso/sh/boot1_arch.h

@@ -0,0 +1,23 @@
+/* Any assmbly language/system dependent hacks needed to setup boot1.c so it
+ * will work as expected and cope with whatever platform specific wierdness is
+ * needed for this architecture.  */
+
+asm("\
+	.text
+	.globl	_dl_boot
+_dl_boot:
+        mov	r15, r4
+        mov.l	.L_dl_boot2, r1
+	mova	.L_dl_boot2, r0
+	add	r1, r0
+	jsr	@r0
+	 add	#4, r4
+	jmp	@r0
+	 mov    #0, r4        /* call _start with arg == 0 */
+.L_dl_boot2:\n\
+	.long	_dl_boot2-.\n\
+	.previous\n\
+");
+
+#define _dl_boot _dl_boot2
+#define LD_BOOT(X)   static void *  __attribute__ ((unused)) _dl_boot (X)

+ 23 - 0
ldso/ldso/sh/dl-startup.h

@@ -0,0 +1,23 @@
+/* Any assmbly language/system dependent hacks needed to setup boot1.c so it
+ * will work as expected and cope with whatever platform specific wierdness is
+ * needed for this architecture.  */
+
+asm("\
+	.text
+	.globl	_dl_boot
+_dl_boot:
+        mov	r15, r4
+        mov.l	.L_dl_boot2, r1
+	mova	.L_dl_boot2, r0
+	add	r1, r0
+	jsr	@r0
+	 add	#4, r4
+	jmp	@r0
+	 mov    #0, r4        /* call _start with arg == 0 */
+.L_dl_boot2:\n\
+	.long	_dl_boot2-.\n\
+	.previous\n\
+");
+
+#define _dl_boot _dl_boot2
+#define LD_BOOT(X)   static void *  __attribute__ ((unused)) _dl_boot (X)

+ 7 - 0
ldso/ldso/sh/dl-syscalls.h

@@ -0,0 +1,7 @@
+/* Define the __set_errno macro as nothing so that we don't bother
+ * setting errno, which is important since we make system calls
+ * before the errno symbol is dynamicly linked. */
+
+#define __set_errno(X)
+#include "sys/syscall.h"
+

+ 145 - 0
ldso/ldso/sh/dl-sysdep.h

@@ -0,0 +1,145 @@
+/*
+ * Various assmbly language/system dependent  hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ */
+
+/* 
+ * Define this if the system uses RELOCA.
+ */
+#define ELF_USES_RELOCA
+
+/*
+ * Get a pointer to the argv array.  On many platforms this can be just
+ * the address if the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*)   ARGS)
+
+/*
+ * Initialization sequence for a GOT.
+ */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{				\
+  GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
+  GOT_BASE[1] = (unsigned long) (MODULE); \
+}
+
+/*
+ * Here is a macro to perform a relocation.  This is only used when
+ * bootstrapping the dynamic loader.  RELP is the relocation that we
+ * are performing, REL is the pointer to the address we are relocating.
+ * SYMBOL is the symbol involved in the relocation, and LOAD is the
+ * load address.
+ */
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)		\
+	switch(ELF32_R_TYPE((RELP)->r_info)){			\
+	case R_SH_REL32:					\
+		*(REL) += (RELP)->r_addend - (LOAD);		\
+		break;						\
+	case R_SH_DIR32:					\
+		*(REL) += (SYMBOL) + (RELP)->r_addend;		\
+		break;						\
+	case R_SH_RELATIVE:					\
+		*(REL) += (LOAD);				\
+		break;						\
+	case R_SH_NONE:						\
+		break;						\
+	default:						\
+		SEND_STDERR("BOOTSTRAP_RELOC: unhandled reloc type "); \
+		SEND_NUMBER_STDERR(ELF32_R_TYPE((RELP)->r_info), 1); \
+		SEND_STDERR("REL, SYMBOL, LOAD: ");		\
+		SEND_ADDRESS_STDERR(REL, 0);			\
+		SEND_STDERR(", ");				\
+		SEND_ADDRESS_STDERR(SYMBOL, 0);			\
+		SEND_STDERR(", ");				\
+		SEND_ADDRESS_STDERR(LOAD, 1);			\
+		_dl_exit(1);					\
+	}
+
+
+/*
+ * Transfer control to the user's application, once the dynamic loader
+ * is done.  This routine has to exit the current function, then 
+ * call the _dl_elf_main function.
+ */
+
+#define START()   return _dl_elf_main;
+
+
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+
+#define MAGIC1 EM_SH
+#undef  MAGIC2
+/* Used for error messages */
+#define ELF_TARGET "sh"
+
+struct elf_resolve;
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+static __inline__ unsigned int
+_dl_urem(unsigned int n, unsigned int base)
+{
+register unsigned int __r0 __asm__ ("r0");
+register unsigned int __r4 __asm__ ("r4") = n;
+register unsigned int __r5 __asm__ ("r5") = base;
+
+	__asm__ ("
+		mov	#0, r0
+		div0u
+
+		! get one bit from the msb of the numerator into the T
+		! bit and divide it by whats in %2.  Put the answer bit
+		! into the T bit so it can come out again at the bottom
+
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+ 
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4
+		mov  r4, r0
+"
+		: "=r" (__r0)
+		: "r" (__r4), "r" (__r5)
+		: "r4", "cc");
+
+	return n - (base * __r0);
+}
+
+#define do_rem(result, n, base)		((result) = _dl_urem((n), (base)))
+
+/* 4096 bytes alignment */
+#define PAGE_ALIGN 0xfffff000
+#define ADDR_ALIGN 0xfff
+#define OFFS_ALIGN 0x7ffff000

+ 416 - 0
ldso/ldso/sh/elfinterp.c

@@ -0,0 +1,416 @@
+/* vi: set sw=4 ts=4: */
+/* SuperH ELF shared library loader suppport
+ *
+ * Copyright (C) 2002, Stefan Allius <allius@atecom.com> and 
+ *                     Eddie C. Dost <ecd@atecom.com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_DEBUG_SYMBOLS)
+static const char *_dl_reltypes_tab[] =
+{
+  [0]	"R_SH_NONE",	"R_SH_DIR32",	"R_SH_REL32",	"R_SH_DIR8WPN",
+  [4]	"R_SH_IND12W",	"R_SH_DIR8WPL",	"R_SH_DIR8WPZ",	"R_SH_DIR8BP",
+  [8]	"R_SH_DIR8W",	"R_SH_DIR8L",
+ [25]	"R_SH_SWITCH16","R_SH_SWITCH32","R_SH_USES",
+ [28]	"R_SH_COUNT",	"R_SH_ALIGN",	"R_SH_CODE",	"R_SH_DATA",
+ [32]	"R_SH_LABEL",	"R_SH_SWITCH8",	"R_SH_GNU_VTINHERIT","R_SH_GNU_VTENTRY",
+[160]	"R_SH_GOT32",	"R_SH_PLT32",	"R_SH_COPY",	"R_SH_GLOB_DAT",
+[164]	"R_SH_JMP_SLOT","R_SH_RELATIVE","R_SH_GOTOFF",	"R_SH_GOTPC",
+};
+
+static const char *
+_dl_reltypes(int type)
+{
+  static char buf[22];  
+  const char *str;
+  
+  if (type >= (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\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";
+    
+#ifdef ELF_USES_RELOCA
+    _dl_dprintf(_dl_debug_file, "\n%s\toffset=%x\taddend=%x %s",
+		_dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
+		rpnt->r_offset,
+		rpnt->r_addend,
+		sym);
+#else
+    _dl_dprintf(_dl_debug_file, "\n%s\toffset=%x %s",
+		_dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
+		rpnt->r_offset,
+		sym);
+#endif
+  }
+}
+#endif
+
+/* Program to load an ELF binary on a linux system, and run it.
+   References to symbols in sharable libraries can be resolved by either
+   an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer:  I have never seen any AT&T source code for SVr4, nor have
+   I ever taken any courses on internals.  This program was developed using
+   information available through the book "UNIX SYSTEM V RELEASE 4,
+   Programmers guide: Ansi C and Programming Support Tools", which did
+   a more than adequate job of explaining everything required to get this
+   working. */
+
+extern int _dl_linux_resolve(void);
+
+unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+	int reloc_type;
+	ELF_RELOC *this_reloc;
+	char *strtab;
+	Elf32_Sym *symtab;
+	int symtab_index;
+	char *rel_addr;
+	char *new_addr;
+	char **got_addr;
+	unsigned long instr_addr;
+
+	rel_addr = (char *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
+
+	this_reloc = (ELF_RELOC *) (rel_addr + reloc_entry);
+	reloc_type = ELF32_R_TYPE(this_reloc->r_info);
+	symtab_index = ELF32_R_SYM(this_reloc->r_info);
+
+	symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
+	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+
+	if (reloc_type != R_SH_JMP_SLOT) {
+	  _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", 
+		       _dl_progname);
+	  _dl_exit(1);
+	}
+	
+	/* Address of jump instruction to fix up */
+	instr_addr = ((unsigned long) this_reloc->r_offset + 
+			(unsigned long) tpnt->loadaddr);
+	got_addr = (char **) instr_addr;
+
+
+	/* Get the address of the GOT entry */
+	new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
+		tpnt->symbol_scope, tpnt, resolver);
+	if (!new_addr) {
+		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
+			_dl_progname, strtab + symtab[symtab_index].st_name);
+		_dl_exit(1);
+	}
+
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_NEVER_FIXUP_SYMBOLS)
+	if ((unsigned long) got_addr < 0x20000000)
+	{
+#ifndef SUPPORT_LD_DEBUG
+          if (_dl_debug_bindings)
+	  {
+	    _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
+			strtab + symtab[symtab_index].st_name);
+	    if(_dl_debug_detail) _dl_dprintf(_dl_debug_file, "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
+	  }
+#endif	  
+#ifndef LD_NEVER_FIXUP_SYMBOLS
+	  *got_addr = new_addr;
+#endif		
+	} else {
+	  *got_addr = new_addr;
+	}
+#else
+	*got_addr = new_addr;
+#endif
+
+	return (unsigned long) new_addr;
+}
+
+
+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))
+{
+	int i;
+	char *strtab;
+	int goof = 0;
+	Elf32_Sym *symtab;
+	ELF_RELOC *rpnt;
+	int symtab_index;
+	/* Now parse the relocation information */
+
+	rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
+	rel_size = rel_size / sizeof(ELF_RELOC);
+
+	symtab = (Elf32_Sym *) (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 '%s'\n");
+			goof += res;
+		}
+	  }
+	  return goof;
+}
+
+
+static int
+_dl_do_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;
+  
+	reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+	reloc_type = ELF32_R_TYPE(rpnt->r_info);
+	symtab_index = ELF32_R_SYM(rpnt->r_info);
+	symbol_addr = 0;
+
+	if (symtab_index) {
+
+
+		symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
+				scope, 
+				(reloc_type == R_SH_JMP_SLOT ? tpnt : NULL), symbolrel);
+
+		/*
+		 * We want to allow undefined references to weak symbols - this might
+		 * have been intentional.  We should not be linking local symbols
+		 * here, so all bases should be covered.
+		 */
+		if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
+			goof++;
+		}
+	}
+
+
+#if defined (SUPPORT_LD_DEBUG)
+	{
+	    unsigned long old_val = *reloc_addr;
+#endif
+	    switch (reloc_type) {
+		case R_SH_NONE:
+			break;
+		case R_SH_COPY:
+			/* handled later on */
+			break;
+		case R_SH_DIR32:
+			*reloc_addr += symbol_addr + rpnt->r_addend;
+			break;
+		case R_SH_JMP_SLOT:
+			*reloc_addr = symbol_addr + rpnt->r_addend;
+			break;
+		case R_SH_REL32:
+			*reloc_addr += rpnt->r_addend -
+					(unsigned long) tpnt->loadaddr;
+			break;
+		case R_SH_RELATIVE:
+			*reloc_addr += (unsigned long) tpnt->loadaddr;
+			break;
+		default:
+			return -1; /*call _dl_exit(1) */
+	    }
+#if defined (SUPPORT_LD_DEBUG)
+	    if(_dl_debug_reloc && _dl_debug_detail)
+	       _dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
+	}
+	
+#endif
+
+	return goof;
+}
+ 
+	  
+static int
+_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
+		   ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
+{
+        int reloc_type;
+	unsigned long *reloc_addr;
+
+	reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+	reloc_type = ELF32_R_TYPE(rpnt->r_info);
+  
+#if defined (SUPPORT_LD_DEBUG)
+	{
+	    unsigned long old_val = *reloc_addr;
+#endif
+	    switch (reloc_type) {
+	      case R_SH_NONE:
+		break;
+	      case R_SH_JMP_SLOT:
+		*reloc_addr += (unsigned long) tpnt->loadaddr;
+		break;
+	      default:
+	        return -1; /*call _dl_exit(1) */
+	    }
+#if defined (SUPPORT_LD_DEBUG)
+	    if(_dl_debug_reloc && _dl_debug_detail)
+	       _dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
+	}
+	
+#endif
+	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. */
+
+/* No, there are cases where the SVr4 linker fails to emit COPY relocs
+   at all */
+static int
+_dl_do_copy (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;
+	  
+	reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+	reloc_type = ELF32_R_TYPE(rpnt->r_info);
+	if (reloc_type != R_SH_COPY) 
+	    return 0;
+	symtab_index = ELF32_R_SYM(rpnt->r_info);
+	symbol_addr = 0;
+		
+	if (symtab_index) {
+
+		symbol_addr = (unsigned long) _dl_find_hash(strtab + 
+			symtab[symtab_index].st_name, 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",
+			     strtab + symtab[symtab_index].st_name,
+			     symtab[symtab_index].st_size,
+			     symbol_addr, symtab[symtab_index].st_value);
+#endif
+		_dl_memcpy((char *) symtab[symtab_index].st_value, 
+			(char *) symbol_addr, symtab[symtab_index].st_size);
+	}
+
+	return goof;
+}
+
+
+void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, 
+	unsigned long rel_addr, unsigned long rel_size, int type)
+{
+  (void)_dl_parse(tpnt, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
+	unsigned long rel_addr, unsigned long rel_size, int type)
+{
+  return _dl_parse(tpnt, tpnt->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+}
+
+int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr, 
+	unsigned long rel_size, int type)
+{
+  return _dl_parse(xpnt->dyn, xpnt->next, rel_addr, rel_size, _dl_do_copy);
+}
+
+

+ 7 - 0
ldso/ldso/sh/ld_syscalls.h

@@ -0,0 +1,7 @@
+/* Define the __set_errno macro as nothing so that we don't bother
+ * setting errno, which is important since we make system calls
+ * before the errno symbol is dynamicly linked. */
+
+#define __set_errno(X)
+#include "sys/syscall.h"
+

+ 145 - 0
ldso/ldso/sh/ld_sysdep.h

@@ -0,0 +1,145 @@
+/*
+ * Various assmbly language/system dependent  hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ */
+
+/* 
+ * Define this if the system uses RELOCA.
+ */
+#define ELF_USES_RELOCA
+
+/*
+ * Get a pointer to the argv array.  On many platforms this can be just
+ * the address if the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*)   ARGS)
+
+/*
+ * Initialization sequence for a GOT.
+ */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{				\
+  GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
+  GOT_BASE[1] = (unsigned long) (MODULE); \
+}
+
+/*
+ * Here is a macro to perform a relocation.  This is only used when
+ * bootstrapping the dynamic loader.  RELP is the relocation that we
+ * are performing, REL is the pointer to the address we are relocating.
+ * SYMBOL is the symbol involved in the relocation, and LOAD is the
+ * load address.
+ */
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)		\
+	switch(ELF32_R_TYPE((RELP)->r_info)){			\
+	case R_SH_REL32:					\
+		*(REL) += (RELP)->r_addend - (LOAD);		\
+		break;						\
+	case R_SH_DIR32:					\
+		*(REL) += (SYMBOL) + (RELP)->r_addend;		\
+		break;						\
+	case R_SH_RELATIVE:					\
+		*(REL) += (LOAD);				\
+		break;						\
+	case R_SH_NONE:						\
+		break;						\
+	default:						\
+		SEND_STDERR("BOOTSTRAP_RELOC: unhandled reloc type "); \
+		SEND_NUMBER_STDERR(ELF32_R_TYPE((RELP)->r_info), 1); \
+		SEND_STDERR("REL, SYMBOL, LOAD: ");		\
+		SEND_ADDRESS_STDERR(REL, 0);			\
+		SEND_STDERR(", ");				\
+		SEND_ADDRESS_STDERR(SYMBOL, 0);			\
+		SEND_STDERR(", ");				\
+		SEND_ADDRESS_STDERR(LOAD, 1);			\
+		_dl_exit(1);					\
+	}
+
+
+/*
+ * Transfer control to the user's application, once the dynamic loader
+ * is done.  This routine has to exit the current function, then 
+ * call the _dl_elf_main function.
+ */
+
+#define START()   return _dl_elf_main;
+
+
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+
+#define MAGIC1 EM_SH
+#undef  MAGIC2
+/* Used for error messages */
+#define ELF_TARGET "sh"
+
+struct elf_resolve;
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+static __inline__ unsigned int
+_dl_urem(unsigned int n, unsigned int base)
+{
+register unsigned int __r0 __asm__ ("r0");
+register unsigned int __r4 __asm__ ("r4") = n;
+register unsigned int __r5 __asm__ ("r5") = base;
+
+	__asm__ ("
+		mov	#0, r0
+		div0u
+
+		! get one bit from the msb of the numerator into the T
+		! bit and divide it by whats in %2.  Put the answer bit
+		! into the T bit so it can come out again at the bottom
+
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+ 
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4 ; div1 r5, r0
+		rotcl	r4
+		mov  r4, r0
+"
+		: "=r" (__r0)
+		: "r" (__r4), "r" (__r5)
+		: "r4", "cc");
+
+	return n - (base * __r0);
+}
+
+#define do_rem(result, n, base)		((result) = _dl_urem((n), (base)))
+
+/* 4096 bytes alignment */
+#define PAGE_ALIGN 0xfffff000
+#define ADDR_ALIGN 0xfff
+#define OFFS_ALIGN 0x7ffff000

+ 69 - 0
ldso/ldso/sh/resolve.S

@@ -0,0 +1,69 @@
+/*
+ * Stolen from glibc-2.2.2 by Eddie C. Dost <ecd@atecom.com>
+ */
+
+	.text
+	.globl	_dl_linux_resolve
+	.type	_dl_linux_resolve, @function
+	.balign	16
+_dl_linux_resolve:
+	mov.l	r3, @-r15
+	mov.l	r4, @-r15
+	mov.l	r5, @-r15
+	mov.l	r6, @-r15
+	mov.l	r7, @-r15
+	mov.l	r12, @-r15
+	movt	r3		! Save T flag
+	mov.l	r3, @-r15
+
+#ifdef HAVE_FPU
+	sts.l	fpscr, @-r15
+	mov	#8,r3
+	swap.w	r3, r3
+	lds	r3, fpscr
+	fmov.s	fr11, @-r15
+	fmov.s	fr10, @-r15
+	fmov.s	fr9, @-r15
+	fmov.s	fr8, @-r15
+	fmov.s	fr7, @-r15
+	fmov.s	fr6, @-r15
+	fmov.s	fr5, @-r15
+	fmov.s	fr4, @-r15
+#endif
+	sts.l	pr, @-r15
+
+	mov	r2, r4		! link map address
+
+	mov.l	3f, r0
+	jsr	@r0		! Call resolver
+	 mov	r1, r5		! Reloc offset
+
+	lds.l	@r15+, pr	! Get register content back
+
+#ifdef HAVE_FPU
+	fmov.s	@r15+, fr4
+	fmov.s	@r15+, fr5
+	fmov.s	@r15+, fr6
+	fmov.s	@r15+, fr7
+	fmov.s	@r15+, fr8
+	fmov.s	@r15+, fr9
+	fmov.s	@r15+, fr10
+	fmov.s	@r15+, fr11
+	lds.l	@r15+, fpscr
+#endif
+
+	mov.l	@r15+, r3
+	shal	r3		! Load T flag
+	mov.l	@r15+, r12
+	mov.l	@r15+, r7
+	mov.l	@r15+, r6
+	mov.l	@r15+, r5
+	mov.l	@r15+, r4
+	jmp	@r0		! Jump to function address
+	 mov.l	@r15+, r3
+
+	.balign	4
+3:
+	.long	_dl_linux_resolver
+	.size	_dl_linux_resolve, . - _dl_linux_resolve
+

+ 1 - 1
ldso/ldso/sparc/boot1_arch.h

@@ -4,4 +4,4 @@
  * can be done.
  */
 
-#define DL_BOOT(X)   void _dl_boot (X)
+#define LD_BOOT(X)   void _dl_boot (X)

+ 1 - 1
ldso/ldso/sparc/dl-startup.h

@@ -4,4 +4,4 @@
  * can be done.
  */
 
-#define DL_BOOT(X)   void _dl_boot (X)
+#define LD_BOOT(X)   void _dl_boot (X)

+ 34 - 22
ldso/ldso/sparc/elfinterp.c

@@ -1,21 +1,33 @@
-/* Run an ELF binary on a linux system.
+/* vi: set sw=4 ts=4: */
+/* sparc ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
+ *				David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
 
-   Copyright (C) 1995, Eric Youngdale.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
 #ifndef VERBOSE_DLINKER
 #define VERBOSE_DLINKER
 #endif
@@ -91,20 +103,20 @@ unsigned int _dl_linux_resolver(unsigned int reloc_entry, unsigned int * plt)
 
   _dl_dprintf(2, "symtab_index %d\n", symtab_index);
 
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_DEBUG_SYMBOLS
   _dl_dprintf(2, "Resolving symbol %s\n",
 	strtab + symtab[symtab_index].st_name);
 #endif
 
   /* Get the address of the GOT entry */
   new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-  			tpnt->symbol_scope, tpnt, 0);
+  			tpnt->symbol_scope, tpnt, resolver);
   if(!new_addr) {
     _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
 	       _dl_progname, strtab + symtab[symtab_index].st_name);
     _dl_exit(31);
   };
-#ifdef DL_NEVER_FIXUP_SYMBOLS
+#ifdef LD_NEVER_FIXUP_SYMBOLS
   if((unsigned int) got_addr < 0x40000000) {
     _dl_dprintf(2, "Calling library function: %s\n",
 	       strtab + symtab[symtab_index].st_name);
@@ -202,7 +214,7 @@ int _dl_parse_relocation_information(struct elf_resolve * tpnt, int rel_addr,
       symbol_addr = (unsigned int) 
 	_dl_find_hash(strtab + symtab[symtab_index].st_name,
 			      tpnt->symbol_scope,
-		      (reloc_type == R_SPARC_JMP_SLOT ? tpnt : NULL), 0);
+		      (reloc_type == R_SPARC_JMP_SLOT ? tpnt : NULL), symbolrel);
 
       if(!symbol_addr &&
 	 ELF32_ST_BIND(symtab [symtab_index].st_info) == STB_GLOBAL) {
@@ -319,7 +331,7 @@ int _dl_parse_copy_information(struct dyn_elf * xpnt, int rel_addr,
 
       symbol_addr = (unsigned int) 
 	_dl_find_hash(strtab + symtab[symtab_index].st_name,
-			      xpnt->next, NULL, 1);
+			      xpnt->next, NULL, copyrel);
       if(!symbol_addr) {
 	_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
 		   _dl_progname, strtab + symtab[symtab_index].st_name);