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 23 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)
 # (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 
 # Since this currently only saves about 300 bytes, I'm going to leave 
 # it enabled...
 # it enabled...
-XXFLAGS+= -DDL_TRACE
+XXFLAGS+= -DLD_TRACE
 
 
-# Enable this to enable debugging output from ld.so
+# Enable this to enable all the code needed for debugging the runtime 
-#XXFLAGS+= -DDL_DEBUG
+# linking of an application using the LD_DEBUG environment variable:
-#XXFLAGS+= -DDL_DEBUG_SYMBOLS
+#   LD_DEBUG=token1,token2,..  prog
-#Enable this to never actually fixup symbols so you can watch each call...
+# enables diagnostics to the stderr.
-#XXFLAGS+= -DDL_NEVER_FIXUP_SYMBOLS
+# 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)\" \
 XXFLAGS+=-DUCLIBC_TARGET_PREFIX=\"$(TARGET_PREFIX)\" \
 	-DUCLIBC_DEVEL_PREFIX=\"$(DEVEL_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 _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 */
  /* 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 _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 */
  /* 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.
+/* vi: set sw=4 ts=4: */
-
+/* ARM ELF shared library loader suppport
-   Copyright (C) 1993, Eric Youngdale.
+ *
-
+ * 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
+ * All rights reserved.
-   the Free Software Foundation; either version 2, or (at your option)
+ *
-   any later version.
+ * Redistribution and use in source and binary forms, with or without
-
+ * modification, are permitted provided that the following conditions
-   This program is distributed in the hope that it will be useful,
+ * are met:
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * 1. Redistributions of source code must retain the above copyright
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    notice, this list of conditions and the following disclaimer.
-   GNU General Public License for more details.
+ * 2. The name of the above contributors may not be
-
+ *    used to endorse or promote products derived from this software
-   You should have received a copy of the GNU General Public License
+ *    without specific prior written permission.
-   along with this program; if not, write to the Free Software
+ *
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
-
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-#ifndef VERBOSE_DLINKER
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-#define VERBOSE_DLINKER
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
-#endif
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-#ifdef VERBOSE_DLINKER
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-static const char *_dl_reltypes[] =
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-	{ "R_ARM_NONE", "R_ARM_PC24", "R_ARM_ABS32", "R_ARM_REL32",
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-	"R_ARM_PC13", "R_ARM_ABS16", "R_ARM_ABS12", "R_ARM_THM_ABS5",
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-	"R_ARM_ABS8", "R_ARM_SBREL32", "R_ARM_THM_PC22", "R_ARM_THM_PC8",
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-	"R_ARM_AMP_VCALL9", "R_ARM_SWI24", "R_ARM_THM_SWI8", "R_ARM_XPC25",
+ * SUCH DAMAGE.
-	"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",
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_DEBUG_SYMBOLS)
-	"R_ARM_ALU_PCREL_23_15", "R_ARM_LDR_SBREL_11_0", "R_ARM_ALU_SBREL_19_12",
+static const char *_dl_reltypes_tab[] =
-	"R_ARM_ALU_SBREL_27_20", "R_ARM_GNU_VTENTRY", "R_ARM_GNU_VTINHERIT",
+  [0]	"R_ARM_NONE",	    "R_ARM_PC24",	"R_ARM_ABS32",		"R_ARM_REL32",
-	"R_ARM_THM_PC11", "R_ARM_THM_PC9", "R_ARM_RXPC25", "R_ARM_RSBREL32",
+  [4]	"R_ARM_PC13",	    "R_ARM_ABS16",	"R_ARM_ABS12",		"R_ARM_THM_ABS5",
-	"R_ARM_THM_RPC22", "R_ARM_RREL32", "R_ARM_RABS22", "R_ARM_RPC24",
+  [8]	"R_ARM_ABS8",		"R_ARM_SBREL32","R_ARM_THM_PC22",	"R_ARM_THM_PC8",
-	"R_ARM_RBASE", "R_ARM_NUM"
+  [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
 #endif
 
 
 /* Program to load an ELF binary on a linux system, and run it.
 /* 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
    a more than adequate job of explaining everything required to get this
    working. */
    working. */
 
 
-
 extern int _dl_linux_resolve(void);
 extern int _dl_linux_resolve(void);
 
 
 unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 {
 {
 	int reloc_type;
 	int reloc_type;
-	Elf32_Rel *this_reloc;
+	ELF_RELOC *this_reloc;
 	char *strtab;
 	char *strtab;
 	Elf32_Sym *symtab;
 	Elf32_Sym *symtab;
-	Elf32_Rel *rel_addr;
+	ELF_RELOC *rel_addr;
 	int symtab_index;
 	int symtab_index;
 	char *new_addr;
 	char *new_addr;
 	char **got_addr;
 	char **got_addr;
 	unsigned long instr_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);
 	this_reloc = rel_addr + (reloc_entry >> 3);
 	reloc_type = ELF32_R_TYPE(this_reloc->r_info);
 	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);
 	symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
 	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
 	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
 
 
+
 	if (reloc_type != R_ARM_JUMP_SLOT) {
 	if (reloc_type != R_ARM_JUMP_SLOT) {
-	  _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", 
+		_dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", 
-		       _dl_progname);
+			_dl_progname);
-	  _dl_exit(1);
+		_dl_exit(1);
 	};
 	};
-	
+
 	/* Address of jump instruction to fix up */
 	/* Address of jump instruction to fix up */
 	instr_addr = ((unsigned long) this_reloc->r_offset + 
 	instr_addr = ((unsigned long) this_reloc->r_offset + 
-			(unsigned long) tpnt->loadaddr);
+		(unsigned long) tpnt->loadaddr);
 	got_addr = (char **) instr_addr;
 	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 */
 	/* Get the address of the GOT entry */
 	new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
 	new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-		tpnt->symbol_scope, tpnt, 0);
+		tpnt->symbol_scope, tpnt, resolver);
 	if (!new_addr) {
 	if (!new_addr) {
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 			_dl_progname, strtab + symtab[symtab_index].st_name);
 			_dl_progname, strtab + symtab[symtab_index].st_name);
 		_dl_exit(1);
 		_dl_exit(1);
 	};
 	};
-#ifdef DL_NEVER_FIXUP_SYMBOLS
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_NEVER_FIXUP_SYMBOLS)
-	if ((unsigned long) got_addr < 0x40000000) {
+	if ((unsigned long) got_addr < 0x40000000)
-		_dl_dprintf(2, "Calling library function: %s\n", 
+	{
+#ifndef SUPPORT_LD_DEBUG
+          if (_dl_debug_bindings)
+	  {
+	    _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
 			strtab + symtab[symtab_index].st_name);
 			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 {
 	} else {
-		*got_addr = new_addr;
+	  *got_addr = new_addr;
 	}
 	}
 #else
 #else
 	*got_addr = new_addr;
 	*got_addr = new_addr;
 #endif
 #endif
+
 	return (unsigned long) new_addr;
 	return (unsigned long) new_addr;
 }
 }
 
 
-void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, 
+static int
-	unsigned long rel_addr, unsigned long rel_size, int type)
+_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;
 	int i;
 	char *strtab;
 	char *strtab;
-	int reloc_type;
+	int goof = 0;
-	int symtab_index;
 	Elf32_Sym *symtab;
 	Elf32_Sym *symtab;
-	Elf32_Rel *rpnt;
+	ELF_RELOC *rpnt;
-	unsigned long *reloc_addr;
+	int symtab_index;
-
 	/* Now parse the relocation information */
 	/* Now parse the relocation information */
-	rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
-	rel_size = rel_size / sizeof(Elf32_Rel);
 
 
-	symtab =
+	rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
-		(Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + 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);
 	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
 
 
-	for (i = 0; i < rel_size; i++, rpnt++) {
+	  for (i = 0; i < rel_size; i++, rpnt++) {
-		reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+	        int res;
-		reloc_type = ELF32_R_TYPE(rpnt->r_info);
+	    
 		symtab_index = ELF32_R_SYM(rpnt->r_info);
 		symtab_index = ELF32_R_SYM(rpnt->r_info);
-
+		
 		/* When the dynamic linker bootstrapped itself, it resolved some symbols.
 		/* When the dynamic linker bootstrapped itself, it resolved some symbols.
 		   Make sure we do not do them again */
 		   Make sure we do not do them again */
 		if (!symtab_index && tpnt->libtype == program_interpreter)
 		if (!symtab_index && tpnt->libtype == program_interpreter)
 			continue;
 			continue;
 		if (symtab_index && tpnt->libtype == program_interpreter &&
 		if (symtab_index && tpnt->libtype == program_interpreter &&
-			_dl_symbol(strtab + symtab[symtab_index].st_name))
+		    _dl_symbol(strtab + symtab[symtab_index].st_name))
 			continue;
 			continue;
 
 
-		switch (reloc_type) {
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_DEBUG_SYMBOLS)
-		case R_ARM_NONE:
+		debug_sym(symtab,strtab,symtab_index);
-			break;
+		debug_reloc(symtab,strtab,rpnt);
-		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]);
 #endif
 #endif
-			if (symtab_index)
+
-				_dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
+		res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
-			_dl_exit(1);
+
-		};
+		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
 static unsigned long
@@ -183,58 +267,40 @@ fix_bad_pc24 (unsigned long *const reloc_addr, unsigned long value)
   return (unsigned long)fix_address;
   return (unsigned long)fix_address;
 }
 }
 
 
-
+static int
-int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
+_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
-	unsigned long rel_addr, unsigned long rel_size, int type)
+	      ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
 {
-	int i;
-	char *strtab;
 	int reloc_type;
 	int reloc_type;
-	int goof = 0;
+	int symtab_index;
-	Elf32_Sym *symtab;
-	Elf32_Rel *rpnt;
 	unsigned long *reloc_addr;
 	unsigned long *reloc_addr;
 	unsigned long symbol_addr;
 	unsigned long symbol_addr;
-	int symtab_index;
+	int goof = 0;
-
-	/* Now parse the relocation information */
 
 
-	rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
+	reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-	rel_size = rel_size / sizeof(Elf32_Rel);
+	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);
+	if (symtab_index) {
-	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
 
 
-	for (i = 0; i < rel_size; i++, rpnt++) {
+		symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-		reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+				scope, (reloc_type == R_ARM_JUMP_SLOT ? tpnt : NULL), symbolrel);
-		reloc_type = ELF32_R_TYPE(rpnt->r_info);
-		symtab_index = ELF32_R_SYM(rpnt->r_info);
-		symbol_addr = 0;
 
 
-		if (!symtab_index && tpnt->libtype == program_interpreter)
+		/*
-			continue;
+		 * We want to allow undefined references to weak symbols - this might
-
+		 * have been intentional.  We should not be linking local symbols
-		if (symtab_index) {
+		 * here, so all bases should be covered.
-
+		 */
-			if (tpnt->libtype == program_interpreter &&
+		if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
-					_dl_symbol(strtab + symtab[symtab_index].st_name))
+			goof++;
-				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++;
-			}
 		}
 		}
