Browse Source

Patch from Steven J. Hill <sjhill@realitydiluted.com>:

    I am very pleased to announce that the MIPS dynamic linker/loader
    for uClibc is now working. It works on big and little endian
    platforms.

A few minor changes were needed to avoid breaking ldd, and since this
makes some non-trivial changes, I have tested on x86, arm, and powerpc
to be sure thoese arches didn't get broken.  Excellent work Steven!
Eric Andersen 22 years ago
parent
commit
4a5a81ac16

+ 3 - 3
ldso/ldso/arm/elfinterp.c

@@ -89,7 +89,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 
 	/* Get the address of the GOT entry */
 	new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-		tpnt->symbol_scope, (unsigned long) got_addr, tpnt, 0);
+		tpnt->symbol_scope, tpnt, 0);
 	if (!new_addr) {
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 			_dl_progname, strtab + symtab[symtab_index].st_name);
@@ -221,7 +221,7 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt,
 				continue;
 
 			symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-					tpnt->symbol_scope, (unsigned long) reloc_addr, 
+					tpnt->symbol_scope,
 					(reloc_type == R_ARM_JUMP_SLOT ? tpnt : NULL), 0);
 
 			/*
@@ -350,7 +350,7 @@ int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
 
 			symbol_addr = (unsigned long) _dl_find_hash(strtab + 
 				symtab[symtab_index].st_name, xpnt->next, 
-				(unsigned long) reloc_addr, NULL, 1);
+				NULL, 1);
 			if (!symbol_addr) {
 				_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 					_dl_progname, strtab + symtab[symtab_index].st_name);

+ 0 - 2
ldso/ldso/arm/resolve.S

@@ -13,8 +13,6 @@
  * where the jump symbol is _really_ supposed to have jumped to and returns
  * that to us.  Once we have that, we overwrite tpnt with this fixed up
  * address. We then clean up after ourselves, put all the registers back how we
- * found them, then we jump to where the fixed up address, which is where the
- * jump symbol that got us here really wanted to jump to in the first place.
  * found them, then we jump to the fixed up address, which is where the jump
  * symbol that got us here really wanted to jump to in the first place.  
  *  -Erik Andersen

+ 66 - 19
ldso/ldso/dl-elf.c

@@ -108,14 +108,14 @@ int _dl_unmap_cache(void)
 /* This function's behavior must exactly match that 
  * in uClibc/ldso/util/ldd.c */
 static struct elf_resolve * 
-search_for_named_library(char *name, int secure, const char *path_list)
+search_for_named_library(char *name, int secure, const char *path_list,
+	struct dyn_elf **rpnt)
 {
 	int i, count = 1;
 	char *path, *path_n;
 	char mylibname[2050];
 	struct elf_resolve *tpnt1;
 
-
 	/* We need a writable copy of this string */
 	path = _dl_strdup(path_list);
 	if (!path) {
@@ -140,8 +140,11 @@ search_for_named_library(char *name, int secure, const char *path_list)
 		_dl_strcpy(mylibname, path_n); 
 		_dl_strcat(mylibname, "/"); 
 		_dl_strcat(mylibname, name);
-		if ((tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0)) != NULL)
-		    return tpnt1;
+		if ((tpnt1 = _dl_load_elf_shared_library(secure, rpnt,
+			mylibname, 0)) != NULL)
+		{
+			return tpnt1;
+		}
 		path_n += (_dl_strlen(path_n) + 1);
 	}
 	return NULL;
@@ -156,7 +159,7 @@ unsigned long _dl_error_number;
 unsigned long _dl_internal_error_number;
 extern char *_dl_ldsopath;
 
-struct elf_resolve *_dl_load_shared_library(int secure, 
+struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 	struct elf_resolve *tpnt, char *full_libname)
 {
 	char *pnt;
@@ -185,7 +188,7 @@ struct elf_resolve *_dl_load_shared_library(int secure,
 	   /usr/i486-sysv4/lib for /usr/lib in library names. */
 
 	if (libname != full_libname) {
-		tpnt1 = _dl_load_elf_shared_library(secure, full_libname, 0);
+		tpnt1 = _dl_load_elf_shared_library(secure, rpnt, full_libname, 0);
 		if (tpnt1)
 			return tpnt1;
 		goto goof;
@@ -204,7 +207,7 @@ struct elf_resolve *_dl_load_shared_library(int secure,
 #ifdef DL_DEBUG
 				_dl_dprintf(2, "searching RPATH: '%s'\n", pnt);
 #endif
-				if ((tpnt1 = search_for_named_library(libname, secure, pnt)) != NULL) 
+				if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) 
 				{
 				    return tpnt1;
 				}
@@ -217,7 +220,7 @@ struct elf_resolve *_dl_load_shared_library(int secure,
 #ifdef DL_DEBUG
 	    _dl_dprintf(2, "searching _dl_library_path: '%s'\n", _dl_library_path);
 #endif
-	    if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path)) != NULL) 
+	    if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL) 
 	    {
 		return tpnt1;
 	    }
@@ -240,7 +243,7 @@ struct elf_resolve *_dl_load_shared_library(int secure,
 				 libent[i].flags == LIB_ELF_LIBC5) &&
 				_dl_strcmp(libname, strs + libent[i].sooffset) == 0 &&
 				(tpnt1 = _dl_load_elf_shared_library(secure, 
-				     strs + libent[i].liboffset, 0)))
+				     rpnt, strs + libent[i].liboffset, 0)))
 				return tpnt1;
 		}
 	}
@@ -251,7 +254,7 @@ struct elf_resolve *_dl_load_shared_library(int secure,
 #ifdef DL_DEBUG
 	_dl_dprintf(2, "searching in ldso dir: %s\n", _dl_ldsopath);
 #endif
-	if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath)) != NULL) 
+	if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt)) != NULL) 
 	{
 	    return tpnt1;
 	}
@@ -268,7 +271,7 @@ struct elf_resolve *_dl_load_shared_library(int secure,
 			UCLIBC_DEVEL_PREFIX "/lib:"
 			UCLIBC_BUILD_DIR "/lib:"
 			"/usr/lib:"
-			"/lib")
+			"/lib", rpnt)
 		    ) != NULL) 
 	{
 	    return tpnt1;
@@ -286,16 +289,15 @@ goof:
 	return NULL;
 }
 
+
 /*
  * Read one ELF library into memory, mmap it into the correct locations and
  * add the symbol info to the symbol chain.  Perform any relocations that
  * are required.
  */
 
