Преглед изворни кода

Steven J. Hill's latest mips dynamic loader updates

Eric Andersen пре 24 година
родитељ
комит
96749a7682

+ 5 - 4
Makefile

@@ -332,16 +332,17 @@ finished2:
 
 distclean clean:
 	@rm -rf tmp lib include/bits libc/tmp _install
-	- find include -type l -exec rm -f {} \;
-	- find . \( -name \*.o -o -name \*.a -o -name \*.so -o -name core -o -name .\#\* \) -exec rm -f {} \;
 	$(MAKE) -C test clean
 	$(MAKE) -C ldso clean
 	$(MAKE) -C libc/misc clean
 	$(MAKE) -C libc/unistd clean
 	$(MAKE) -C libc/sysdeps/linux/common clean
-	$(MAKE) -C libc/sysdeps/linux/$(TARGET_ARCH) clean
 	$(MAKE) -C extra/gcc-uClibc clean
-	find . -name mipsel -exec rm -rf {} \;
+	@if [ -d libc/sysdeps/linux/$(TARGET_ARCH) ]; then		\
+	    $(MAKE) -C libc/sysdeps/linux/$(TARGET_ARCH) clean;		\
+	fi;
+	- find . \( -name \*.o -o -name \*.a -o -name \*.so -o -name core -o -name .\#\* \) -exec rm -f {} \;
+	- find -type l -exec rm -f {} \;
 
 dist release: distclean
 	cd ..;					\

+ 4 - 3
ldso/ldso/dl-elf.c

@@ -308,7 +308,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	int flags;
 	char header[4096];
 	unsigned long dynamic_info[24];
-	int *lpnt;
+	unsigned long *lpnt;
 	unsigned long libaddr;
 	unsigned long minvma = 0xffffffff, maxvma = 0;
 
@@ -553,10 +553,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	 * resolved. 
 	 */
 
-	lpnt = (int *) dynamic_info[DT_PLTGOT];
+	lpnt = (unsigned long *) dynamic_info[DT_PLTGOT];
 
 	if (lpnt) {
-		lpnt = (int *) (dynamic_info[DT_PLTGOT] + ((int) libaddr));
+		lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT] +
+			((int) libaddr));
 		INIT_GOT(lpnt, tpnt);
 	};
 

+ 1 - 1
ldso/ldso/ld_string.h

@@ -221,7 +221,7 @@ static inline char *_dl_simple_ltoahex(char * local, unsigned long i)
 }
 
 
-#if defined mc68000 || defined __arm__
+#if defined mc68000 || defined __arm__ || defined __mips__
 /* On some arches constant strings are referenced through the GOT. */
 /* XXX Requires load_addr to be defined. */
 #define SEND_STDERR(X)				\

+ 2 - 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);
 
 
-#ifdef __powerpc__
-/* PowerPC has a different calling convention for mmap(). */
+#if defined(__powerpc) || defined(__mips__)
+/* PowerPC and MIPS have a different calling convention for mmap(). */
 #define __NR__dl_mmap __NR_mmap
 static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
 		int, prot, int, flags, int, fd, off_t, offset);

+ 36 - 10
ldso/ldso/ldso.c

@@ -20,11 +20,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
  */
 
-/* Enable this to turn on debugging noise */
-//#define DL_DEBUG
-
-/* Enable mprotect protection munging.  ARM Linux needs this it seems,
- * so leave this enabled by default */
+/* Enable mprotect protection munging.  ARM and MIPS Linux needs this
+ * it seems, so leave this enabled by default */
 #define DO_MPROTECT_HACKS
 
 // Support a list of library preloads in /etc/ld.so.preload
@@ -209,10 +206,16 @@ DL_BOOT(unsigned long args)
 	Elf32_auxv_t auxvt[AT_EGID + 1];
 	unsigned char *malloc_buffer, *mmap_zero;
 	Elf32_Dyn *dpnt;
+	Elf32_Dyn *dpnt_debug = NULL;
 	unsigned long *hash_addr;
 	struct r_debug *debug_addr;
 	int indx;
 	int status;
+#if defined(__mips__)
+	unsigned long mips_gotsym = 0;
+	unsigned long mips_local_gotno = 0;
+	unsigned long mips_symtabno = 0;
+#endif
 
 
 	/* WARNING! -- we cannot make _any_ funtion calls until we have
@@ -223,7 +226,7 @@ DL_BOOT(unsigned long args)
 	/* First obtain the information on the stack that tells us more about
 	   what binary is loaded, where it is loaded, etc, etc */
 	GET_ARGV(aux_dat, args);