+	}
+
+#if defined (SUPPORT_LD_DEBUG)
+	{
+		unsigned long old_val = *reloc_addr;
+#endif
 		switch (reloc_type) {
 		switch (reloc_type) {
 			case R_ARM_NONE:
 			case R_ARM_NONE:
 				break;
 				break;
@@ -286,19 +352,50 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt,
 #endif
 #endif
 				break;
 				break;
 			default:
 			default:
-				_dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
+				return -1; /*call _dl_exit(1) */
-#ifdef VERBOSE_DLINKER
+		}
-				_dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
+#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
 #endif
-				if (symtab_index)
-					_dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
-				_dl_exit(1);
-		};
 
 
-	};
 	return goof;
 	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
 /* This is done as a separate step, because there are cases where
    information is first copied and later initialized.  This results in
    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
 /* No, there are cases where the SVr4 linker fails to emit COPY relocs
    at all */
    at all */
-
+static int
-int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr, 
+_dl_do_copy (struct elf_resolve *tpnt, struct dyn_elf *scope,
-	unsigned long rel_size, int type)
+	     ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
 {
-	int i;
+        int reloc_type;
-	char *strtab;
+	int symtab_index;
-	int reloc_type;
-	int goof = 0;
-	Elf32_Sym *symtab;
-	Elf32_Rel *rpnt;
 	unsigned long *reloc_addr;
 	unsigned long *reloc_addr;
 	unsigned long symbol_addr;
 	unsigned long symbol_addr;
-	struct elf_resolve *tpnt;
+	int goof = 0;
-	int symtab_index;
+	  
-
+	reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-	/* Now parse the relocation information */
+	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);
+void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, 
-	rel_size = rel_size / sizeof(Elf32_Rel);
+	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);
+int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
-	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+	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++) {
+int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr, 
-		reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+	unsigned long rel_size, int type)
-		reloc_type = ELF32_R_TYPE(rpnt->r_info);
+{
-		if (reloc_type != R_ARM_COPY)
+  return _dl_parse(xpnt->dyn, xpnt->next, rel_addr, rel_size, _dl_do_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;
 }
 }
+

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

@@ -1,21 +1,34 @@
-/* Load an ELF sharable library into memory.
+/* vi: set sw=4 ts=4: */
-
+/* Program to load an ELF binary on a linux system, and run it
-   Copyright (C) 1993-1996, Eric Youngdale.
+ * after resolving ELF shared library symbols
-
+ *
-   This program is free software; you can redistribute it and/or modify
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
-   it under the terms of the GNU General Public License as published by
+ *				David Engel, Hongjiu Lu and Mitch D'Souza
-   the Free Software Foundation; either version 2, or (at your option)
+ * Copyright (C) 2001-2002, Erik Andersen
-   any later version.
+ *
-
+ * All rights reserved.
-   This program is distributed in the hope that it will be useful,
+ *
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * Redistribution and use in source and binary forms, with or without
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * modification, are permitted provided that the following conditions
-   GNU General Public License for more details.
+ * are met:
-
+ * 1. Redistributions of source code must retain the above copyright
-   You should have received a copy of the GNU General Public License
+ *    notice, this list of conditions and the following disclaimer.
-   along with this program; if not, write to the Free Software
+ * 2. The name of the above contributors may not be
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+ *    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
 /* 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++;
 		pnt++;
 	}
 	}
 
 
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-	    _dl_dprintf(2, "searching for library: '%s'\n", libname);
+	    _dl_dprintf(_dl_debug_file, "searching for library: '%s'\n", libname);
 #endif
 #endif
 	/* If the filename has any '/', try it straight and leave it at that.
 	/* If the filename has any '/', try it straight and leave it at that.
 	   For IBCS2 compatibility under linux, we substitute the string 
 	   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) {
 			if (pnt) {
 				pnt += (unsigned long) tpnt->loadaddr +
 				pnt += (unsigned long) tpnt->loadaddr +
 					tpnt->dynamic_info[DT_STRTAB];
 					tpnt->dynamic_info[DT_STRTAB];
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-				_dl_dprintf(2, "searching RPATH: '%s'\n", pnt);
+				_dl_dprintf(_dl_debug_file, "searching RPATH: '%s'\n", pnt);
 #endif
 #endif
 				if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) 
 				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 */
 	/* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
 	if (_dl_library_path) {
 	if (_dl_library_path) {
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-	    _dl_dprintf(2, "searching _dl_library_path: '%s'\n", _dl_library_path);
+	    _dl_dprintf(_dl_debug_file, "searching _dl_library_path: '%s'\n", _dl_library_path);
 #endif
 #endif
 	    if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL) 
 	    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
 	/* Look for libraries wherever the shared library loader
 	 * was installed */
 	 * was installed */
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-	_dl_dprintf(2, "searching in ldso dir: %s\n", _dl_ldsopath);
+	_dl_dprintf(_dl_debug_file, "searching in ldso dir: %s\n", _dl_ldsopath);
 #endif
 #endif
 	if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt)) != NULL) 
 	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.
 	/* Lastly, search the standard list of paths for the library.
 	   This list must exactly match the list in uClibc/ldso/util/ldd.c */
 	   This list must exactly match the list in uClibc/ldso/util/ldd.c */
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-	    _dl_dprintf(2, "searching full lib path list\n");
+	    _dl_dprintf(_dl_debug_file, "searching full lib path list\n");
 #endif
 #endif
 	if ((tpnt1 = search_for_named_library(libname, secure, 
 	if ((tpnt1 = search_for_named_library(libname, secure, 
 			UCLIBC_TARGET_PREFIX "/usr/lib:"
 			UCLIBC_TARGET_PREFIX "/usr/lib:"
@@ -282,8 +295,8 @@ goof:
 	if (_dl_internal_error_number)
 	if (_dl_internal_error_number)
 		_dl_error_number = _dl_internal_error_number;
 		_dl_error_number = _dl_internal_error_number;
 	else
 	else
-		_dl_error_number = DL_ERROR_NOFILE;
+		_dl_error_number = LD_ERROR_NOFILE;
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 	    _dl_dprintf(2, "Bummer: could not find '%s'!\n", libname);
 	    _dl_dprintf(2, "Bummer: could not find '%s'!\n", libname);
 #endif
 #endif
 	return NULL;
 	return NULL;
@@ -323,6 +336,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 			(*rpnt)->next = (struct dyn_elf *)
 			(*rpnt)->next = (struct dyn_elf *)
 				_dl_malloc(sizeof(struct dyn_elf));
 				_dl_malloc(sizeof(struct dyn_elf));
 			_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
 			_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+			(*rpnt)->next->prev = (*rpnt);
 			*rpnt = (*rpnt)->next;
 			*rpnt = (*rpnt)->next;
 			(*rpnt)->dyn = tpnt;
 			(*rpnt)->dyn = tpnt;
 			tpnt->symbol_scope = _dl_symbol_tables;
 			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);
 		_dl_dprintf(2, "%s: can't open '%s'\n", _dl_progname, libname);
 #endif
 #endif
-		_dl_internal_error_number = DL_ERROR_NOFILE;
+		_dl_internal_error_number = LD_ERROR_NOFILE;
 		return NULL;
 		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,
 		_dl_dprintf(2, "%s: '%s' is not an ELF file\n", _dl_progname,
 					 libname);
 					 libname);
-		_dl_internal_error_number = DL_ERROR_NOTELF;
+		_dl_internal_error_number = LD_ERROR_NOTELF;
 		_dl_close(infile);
 		_dl_close(infile);
 		return NULL;
 		return NULL;
 	};
 	};
@@ -377,7 +391,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 		)) 
 		)) 
 	{
 	{
 		_dl_internal_error_number = 
 		_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 
 		_dl_dprintf(2, "%s: '%s' is not an ELF executable for " ELF_TARGET 
 			"\n", _dl_progname, libname);
 			"\n", _dl_progname, libname);
 		_dl_close(infile);
 		_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);
 		maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
 	if (_dl_mmap_check_error(status)) {
 	if (_dl_mmap_check_error(status)) {
 		_dl_dprintf(2, "%s: can't map %s\n", _dl_progname, libname);
 		_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);
 		_dl_close(infile);
 		return NULL;
 		return NULL;
 	};
 	};
@@ -457,7 +471,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 				if (_dl_mmap_check_error(status)) {
 				if (_dl_mmap_check_error(status)) {
 					_dl_dprintf(2, "%s: can't map '%s'\n", 
 					_dl_dprintf(2, "%s: can't map '%s'\n", 
 						_dl_progname, libname);
 						_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_munmap((char *) libaddr, maxvma - minvma);
 					_dl_close(infile);
 					_dl_close(infile);
 					return NULL;
 					return NULL;
@@ -488,7 +502,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 					infile, ppnt->p_offset & OFFS_ALIGN);
 					infile, ppnt->p_offset & OFFS_ALIGN);
 			if (_dl_mmap_check_error(status)) {
 			if (_dl_mmap_check_error(status)) {
 				_dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname);
 				_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_munmap((char *) libaddr, maxvma - minvma);
 				_dl_close(infile);
 				_dl_close(infile);
 				return NULL;
 				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 */
 	/* Start by scanning the dynamic section to get all of the pointers */
 
 
 	if (!dynamic_addr) {
 	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_dprintf(2, "%s: '%s' is missing a dynamic section\n", 
 			_dl_progname, libname);
 			_dl_progname, libname);
 		return NULL;
 		return NULL;
@@ -580,6 +594,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 		(*rpnt)->next = (struct dyn_elf *)
 		(*rpnt)->next = (struct dyn_elf *)
 			_dl_malloc(sizeof(struct dyn_elf));
 			_dl_malloc(sizeof(struct dyn_elf));
 		_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
 		_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+		(*rpnt)->next->prev = (*rpnt);
 		*rpnt = (*rpnt)->next;
 		*rpnt = (*rpnt)->next;
 		(*rpnt)->dyn = tpnt;
 		(*rpnt)->dyn = tpnt;
 		tpnt->symbol_scope = _dl_symbol_tables;
 		tpnt->symbol_scope = _dl_symbol_tables;
@@ -626,6 +641,10 @@ int _dl_copy_fixups(struct dyn_elf *rpnt)
 		return goof;
 		return goof;
 	tpnt->init_flag |= COPY_RELOCS_DONE;
 	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
 #ifdef ELF_USES_RELOCA
 	goof += _dl_parse_copy_information(rpnt, 
 	goof += _dl_parse_copy_information(rpnt, 
 		tpnt->dynamic_info[DT_RELA], tpnt->dynamic_info[DT_RELASZ], 0);
 		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);
 		tpnt->dynamic_info[DT_RELSZ], 0);
 
 
 #endif
 #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;
 	return goof;
 }
 }

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