-//extern _elf_rtbndr(void);
-
-struct elf_resolve *_dl_load_elf_shared_library(int secure, 
-	char *libname, int flag)
+struct elf_resolve *_dl_load_elf_shared_library(int secure,
+	struct dyn_elf **rpnt, char *libname, int flag)
 {
 	elfhdr *epnt;
 	unsigned long dynamic_addr = 0;
@@ -311,14 +313,27 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	unsigned long *lpnt;
 	unsigned long libaddr;
 	unsigned long minvma = 0xffffffff, maxvma = 0;
-
 	int i;
 	int infile;
+#if defined(__mips__)
+	unsigned long mips_gotsym = 0;
+	unsigned long mips_local_gotno = 0;
+	unsigned long mips_symtabno = 0;
+#endif
 
 	/* If this file is already loaded, skip this step */
 	tpnt = _dl_check_hashed_files(libname);
-	if (tpnt)
+	if (tpnt) {
+		(*rpnt)->next = (struct dyn_elf *)
+			_dl_malloc(sizeof(struct dyn_elf));
+		_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+		*rpnt = (*rpnt)->next;
+		tpnt->usage_count++;
+		tpnt->symbol_scope = _dl_symbol_tables;
+		tpnt->libtype = elf_lib;
+		(*rpnt)->dyn = tpnt;
 		return tpnt;
+	}
 
 	/* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD),
 	   we don't load the library if it isn't setuid. */
@@ -514,7 +529,22 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 
 	dynamic_size = dynamic_size / sizeof(Elf32_Dyn);
 	_dl_memset(dynamic_info, 0, sizeof(dynamic_info));
+#if defined(__mips__)
+	/*
+	 * The program header file size for the dynamic section is
+	 * calculated differently for MIPS. We look for a null tag
+	 * value instead.
+	 */
+	while(dpnt->d_tag) {
+		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;
+#else
 	for (i = 0; i < dynamic_size; i++) {
+#endif
 		if (dpnt->d_tag > DT_JMPREL) {
 			dpnt++;
 			continue;
@@ -526,8 +556,8 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	};
 
 	/* If the TEXTREL is set, this means that we need to make the pages
-	   writable before we perform relocations.  Do this now. They get set back
-	   again later. */
+	   writable before we perform relocations.  Do this now. They get set
+	   back again later. */
 
 	if (dynamic_info[DT_TEXTREL]) {
 		ppnt = (elf_phdr *) & header[epnt->e_phoff];
@@ -547,6 +577,18 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	tpnt->ppnt = (elf_phdr *) (tpnt->loadaddr + epnt->e_phoff);
 	tpnt->n_phent = epnt->e_phnum;
 
+	/*
+	 * Add this object into the symbol chain
+	 */
+	(*rpnt)->next = (struct dyn_elf *)
+		_dl_malloc(sizeof(struct dyn_elf));
+	_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+	*rpnt = (*rpnt)->next;
+	tpnt->usage_count++;
+	tpnt->symbol_scope = _dl_symbol_tables;
+	tpnt->libtype = elf_lib;
+	(*rpnt)->dyn = tpnt;
+
 	/*
 	 * OK, the next thing we need to do is to insert the dynamic linker into
 	 * the proper entry in the GOT so that the PLT symbols can be properly
@@ -558,6 +600,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	if (lpnt) {
 		lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT] +
 			((int) libaddr));
+#if defined(__mips__)
+		tpnt->mips_gotsym = mips_gotsym;
+		tpnt->mips_local_gotno = mips_local_gotno;
+		tpnt->mips_symtabno = mips_symtabno;
+#endif
 		INIT_GOT(lpnt, tpnt);
 	};
 

+ 1 - 1
ldso/ldso/dl-hash.c

@@ -135,7 +135,7 @@ struct elf_resolve *_dl_add_elf_hash_table(char *libname,
  */
 
 char *_dl_find_hash(char *name, struct dyn_elf *rpnt1, 
-	unsigned long instr_addr, struct elf_resolve *f_tpnt, int copyrel)
+	struct elf_resolve *f_tpnt, int copyrel)
 {
 	struct elf_resolve *tpnt;
 	int si;

+ 1 - 1
ldso/ldso/hash.c

@@ -135,7 +135,7 @@ struct elf_resolve *_dl_add_elf_hash_table(char *libname,
  */
 
 char *_dl_find_hash(char *name, struct dyn_elf *rpnt1, 
-	unsigned long instr_addr, struct elf_resolve *f_tpnt, int copyrel)
+	struct elf_resolve *f_tpnt, int copyrel)
 {
 	struct elf_resolve *tpnt;
 	int si;

+ 3 - 3
ldso/ldso/i386/elfinterp.c

@@ -81,7 +81,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 
 	/* Get the address of the GOT entry */
 	new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-		tpnt->symbol_scope, (unsigned long) got_addr, tpnt, 0);
+		tpnt->symbol_scope, tpnt, 0);
 	if (!new_addr) {
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 			_dl_progname, strtab + symtab[symtab_index].st_name);
@@ -188,7 +188,7 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt,
 				continue;
 
 			symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-					tpnt->symbol_scope, (unsigned long) reloc_addr, 
+					tpnt->symbol_scope,
 					(reloc_type == R_386_JMP_SLOT ? tpnt : NULL), 0);
 
 			/*
@@ -294,7 +294,7 @@ int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
 
 			symbol_addr = (unsigned long) _dl_find_hash(strtab + 
 				symtab[symtab_index].st_name, xpnt->next, 
-				(unsigned long) reloc_addr, NULL, 1);
+				NULL, 1);
 			if (!symbol_addr) {
 				_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 					_dl_progname, strtab + symtab[symtab_index].st_name);

+ 8 - 2
ldso/ldso/ld_hash.h

@@ -71,6 +71,13 @@ struct elf_resolve{
   unsigned long n_phent;
   Elf32_Phdr * ppnt;
 
+#if defined(__mips__)
+  /* Needed for MIPS relocation */
+  unsigned long mips_gotsym;
+  unsigned long mips_local_gotno;
+  unsigned long mips_symtabno;
+#endif
+
 #ifdef __powerpc__
   /* this is used to store the address of relocation data words, so
    * we don't have to calculate it every time, which requires a divide */
@@ -107,8 +114,7 @@ extern struct elf_resolve * _dl_add_elf_hash_table(char * libname,
 	char * loadaddr, unsigned long * dynamic_info, 
 	unsigned long dynamic_addr, unsigned long dynamic_size);
 extern char * _dl_find_hash(char * name, struct dyn_elf * rpnt1, 
-	unsigned long instr_addr, struct elf_resolve * f_tpnt, 
-	int copyrel);
+	struct elf_resolve * f_tpnt, int copyrel);
 extern int _dl_linux_dynamic_link(void);
 
 extern char * _dl_library_path;

+ 49 - 53
ldso/ldso/ldso.c

@@ -211,11 +211,6 @@ DL_BOOT(unsigned long args)
 	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
@@ -381,11 +376,11 @@ DL_BOOT(unsigned long args)
 		}
 #if defined(__mips__)
 		if (dpnt->d_tag == DT_MIPS_GOTSYM)
-			mips_gotsym = (unsigned long) dpnt->d_un.d_val;
+			tpnt->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;
+			tpnt->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;
+			tpnt->mips_symtabno = (unsigned long) dpnt->d_un.d_val;
 #endif
 		dpnt++;
 	}