-#if defined(__arm__) || defined(__mips__)
+#if defined (__arm__) || defined (__mips__)
 	aux_dat += 1;
 #endif
 	argc = *(aux_dat - 1);
@@ -267,7 +270,7 @@ DL_BOOT(unsigned long args)
 		_dl_exit(0);
 	}
 #ifdef DL_DEBUG
-	SEND_STDERR("ELF header =");
+	SEND_STDERR("ELF header=");
 	SEND_ADDRESS_STDERR(load_addr, 1);
 #endif
 
@@ -287,7 +290,7 @@ DL_BOOT(unsigned long args)
 #elif defined(__powerpc__)
   __asm__("\tbl _GLOBAL_OFFSET_TABLE_-4@local\n\t":"=l"(got));
 #elif defined(__mips__)
-  __asm__("\tmove %0, $28\n\t":"=r"(got));
+  __asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got));
 #else
 	/* Do things the slow way in C */
 	{
@@ -334,7 +337,7 @@ DL_BOOT(unsigned long args)
 		_dl_exit(0);
 
 	  found_got:
-		got = (unsigned long *) (dynamic->d_un.d_val - tx_reloc + 
+		got = (unsigned long *) (dynamic->d_un.d_val - tx_reloc +
 				(char *) header);
 	}
 #endif
@@ -376,6 +379,14 @@ DL_BOOT(unsigned long args)
 				tpnt->dynamic_info[DT_TEXTREL] = 1;
 			}
 		}
+#if defined(__mips__)
+		if (dpnt->d_tag == DT_MIPS_GOTSYM)
+			mips_gotsym = (unsigned long) dpnt->d_un.d_val;
+		if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
+			mips_local_gotno = (unsigned long) dpnt->d_un.d_val;
+		if (dpnt->d_tag == DT_MIPS_SYMTABNO)
+			mips_symtabno = (unsigned long) dpnt->d_un.d_val;
+#endif
 		dpnt++;
 	}
 
@@ -394,7 +405,11 @@ DL_BOOT(unsigned long args)
 					}
 					app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
 					if (dpnt->d_tag == DT_DEBUG)
+#ifndef DO_MPROTECT_HACKS
 						dpnt->d_un.d_val = (unsigned long) debug_addr;
+#else
+						dpnt_debug = dpnt;
+#endif
 					if (dpnt->d_tag == DT_TEXTREL || SVR4_BUGCOMPAT)
 						app_tpnt->dynamic_info[DT_TEXTREL] = 1;
 					dpnt++;
@@ -446,6 +461,16 @@ DL_BOOT(unsigned long args)
 			}
 		}
 	}
+
+	/* Now we can store the debug structure address */
+	dpnt_debug->d_un.d_val = (unsigned long) debug_addr;
+#endif
+
+
+	/* For MIPS, we have to do special stuff to the GOT before we do
+	   any relocations. */
+#if defined(__mips__)
+	PERFORM_BOOTSTRAP_GOT(got);
 #endif
 
 
@@ -454,6 +479,7 @@ DL_BOOT(unsigned long args)
 #ifdef DL_DEBUG
 	SEND_STDERR("About to do library loader relocations.\n");
 #endif
+
 	goof = 0;
 	for (indx = 0; indx < 2; indx++) {
 		int i;
@@ -476,7 +502,6 @@ DL_BOOT(unsigned long args)
 			 dynamic_info[DT_RELSZ]);
 #endif
 
-
 		if (!rel_addr)
 			continue;
 
@@ -499,6 +524,7 @@ DL_BOOT(unsigned long args)
 				if (!_dl_symbol(strtab + symtab[symtab_index].st_name))
 					continue;
 				symbol_addr = load_addr + symtab[symtab_index].st_value;