@@ -1,21 +1,34 @@
-/* Run an ELF binary on a linux system.
+/* vi: set sw=4 ts=4: */
-
+/* Program to load an ELF binary on a linux system, and run it
-   Copyright (C) 1993-1996, Eric Youngdale.
+ * after resolving ELF shared library symbols
-
+ *
-   This program is free software; you can redistribute it and/or modify
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
-   it under the terms of the GNU General Public License as published by
+ *				David Engel, Hongjiu Lu and Mitch D'Souza
-   the Free Software Foundation; either version 2, or (at your option)
+ * Copyright (C) 2001-2002, Erik Andersen
-   any later version.
+ *
-
+ * All rights reserved.
-   This program is distributed in the hope that it will be useful,
+ *
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * Redistribution and use in source and binary forms, with or without
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * modification, are permitted provided that the following conditions
-   GNU General Public License for more details.
+ * are met:
-
+ * 1. Redistributions of source code must retain the above copyright
-   You should have received a copy of the GNU General Public License
+ *    notice, this list of conditions and the following disclaimer.
-   along with this program; if not, write to the Free Software
+ * 2. The name of the above contributors may not be
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+ *    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 */
 /* 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, 
 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;
 	struct elf_resolve *tpnt;
 	int si;
 	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
 	   that any shared library data symbols referenced in the executable
 	   will be seen at the same address by the executable, shared libraries
 	   will be seen at the same address by the executable, shared libraries
 	   and dynamically loaded code. -Rob Ryan (robr@cmu.edu) */
 	   and dynamically loaded code. -Rob Ryan (robr@cmu.edu) */
-	if (!copyrel && rpnt1) {
+	if (copyrel!=caller_type && rpnt1) {
 		first = (*_dl_symbol_tables);
 		first = (*_dl_symbol_tables);
 		first.next = rpnt1;
 		first.next = rpnt1;
 		rpnt1 = (&first);
 		rpnt1 = (&first);
@@ -247,11 +260,12 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
 				pnt = strtab + symtab[si].st_name;
 				pnt = strtab + symtab[si].st_name;
 
 
 				if (_dl_strcmp(pnt, name) == 0 &&
 				if (_dl_strcmp(pnt, name) == 0 &&
-					(ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
+				    symtab[si].st_value != 0)
-					 ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
+				{
-					 ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
+				  if ((ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
-					symtab[si].st_value != 0 &&
+				       ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
-					symtab[si].st_shndx != 0) {
+				       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
 					/* Here we make sure that we find a module where the symbol is
 					 * actually defined.
 					 * actually defined.
@@ -284,6 +298,24 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
 					default:	/* Do local symbols need to be examined? */
 					default:	/* Do local symbols need to be examined? */
 						break;
 						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.
+/* vi: set sw=4 ts=4: */
-
+/* Program to load an ELF binary on a linux system, and run it
-   Copyright (C) 1993-1996, Eric Youngdale.
+ * after resolving ELF shared library symbols
-
+ *
-   This program is free software; you can redistribute it and/or modify
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
-   it under the terms of the GNU General Public License as published by
+ *				David Engel, Hongjiu Lu and Mitch D'Souza
-   the Free Software Foundation; either version 2, or (at your option)
+ * Copyright (C) 2001-2002, Erik Andersen
-   any later version.
+ *
-
+ * All rights reserved.
-   This program is distributed in the hope that it will be useful,
+ *
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * Redistribution and use in source and binary forms, with or without
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * modification, are permitted provided that the following conditions
-   GNU General Public License for more details.
+ * are met:
-
+ * 1. Redistributions of source code must retain the above copyright
-   You should have received a copy of the GNU General Public License
+ *    notice, this list of conditions and the following disclaimer.
-   along with this program; if not, write to the Free Software
+ * 2. The name of the above contributors may not be
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+ *    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 */
 /* 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, 
 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;
 	struct elf_resolve *tpnt;
 	int si;
 	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
 	   that any shared library data symbols referenced in the executable
 	   will be seen at the same address by the executable, shared libraries
 	   will be seen at the same address by the executable, shared libraries
 	   and dynamically loaded code. -Rob Ryan (robr@cmu.edu) */
 	   and dynamically loaded code. -Rob Ryan (robr@cmu.edu) */
-	if (!copyrel && rpnt1) {
+	if (copyrel!=caller_type && rpnt1) {
 		first = (*_dl_symbol_tables);
 		first = (*_dl_symbol_tables);
 		first.next = rpnt1;
 		first.next = rpnt1;
 		rpnt1 = (&first);
 		rpnt1 = (&first);
@@ -247,11 +260,12 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
 				pnt = strtab + symtab[si].st_name;
 				pnt = strtab + symtab[si].st_name;
 
 
 				if (_dl_strcmp(pnt, name) == 0 &&
 				if (_dl_strcmp(pnt, name) == 0 &&
-					(ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
+				    symtab[si].st_value != 0)
-					 ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
+				{
-					 ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
+				  if ((ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
-					symtab[si].st_value != 0 &&
+				       ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
-					symtab[si].st_shndx != 0) {
+				       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
 					/* Here we make sure that we find a module where the symbol is
 					 * actually defined.
 					 * actually defined.
@@ -284,6 +298,24 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
 					default:	/* Do local symbols need to be examined? */
 					default:	/* Do local symbols need to be examined? */
 						break;
 						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.
  * 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.
  * 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.
+/* vi: set sw=4 ts=4: */
-
+/* i386 ELF shared library loader suppport
-   Copyright (C) 1993, Eric Youngdale.
+ *
-
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
-   This program is free software; you can redistribute it and/or modify
+ *				David Engel, Hongjiu Lu and Mitch D'Souza
-   it under the terms of the GNU General Public License as published by
+ * Copyright (C) 2001-2002, Erik Andersen
-   the Free Software Foundation; either version 2, or (at your option)
+ *
-   any later version.
+ * All rights reserved.
-
+ *
-   This program is distributed in the hope that it will be useful,
+ * Redistribution and use in source and binary forms, with or without
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * modification, are permitted provided that the following conditions
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * are met:
-   GNU General Public License for more details.
+ * 1. Redistributions of source code must retain the above copyright
-
+ *    notice, this list of conditions and the following disclaimer.
-   You should have received a copy of the GNU General Public License
+ * 2. The name of the above contributors may not be
-   along with this program; if not, write to the Free Software
+ *    used to endorse or promote products derived from this software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+ *    without specific prior written permission.
-
+ *
-#ifndef VERBOSE_DLINKER
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
-#define VERBOSE_DLINKER
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-#endif
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-#ifdef VERBOSE_DLINKER
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
-static const char *_dl_reltypes[] =
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-	{ "R_386_NONE", "R_386_32", "R_386_PC32", "R_386_GOT32",
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-	"R_386_PLT32", "R_386_COPY", "R_386_GLOB_DAT",
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-	"R_386_JMP_SLOT", "R_386_RELATIVE", "R_386_GOTOFF",
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-	"R_386_GOTPC", "R_386_NUM"
+ * 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
 #endif
 
 
 /* Program to load an ELF binary on a linux system, and run it.
 /* 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)
 unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 {
 {
 	int reloc_type;
 	int reloc_type;
-	Elf32_Rel *this_reloc;
+	ELF_RELOC *this_reloc;
 	char *strtab;
 	char *strtab;
 	Elf32_Sym *symtab;
 	Elf32_Sym *symtab;
-	Elf32_Rel *rel_addr;
+	ELF_RELOC *rel_addr;
 	int symtab_index;
 	int symtab_index;
 	char *new_addr;
 	char *new_addr;
 	char **got_addr;
 	char **got_addr;
 	unsigned long instr_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);
 	this_reloc = rel_addr + (reloc_entry >> 3);
 	reloc_type = ELF32_R_TYPE(this_reloc->r_info);
 	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);
 		(unsigned long) tpnt->loadaddr);
 	got_addr = (char **) instr_addr;
 	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 */
 	/* Get the address of the GOT entry */
 	new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
 	new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-		tpnt->symbol_scope, tpnt, 0);
+		tpnt->symbol_scope, tpnt, resolver);
 	if (!new_addr) {
 	if (!new_addr) {
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 			_dl_progname, strtab + symtab[symtab_index].st_name);
 			_dl_progname, strtab + symtab[symtab_index].st_name);
 		_dl_exit(1);
 		_dl_exit(1);
 	};
 	};
-#ifdef DL_NEVER_FIXUP_SYMBOLS
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_NEVER_FIXUP_SYMBOLS)
-	if ((unsigned long) got_addr < 0x40000000) {
+	if ((unsigned long) got_addr < 0x40000000)
-		_dl_dprintf(2, "Calling library function: %s\n", 
+	{
+#ifndef SUPPORT_LD_DEBUG
+          if (_dl_debug_bindings)
+	  {
+	    _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
 			strtab + symtab[symtab_index].st_name);
 			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 {
 	} else {
-		*got_addr = new_addr;
+	  *got_addr = new_addr;
 	}
 	}
 #else
 #else
 	*got_addr = new_addr;
 	*got_addr = new_addr;
 #endif
 #endif
+
 	return (unsigned long) new_addr;
 	return (unsigned long) new_addr;
 }
 }
 
 
-void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, 
+static int
-	unsigned long rel_addr, unsigned long rel_size, int type)
+_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;
 	int i;
 	char *strtab;
 	char *strtab;
-	int reloc_type;
+	int goof = 0;
-	int symtab_index;
 	Elf32_Sym *symtab;
 	Elf32_Sym *symtab;
-	Elf32_Rel *rpnt;
+	ELF_RELOC *rpnt;
-	unsigned long *reloc_addr;
+	int symtab_index;
-
 	/* Now parse the relocation information */
 	/* Now parse the relocation information */
-	rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
-	rel_size = rel_size / sizeof(Elf32_Rel);
 
 
-	symtab =
+	rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
-		(Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + 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);
 	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
 
 
-	for (i = 0; i < rel_size; i++, rpnt++) {
+	  for (i = 0; i < rel_size; i++, rpnt++) {
-		reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+	        int res;
-		reloc_type = ELF32_R_TYPE(rpnt->r_info);
+	    
 		symtab_index = ELF32_R_SYM(rpnt->r_info);
 		symtab_index = ELF32_R_SYM(rpnt->r_info);
-
+		
 		/* When the dynamic linker bootstrapped itself, it resolved some symbols.
 		/* When the dynamic linker bootstrapped itself, it resolved some symbols.
 		   Make sure we do not do them again */
 		   Make sure we do not do them again */
 		if (!symtab_index && tpnt->libtype == program_interpreter)
 		if (!symtab_index && tpnt->libtype == program_interpreter)
 			continue;
 			continue;
 		if (symtab_index && tpnt->libtype == program_interpreter &&
 		if (symtab_index && tpnt->libtype == program_interpreter &&
-			_dl_symbol(strtab + symtab[symtab_index].st_name))
+		    _dl_symbol(strtab + symtab[symtab_index].st_name))
 			continue;
 			continue;
 
 
-		switch (reloc_type) {
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_DEBUG_SYMBOLS)
-		case R_386_NONE:
+		debug_sym(symtab,strtab,symtab_index);
-			break;
+		debug_reloc(symtab,strtab,rpnt);
-		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]);
 #endif
 #endif
-			if (symtab_index)
+
-				_dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
+		res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
-			_dl_exit(1);
+
-		};
+		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, 
+static int
-	unsigned long rel_addr, unsigned long rel_size, int type)
+_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 reloc_type;
-	int goof = 0;
+	int symtab_index;
-	Elf32_Sym *symtab;
-	Elf32_Rel *rpnt;
 	unsigned long *reloc_addr;
 	unsigned long *reloc_addr;
 	unsigned long symbol_addr;
 	unsigned long symbol_addr;
-	int symtab_index;
+	int goof = 0;
-
-	/* 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);
+	reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+	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++) {
+	if (symtab_index) {
-		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 && tpnt->libtype == program_interpreter)
+		symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-			continue;
+				scope, (reloc_type == R_386_JMP_SLOT ? tpnt : NULL), symbolrel);
 
 
-		if (symtab_index) {
+		/*
-
+		 * We want to allow undefined references to weak symbols - this might
-			if (tpnt->libtype == program_interpreter &&
+		 * have been intentional.  We should not be linking local symbols
-				_dl_symbol(strtab + symtab[symtab_index].st_name))
+		 * here, so all bases should be covered.
-				continue;
+		 */
-
+		if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
-			symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
+			goof++;
-					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++;
-			}
 		}
 		}
+	}
+
+#if defined (SUPPORT_LD_DEBUG)
+	{
+		unsigned long old_val = *reloc_addr;
+#endif
 		switch (reloc_type) {
 		switch (reloc_type) {
-		case R_386_NONE:
+			case R_386_NONE:
-			break;
+				break;
-		case R_386_32:
+			case R_386_32:
-			*reloc_addr += symbol_addr;
+				*reloc_addr += symbol_addr;
-			break;
+				break;
-		case R_386_PC32:
+			case R_386_PC32:
-			*reloc_addr += symbol_addr - (unsigned long) reloc_addr;
+				*reloc_addr += symbol_addr - (unsigned long) reloc_addr;
-			break;
+				break;
-		case R_386_GLOB_DAT:
+			case R_386_GLOB_DAT:
-		case R_386_JMP_SLOT:
+			case R_386_JMP_SLOT:
-			*reloc_addr = symbol_addr;
+				*reloc_addr = symbol_addr;
-			break;
+				break;
-		case R_386_RELATIVE:
+			case R_386_RELATIVE:
-			*reloc_addr += (unsigned long) tpnt->loadaddr;
+				*reloc_addr += (unsigned long) tpnt->loadaddr;
-			break;
+				break;
-		case R_386_COPY:
+			case R_386_COPY:
-#if 0							
+#if 0
-			/* Do this later */
+				/* Do this later */
-			_dl_dprintf(2, "Doing copy for symbol ");
+				_dl_dprintf(2, "Doing copy for symbol ");
-			if (symtab_index) _dl_dprintf(2, strtab + symtab[symtab_index].st_name);
+				if (symtab_index) _dl_dprintf(2, strtab + symtab[symtab_index].st_name);
-			_dl_dprintf(2, "\n");
+				_dl_dprintf(2, "\n");
-			_dl_memcpy((void *) symtab[symtab_index].st_value, 
+				_dl_memcpy((void *) symtab[symtab_index].st_value, 
-				(void *) symbol_addr, symtab[symtab_index].st_size);
+						(void *) symbol_addr, symtab[symtab_index].st_size);
 #endif
 #endif
-			break;
+				break;
-		default:
+
-			_dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
+			default:
-#ifdef VERBOSE_DLINKER
+				return -1; /*call _dl_exit(1) */
-			_dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
+		}
+#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
 #endif
-			if (symtab_index)
-				_dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
-			_dl_exit(1);
-		};
 
 
-	};
 	return goof;
 	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
 /* This is done as a separate step, because there are cases where
    information is first copied and later initialized.  This results in
    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
 /* No, there are cases where the SVr4 linker fails to emit COPY relocs
    at all */
    at all */
-
+static int
-int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr, 
+_dl_do_copy (struct elf_resolve *tpnt, struct dyn_elf *scope,
-	unsigned long rel_size, int type)
+	     ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
 {
-	int i;
+        int reloc_type;
-	char *strtab;
+	int symtab_index;
-	int reloc_type;
-	int goof = 0;
-	Elf32_Sym *symtab;
-	Elf32_Rel *rpnt;
 	unsigned long *reloc_addr;
 	unsigned long *reloc_addr;
 	unsigned long symbol_addr;
 	unsigned long symbol_addr;
-	struct elf_resolve *tpnt;
+	int goof = 0;
-	int symtab_index;
+	  
-
+	reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-	/* Now parse the relocation information */
+	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);
+void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, 
-	rel_size = rel_size / sizeof(Elf32_Rel);
+	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);
+int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
-	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+	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++) {
+int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr, 
-		reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+	unsigned long rel_size, int type)
-		reloc_type = ELF32_R_TYPE(rpnt->r_info);
+{
-		if (reloc_type != R_386_COPY)
+  return _dl_parse(xpnt->dyn, xpnt->next, rel_addr, rel_size, _dl_do_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;
 }
 }