@@ -399,6 +394,17 @@ DL_BOOT(unsigned long args)
 			if (ppnt->p_type == PT_DYNAMIC) {
 				dpnt = (Elf32_Dyn *) ppnt->p_vaddr;
 				while (dpnt->d_tag) {
+#if defined(__mips__)
+					if (dpnt->d_tag == DT_MIPS_GOTSYM)
+						app_tpnt->mips_gotsym =
+							(unsigned long) dpnt->d_un.d_val;
+					if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
+						app_tpnt->mips_local_gotno =
+							(unsigned long) dpnt->d_un.d_val;
+					if (dpnt->d_tag == DT_MIPS_SYMTABNO)
+						app_tpnt->mips_symtabno =
+							(unsigned long) dpnt->d_un.d_val;
+#endif
 					if (dpnt->d_tag > DT_JMPREL) {
 						dpnt++;
 						continue;
@@ -524,7 +530,6 @@ 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
@@ -580,7 +585,6 @@ DL_BOOT(unsigned long args)
 
 
 
-
 	/* OK we are done here.  Turn out the lights, and lock up. */
 	_dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_fcn;
 
@@ -608,6 +612,11 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 	struct elf_resolve *tpnt1;
 	unsigned long brk_addr, *lpnt;
 	int (*_dl_atexit) (void *);
+#ifdef __mips__
+	unsigned long mips_gotsym = 0;
+	unsigned long mips_local_gotno = 0;
+	unsigned long mips_symtabno = 0;
+#endif
 
 
 	/* Now we have done the mandatory linking of some things.  We are now
@@ -615,6 +624,13 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 	   fixed up by now.  Still no function calls outside of this library ,
 	   since the dynamic resolver is not yet ready. */
 	lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT] + load_addr);
+
+	tpnt->chains = hash_addr;
+	tpnt->next = 0;
+	tpnt->libname = 0;
+	tpnt->libtype = program_interpreter;
+	tpnt->loadaddr = (char *) load_addr;
+
 	INIT_GOT(lpnt, tpnt);
 #ifdef DL_DEBUG
 	_dl_dprintf(2, "GOT found at %x\n", tpnt);
@@ -622,10 +638,6 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 	/* OK, this was a big step, now we need to scan all of the user images
 	   and load them properly. */
 
-	tpnt->next = 0;
-	tpnt->libname = 0;
-	tpnt->libtype = program_interpreter;
-
 	{
 		elfhdr *epnt;
 		elf_phdr *ppnt;
@@ -642,9 +654,6 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 		}
 	}
 
-	tpnt->chains = hash_addr;
-	tpnt->loadaddr = (char *) load_addr;
-
 	brk_addr = 0;
 	rpnt = NULL;
 
@@ -665,11 +674,21 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 				continue;
 #endif
 			/* OK, we have what we need - slip this one into the list. */
+#ifdef __mips__
+			mips_gotsym = app_tpnt->mips_gotsym;
+			mips_local_gotno = app_tpnt->mips_local_gotno;
+			mips_symtabno = app_tpnt->mips_symtabno;
+#endif
 			app_tpnt = _dl_add_elf_hash_table("", 0, 
 					app_tpnt->dynamic_info, ppnt->p_vaddr, ppnt->p_filesz);
 			_dl_loaded_modules->libtype = elf_executable;
 			_dl_loaded_modules->ppnt = (elf_phdr *) auxvt[AT_PHDR].a_un.a_ptr;
 			_dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val;
+#ifdef __mips__
+			_dl_loaded_modules->mips_gotsym = mips_gotsym; 
+			_dl_loaded_modules->mips_local_gotno = mips_local_gotno;
+			_dl_loaded_modules->mips_symtabno = mips_symtabno;
+#endif
 			_dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
 			_dl_memset(rpnt, 0, sizeof(*rpnt));
 			rpnt->dyn = _dl_loaded_modules;
@@ -774,7 +793,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 			*str2 = '\0';
 			if (!_dl_secure || _dl_strchr(str, '/') == NULL) 
 			{
-				tpnt1 = _dl_load_shared_library(_dl_secure, NULL, str);
+				tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str);
 				if (!tpnt1) {
 #ifdef DL_TRACE
 					if (_dl_trace_loaded_objects)
@@ -793,7 +812,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 #endif
 #ifdef DL_TRACE
 					if (_dl_trace_loaded_objects
-							&& !tpnt1->usage_count) {
+							&& tpnt1->usage_count==1) {
 						/* this is a real hack to make ldd not print 
 						 * the library itself when run on a library. */
 						if (_dl_strcmp(_dl_progname, str) != 0)
@@ -801,14 +820,6 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 									(unsigned) tpnt1->loadaddr);
 					}
 #endif
-					rpnt->next = (struct dyn_elf *)
-						_dl_malloc(sizeof(struct dyn_elf));
-					_dl_memset(rpnt->next, 0, sizeof(*(rpnt->next)));
-					rpnt = rpnt->next;
-					tpnt1->usage_count++;
-					tpnt1->symbol_scope = _dl_symbol_tables;
-					tpnt1->libtype = elf_lib;
-					rpnt->dyn = tpnt1;
 				}
 			}
 			*str2 = c;
@@ -861,7 +872,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 						c = *cp;
 						*cp = '\0';
 
-						tpnt1 = _dl_load_shared_library(0, NULL, cp2);
+						tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2);
 						if (!tpnt1) {
 #ifdef DL_TRACE
 							if (_dl_trace_loaded_objects)
@@ -880,20 +891,11 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 #endif
 #ifdef DL_TRACE
 							if (_dl_trace_loaded_objects
-									&& !tpnt1->usage_count) {
+									&& tpnt1->usage_count==1) {
 								_dl_dprintf(1, "\t%s => %s (0x%x)\n", cp2, 
 										tpnt1->libname, (unsigned) tpnt1->loadaddr);
 							}
 #endif
-							rpnt->next = (struct dyn_elf *)
-								_dl_malloc(sizeof(struct dyn_elf));
-							_dl_memset(rpnt->next, 0, 
-									sizeof(*(rpnt->next)));
-							rpnt = rpnt->next;
-							tpnt1->usage_count++;
-							tpnt1->symbol_scope = _dl_symbol_tables;
-							tpnt1->libtype = elf_lib;
-							rpnt->dyn = tpnt1;
 						}
 
 						/* find start of next library */
@@ -924,7 +926,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 					struct elf_resolve *ttmp;
 
 #ifdef DL_TRACE
-					if (_dl_trace_loaded_objects && !tpnt->usage_count) {
+					if (_dl_trace_loaded_objects && tpnt->usage_count==1) {
 						_dl_dprintf(1, "\t%s => %s (0x%x)\n", 
 								lpntstr, tpnt->libname, (unsigned) tpnt->loadaddr);
 					}
@@ -945,7 +947,8 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 					tpnt = NULL;
 					continue;
 				}
-				if (!(tpnt1 = _dl_load_shared_library(0, tcurr, lpntstr))) {
+				if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr)))
+				{
 #ifdef DL_TRACE
 					if (_dl_trace_loaded_objects)
 						_dl_dprintf(1, "\t%s => not found\n", lpntstr);
@@ -962,18 +965,10 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 					_dl_dprintf(2, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
 #endif
 #ifdef DL_TRACE
-					if (_dl_trace_loaded_objects && !tpnt1->usage_count)
+					if (_dl_trace_loaded_objects && tpnt1->usage_count==1)
 						_dl_dprintf(1, "\t%s => %s (0x%x)\n", lpntstr, tpnt1->libname, 
 								(unsigned) tpnt1->loadaddr);
 #endif
-					rpnt->next = (struct dyn_elf *)
-						_dl_malloc(sizeof(struct dyn_elf));
-					_dl_memset(rpnt->next, 0, sizeof(*(rpnt->next)));
-					rpnt = rpnt->next;
-					tpnt1->usage_count++;
-					tpnt1->symbol_scope = _dl_symbol_tables;
-					tpnt1->libtype = elf_lib;
-					rpnt->dyn = tpnt1;
 				}
 			}
 		}