+					SEND_NUMBER_STDERR(symbol_addr,1);
 
 				if (!symbol_addr) {
 					/* This will segfault - you cannot call a function until

+ 43 - 0
ldso/ldso/mips/README

@@ -0,0 +1,43 @@
+Almost all of the code present in these source files was taken
+from GLIBC. In the descriptions below, all files mentioned are
+with respect to the top level GLIBC source directory accept for
+the code taken from the Linux kernel.
+
+boot1_arch.h
+------------
+Contains code to fix up the stack pointer so that the dynamic
+linker can find argc, argv and Auxillary Vector Table (AVT).
+The codes is taken from the function 'RTLD_START' in the
+file 'sysdeps/mips/dl-machine.h'.
+
+elfinterp.c
+-----------
+Contains '_dl_init_got' which initializes the GOT for the
+application being dynamically linked and loaded. The code is
+taken from the functions 'elf_machine_runtime_setup' and 
+'elf_machine_got_rel' in the file 'sysdeps/mips/dl-machine.h'.
+
+ld_syscalls.h
+-------------
+Contains all the macro function prototypes for the system calls
+as well as the list of system calls supported. The macros were
+taken from the Linux kernel source 2.4.17 found in the file
+'include/asm-mips/unistd.h'.
+
+ld_sysdep.h
+-----------
+Contains bootstrap code for the dynamic linker, magic numbers
+for detecting MIPS target types and some macros. The macro
+function 'PERFORM_BOOTSTRAP_GOT' is used to relocate the dynamic
+linker's GOT so that function calls can be made. The code is
+taken from the function 'ELF_MACHINE_BEFORE_RTLD_RELOC' in the
+file 'sysdep/mips/dl-machine.h'. The other macro function
+'PERFORM_BOOTSTRAP_RELOC' is used to do the relocations for
+the dynamic loader. The code is taken from the function
+'elf_machine_rel' in the file 'sysdep/mips/dl-machine.h'.
+
+resolve.S
+---------
+Contains the low-level assembly code for the dynamic runtime
+resolver. The code is taken from the assembly code function
+'_dl_runtime_resolve' in the file 'sysdesp/mips/dl-machine.h'.

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

@@ -13,11 +13,8 @@ _dl_boot:
 	nop
 0:	.cpload $31
 	.set reorder
-	# i386 ABI book says that the first entry of GOT holds
-	# the address of the dynamic structure. Though MIPS ABI
-	# doesn't say nothing about this, I emulate this here.
+	# Store offset of DYNAMIC section in first entry of GOT
 	la $4, _DYNAMIC
-	# Subtract OFFSET_GP_GOT
 	sw $4, -0x7ff0($28)
 	move $4, $29
 	la $8, coff

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

@@ -13,11 +13,8 @@ _dl_boot:
 	nop
 0:	.cpload $31
 	.set reorder
-	# i386 ABI book says that the first entry of GOT holds
-	# the address of the dynamic structure. Though MIPS ABI
-	# doesn't say nothing about this, I emulate this here.
+	# Store offset of DYNAMIC section in first entry of GOT
 	la $4, _DYNAMIC
-	# Subtract OFFSET_GP_GOT
 	sw $4, -0x7ff0($28)
 	move $4, $29
 	la $8, coff

+ 30 - 0
ldso/ldso/mips/dl-syscalls.h

@@ -142,4 +142,34 @@ type name(atype a, btype b, ctype c, dtype d) \
 	return (type) -1; \
 }
 
+#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
+type name(atype a, btype b, ctype c, dtype d, etype e, ftype f) \
+{ \
+	register unsigned long __v0 asm("$2") = __NR_##name; \
+	register unsigned long __a0 asm("$4") = (unsigned long) a; \
+	register unsigned long __a1 asm("$5") = (unsigned long) b; \
+	register unsigned long __a2 asm("$6") = (unsigned long) c; \
+	register unsigned long __a3 asm("$7") = (unsigned long) d; \
+	\
+	__asm__ volatile ( \
+	".set\tnoreorder\n\t" \
+	"lw\t$2, %6\n\t" \
+	"lw\t$8, %7\n\t" \
+	"subu\t$29, 32\n\t" \
+	"sw\t$2, 16($29)\n\t" \
+	"sw\t$8, 20($29)\n\t" \
+	"li\t$2, %5\t\t\t# " #name "\n\t" \
+	"syscall\n\t" \
+	"addiu\t$29, 32\n\t" \
+	".set\treorder" \
+	: "=&r" (__v0), "+r" (__a3) \
+	: "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name), \
+	  "m" ((unsigned long)e), "m" ((unsigned long)f) \
+	: "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \
+	\
+	if (__a3 == 0) \
+		return (type) __v0; \
+	return (type) -1; \
+}
+
 #endif

+ 70 - 22
ldso/ldso/mips/dl-sysdep.h

@@ -8,36 +8,82 @@
  */
 #undef 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)
+#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long *) ARGS)
+
 
 /*
- * Initialization sequence for a GOT.
+ * Initialization sequence for the application GOT.
  */
-#define INIT_GOT(GOT_BASE,MODULE) \
-{				\
-  GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
-  GOT_BASE[1] = (unsigned long) MODULE; \
-}
+#define INIT_GOT(GOT_BASE,MODULE)	_dl_init_got(GOT_BASE,MODULE)
+
+
+/*
+ * Here is a macro to perform the GOT relocation.  This is only
+ * used when bootstrapping the dynamic loader.
+ */
+#define PERFORM_BOOTSTRAP_GOT(got)					\
+do {									\
+	Elf32_Sym *sym;							\
+	unsigned long i;						\
+									\
+	/* Add load address displacement to all local GOT entries */	\
+	i = 2;								\
+	while (i < mips_local_gotno)					\
+		got[i++] += load_addr;					\
+									\
+	/* Handle global GOT entries */					\
+	got += mips_local_gotno;					\
+	sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] +		\
+		 load_addr) + mips_gotsym;				\
+	i = mips_symtabno - mips_gotsym;				\
+									\
+	while (i--) {							\
+		if (sym->st_shndx == SHN_UNDEF ||			\
+			sym->st_shndx == SHN_COMMON)			\
+			*got = load_addr + sym->st_value;		\
+		else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&	\
+			*got != sym->st_value)				\
+			*got += load_addr;				\
+		else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) {	\
+			if (sym->st_other == 0)				\
+				*got += load_addr;			\
+		}							\
+		else							\
+			*got = load_addr + sym->st_value;		\
+									\
+		got++;							\
+		sym++;							\
+	}								\
+} while (0)
+
 
 /*
  * 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.
- *
- * !!!NOTE!!!
- *
- * For MIPS, we don't have any DT_JMPREL or DT_PLTRELSZ dynamic
- * entries, so this macro function is empty. The code contained
- * in elfinterp.c does the real relocation work.
+ * bootstrapping the dynamic loader.
  */