+

+ 15 - 11
ldso/ldso/ld_hash.h

@@ -43,6 +43,7 @@ struct dyn_elf{
   struct elf_resolve * dyn;
   struct elf_resolve * dyn;
   struct dyn_elf * next_handle;  /* Used by dlopen et al. */
   struct dyn_elf * next_handle;  /* Used by dlopen et al. */
   struct dyn_elf * next;
   struct dyn_elf * next;
+  struct dyn_elf * prev;
 };
 };
  
  
 struct elf_resolve{
 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, 
 extern struct elf_resolve * _dl_add_elf_hash_table(char * libname, 
 	char * loadaddr, unsigned long * dynamic_info, 
 	char * loadaddr, unsigned long * dynamic_info, 
 	unsigned long dynamic_addr, unsigned long dynamic_size);
 	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, 
 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 int _dl_linux_dynamic_link(void);
 
 
 extern char * _dl_library_path;
 extern char * _dl_library_path;
@@ -129,16 +133,16 @@ static inline int _dl_symbol(char * name)
 }
 }
 
 
 
 
-#define DL_ERROR_NOFILE 1
+#define LD_ERROR_NOFILE 1
-#define DL_ERROR_NOZERO 2
+#define LD_ERROR_NOZERO 2
-#define DL_ERROR_NOTELF 3
+#define LD_ERROR_NOTELF 3
-#define DL_ERROR_NOTMAGIC 4
+#define LD_ERROR_NOTMAGIC 4
-#define DL_ERROR_NOTDYN 5
+#define LD_ERROR_NOTDYN 5
-#define DL_ERROR_MMAP_FAILED 6
+#define LD_ERROR_MMAP_FAILED 6
-#define DL_ERROR_NODYNAMIC 7
+#define LD_ERROR_NODYNAMIC 7
-#define DL_WRONG_RELOCS 8
+#define LD_WRONG_RELOCS 8
-#define DL_BAD_HANDLE 9
+#define LD_BAD_HANDLE 9
-#define DL_NO_SYMBOL 10
+#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 int _dl_strncmp(const char * s1,const char * s2,size_t len);
 static char * _dl_strchr(const char * str,int c);
 static char * _dl_strchr(const char * str,int c);
 static char *_dl_strrchr(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 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 int _dl_memcmp(const void * s1,const void * s2,size_t len);
 static void *_dl_memset(void * str,int c,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);
     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)
 static inline void * _dl_memcpy(void * dst, const void * src, size_t len)
 {
 {
 	register char *a = dst;
 	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. */
 /* On some arches constant strings are referenced through the GOT. */
 /* XXX Requires load_addr to be defined. */
 /* XXX Requires load_addr to be defined. */
 #define SEND_STDERR(X)				\
 #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);
 static inline _syscall1(int, _dl_close, int, fd);
 
 
 
 
-#if defined(__powerpc) || defined(__mips__)
+#if defined(__powerpc) || defined(__mips__) || defined(__sh__)
-/* PowerPC and MIPS have a different calling convention for mmap(). */
+/* PowerPC, MIPS and SuperH have a different calling convention for mmap(). */
 #define __NR__dl_mmap __NR_mmap
 #define __NR__dl_mmap __NR_mmap
 static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
 static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
 		int, prot, int, flags, int, fd, off_t, offset);
 		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 __NR__dl_open __NR_open
 #define O_RDONLY        0x0000
 #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);
 static inline _syscall2(int, _dl_open, const char *, fn, int, flags);
 
 
 #define __NR__dl_write __NR_write
 #define __NR__dl_write __NR_write
@@ -126,6 +129,9 @@ static inline _syscall0(gid_t, _dl_getgid);
 #define __NR__dl_getegid __NR_getegid
 #define __NR__dl_getegid __NR_getegid
 static inline _syscall0(gid_t, _dl_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
  * Not an actual syscall, but we need something in assembly to say whether
  * this is OK or not.
  * this is OK or not.

+ 194 - 94
ldso/ldso/ldso.c

@@ -1,23 +1,33 @@
 /* vi: set sw=4 ts=4: */
 /* vi: set sw=4 ts=4: */
 /* Program to load an ELF binary on a linux system, and run it
 /* Program to load an ELF binary on a linux system, and run it
  * after resolving ELF shared library symbols
  * 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
  * Copyright (C) 2001-2002, Erik Andersen
  *
  *
- * This program is free software; you can redistribute it and/or modify 
+ * All rights reserved.
- * it under the terms of the GNU General Public License as published by 
+ *
- * the Free Software Foundation; either version 2, or (at your option) 
+ * Redistribution and use in source and binary forms, with or without
- * any later version.  
+ * modification, are permitted provided that the following conditions
- * 
+ * are met:
- * This program is distributed in the hope that it will be useful, 
+ * 1. Redistributions of source code must retain the above copyright
- * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+ *    notice, this list of conditions and the following disclaimer.
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * 2. The name of the above contributors may not be
- * GNU General Public License for more details.  
+ *    used to endorse or promote products derived from this software
- * 
+ *    without specific prior written permission.
- * You should have received a copy of the GNU General Public License 
+ *
- * along with this program; if not, write to the Free Software 
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+ * 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
 /* 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
 // Support a list of library preloads in /etc/ld.so.preload
 //#define SUPPORT_LDSO_PRELOAD_FILE
 //#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
 /* 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
    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
  * housekeeping chores and we can transfer control to the user's
  * application.
  * application.
  */
  */
+#ifdef LD_DEBUG_SYMBOLS
+#ifdef SUPPORT_LD_DEBUG
+#undef SUPPORT_LD_DEBUG
+#endif
+#define SUPPORT_LD_DEBUG
+#endif
 
 
 #include "ld_syscall.h"
 #include "ld_syscall.h"
 #include "linuxelf.h"
 #include "linuxelf.h"
@@ -127,11 +128,11 @@
 #define	    ELFMAGIC	ELFMAG
 #define	    ELFMAGIC	ELFMAG
 
 
 /* This is a poor man's malloc, used prior to resolving our internal poor man's malloc */
 /* 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
  * 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
  * 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))
 #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_preload = 0;			/* Things to be loaded before the libs. */
 char *_dl_ldsopath = 0;
 char *_dl_ldsopath = 0;
 static char *_dl_not_lazy = 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_malloc_addr, *_dl_mmap_zero;
 
 
 static char *_dl_trace_loaded_objects = 0;
 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)
 		auxvt[0...N]   Auxiliary Vector Table elements (mixed types)
 */
 */
 
 
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 /* Debugging is especially tricky on PowerPC, since string literals
 /* Debugging is especially tricky on PowerPC, since string literals
  * require relocations.  Thus, you can't use _dl_dprintf() for
  * require relocations.  Thus, you can't use _dl_dprintf() for
  * anything until the bootstrap relocations are finished. */
  * anything until the bootstrap relocations are finished. */
@@ -192,7 +204,7 @@ static inline void hexprint(unsigned long x)
 }
 }
 #endif
 #endif
 
 