@@ -1069,12 +1064,12 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 
 
 	_dl_brkp =
-		(unsigned long *) _dl_find_hash("___brk_addr", NULL, 1, NULL, 0);
+		(unsigned long *) _dl_find_hash("___brk_addr", NULL, NULL, 0);
 	if (_dl_brkp) {
 		*_dl_brkp = brk_addr;
 	}
 	_dl_envp =
-		(unsigned long *) _dl_find_hash("__environ", NULL, 1, NULL, 0);
+		(unsigned long *) _dl_find_hash("__environ", NULL, NULL, 0);
 
 	if (_dl_envp) {
 		*_dl_envp = (unsigned long) envp;
@@ -1098,7 +1093,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 
 	}
 #endif
-	_dl_atexit = (int (*)(void *)) _dl_find_hash("atexit", NULL, 1, NULL, 0);
+	_dl_atexit = (int (*)(void *)) _dl_find_hash("atexit", NULL, NULL, 0);
 
 	/*
 	 * OK, fix one more thing - set up the debug_addr structure to point
@@ -1209,8 +1204,9 @@ void *_dl_malloc(int size)
 	void *retval;
 
 #if 0
-//#ifdef DL_DEBUG
+#ifdef DL_DEBUG
 	_dl_dprintf(2, "malloc: request for %d bytes\n", size);
+#endif
 #endif
 
 	if (_dl_malloc_function)

+ 8 - 8
ldso/ldso/linuxelf.h

@@ -16,16 +16,16 @@ extern void * _dl_malloc(int size);
 extern int _dl_map_cache(void);
 extern int _dl_unmap_cache(void);
 int _dl_copy_fixups(struct dyn_elf * tpnt);
-extern int _dl_parse_relocation_information(struct elf_resolve * tpnt, unsigned long rel_addr,
-       unsigned long rel_size, int type);
-extern void _dl_parse_lazy_relocation_information(struct elf_resolve * tpnt, unsigned long rel_addr,
-       unsigned long rel_size, int type);
+extern int _dl_parse_copy_information(struct dyn_elf *rpnt,
+	unsigned long rel_addr, unsigned long rel_size, int type);
+extern void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
+	unsigned long rel_addr, unsigned long rel_size, int type);
+extern int _dl_parse_relocation_information(struct elf_resolve *tpnt,
+	unsigned long rel_addr, unsigned long rel_size, int type);
 extern struct elf_resolve * _dl_load_shared_library(int secure, 
-				struct elf_resolve *, char * libname);
+	struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname);
 extern struct elf_resolve * _dl_load_elf_shared_library(int secure, 
-				char * libname, int flag);
-extern int _dl_parse_copy_information(struct dyn_elf * rpnt, unsigned long rel_addr,
-       unsigned long rel_size, int type);
+	struct dyn_elf **rpnt, char *libname, int flag);
 extern int _dl_linux_resolve(void);
 #define ELF_CLASS   ELFCLASS32
 

+ 3 - 3
ldso/ldso/m68k/elfinterp.c

@@ -90,7 +90,7 @@ unsigned int _dl_linux_resolver (int dummy1, int dummy2,
 
   /* Get the address of the GOT entry.  */
   new_addr = _dl_find_hash (strtab + symtab[symtab_index].st_name,
-			    tpnt->symbol_scope, (int) got_addr, tpnt, 0);
+			    tpnt->symbol_scope, tpnt, 0);
   if (!new_addr)
     {
       _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
@@ -201,7 +201,7 @@ _dl_parse_relocation_information (struct elf_resolve *tpnt,
 	{
 	  symbol_addr = (unsigned int)
 	    _dl_find_hash (strtab + symtab[symtab_index].st_name,
-			   tpnt->symbol_scope, (int) reloc_addr,
+			   tpnt->symbol_scope,
 			   reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, 0);
 
 	  /* We want to allow undefined references to weak symbols -
@@ -327,7 +327,7 @@ _dl_parse_copy_information (struct dyn_elf *xpnt, unsigned long rel_addr,
 	{
 	  symbol_addr = (unsigned int)
 	    _dl_find_hash (strtab + symtab[symtab_index].st_name,
-			   xpnt->next, (int) reloc_addr, NULL, 1);
+			   xpnt->next, NULL, 1);
 	  if (!symbol_addr)
 	    {
 	      _dl_dprintf (2, "%s: can't resolve symbol '%s'\n",

+ 21 - 14
ldso/ldso/mips/README

@@ -1,28 +1,29 @@
 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.
+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'.
+The code 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'.
+Contains the runtime resolver code taken from the function
+'__dl_runtime_resolve' in 'sysdeps/mips/dl-machine.h'. Also
+contains the function to perform relocations for objects
+other than the linker itself. The code was taken from the
+function 'elf_machine_rel' in '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'.
+Contains all the macro functions for the system calls as well
+as the list of system calls supported. The functions were taken
+from the Linux kernel source 2.4.17 and can be found in the
+file 'include/asm-mips/unistd.h'.
 
 ld_sysdep.h
 -----------
@@ -31,13 +32,19 @@ 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
+file 'sysdeps/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'.
+'elf_machine_rel' in the file 'sysdeps/mips/dl-machine.h'. The
+final macro function is '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 'sysdeps/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'.
+'_dl_runtime_resolve' in the file 'sysdeps/mips/dl-machine.h'.
+The code looks a bit different since we only need to pass the
+symbol index and the old GP register.

+ 9 - 3
ldso/ldso/mips/boot1_arch.h

@@ -1,7 +1,6 @@
 /* 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.  See arm/boot1_arch.h for an example of what
- * can be done.
+ * needed for this architecture.
  */
 
 asm("
@@ -13,7 +12,6 @@ _dl_boot:
 	nop
 0:	.cpload $31
 	.set reorder
-	# Store offset of DYNAMIC section in first entry of GOT
 	la $4, _DYNAMIC
 	sw $4, -0x7ff0($28)
 	move $4, $29
@@ -23,6 +21,14 @@ coff:	subu $8, $31, $8
 	la $25, _dl_boot2
 	addu $25, $8
 	jalr $25
+	lw $4, 0($29)
+	la $5, 4($29)
+	sll $6, $4, 2
+	addu $6, $6, $5
+	addu $6, $6, 4
+	la $7, _dl_elf_main
+	lw $25, 0($7)
+	jr $25
 ");
 
 #define _dl_boot _dl_boot2

+ 9 - 3
ldso/ldso/mips/dl-startup.h

@@ -1,7 +1,6 @@
 /* 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.  See arm/boot1_arch.h for an example of what
- * can be done.
+ * needed for this architecture.
  */
 
 asm("
@@ -13,7 +12,6 @@ _dl_boot:
 	nop
 0:	.cpload $31
 	.set reorder
-	# Store offset of DYNAMIC section in first entry of GOT
 	la $4, _DYNAMIC
 	sw $4, -0x7ff0($28)
 	move $4, $29
@@ -23,6 +21,14 @@ coff:	subu $8, $31, $8
 	la $25, _dl_boot2
 	addu $25, $8
 	jalr $25
+	lw $4, 0($29)
+	la $5, 4($29)
+	sll $6, $4, 2
+	addu $6, $6, $5
+	addu $6, $6, 4
+	la $7, _dl_elf_main
+	lw $25, 0($7)
+	jr $25
 ");
 
 #define _dl_boot _dl_boot2

+ 117 - 58
ldso/ldso/mips/dl-sysdep.h

@@ -1,5 +1,7 @@
+/* vi: set sw=4 ts=4: */
+
 /*
- * Various assmbly language/system dependent  hacks that are required
+ * Various assmbly language/system dependent hacks that are required
  * so that we can minimize the amount of platform specific code.
  */
 
@@ -20,46 +22,102 @@
 /*
  * Initialization sequence for the application GOT.
  */
-#define INIT_GOT(GOT_BASE,MODULE)	_dl_init_got(GOT_BASE,MODULE)
+#define INIT_GOT(GOT_BASE,MODULE)										\
+do {																	\
+	Elf32_Sym *sym;														\
+	char *strtab;														\
+	unsigned long i;													\
+																		\
+	/* Check if this is the dynamic linker itself */					\
+	if (MODULE->libtype == program_interpreter)							\
+		continue;														\
+																		\
+	/* Fill in first two GOT entries according to the ABI */			\
+	GOT_BASE[0] = (unsigned long) _dl_linux_resolve;					\
+	GOT_BASE[1] = (unsigned long) MODULE;								\
+																		\
+	/* Add load address displacement to all local GOT entries */		\
+	i = 2;																\
+	while (i < MODULE->mips_local_gotno)								\
+		GOT_BASE[i++] += (unsigned long) MODULE->loadaddr;				\
+																		\
+	/* Handle global GOT entries */										\
+	GOT_BASE += MODULE->mips_local_gotno;								\
+	sym = (Elf32_Sym *) (MODULE->dynamic_info[DT_SYMTAB] +				\
+		(unsigned long) MODULE->loadaddr) + MODULE->mips_gotsym;		\
+	strtab = (char *) (MODULE->dynamic_info[DT_STRTAB] +				\
+		(unsigned long) MODULE->loadaddr);								\
+	i = MODULE->mips_symtabno - MODULE->mips_gotsym;					\
+	while (i--) {														\
+		if (sym->st_shndx == SHN_UNDEF) {								\
+			if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&				\
+				sym->st_value)											\
+				*GOT_BASE = sym->st_value +								\
+					(unsigned long) MODULE->loadaddr;					\
+			else {														\
+				*GOT_BASE = (unsigned long) _dl_find_hash(strtab +		\
+					sym->st_name, MODULE->symbol_scope, NULL, 0);		\
+			}															\
+		}																\
+		else if (sym->st_shndx == SHN_COMMON) {							\
+			*GOT_BASE = (unsigned long) _dl_find_hash(strtab +			\
+				sym->st_name, MODULE->symbol_scope, NULL, 0);			\
+		}																\
+		else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&				\
+			*GOT_BASE != sym->st_value)									\
+			*GOT_BASE += (unsigned long) MODULE->loadaddr;				\
+		else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) {			\
+			if (sym->st_other == 0)										\
+				*GOT_BASE += (unsigned long) MODULE->loadaddr;			\
+		}																\
+		else {															\
+			*GOT_BASE = (unsigned long) _dl_find_hash(strtab +			\
+				sym->st_name, MODULE->symbol_scope, NULL, 0);			\
+		}																\
+																		\
+		++GOT_BASE;														\
+		++sym;															\
+	}																	\
+} while (0)
 
 
 /*
- * Here is a macro to perform the GOT relocation.  This is only
+ * 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++;							\
-	}								\
+#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 < tpnt->mips_local_gotno)									\
+		got[i++] += load_addr;											\
+																		\
+	/* Handle global GOT entries */										\
+	got += tpnt->mips_local_gotno;										\
+	sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] +				\
+		 load_addr) + tpnt->mips_gotsym;								\
+	i = tpnt->mips_symtabno - tpnt->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)
 
 
@@ -67,31 +125,33 @@ do {									\
  * Here is a macro to perform a relocation.  This is only used when
  * bootstrapping the dynamic loader.
  */
-#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);						\
+#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 < tpnt->mips_gotsym)						\
+				*REL += SYMBOL;											\
+		}																\
+		else {															\
+			*REL += LOAD;												\
+		}																\
+		break;															\
+	case R_MIPS_NONE:													\
+		break;															\
+	default:															\
+		SEND_STDERR("Aiieeee!");										\
+		_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.
+ * call the _dl_elf_main function. For MIPS, we do it in assembly
+ * because the stack doesn't get properly restored otherwise. Got look
+ * at boot1_arch.h
  */