-#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)			\
+	switch(ELF32_R_TYPE((RELP)->r_info)) {				\
+	case R_MIPS_REL32:						\
+		if (symtab_index) {					\
+			if (symtab_index < mips_gotsym)			\
+				*REL += SYMBOL + LOAD;			\
+		}							\
+		else {							\
+			*REL += LOAD;					\
+		}							\
+		break;							\
+	case R_MIPS_NONE:						\
+		break;							\
+	default:							\
+		SEND_STDERR("Aiieeee!");				\
+		_dl_exit(1);						\
+	}
 
 
 /*
@@ -45,19 +91,21 @@
  * is done.  This routine has to exit the current function, then 
  * call the _dl_elf_main function.
  */
-
 #define START()   return (void) _dl_elf_main;      
 
 
-
 /* Here we define the magic numbers that this dynamic loader should accept */
-
 #define MAGIC1 EM_MIPS
 #define MAGIC2 EM_MIPS_RS3_LE
+
+
 /* Used for error messages */
 #define ELF_TARGET "MIPS"
 
+
 struct elf_resolve;
-unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt,
+	int reloc_entry);
+void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt);
 
 #define do_rem(result, n, base)  result = (n % base)

+ 49 - 0
ldso/ldso/mips/elfinterp.c

@@ -0,0 +1,49 @@
+/* Run an ELF binary on a linux system.
+
+   Copyright (C) 1993, Eric Youngdale.
+   Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com)
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+
+/* Program to load an ELF binary on a linux system, and run it.
+   References to symbols in sharable libraries can be resolved by either
+   an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer:  I have never seen any AT&T source code for SVr4, nor have
+   I ever taken any courses on internals.  This program was developed using
+   information available through the book "UNIX SYSTEM V RELEASE 4,
+   Programmers guide: Ansi C and Programming Support Tools", which did
+   a more than adequate job of explaining everything required to get this
+   working. */
+
+
+extern int _dl_linux_resolve(void);
+
+void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt)
+{
+	return;
+}
+
+unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+	return 0;
+}
+
+int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
+	unsigned long rel_addr, unsigned long rel_size, int type)
+{
+	return 1;
+}

+ 30 - 0
ldso/ldso/mips/ld_syscalls.h

@@ -142,4 +142,34 @@ type name(atype a, btype b, ctype c, dtype d) \
 	return (type) -1; \
 }
 