-DL_BOOT(unsigned long args)
+LD_BOOT(unsigned long args)
 {
 {
 	unsigned int argc;
 	unsigned int argc;
 	char **argv, **envp;
 	char **argv, **envp;
@@ -257,14 +269,19 @@ DL_BOOT(unsigned long args)
 	/* Check the ELF header to make sure everything looks ok.  */
 	/* Check the ELF header to make sure everything looks ok.  */
 	if (!header || header->e_ident[EI_CLASS] != ELFCLASS32 ||
 	if (!header || header->e_ident[EI_CLASS] != ELFCLASS32 ||
 		header->e_ident[EI_VERSION] != EV_CURRENT
 		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
 		|| _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
 #endif
 		) {
 		) {
 		SEND_STDERR("Invalid ELF header\n");
 		SEND_STDERR("Invalid ELF header\n");
 		_dl_exit(0);
 		_dl_exit(0);
 	}
 	}
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 	SEND_STDERR("ELF header=");
 	SEND_STDERR("ELF header=");
 	SEND_ADDRESS_STDERR(load_addr, 1);
 	SEND_ADDRESS_STDERR(load_addr, 1);
 #endif
 #endif
@@ -286,6 +303,16 @@ DL_BOOT(unsigned long args)
   __asm__("\tbl _GLOBAL_OFFSET_TABLE_-4@local\n\t":"=l"(got));
   __asm__("\tbl _GLOBAL_OFFSET_TABLE_-4@local\n\t":"=l"(got));
 #elif defined(__mips__)
 #elif defined(__mips__)
   __asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got));
   __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
 #else
 	/* Do things the slow way in C */
 	/* Do things the slow way in C */
 	{
 	{
@@ -294,7 +321,7 @@ DL_BOOT(unsigned long args)
 		Elf32_Shdr *shdr;
 		Elf32_Shdr *shdr;
 		Elf32_Phdr *pt_load;
 		Elf32_Phdr *pt_load;
 
 
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 		SEND_STDERR("Finding the GOT using C code to read the ELF file\n");
 		SEND_STDERR("Finding the GOT using C code to read the ELF file\n");
 #endif
 #endif
 		/* Find where the dynamic linking information section is hiding */
 		/* 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 */
 	/* Now, finally, fix up the location of the dynamic stuff */
 	dpnt = (Elf32_Dyn *) (*got + load_addr);
 	dpnt = (Elf32_Dyn *) (*got + load_addr);
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 	SEND_STDERR("First Dynamic section entry=");
 	SEND_STDERR("First Dynamic section entry=");
 	SEND_ADDRESS_STDERR(dpnt, 1);
 	SEND_ADDRESS_STDERR(dpnt, 1);
 #endif
 #endif
@@ -354,15 +381,15 @@ DL_BOOT(unsigned long args)
 		_dl_exit(13);
 		_dl_exit(13);
 	}
 	}
 
 
-	tpnt = DL_MALLOC(sizeof(struct elf_resolve));
+	tpnt = LD_MALLOC(sizeof(struct elf_resolve));
 	_dl_memset(tpnt, 0, sizeof(*tpnt));
 	_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));
 	_dl_memset(app_tpnt, 0, sizeof(*app_tpnt));
 
 
 	/*
 	/*
 	 * This is used by gdb to locate the chain of shared libraries that are currently loaded.
 	 * 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));
 	_dl_memset(debug_addr, 0, sizeof(*debug_addr));
 
 
 	/* OK, that was easy.  Next scan the DYNAMIC section of the image.
 	/* 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
 	/* OK, now do the relocations.  We do not do a lazy binding here, so
 	   that once we are done, we have considerably more flexibility. */
 	   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");
 	SEND_STDERR("About to do library loader relocations.\n");
 #endif
 #endif
 
 
@@ -541,7 +568,7 @@ DL_BOOT(unsigned long args)
 					SEND_STDERR(" undefined.\n");
 					SEND_STDERR(" undefined.\n");
 					goof++;
 					goof++;
 				}
 				}
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_DEBUG_SYMBOLS
 				SEND_STDERR("About to fixup symbol: ");
 				SEND_STDERR("About to fixup symbol: ");
 				SEND_STDERR(strtab + symtab[symtab_index].st_name);
 				SEND_STDERR(strtab + symtab[symtab_index].st_name);
 				SEND_STDERR("\n");
 				SEND_STDERR("\n");
@@ -557,9 +584,9 @@ DL_BOOT(unsigned long args)
 	if (goof) {
 	if (goof) {
 		_dl_exit(14);
 		_dl_exit(14);
 	}
 	}
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 	/* Wahoo!!! */
 	/* 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
 #endif
 
 
 	if (argv[0]) {
 	if (argv[0]) {
@@ -594,9 +621,12 @@ DL_BOOT(unsigned long args)
 	 * Transfer control to the application.
 	 * Transfer control to the application.
 	 */
 	 */
 	status = 0;					/* Used on x86, but not on other arches */
 	status = 0;					/* Used on x86, but not on other arches */
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-	_dl_dprintf(2, "Calling application main()\n");
+	_dl_dprintf(_dl_debug_file, "Calling application main()\n");
 #endif
 #endif