-#define START()   return (void) _dl_elf_main;      
+#define START()
 
 
 /* Here we define the magic numbers that this dynamic loader should accept */
@@ -103,9 +163,8 @@ do {									\
 #define ELF_TARGET "MIPS"
 
 
-struct elf_resolve;
-extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt,
-	int reloc_entry);
-void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt);
+unsigned long _dl_linux_resolver(unsigned long sym_index,
+	unsigned long old_gpreg);
+
 
 #define do_rem(result, n, base)  result = (n % base)

+ 100 - 5
ldso/ldso/mips/elfinterp.c

@@ -1,6 +1,7 @@
+/* vi: set sw=4 ts=4: */
+
 /* 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
@@ -32,18 +33,112 @@
 
 extern int _dl_linux_resolve(void);
 
-void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt)
+#define OFFSET_GP_GOT 0x7ff0
+
+unsigned long _dl_linux_resolver(unsigned long sym_index,
+	unsigned long old_gpreg)
 {
+	unsigned long *got = (unsigned long *) (old_gpreg - OFFSET_GP_GOT);
+	struct elf_resolve *tpnt = (struct elf_resolve *) got[1];
+	Elf32_Sym *sym;
+	char *strtab;
+	unsigned long local_gotno;
+	unsigned long gotsym;
+	unsigned long value;
+
+	gotsym = tpnt->mips_gotsym;
+	local_gotno = tpnt->mips_local_gotno;
+
+	sym = ((Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr)) +
+		sym_index;
+
+	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+
+	value = (unsigned long) _dl_find_hash(strtab + sym->st_name,
+		 tpnt->symbol_scope, tpnt, 1);
+
+	*(got + local_gotno + sym_index - gotsym) = value;
+
+#ifdef DL_DEBUG
+	_dl_dprintf(2, "---RESOLVER---\n");
+	_dl_dprintf(2, "SYMTAB INDEX: %i\n", sym_index);
+	_dl_dprintf(2, "      GOTSYM: %i\n", gotsym);
+	_dl_dprintf(2, " LOCAL GOTNO: %i\n", local_gotno);
+	_dl_dprintf(2, "       VALUE: %x\n", value);
+	_dl_dprintf(2, "      SYMBOL: %s\n\n", strtab + sym->st_name);
+#endif
+
+	return value;
+}
+
+void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
+	unsigned long rel_addr, unsigned long rel_size, int type)
+{
+	/* Nothing to do */
 	return;
 }
 
-unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
+	unsigned long rel_size, int type)
 {
+	/* Nothing to do */
 	return 0;
 }
-
+        
 int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
 	unsigned long rel_addr, unsigned long rel_size, int type)
 {
-	return 1;
+	Elf32_Sym *symtab;
+	Elf32_Rel *rpnt;
+	char *strtab;
+	unsigned long *got;
+	unsigned long *reloc_addr;
+	unsigned long symbol_addr;
+	int i, reloc_type, symtab_index;
+
+	/* Now parse the relocation information */
+	rel_size = rel_size / sizeof(Elf32_Rel);
+	rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
+
+	symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
+	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+	got = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
+
+	for (i = 0; i < rel_size; i++, rpnt++) {
+		reloc_addr = (unsigned long *) (tpnt->loadaddr +
+			(unsigned long) rpnt->r_offset);
+		reloc_type = ELF32_R_TYPE(rpnt->r_info);
+		symtab_index = ELF32_R_SYM(rpnt->r_info);
+		symbol_addr = 0;
+
+		if (!symtab_index && tpnt->libtype == program_interpreter)
+			continue;
+
+		switch (reloc_type) {
+		case R_MIPS_REL32:
+			if (symtab_index) {
+				if (symtab_index < tpnt->mips_gotsym)
+					*reloc_addr +=
+						symtab[symtab_index].st_value +
+						(unsigned long) tpnt->loadaddr;
+				else {
+					*reloc_addr += got[symtab_index + tpnt->mips_local_gotno -
+						tpnt->mips_gotsym];
+				}
+			}
+			else {
+				*reloc_addr += (unsigned long) tpnt->loadaddr;
+			}
+			break;
+		case R_MIPS_NONE:
+			break;
+		default:
+			_dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
+			if (symtab_index)
+				_dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
+			_dl_exit(1);
+		};
+
+	};
+	return 0;
 }

+ 117 - 58
ldso/ldso/mips/ld_sysdep.h

@@ -1,5 +1,7 @@
+/* vi: set sw=4 ts=4: */
+
 /*
- * Various assmbly language/system dependent  hacks that are required
+ * Various assmbly language/system dependent hacks that are required
  * so that we can minimize the amount of platform specific code.
  */
 
@@ -20,46 +22,102 @@
 /*
  * Initialization sequence for the application GOT.
  */
-#define INIT_GOT(GOT_BASE,MODULE)	_dl_init_got(GOT_BASE,MODULE)
+#define INIT_GOT(GOT_BASE,MODULE)										\
+do {																	\
+	Elf32_Sym *sym;														\
+	char *strtab;														\
+	unsigned long i;													\
+																		\
+	/* Check if this is the dynamic linker itself */					\
+	if (MODULE->libtype == program_interpreter)							\
+		continue;														\
+																		\
+	/* Fill in first two GOT entries according to the ABI */			\
+	GOT_BASE[0] = (unsigned long) _dl_linux_resolve;					\
+	GOT_BASE[1] = (unsigned long) MODULE;								\
+																		\
+	/* Add load address displacement to all local GOT entries */		\
+	i = 2;																\
+	while (i < MODULE->mips_local_gotno)								\
+		GOT_BASE[i++] += (unsigned long) MODULE->loadaddr;				\
+																		\
+	/* Handle global GOT entries */										\
+	GOT_BASE += MODULE->mips_local_gotno;								\
+	sym = (Elf32_Sym *) (MODULE->dynamic_info[DT_SYMTAB] +				\
+		(unsigned long) MODULE->loadaddr) + MODULE->mips_gotsym;		\
+	strtab = (char *) (MODULE->dynamic_info[DT_STRTAB] +				\
+		(unsigned long) MODULE->loadaddr);								\
+	i = MODULE->mips_symtabno - MODULE->mips_gotsym;					\
+	while (i--) {														\
+		if (sym->st_shndx == SHN_UNDEF) {								\
+			if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&				\
+				sym->st_value)											\
+				*GOT_BASE = sym->st_value +								\
+					(unsigned long) MODULE->loadaddr;					\
+			else {														\
+				*GOT_BASE = (unsigned long) _dl_find_hash(strtab +		\
+					sym->st_name, MODULE->symbol_scope, NULL, 0);		\
+			}															\
+		}																\
+		else if (sym->st_shndx == SHN_COMMON) {							\
+			*GOT_BASE = (unsigned long) _dl_find_hash(strtab +			\
+				sym->st_name, MODULE->symbol_scope, NULL, 0);			\
+		}																\
+		else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&				\
+			*GOT_BASE != sym->st_value)									\
+			*GOT_BASE += (unsigned long) MODULE->loadaddr;				\
+		else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) {			\
+			if (sym->st_other == 0)										\
+				*GOT_BASE += (unsigned long) MODULE->loadaddr;			\
+		}																\
+		else {															\
+			*GOT_BASE = (unsigned long) _dl_find_hash(strtab +			\
+				sym->st_name, MODULE->symbol_scope, NULL, 0);			\
+		}																\
+																		\
+		++GOT_BASE;														\
+		++sym;															\
+	}																	\
+} while (0)
 
 
 /*
- * Here is a macro to perform the GOT relocation.  This is only
+ * 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++;							\
-	}								\
+#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 < tpnt->mips_local_gotno)									\
+		got[i++] += load_addr;											\
+																		\
+	/* Handle global GOT entries */										\
+	got += tpnt->mips_local_gotno;										\
+	sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] +				\
+		 load_addr) + tpnt->mips_gotsym;								\
+	i = tpnt->mips_symtabno - tpnt->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)
 
 
@@ -67,31 +125,33 @@ do {									\
  * Here is a macro to perform a relocation.  This is only used when
  * bootstrapping the dynamic loader.
  */
-#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);						\
+#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 < tpnt->mips_gotsym)						\
+				*REL += SYMBOL;											\
+		}																\
+		else {															\
+			*REL += LOAD;												\
+		}																\
+		break;															\
+	case R_MIPS_NONE:													\
+		break;															\
+	default:															\
+		SEND_STDERR("Aiieeee!");										\
+		_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.
+ * call the _dl_elf_main function. For MIPS, we do it in assembly
+ * because the stack doesn't get properly restored otherwise. Got look
+ * at boot1_arch.h
  */
-#define START()   return (void) _dl_elf_main;      
+#define START()
 
 
 /* Here we define the magic numbers that this dynamic loader should accept */
@@ -103,9 +163,8 @@ do {									\
 #define ELF_TARGET "MIPS"
 
 
-struct elf_resolve;
-extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt,
-	int reloc_entry);
-void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt);
+unsigned long _dl_linux_resolver(unsigned long sym_index,
+	unsigned long old_gpreg);
+
 
 #define do_rem(result, n, base)  result = (n % base)