+#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
+type name(atype a, btype b, ctype c, dtype d, etype e, ftype f) \
+{ \
+	register unsigned long __v0 asm("$2") = __NR_##name; \
+	register unsigned long __a0 asm("$4") = (unsigned long) a; \
+	register unsigned long __a1 asm("$5") = (unsigned long) b; \
+	register unsigned long __a2 asm("$6") = (unsigned long) c; \
+	register unsigned long __a3 asm("$7") = (unsigned long) d; \
+	\
+	__asm__ volatile ( \
+	".set\tnoreorder\n\t" \
+	"lw\t$2, %6\n\t" \
+	"lw\t$8, %7\n\t" \
+	"subu\t$29, 32\n\t" \
+	"sw\t$2, 16($29)\n\t" \
+	"sw\t$8, 20($29)\n\t" \
+	"li\t$2, %5\t\t\t# " #name "\n\t" \
+	"syscall\n\t" \
+	"addiu\t$29, 32\n\t" \
+	".set\treorder" \
+	: "=&r" (__v0), "+r" (__a3) \
+	: "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name), \
+	  "m" ((unsigned long)e), "m" ((unsigned long)f) \
+	: "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \
+	\
+	if (__a3 == 0) \
+		return (type) __v0; \
+	return (type) -1; \
+}
+
 #endif

+ 70 - 22
ldso/ldso/mips/ld_sysdep.h

@@ -8,36 +8,82 @@
  */
 #undef 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)
+#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long *) ARGS)
+
 
 /*
- * Initialization sequence for a GOT.
+ * Initialization sequence for the application GOT.
  */
-#define INIT_GOT(GOT_BASE,MODULE) \
-{				\
-  GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
-  GOT_BASE[1] = (unsigned long) MODULE; \
-}
+#define INIT_GOT(GOT_BASE,MODULE)	_dl_init_got(GOT_BASE,MODULE)
+
+
+/*
+ * Here is a macro to perform the GOT relocation.  This is only
+ * used when bootstrapping the dynamic loader.
+ */
+#define PERFORM_BOOTSTRAP_GOT(got)					\
+do {									\
+	Elf32_Sym *sym;							\
+	unsigned long i;						\
+									\
+	/* Add load address displacement to all local GOT entries */	\
+	i = 2;								\
+	while (i < mips_local_gotno)					\
+		got[i++] += load_addr;					\
+									\
+	/* Handle global GOT entries */					\
+	got += mips_local_gotno;					\
+	sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] +		\
+		 load_addr) + mips_gotsym;				\
+	i = mips_symtabno - mips_gotsym;				\
+									\
+	while (i--) {							\
+		if (sym->st_shndx == SHN_UNDEF ||			\
+			sym->st_shndx == SHN_COMMON)			\
+			*got = load_addr + sym->st_value;		\
+		else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&	\
+			*got != sym->st_value)				\
+			*got += load_addr;				\
+		else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) {	\
+			if (sym->st_other == 0)				\
+				*got += load_addr;			\
+		}							\
+		else							\
+			*got = load_addr + sym->st_value;		\
+									\
+		got++;							\
+		sym++;							\
+	}								\
+} while (0)
+
 
 /*
  * 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.
- *
- * !!!NOTE!!!
- *
- * For MIPS, we don't have any DT_JMPREL or DT_PLTRELSZ dynamic
- * entries, so this macro function is empty. The code contained
- * in elfinterp.c does the real relocation work.
+ * bootstrapping the dynamic loader.
  */
-#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)			\
+	switch(ELF32_R_TYPE((RELP)->r_info)) {				\
+	case R_MIPS_REL32:						\
+		if (symtab_index) {					\
+			if (symtab_index < mips_gotsym)			\
+				*REL += SYMBOL + LOAD;			\
+		}							\
+		else {							\
+			*REL += LOAD;					\
+		}							\
+		break;							\
+	case R_MIPS_NONE:						\
+		break;							\
+	default:							\
+		SEND_STDERR("Aiieeee!");				\
+		_dl_exit(1);						\
+	}
 
 
 /*
@@ -45,19 +91,21 @@
  * is done.  This routine has to exit the current function, then 
  * call the _dl_elf_main function.
  */
-
 #define START()   return (void) _dl_elf_main;      
 
 
-
 /* Here we define the magic numbers that this dynamic loader should accept */
-
 #define MAGIC1 EM_MIPS
 #define MAGIC2 EM_MIPS_RS3_LE
+
+
 /* Used for error messages */
 #define ELF_TARGET "MIPS"
 
+
 struct elf_resolve;
-unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt,
+	int reloc_entry);
+void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt);
 
 #define do_rem(result, n, base)  result = (n % base)

+ 4 - 3
ldso/ldso/readelflib1.c

@@ -308,7 +308,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	int flags;
 	char header[4096];
 	unsigned long dynamic_info[24];
-	int *lpnt;
+	unsigned long *lpnt;
 	unsigned long libaddr;
 	unsigned long minvma = 0xffffffff, maxvma = 0;
 
@@ -553,10 +553,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	 * resolved. 
 	 */
 
-	lpnt = (int *) dynamic_info[DT_PLTGOT];
+	lpnt = (unsigned long *) dynamic_info[DT_PLTGOT];
 
 	if (lpnt) {
-		lpnt = (int *) (dynamic_info[DT_PLTGOT] + ((int) libaddr));
+		lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT] +
+			((int) libaddr));
 		INIT_GOT(lpnt, tpnt);
 	};