+#if defined (SUPPORT_LD_DEBUG)
+	if(_dl_debug) _dl_dprintf(_dl_debug_file,"\ntransfering control: %s\n\n", _dl_progname);	
+#endif    
 	START();
 	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;
 	tpnt->loadaddr = (char *) load_addr;
 
 
 	INIT_GOT(lpnt, tpnt);
 	INIT_GOT(lpnt, tpnt);
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-	_dl_dprintf(2, "GOT found at %x\n", tpnt);
+	_dl_dprintf(_dl_debug_file, "GOT found at %x\n", lpnt);
 #endif
 #endif
 	/* OK, this was a big step, now we need to scan all of the user images
 	/* OK, this was a big step, now we need to scan all of the user images
 	   and load them properly. */
 	   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) {
 			if (readsize > 0 && readsize < sizeof(buf)-1) {
 				pnt1 = _dl_strrchr(buf, '/');
 				pnt1 = _dl_strrchr(buf, '/');
 				if (pnt1 && buf != pnt1) {
 				if (pnt1 && buf != pnt1) {
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-					_dl_dprintf(2, "changing tpnt->libname from '%s' to '%s'\n", tpnt->libname, buf);
+					_dl_dprintf(_dl_debug_file, "changing tpnt->libname from '%s' to '%s'\n", tpnt->libname, buf);
 #endif
 #endif
 					tpnt->libname = _dl_strdup(buf);
 					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 {
 			} else {
 				_dl_ldsopath = tpnt->libname;
 				_dl_ldsopath = tpnt->libname;
 			}
 			}
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-			_dl_dprintf(2, "Lib Loader:\t(%x) %s\n", tpnt->loadaddr, tpnt->libname);
+			_dl_dprintf(_dl_debug_file, "Lib Loader:\t(%x) %s\n", tpnt->loadaddr, tpnt->libname);
 #endif
 #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);
 	_dl_trace_loaded_objects = _dl_getenv("LD_TRACE_LOADED_OBJECTS", envp);
-#ifndef DL_TRACE
+#ifndef LD_TRACE
 	if (_dl_trace_loaded_objects) {
 	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);
 		_dl_exit(1);
 	}
 	}
 #endif
 #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);
 				tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str);
 				if (!tpnt1) {
 				if (!tpnt1) {
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 					if (_dl_trace_loaded_objects)
 					if (_dl_trace_loaded_objects)
 						_dl_dprintf(1, "\t%s => not found\n", str);
 						_dl_dprintf(1, "\t%s => not found\n", str);
 					else {
 					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 "
 						_dl_dprintf(2, "%s: can't load "
 								"library '%s'\n", _dl_progname, str);
 								"library '%s'\n", _dl_progname, str);
 						_dl_exit(15);
 						_dl_exit(15);
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 					}
 					}
 #endif
 #endif
 				} else {
 				} else {
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-					_dl_dprintf(2, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
+					_dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
 #endif
 #endif
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 					if (_dl_trace_loaded_objects
 					if (_dl_trace_loaded_objects
 							&& tpnt1->usage_count==1) {
 							&& tpnt1->usage_count==1) {
 						/* this is a real hack to make ldd not print 
 						/* 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);
 						tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2);
 						if (!tpnt1) {
 						if (!tpnt1) {
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 							if (_dl_trace_loaded_objects)
 							if (_dl_trace_loaded_objects)
 								_dl_dprintf(1, "\t%s => not found\n", cp2);
 								_dl_dprintf(1, "\t%s => not found\n", cp2);
 							else {
 							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_dprintf(2, "%s: can't load library '%s'\n", 
 										_dl_progname, cp2);
 										_dl_progname, cp2);
 								_dl_exit(15);
 								_dl_exit(15);
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 							}
 							}
 #endif
 #endif
 						} else {
 						} else {
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-							_dl_dprintf(2, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
+							_dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
 #endif
 #endif
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 							if (_dl_trace_loaded_objects
 							if (_dl_trace_loaded_objects
 									&& tpnt1->usage_count==1) {
 									&& tpnt1->usage_count==1) {
 								_dl_dprintf(1, "\t%s => %s (0x%x)\n", cp2, 
 								_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) {
 				if (tpnt && _dl_strcmp(lpntstr, _dl_get_last_path_component(tpnt->libname)) == 0) {
 					struct elf_resolve *ttmp;
 					struct elf_resolve *ttmp;
 
 
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 					if (_dl_trace_loaded_objects && tpnt->usage_count==1) {
 					if (_dl_trace_loaded_objects && tpnt->usage_count==1) {
 						_dl_dprintf(1, "\t%s => %s (0x%x)\n", 
 						_dl_dprintf(1, "\t%s => %s (0x%x)\n", 
 								lpntstr, tpnt->libname, (unsigned) tpnt->loadaddr);
 								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 *)
 					rpnt->next = (struct dyn_elf *)
 						_dl_malloc(sizeof(struct dyn_elf));
 						_dl_malloc(sizeof(struct dyn_elf));
 					_dl_memset(rpnt->next, 0, sizeof(*(rpnt->next)));
 					_dl_memset(rpnt->next, 0, sizeof(*(rpnt->next)));
+					rpnt->next->prev = rpnt;
 					rpnt = rpnt->next;
 					rpnt = rpnt->next;
 					rpnt->dyn = tpnt;
 					rpnt->dyn = tpnt;
 					tpnt->usage_count++;
 					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)))
 				if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr)))
 				{
 				{
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 					if (_dl_trace_loaded_objects)
 					if (_dl_trace_loaded_objects)
 						_dl_dprintf(1, "\t%s => not found\n", lpntstr);
 						_dl_dprintf(1, "\t%s => not found\n", lpntstr);
 					else {
 					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_dprintf(2, "%s: can't load library '%s'\n", 
 								_dl_progname, lpntstr);
 								_dl_progname, lpntstr);
 						_dl_exit(16);
 						_dl_exit(16);
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 					}
 					}
 #endif
 #endif
 				} else {
 				} else {
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-					_dl_dprintf(2, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
+					_dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
 #endif
 #endif
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 					if (_dl_trace_loaded_objects && tpnt1->usage_count==1)
 					if (_dl_trace_loaded_objects && tpnt1->usage_count==1)
 						_dl_dprintf(1, "\t%s => %s (0x%x)\n", lpntstr, tpnt1->libname, 
 						_dl_dprintf(1, "\t%s => %s (0x%x)\n", lpntstr, tpnt1->libname, 
 								(unsigned) tpnt1->loadaddr);
 								(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();
 	_dl_unmap_cache();
 #endif
 #endif
 	/* ldd uses uses this.  I am not sure how you pick up the other flags */
 	/* 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) {
 	if (_dl_trace_loaded_objects) {
 		char *_dl_warn = 0;
 		char *_dl_warn = 0;
 		_dl_warn = _dl_getenv("LD_WARN", envp);
 		_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 =
 			rpnt->next =
 				(struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
 				(struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
 			_dl_memset(rpnt->next, 0, sizeof(*(rpnt->next)));
 			_dl_memset(rpnt->next, 0, sizeof(*(rpnt->next)));
+			rpnt->next->prev = rpnt;
 			rpnt = rpnt->next;
 			rpnt = rpnt->next;
 		} else {
 		} else {
 			rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
 			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;
 		rpnt->dyn = tpnt;
 		tpnt = NULL;
 		tpnt = NULL;
 	}
 	}
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 	if (_dl_trace_loaded_objects) {
 	if (_dl_trace_loaded_objects) {
 		_dl_dprintf(1, "\t%s => %s (0x%x)\n", rpnt->dyn->libname + (_dl_strlen(_dl_ldsopath)) + 1, 
 		_dl_dprintf(1, "\t%s => %s (0x%x)\n", rpnt->dyn->libname + (_dl_strlen(_dl_ldsopath)) + 1, 
 				rpnt->dyn->libname, rpnt->dyn->loadaddr);  
 				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);
 	_dl_perform_mips_global_got_relocations(_dl_loaded_modules);
 #endif
 #endif
 
 
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-	_dl_dprintf(2, "Beginning relocation fixups\n");
+	_dl_dprintf(_dl_debug_file, "Beginning relocation fixups\n");
 #endif
 #endif
 	/*
 	/*
 	 * OK, now all of the kids are tucked into bed in their proper addresses.
 	 * 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. 
 	   and we have to manually search for entries that require fixups. 
 	   Solaris gets this one right, from what I understand.  */
 	   Solaris gets this one right, from what I understand.  */
 
 
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-	_dl_dprintf(2, "Beginning copy fixups\n");
+	_dl_dprintf(_dl_debug_file, "Beginning copy fixups\n");
 #endif
 #endif
 	if (_dl_symbol_tables)
 	if (_dl_symbol_tables)
 		goof += _dl_copy_fixups(_dl_symbol_tables);
 		goof += _dl_copy_fixups(_dl_symbol_tables);
-#ifdef DL_TRACE
+#ifdef LD_TRACE
 	if (goof || _dl_trace_loaded_objects)
 	if (goof || _dl_trace_loaded_objects)
 		_dl_exit(0);
 		_dl_exit(0);
 #endif
 #endif
@@ -1083,13 +1161,13 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 	   up each symbol individually. */
 	   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) {
 	if (_dl_brkp) {
 		*_dl_brkp = brk_addr;
 		*_dl_brkp = brk_addr;
 	}
 	}
 	_dl_envp =
 	_dl_envp =
-		(unsigned long *) _dl_find_hash("__environ", NULL, NULL, 0);
+		(unsigned long *) _dl_find_hash("__environ", NULL, NULL, symbolrel);
 
 
 	if (_dl_envp) {
 	if (_dl_envp) {
 		*_dl_envp = (unsigned long) 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
 #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
 	 * 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. */
 	   function call. */
 	((void (*)(void)) debug_addr->r_brk) ();
 	((void (*)(void)) debug_addr->r_brk) ();
 
 
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-	_dl_dprintf(2, "Calling init/fini for shared libraries\n");
+ 	_dl_dprintf(_dl_debug_file, "Calling init/fini for shared libraries\n");
 #endif
 #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
 		 * We only need to run the init/fini for shared libraries
 		 */
 		 */
-		if (tpnt->libtype == program_interpreter || tpnt->libtype == elf_executable)
+	        if (tpnt->libtype == elf_executable)
-			continue;
+			break;      /* at this point all shared libs are initialized !! */
+
 		if (tpnt->init_flag & INIT_FUNCS_CALLED)
 		if (tpnt->init_flag & INIT_FUNCS_CALLED)
 			continue;
 			continue;
 		tpnt->init_flag |= INIT_FUNCS_CALLED;
 		tpnt->init_flag |= INIT_FUNCS_CALLED;
 
 
 		if (tpnt->dynamic_info[DT_INIT]) {
 		if (tpnt->dynamic_info[DT_INIT]) {
 			_dl_elf_init = (int (*)(void)) (tpnt->loadaddr + 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) ();
 			(*_dl_elf_init) ();
 		}
 		}
 		if (_dl_atexit && tpnt->dynamic_info[DT_FINI]) {
 		if (_dl_atexit && tpnt->dynamic_info[DT_FINI]) {
 			(*_dl_atexit) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
 			(*_dl_atexit) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
 		}
 		}
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 		else {
 		else {
 			if (!_dl_atexit)
 			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 0
 			if (!tpnt->dynamic_info[DT_FINI])
 			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
 		}
 		}
 #endif
 #endif
@@ -1179,6 +1272,10 @@ int _dl_fixup(struct elf_resolve *tpnt)
 
 
 	if (tpnt->next)
 	if (tpnt->next)
 		goof += _dl_fixup(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]) {
 	if (tpnt->dynamic_info[DT_REL]) {
 #ifdef ELF_USES_RELOCA
 #ifdef ELF_USES_RELOCA
 		_dl_dprintf(2, "%s: can't handle REL relocation records\n",
 		_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], 
 			goof += _dl_parse_relocation_information(tpnt, tpnt->dynamic_info[DT_JMPREL], 
 					tpnt->dynamic_info[DT_PLTRELSZ], 0);
 					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;
 	return goof;
 }
 }
 
 
@@ -1224,8 +1324,8 @@ void *_dl_malloc(int size)
 	void *retval;
 	void *retval;
 
 
 #if 0
 #if 0
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-	_dl_dprintf(2, "malloc: request for %d bytes\n", size);
+	_dl_dprintf(_dl_debug_file, "malloc: request for %d bytes\n", size);
 #endif
 #endif
 #endif
 #endif
 
 
@@ -1233,8 +1333,8 @@ void *_dl_malloc(int size)
 		return (*_dl_malloc_function) (size);
 		return (*_dl_malloc_function) (size);
 
 
 	if (_dl_malloc_addr - _dl_mmap_zero + size > 4096) {
 	if (_dl_malloc_addr - _dl_mmap_zero + size > 4096) {
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-		_dl_dprintf(2, "malloc: mmapping more memory\n");
+		_dl_dprintf(_dl_debug_file, "malloc: mmapping more memory\n");
 #endif
 #endif
 		_dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, size, 
 		_dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, size, 
 				PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
 				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.
  * 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.
  * 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.
+/* vi: set sw=4 ts=4: */
-
+/* m68k ELF shared library loader suppport
-   Copyright (C) 1993, Eric Youngdale.
+ *
-   Copyright (C) 1995, Andreas Schwab.
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
-
+ *				David Engel, Hongjiu Lu and Mitch D'Souza
-   This program is free software; you can redistribute it and/or modify
+ * Adapted to ELF/68k by Andreas Schwab.
-   it under the terms of the GNU General Public License as published by
+ *
-   the Free Software Foundation; either version 2, or (at your option)
+ * All rights reserved.
-   any later version.
+ *
-
+ * Redistribution and use in source and binary forms, with or without
-   This program is distributed in the hope that it will be useful,
+ * modification, are permitted provided that the following conditions
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * are met:
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 1. Redistributions of source code must retain the above copyright
-   GNU General Public License for more details.
+ *    notice, this list of conditions and the following disclaimer.
-
+ * 2. The name of the above contributors may not be
-   You should have received a copy of the GNU General Public License
+ *    used to endorse or promote products derived from this software
-   along with this program; if not, write to the Free Software
+ *    without specific prior written permission.
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+ *
-
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
-/* Adapted to ELF/68k by Andreas Schwab.  */
+ * 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
 #ifndef VERBOSE_DLINKER
 #define 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;
   instr_addr = (int) this_reloc->r_offset + (int) tpnt->loadaddr;
   got_addr = (char **) instr_addr;
   got_addr = (char **) instr_addr;
 
 
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_DEBUG_SYMBOLS
   _dl_dprintf (2, "Resolving symbol %s\n",
   _dl_dprintf (2, "Resolving symbol %s\n",
 		strtab + symtab[symtab_index].st_name);
 		strtab + symtab[symtab_index].st_name);
 #endif
 #endif
 
 
   /* Get the address of the GOT entry.  */
   /* Get the address of the GOT entry.  */
   new_addr = _dl_find_hash (strtab + symtab[symtab_index].st_name,
   new_addr = _dl_find_hash (strtab + symtab[symtab_index].st_name,
-			    tpnt->symbol_scope, tpnt, 0);
+			    tpnt->symbol_scope, tpnt, resolver);
   if (!new_addr)
   if (!new_addr)
     {
     {
       _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
       _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
 		    _dl_progname, strtab + symtab[symtab_index].st_name);
 		    _dl_progname, strtab + symtab[symtab_index].st_name);
       _dl_exit (1);
       _dl_exit (1);
     }
     }
-#ifdef DL_NEVER_FIXUP_SYMBOLS
+#ifdef LD_NEVER_FIXUP_SYMBOLS
   if ((unsigned int) got_addr < 0x40000000) {
   if ((unsigned int) got_addr < 0x40000000) {
       _dl_dprintf (2, "Calling library function: %s\n",
       _dl_dprintf (2, "Calling library function: %s\n",
 	      strtab + symtab[symtab_index].st_name);
 	      strtab + symtab[symtab_index].st_name);
@@ -202,7 +212,7 @@ _dl_parse_relocation_information (struct elf_resolve *tpnt,
 	  symbol_addr = (unsigned int)
 	  symbol_addr = (unsigned int)
 	    _dl_find_hash (strtab + symtab[symtab_index].st_name,
 	    _dl_find_hash (strtab + symtab[symtab_index].st_name,
 			   tpnt->symbol_scope,
 			   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 -
 	  /* We want to allow undefined references to weak symbols -
 	     this might have been intentional.  We should not be
 	     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)
 	  symbol_addr = (unsigned int)
 	    _dl_find_hash (strtab + symtab[symtab_index].st_name,
 	    _dl_find_hash (strtab + symtab[symtab_index].st_name,
-			   xpnt->next, NULL, 1);
+			   xpnt->next, NULL, copyrel);
 	  if (!symbol_addr)
 	  if (!symbol_addr)
 	    {
 	    {
 	      _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
 	      _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 _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 _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: */
 /* vi: set sw=4 ts=4: */
-
+/* mips/mipsel ELF shared library loader suppport
-/* Run an ELF binary on a linux system.
+ *
-
    Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com)
    Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com)
-
+ *
-   This program is free software; you can redistribute it and/or modify
+ * All rights reserved.
-   it under the terms of the GNU General Public License as published by
+ *
-   the Free Software Foundation; either version 2, or (at your option)
+ * Redistribution and use in source and binary forms, with or without
-   any later version.
+ * modification, are permitted provided that the following conditions
-
+ * are met:
-   This program is distributed in the hope that it will be useful,
+ * 1. Redistributions of source code must retain the above copyright
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    notice, this list of conditions and the following disclaimer.
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 2. The name of the above contributors may not be
-   GNU General Public License for more details.
+ *    used to endorse or promote products derived from this software
-
+ *    without specific prior written permission.
-   You should have received a copy of the GNU General Public License
+ *
-   along with this program; if not, write to the Free Software
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+ * 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
-/* Program to load an ELF binary on a linux system, and run it.
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-   References to symbols in sharable libraries can be resolved by either
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-   an ELF sharable library or a linux style of shared library. */
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-/* Disclaimer:  I have never seen any AT&T source code for SVr4, nor have
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-   I ever taken any courses on internals.  This program was developed using
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-   information available through the book "UNIX SYSTEM V RELEASE 4,
+ * SUCH DAMAGE.
-   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);
 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);
 	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
 
 
 	value = (unsigned long) _dl_find_hash(strtab + sym->st_name,
 	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;
 	*(got + local_gotno + sym_index - gotsym) = value;
 
 
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 	_dl_dprintf(2, "---RESOLVER---\n");
 	_dl_dprintf(2, "---RESOLVER---\n");
 	_dl_dprintf(2, "SYMTAB INDEX: %i\n", sym_index);
 	_dl_dprintf(2, "SYMTAB INDEX: %i\n", sym_index);
 	_dl_dprintf(2, "      GOTSYM: %i\n", gotsym);
 	_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 */
 		/* Relocate the global GOT entries for the object */
 		while(i--) {
 		while(i--) {
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 			_dl_dprintf(2,"BEFORE: %s=%x\n", strtab + sym->st_name,
 			_dl_dprintf(2,"BEFORE: %s=%x\n", strtab + sym->st_name,
 				*got_entry);
 				*got_entry);
 #endif
 #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;
 					*got_entry = sym->st_value + (unsigned long) tpnt->loadaddr;
 				else {
 				else {
 					*got_entry = (unsigned long) _dl_find_hash(strtab +
 					*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) {
 			else if (sym->st_shndx == SHN_COMMON) {
 				*got_entry = (unsigned long) _dl_find_hash(strtab +
 				*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 &&
 			else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&
 				*got_entry != sym->st_value)
 				*got_entry != sym->st_value)
@@ -192,10 +189,10 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
 			}
 			}
 			else {
 			else {
 				*got_entry = (unsigned long) _dl_find_hash(strtab +
 				*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)
 			if (*got_entry == 0)
 				_dl_dprintf(2,"ZERO: %s\n", strtab + sym->st_name);
 				_dl_dprintf(2,"ZERO: %s\n", strtab + sym->st_name);
 			else
 			else

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

@@ -17,5 +17,5 @@ _dl_boot:
 ");
 ");
 
 
 #define _dl_boot _dl_boot2
 #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 _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
+/* vi: set sw=4 ts=4: */
-/* Run an ELF binary on a linux system.
+/* 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
 #ifndef VERBOSE_DLINKER
 #define VERBOSE_DLINKER
 #define VERBOSE_DLINKER
 #endif
 #endif
@@ -49,7 +59,7 @@ static const char *_dl_reltypes[] =
    working. */
    working. */
 
 
 
 
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_DEBUG_SYMBOLS
 static void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index);
 static void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index);
 static void debug_reloc(ELF_RELOC *rpnt);
 static void debug_reloc(ELF_RELOC *rpnt);
 #define DPRINTF(fmt,args...) _dl_dprintf(2,fmt,args)
 #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 */
 	/* Get the address of the GOT entry */
 	targ_addr = (unsigned long) _dl_find_hash(
 	targ_addr = (unsigned long) _dl_find_hash(
 		strtab + symtab[symtab_index].st_name, 
 		strtab + symtab[symtab_index].st_name, 
-		tpnt->symbol_scope, tpnt, 0);
+		tpnt->symbol_scope, tpnt, resolver);
 	if (!targ_addr) {
 	if (!targ_addr) {
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 			_dl_progname, strtab + symtab[symtab_index].st_name);
 			_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, 
 			symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
 					tpnt->symbol_scope,
 					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
 			 * 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 + 
 			symbol_addr = (unsigned long) _dl_find_hash(strtab + 
 				symtab[symtab_index].st_name, xpnt->next, 
 				symtab[symtab_index].st_name, xpnt->next, 
-				NULL, 1);
+				NULL, copyrel);
 			if (!symbol_addr) {
 			if (!symbol_addr) {
 				_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 				_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 					_dl_progname, strtab + symtab[symtab_index].st_name);
 					_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
 #endif
 
 
 
 
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_DEBUG_SYMBOLS
 static void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index)
 static void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index)
 {
 {
 	if(symtab_index){
 	if(symtab_index){

+ 59 - 37
ldso/ldso/readelflib1.c

@@ -1,21 +1,34 @@
-/* Load an ELF sharable library into memory.
+/* vi: set sw=4 ts=4: */
-
+/* Program to load an ELF binary on a linux system, and run it
-   Copyright (C) 1993-1996, Eric Youngdale.
+ * after resolving ELF shared library symbols
-
+ *
-   This program is free software; you can redistribute it and/or modify
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
-   it under the terms of the GNU General Public License as published by
+ *				David Engel, Hongjiu Lu and Mitch D'Souza
-   the Free Software Foundation; either version 2, or (at your option)
+ * Copyright (C) 2001-2002, Erik Andersen
-   any later version.
+ *
-
+ * All rights reserved.
-   This program is distributed in the hope that it will be useful,
+ *
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * Redistribution and use in source and binary forms, with or without
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * modification, are permitted provided that the following conditions
-   GNU General Public License for more details.
+ * are met:
-
+ * 1. Redistributions of source code must retain the above copyright
-   You should have received a copy of the GNU General Public License
+ *    notice, this list of conditions and the following disclaimer.
-   along with this program; if not, write to the Free Software
+ * 2. The name of the above contributors may not be
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+ *    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
 /* 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++;
 		pnt++;
 	}
 	}
 
 
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-	    _dl_dprintf(2, "searching for library: '%s'\n", libname);
+	    _dl_dprintf(_dl_debug_file, "searching for library: '%s'\n", libname);
 #endif
 #endif
 	/* If the filename has any '/', try it straight and leave it at that.
 	/* If the filename has any '/', try it straight and leave it at that.
 	   For IBCS2 compatibility under linux, we substitute the string 
 	   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) {
 			if (pnt) {
 				pnt += (unsigned long) tpnt->loadaddr +
 				pnt += (unsigned long) tpnt->loadaddr +
 					tpnt->dynamic_info[DT_STRTAB];
 					tpnt->dynamic_info[DT_STRTAB];
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-				_dl_dprintf(2, "searching RPATH: '%s'\n", pnt);
+				_dl_dprintf(_dl_debug_file, "searching RPATH: '%s'\n", pnt);
 #endif
 #endif
 				if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) 
 				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 */
 	/* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
 	if (_dl_library_path) {
 	if (_dl_library_path) {
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-	    _dl_dprintf(2, "searching _dl_library_path: '%s'\n", _dl_library_path);
+	    _dl_dprintf(_dl_debug_file, "searching _dl_library_path: '%s'\n", _dl_library_path);
 #endif
 #endif
 	    if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL) 
 	    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
 	/* Look for libraries wherever the shared library loader
 	 * was installed */
 	 * was installed */
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-	_dl_dprintf(2, "searching in ldso dir: %s\n", _dl_ldsopath);
+	_dl_dprintf(_dl_debug_file, "searching in ldso dir: %s\n", _dl_ldsopath);
 #endif
 #endif
 	if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt)) != NULL) 
 	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.
 	/* Lastly, search the standard list of paths for the library.
 	   This list must exactly match the list in uClibc/ldso/util/ldd.c */
 	   This list must exactly match the list in uClibc/ldso/util/ldd.c */
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
-	    _dl_dprintf(2, "searching full lib path list\n");
+	    _dl_dprintf(_dl_debug_file, "searching full lib path list\n");
 #endif
 #endif
 	if ((tpnt1 = search_for_named_library(libname, secure, 
 	if ((tpnt1 = search_for_named_library(libname, secure, 
 			UCLIBC_TARGET_PREFIX "/usr/lib:"
 			UCLIBC_TARGET_PREFIX "/usr/lib:"
@@ -282,8 +295,8 @@ goof:
 	if (_dl_internal_error_number)
 	if (_dl_internal_error_number)
 		_dl_error_number = _dl_internal_error_number;
 		_dl_error_number = _dl_internal_error_number;
 	else
 	else
-		_dl_error_number = DL_ERROR_NOFILE;
+		_dl_error_number = LD_ERROR_NOFILE;
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
 	    _dl_dprintf(2, "Bummer: could not find '%s'!\n", libname);
 	    _dl_dprintf(2, "Bummer: could not find '%s'!\n", libname);
 #endif
 #endif
 	return NULL;
 	return NULL;
@@ -323,6 +336,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 			(*rpnt)->next = (struct dyn_elf *)
 			(*rpnt)->next = (struct dyn_elf *)
 				_dl_malloc(sizeof(struct dyn_elf));
 				_dl_malloc(sizeof(struct dyn_elf));
 			_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
 			_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+			(*rpnt)->next->prev = (*rpnt);
 			*rpnt = (*rpnt)->next;
 			*rpnt = (*rpnt)->next;
 			(*rpnt)->dyn = tpnt;
 			(*rpnt)->dyn = tpnt;
 			tpnt->symbol_scope = _dl_symbol_tables;
 			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);
 		_dl_dprintf(2, "%s: can't open '%s'\n", _dl_progname, libname);
 #endif
 #endif
-		_dl_internal_error_number = DL_ERROR_NOFILE;
+		_dl_internal_error_number = LD_ERROR_NOFILE;
 		return NULL;
 		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,
 		_dl_dprintf(2, "%s: '%s' is not an ELF file\n", _dl_progname,
 					 libname);
 					 libname);
-		_dl_internal_error_number = DL_ERROR_NOTELF;
+		_dl_internal_error_number = LD_ERROR_NOTELF;
 		_dl_close(infile);
 		_dl_close(infile);
 		return NULL;
 		return NULL;
 	};
 	};
@@ -377,7 +391,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 		)) 
 		)) 
 	{
 	{
 		_dl_internal_error_number = 
 		_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 
 		_dl_dprintf(2, "%s: '%s' is not an ELF executable for " ELF_TARGET 
 			"\n", _dl_progname, libname);
 			"\n", _dl_progname, libname);
 		_dl_close(infile);
 		_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);
 		maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
 	if (_dl_mmap_check_error(status)) {
 	if (_dl_mmap_check_error(status)) {
 		_dl_dprintf(2, "%s: can't map %s\n", _dl_progname, libname);
 		_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);
 		_dl_close(infile);
 		return NULL;
 		return NULL;
 	};
 	};
@@ -457,7 +471,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 				if (_dl_mmap_check_error(status)) {
 				if (_dl_mmap_check_error(status)) {
 					_dl_dprintf(2, "%s: can't map '%s'\n", 
 					_dl_dprintf(2, "%s: can't map '%s'\n", 
 						_dl_progname, libname);
 						_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_munmap((char *) libaddr, maxvma - minvma);
 					_dl_close(infile);
 					_dl_close(infile);
 					return NULL;
 					return NULL;
@@ -488,7 +502,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 					infile, ppnt->p_offset & OFFS_ALIGN);
 					infile, ppnt->p_offset & OFFS_ALIGN);
 			if (_dl_mmap_check_error(status)) {
 			if (_dl_mmap_check_error(status)) {
 				_dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname);
 				_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_munmap((char *) libaddr, maxvma - minvma);
 				_dl_close(infile);
 				_dl_close(infile);
 				return NULL;
 				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 */
 	/* Start by scanning the dynamic section to get all of the pointers */
 
 
 	if (!dynamic_addr) {
 	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_dprintf(2, "%s: '%s' is missing a dynamic section\n", 
 			_dl_progname, libname);
 			_dl_progname, libname);
 		return NULL;
 		return NULL;
@@ -580,6 +594,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 		(*rpnt)->next = (struct dyn_elf *)
 		(*rpnt)->next = (struct dyn_elf *)
 			_dl_malloc(sizeof(struct dyn_elf));
 			_dl_malloc(sizeof(struct dyn_elf));
 		_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
 		_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+		(*rpnt)->next->prev = (*rpnt);
 		*rpnt = (*rpnt)->next;
 		*rpnt = (*rpnt)->next;
 		(*rpnt)->dyn = tpnt;
 		(*rpnt)->dyn = tpnt;
 		tpnt->symbol_scope = _dl_symbol_tables;
 		tpnt->symbol_scope = _dl_symbol_tables;
@@ -626,6 +641,10 @@ int _dl_copy_fixups(struct dyn_elf *rpnt)
 		return goof;
 		return goof;
 	tpnt->init_flag |= COPY_RELOCS_DONE;
 	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
 #ifdef ELF_USES_RELOCA
 	goof += _dl_parse_copy_information(rpnt, 
 	goof += _dl_parse_copy_information(rpnt, 
 		tpnt->dynamic_info[DT_RELA], tpnt->dynamic_info[DT_RELASZ], 0);
 		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);
 		tpnt->dynamic_info[DT_RELSZ], 0);
 
 
 #endif
 #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;
 	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.
  * 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.
  * 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
 #ifndef VERBOSE_DLINKER
 #define VERBOSE_DLINKER
 #define VERBOSE_DLINKER
 #endif
 #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);
   _dl_dprintf(2, "symtab_index %d\n", symtab_index);
 
 
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_DEBUG_SYMBOLS
   _dl_dprintf(2, "Resolving symbol %s\n",
   _dl_dprintf(2, "Resolving symbol %s\n",
 	strtab + symtab[symtab_index].st_name);
 	strtab + symtab[symtab_index].st_name);
 #endif
 #endif
 
 
   /* Get the address of the GOT entry */
   /* Get the address of the GOT entry */
   new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
   new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-  			tpnt->symbol_scope, tpnt, 0);
+  			tpnt->symbol_scope, tpnt, resolver);
   if(!new_addr) {
   if(!new_addr) {
     _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
     _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
 	       _dl_progname, strtab + symtab[symtab_index].st_name);
 	       _dl_progname, strtab + symtab[symtab_index].st_name);
     _dl_exit(31);
     _dl_exit(31);
   };
   };
-#ifdef DL_NEVER_FIXUP_SYMBOLS
+#ifdef LD_NEVER_FIXUP_SYMBOLS
   if((unsigned int) got_addr < 0x40000000) {
   if((unsigned int) got_addr < 0x40000000) {
     _dl_dprintf(2, "Calling library function: %s\n",
     _dl_dprintf(2, "Calling library function: %s\n",
 	       strtab + symtab[symtab_index].st_name);
 	       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) 
       symbol_addr = (unsigned int) 
 	_dl_find_hash(strtab + symtab[symtab_index].st_name,
 	_dl_find_hash(strtab + symtab[symtab_index].st_name,
 			      tpnt->symbol_scope,
 			      tpnt->symbol_scope,
-		      (reloc_type == R_SPARC_JMP_SLOT ? tpnt : NULL), 0);
+		      (reloc_type == R_SPARC_JMP_SLOT ? tpnt : NULL), symbolrel);
 
 
       if(!symbol_addr &&
       if(!symbol_addr &&
 	 ELF32_ST_BIND(symtab [symtab_index].st_info) == STB_GLOBAL) {
 	 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) 
       symbol_addr = (unsigned int) 
 	_dl_find_hash(strtab + symtab[symtab_index].st_name,
 	_dl_find_hash(strtab + symtab[symtab_index].st_name,
-			      xpnt->next, NULL, 1);
+			      xpnt->next, NULL, copyrel);
       if(!symbol_addr) {
       if(!symbol_addr) {
 	_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
 	_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
 		   _dl_progname, strtab + symtab[symtab_index].st_name);
 		   _dl_progname, strtab + symtab[symtab_index].st_name);