+ 8 - 15
ldso/ldso/mips/resolve.S

@@ -1,4 +1,4 @@
-/*
+	/*
  * Linux dynamic resolving code for MIPS. Fixes up the GOT entry as
  * indicated in register t8 and jumps to the resolved address. Shamelessly
  * ripped from 'sysdeps/mips/dl-machine.h' in glibc-2.2.5.
@@ -23,26 +23,19 @@ _dl_linux_resolve:
 	addu	$25, 8		# t9 ($25) now points at .cpload instruction
 	.cpload	$25		# Compute GP
 	.set reorder
-	move	$2, $31		# Save slot call pc
-	subu	$29, 40		# Save arguments and sp value in stack
-	.cprestore 32
-	sw	$15, 36($29)
+	subu	$29, 32
+	.cprestore 28
 	sw	$4, 16($29)
 	sw	$5, 20($29)
-	sw	$6, 24($29)
-	sw	$7, 28($29)
+	sw	$15, 24($29)
 	move	$4, $24
-	move	$5, $15
-	move	$6, $3
-	move	$7, $2
+	move	$5, $3
 	jal     _dl_linux_resolver
-	lw	$31, 36($29)
+	lw	$31, 24($29)
 	lw	$4, 16($29)
 	lw	$5, 20($29)
-	lw	$6, 24($29)
-	lw	$7, 28($29)
-	addu	$29, 40
+	addu	$29, 32
 	move	$25, $2
-        jr	$25
+	jr	$25
 .size _dl_linux_resolve,.-_dl_linux_resolve
 .end _dl_linux_resolve

+ 3 - 3
ldso/ldso/powerpc/elfinterp.c

@@ -161,7 +161,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 	/* Get the address of the GOT entry */
 	targ_addr = (unsigned long) _dl_find_hash(
 		strtab + symtab[symtab_index].st_name, 
-		tpnt->symbol_scope, insn_addr, tpnt, 0);
+		tpnt->symbol_scope, tpnt, 0);
 	if (!targ_addr) {
 		_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 			_dl_progname, strtab + symtab[symtab_index].st_name);
@@ -337,7 +337,7 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt,
 				continue;
 
 			symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-					tpnt->symbol_scope, (unsigned long) reloc_addr, 
+					tpnt->symbol_scope,
 					(reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), 0);
 
 			/*
@@ -499,7 +499,7 @@ int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
 
 			symbol_addr = (unsigned long) _dl_find_hash(strtab + 
 				symtab[symtab_index].st_name, xpnt->next, 
-				(unsigned long) reloc_addr, NULL, 1);
+				NULL, 1);
 			if (!symbol_addr) {
 				_dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
 					_dl_progname, strtab + symtab[symtab_index].st_name);

+ 66 - 19
ldso/ldso/readelflib1.c

@@ -108,14 +108,14 @@ int _dl_unmap_cache(void)
 /* This function's behavior must exactly match that 
  * in uClibc/ldso/util/ldd.c */
 static struct elf_resolve * 
-search_for_named_library(char *name, int secure, const char *path_list)
+search_for_named_library(char *name, int secure, const char *path_list,
+	struct dyn_elf **rpnt)
 {
 	int i, count = 1;
 	char *path, *path_n;
 	char mylibname[2050];
 	struct elf_resolve *tpnt1;
 
-
 	/* We need a writable copy of this string */
 	path = _dl_strdup(path_list);
 	if (!path) {
@@ -140,8 +140,11 @@ search_for_named_library(char *name, int secure, const char *path_list)
 		_dl_strcpy(mylibname, path_n); 
 		_dl_strcat(mylibname, "/"); 
 		_dl_strcat(mylibname, name);
-		if ((tpnt1 = _dl_load_elf_shared_library(secure, mylibname, 0)) != NULL)
-		    return tpnt1;
+		if ((tpnt1 = _dl_load_elf_shared_library(secure, rpnt,
+			mylibname, 0)) != NULL)
+		{
+			return tpnt1;
+		}
 		path_n += (_dl_strlen(path_n) + 1);
 	}
 	return NULL;
@@ -156,7 +159,7 @@ unsigned long _dl_error_number;
 unsigned long _dl_internal_error_number;
 extern char *_dl_ldsopath;
 
-struct elf_resolve *_dl_load_shared_library(int secure, 
+struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 	struct elf_resolve *tpnt, char *full_libname)
 {
 	char *pnt;
@@ -185,7 +188,7 @@ struct elf_resolve *_dl_load_shared_library(int secure,
 	   /usr/i486-sysv4/lib for /usr/lib in library names. */
 
 	if (libname != full_libname) {
-		tpnt1 = _dl_load_elf_shared_library(secure, full_libname, 0);
+		tpnt1 = _dl_load_elf_shared_library(secure, rpnt, full_libname, 0);
 		if (tpnt1)
 			return tpnt1;
 		goto goof;
@@ -204,7 +207,7 @@ struct elf_resolve *_dl_load_shared_library(int secure,
 #ifdef DL_DEBUG
 				_dl_dprintf(2, "searching RPATH: '%s'\n", pnt);
 #endif
-				if ((tpnt1 = search_for_named_library(libname, secure, pnt)) != NULL) 
+				if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) 
 				{
 				    return tpnt1;
 				}
@@ -217,7 +220,7 @@ struct elf_resolve *_dl_load_shared_library(int secure,
 #ifdef DL_DEBUG
 	    _dl_dprintf(2, "searching _dl_library_path: '%s'\n", _dl_library_path);
 #endif
-	    if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path)) != NULL) 
+	    if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL) 
 	    {
 		return tpnt1;
 	    }
@@ -240,7 +243,7 @@ struct elf_resolve *_dl_load_shared_library(int secure,
 				 libent[i].flags == LIB_ELF_LIBC5) &&
 				_dl_strcmp(libname, strs + libent[i].sooffset) == 0 &&
 				(tpnt1 = _dl_load_elf_shared_library(secure, 
-				     strs + libent[i].liboffset, 0)))
+				     rpnt, strs + libent[i].liboffset, 0)))
 				return tpnt1;
 		}
 	}
@@ -251,7 +254,7 @@ struct elf_resolve *_dl_load_shared_library(int secure,
 #ifdef DL_DEBUG
 	_dl_dprintf(2, "searching in ldso dir: %s\n", _dl_ldsopath);
 #endif
-	if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath)) != NULL) 
+	if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt)) != NULL) 
 	{
 	    return tpnt1;
 	}
@@ -268,7 +271,7 @@ struct elf_resolve *_dl_load_shared_library(int secure,
 			UCLIBC_DEVEL_PREFIX "/lib:"
 			UCLIBC_BUILD_DIR "/lib:"
 			"/usr/lib:"
-			"/lib")
+			"/lib", rpnt)
 		    ) != NULL) 
 	{
 	    return tpnt1;
@@ -286,16 +289,15 @@ goof:
 	return NULL;
 }
 
+
 /*
  * Read one ELF library into memory, mmap it into the correct locations and
  * add the symbol info to the symbol chain.  Perform any relocations that
  * are required.
  */
 
-//extern _elf_rtbndr(void);
-
-struct elf_resolve *_dl_load_elf_shared_library(int secure, 
-	char *libname, int flag)
+struct elf_resolve *_dl_load_elf_shared_library(int secure,
+	struct dyn_elf **rpnt, char *libname, int flag)
 {
 	elfhdr *epnt;
 	unsigned long dynamic_addr = 0;
@@ -311,14 +313,27 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	unsigned long *lpnt;
 	unsigned long libaddr;
 	unsigned long minvma = 0xffffffff, maxvma = 0;
-
 	int i;
 	int infile;
+#if defined(__mips__)
+	unsigned long mips_gotsym = 0;
+	unsigned long mips_local_gotno = 0;
+	unsigned long mips_symtabno = 0;
+#endif
 
 	/* If this file is already loaded, skip this step */
 	tpnt = _dl_check_hashed_files(libname);
-	if (tpnt)
+	if (tpnt) {
+		(*rpnt)->next = (struct dyn_elf *)
+			_dl_malloc(sizeof(struct dyn_elf));
+		_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+		*rpnt = (*rpnt)->next;
+		tpnt->usage_count++;
+		tpnt->symbol_scope = _dl_symbol_tables;
+		tpnt->libtype = elf_lib;
+		(*rpnt)->dyn = tpnt;
 		return tpnt;
+	}
 
 	/* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD),
 	   we don't load the library if it isn't setuid. */
@@ -514,7 +529,22 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 
 	dynamic_size = dynamic_size / sizeof(Elf32_Dyn);
 	_dl_memset(dynamic_info, 0, sizeof(dynamic_info));
+#if defined(__mips__)
+	/*
+	 * The program header file size for the dynamic section is
+	 * calculated differently for MIPS. We look for a null tag
+	 * value instead.
+	 */
+	while(dpnt->d_tag) {
+		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;
+#else
 	for (i = 0; i < dynamic_size; i++) {
+#endif
 		if (dpnt->d_tag > DT_JMPREL) {
 			dpnt++;
 			continue;
@@ -526,8 +556,8 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	};
 
 	/* If the TEXTREL is set, this means that we need to make the pages
-	   writable before we perform relocations.  Do this now. They get set back
-	   again later. */
+	   writable before we perform relocations.  Do this now. They get set
+	   back again later. */
 
 	if (dynamic_info[DT_TEXTREL]) {
 		ppnt = (elf_phdr *) & header[epnt->e_phoff];
@@ -547,6 +577,18 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	tpnt->ppnt = (elf_phdr *) (tpnt->loadaddr + epnt->e_phoff);
 	tpnt->n_phent = epnt->e_phnum;
 
+	/*
+	 * Add this object into the symbol chain
+	 */
+	(*rpnt)->next = (struct dyn_elf *)
+		_dl_malloc(sizeof(struct dyn_elf));
+	_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+	*rpnt = (*rpnt)->next;
+	tpnt->usage_count++;
+	tpnt->symbol_scope = _dl_symbol_tables;
+	tpnt->libtype = elf_lib;
+	(*rpnt)->dyn = tpnt;
+
 	/*
 	 * OK, the next thing we need to do is to insert the dynamic linker into
 	 * the proper entry in the GOT so that the PLT symbols can be properly
@@ -558,6 +600,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	if (lpnt) {
 		lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT] +
 			((int) libaddr));
+#if defined(__mips__)
+		tpnt->mips_gotsym = mips_gotsym;
+		tpnt->mips_local_gotno = mips_local_gotno;
+		tpnt->mips_symtabno = mips_symtabno;
+#endif
 		INIT_GOT(lpnt, tpnt);
 	};
 

+ 3 - 3
ldso/ldso/sparc/elfinterp.c

@@ -98,7 +98,7 @@ unsigned int _dl_linux_resolver(unsigned int reloc_entry, unsigned int * plt)
 
   /* Get the address of the GOT entry */
   new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-  			tpnt->symbol_scope, (int) got_addr, tpnt, 0);
+  			tpnt->symbol_scope, tpnt, 0);
   if(!new_addr) {
     _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
 	       _dl_progname, strtab + symtab[symtab_index].st_name);
@@ -201,7 +201,7 @@ int _dl_parse_relocation_information(struct elf_resolve * tpnt, int rel_addr,
 
       symbol_addr = (unsigned int) 
 	_dl_find_hash(strtab + symtab[symtab_index].st_name,
-			      tpnt->symbol_scope, (int) reloc_addr, 
+			      tpnt->symbol_scope,
 		      (reloc_type == R_SPARC_JMP_SLOT ? tpnt : NULL), 0);
 
       if(!symbol_addr &&
@@ -319,7 +319,7 @@ int _dl_parse_copy_information(struct dyn_elf * xpnt, int rel_addr,
 
       symbol_addr = (unsigned int) 
 	_dl_find_hash(strtab + symtab[symtab_index].st_name,
-			      xpnt->next, (int) reloc_addr, NULL, 1);
+			      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);

+ 3 - 3
ldso/libdl/dlib.c

@@ -108,7 +108,7 @@ void *_dlopen(char *libname, int flag)
 			tfrom = tpnt;
 	}
 
-	if (!(tpnt = _dl_load_shared_library(0, tfrom, libname))) {
+	if (!(tpnt = _dl_load_shared_library(0, &rpnt, tfrom, libname))) {
 #ifdef USE_CACHE
 		_dl_unmap_cache();
 #endif
@@ -145,7 +145,7 @@ void *_dlopen(char *libname, int flag)
 		    {
 		      lpnt = tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] + 
 			dpnt->d_un.d_val;
-		      if(!(tpnt1 = _dl_load_shared_library(0, tcurr, lpnt)))
+		      if(!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpnt)))
 			goto oops;
 
 		      rpnt->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
@@ -304,7 +304,7 @@ void *_dlsym(void *vhandle, char *name)
 		}
 	}
 
-	ret = _dl_find_hash(name, handle, 1, NULL, 1);
+	ret = _dl_find_hash(name, handle, NULL, 1);
 
 	/*
 	 * Nothing found.

+ 3 - 3
ldso/libdl/libdl.c

@@ -108,7 +108,7 @@ void *_dlopen(char *libname, int flag)
 			tfrom = tpnt;
 	}
 
-	if (!(tpnt = _dl_load_shared_library(0, tfrom, libname))) {
+	if (!(tpnt = _dl_load_shared_library(0, &rpnt, tfrom, libname))) {
 #ifdef USE_CACHE
 		_dl_unmap_cache();
 #endif
@@ -145,7 +145,7 @@ void *_dlopen(char *libname, int flag)
 		    {
 		      lpnt = tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] + 
 			dpnt->d_un.d_val;
-		      if(!(tpnt1 = _dl_load_shared_library(0, tcurr, lpnt)))
+		      if(!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpnt)))
 			goto oops;
 
 		      rpnt->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf));
@@ -304,7 +304,7 @@ void *_dlsym(void *vhandle, char *name)
 		}
 	}
 
-	ret = _dl_find_hash(name, handle, 1, NULL, 1);
+	ret = _dl_find_hash(name, handle, NULL, 1);
 
 	/*
 	 * Nothing found.