浏览代码

Joakim Tjernlund writes:

Hi again

All dltest* and test* programs pass for me.
uClibc ld.so resolves according to the OLD weak symbol handling.

I have tried to use the new scheme as well, but that segfaults in all
cases but test3.
Eric Andersen 21 年之前
父节点
当前提交
9770574ad3
共有 2 个文件被更改,包括 90 次插入220 次删除
  1. 45 110
      ldso/ldso/dl-hash.c
  2. 45 110
      ldso/ldso/hash.c

+ 45 - 110
ldso/ldso/dl-hash.c

@@ -1,12 +1,12 @@
 /* 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) 1994-2000 Eric Youngdale, Peter MacDonald, 
+ * Copyright (C) 2004 by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
+ * Copyright (C) 2000-2004 by Erik Andersen <andersen@codpoet.org>
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
  *				David Engel, Hongjiu Lu and Mitch D'Souza
  *				David Engel, Hongjiu Lu and Mitch D'Souza
- * Copyright (C) 2001-2002, Erik Andersen
- *
- * All rights reserved.
  *
  *
  * Redistribution and use in source and binary forms, with or without
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * modification, are permitted provided that the following conditions
@@ -35,10 +35,9 @@
 
 
 /*
 /*
  * This is the start of the linked list that describes all of the files present
  * This is the start of the linked list that describes all of the files present
- * in the system with pointers to all of the symbol, string, and hash tables, 
+ * in the system with pointers to all of the symbol, string, and hash tables,
  * as well as all of the other good stuff in the binary.
  * as well as all of the other good stuff in the binary.
  */
  */
-
 struct elf_resolve *_dl_loaded_modules = NULL;
 struct elf_resolve *_dl_loaded_modules = NULL;
 
 
 /*
 /*
@@ -55,12 +54,9 @@ struct dyn_elf *_dl_symbol_tables = NULL;
 struct dyn_elf *_dl_handles = NULL;
 struct dyn_elf *_dl_handles = NULL;
 
 
 
 
-/*
- * This is the hash function that is used by the ELF linker to generate
- * the hash table that each executable and library is required to
- * have.  We need it to decode the hash table.
- */
-
+/* This is the hash function that is used by the ELF linker to generate the
+ * hash table that each executable and library is required to have.  We need
+ * it to decode the hash table.  */
 unsigned long _dl_elf_hash(const char *name)
 unsigned long _dl_elf_hash(const char *name)
 {
 {
 	unsigned long hash = 0;
 	unsigned long hash = 0;
@@ -75,9 +71,7 @@ unsigned long _dl_elf_hash(const char *name)
 	return hash;
 	return hash;
 }
 }
 
 
-/*
- * Check to see if a library has already been added to the hash chain.
- */
+/* Check to see if a library has already been added to the hash chain.  */
 struct elf_resolve *_dl_check_hashed_files(const char *libname)
 struct elf_resolve *_dl_check_hashed_files(const char *libname)
 {
 {
 	struct elf_resolve *tpnt;
 	struct elf_resolve *tpnt;
@@ -97,9 +91,8 @@ struct elf_resolve *_dl_check_hashed_files(const char *libname)
  * We add the relevant info to the symbol chain, so that we can resolve all
  * We add the relevant info to the symbol chain, so that we can resolve all
  * externals properly.
  * externals properly.
  */
  */
-
-struct elf_resolve *_dl_add_elf_hash_table(const char *libname, 
-	char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr, 
+struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
+	char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,
 	unsigned long dynamic_size)
 	unsigned long dynamic_size)
 {
 {
 	unsigned long *hash_addr;
 	unsigned long *hash_addr;
@@ -107,8 +100,7 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
 	int i;
 	int i;
 
 
 	if (!_dl_loaded_modules) {
 	if (!_dl_loaded_modules) {
-		tpnt = _dl_loaded_modules = 
-		    (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));
+		tpnt = _dl_loaded_modules = (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));
 		_dl_memset(tpnt, 0, sizeof(struct elf_resolve));
 		_dl_memset(tpnt, 0, sizeof(struct elf_resolve));
 	} else {
 	} else {
 		tpnt = _dl_loaded_modules;
 		tpnt = _dl_loaded_modules;
@@ -161,21 +153,18 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
  * This function resolves externals, and this is either called when we process
  * This function resolves externals, and this is either called when we process
  * relocations or when we call an entry in the PLT table for the first time.
  * relocations or when we call an entry in the PLT table for the first time.
  */
  */
-
-char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1, 
+char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,
 	struct elf_resolve *f_tpnt, enum caller_type caller_type)
 	struct elf_resolve *f_tpnt, enum caller_type caller_type)
 {
 {
 	struct elf_resolve *tpnt;
 	struct elf_resolve *tpnt;
 	int si;
 	int si;
-	char *pnt;
 	int pass;
 	int pass;
 	char *strtab;
 	char *strtab;
 	Elf32_Sym *symtab;
 	Elf32_Sym *symtab;
 	unsigned long elf_hash_number, hn;
 	unsigned long elf_hash_number, hn;
 	char *weak_result;
 	char *weak_result;
-	struct elf_resolve *first_def;
 	struct dyn_elf *rpnt, first;
 	struct dyn_elf *rpnt, first;
-	char *data_result = 0;		/* nakao */
+	const ElfW(Sym) *sym;
 
 
 	weak_result = 0;
 	weak_result = 0;
 	elf_hash_number = _dl_elf_hash(name);
 	elf_hash_number = _dl_elf_hash(name);
@@ -185,7 +174,7 @@ char *_dl_find_hash(const 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 (_dl_symbol_tables && !caller_type && rpnt1) {
+	if (_dl_symbol_tables && rpnt1) {
 		first = (*_dl_symbol_tables);
 		first = (*_dl_symbol_tables);
 		first.next = rpnt1;
 		first.next = rpnt1;
 		rpnt1 = (&first);
 		rpnt1 = (&first);
@@ -222,24 +211,16 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,
 		if (pass != 0) {
 		if (pass != 0) {
 			if (rpnt1 == NULL)
 			if (rpnt1 == NULL)
 				break;
 				break;
-			if ((rpnt1->flags & RTLD_GLOBAL) == 0)
-				continue;
+			//if ((rpnt1->flags & RTLD_GLOBAL) == 0)
+				//continue;
 		}
 		}
 
 
 		for (rpnt = (rpnt1 ? rpnt1 : _dl_symbol_tables); rpnt; rpnt = rpnt->next) {
 		for (rpnt = (rpnt1 ? rpnt1 : _dl_symbol_tables); rpnt; rpnt = rpnt->next) {
 			tpnt = rpnt->dyn;
 			tpnt = rpnt->dyn;
 
 
-			/*
-			 * The idea here is that if we are using dlsym, we want to
-			 * first search the entire chain loaded from dlopen, and
-			 * return a result from that if we found anything.  If this
-			 * fails, then we continue the search into the stuff loaded
-			 * when the image was activated.  For normal lookups, we start
-			 * with rpnt == NULL, so we should never hit this.  
-			 */
-			if (tpnt->libtype == elf_executable && weak_result != 0) {
-				break;
-			}
+			/* Don't search the executable when resolving a copy reloc. */
+			if (tpnt->libtype == elf_executable && caller_type == copyrel)
+				continue;
 
 
 			/*
 			/*
 			 * Avoid calling .urem here.
 			 * Avoid calling .urem here.
@@ -247,81 +228,35 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,
 			do_rem(hn, elf_hash_number, tpnt->nbucket);
 			do_rem(hn, elf_hash_number, tpnt->nbucket);
 			symtab = (Elf32_Sym *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
 			symtab = (Elf32_Sym *) (intptr_t) (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);
-			/*
-			 * This crap is required because the first instance of a
-			 * symbol on the chain will be used for all symbol references.
-			 * Thus this instance must be resolved to an address that
-			 * contains the actual function, 
-			 */
-
-			first_def = NULL;
-
-			for (si = tpnt->elf_buckets[hn]; si; si = tpnt->chains[si]) {
-				pnt = strtab + symtab[si].st_name;
-
-				if (_dl_strcmp(pnt, name) == 0 &&
-				    symtab[si].st_value != 0)
-				{
-				  if ((ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
-				       ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
-				       ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
-				      symtab[si].st_shndx != SHN_UNDEF) {
-
-					/* Here we make sure that we find a module where the symbol is
-					 * actually defined.
-					 */
-
-					if (f_tpnt) {
-						if (!first_def)
-							first_def = tpnt;
-						if (first_def == f_tpnt
-							&& symtab[si].st_shndx == 0)
-							continue;
-					}
 
 
-					switch (ELF32_ST_BIND(symtab[si].st_info)) {
-					case STB_GLOBAL:
-						if (tpnt->libtype != elf_executable && 
-							ELF32_ST_TYPE(symtab[si].st_info) 
-							== STT_NOTYPE) 
-						{	/* nakao */
-							data_result = (char *)tpnt->loadaddr + 
-							    symtab[si].st_value;	/* nakao */
-							break;	/* nakao */
-						} else	/* nakao */
-							return (char*)tpnt->loadaddr + symtab[si].st_value;
-					case STB_WEAK:
-						if (!weak_result)
-							weak_result = (char *)tpnt->loadaddr + symtab[si].st_value;
-						break;
-					default:	/* Do local symbols need to be examined? */
-						break;
-					}
-				  }
-#ifndef __mips__
-				  /*
-				   * 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;
-				  }
+			for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) {
+				sym = &symtab[si];
+
+				if (sym->st_value == 0)
+					continue;
+				if (ELF32_ST_TYPE(sym->st_info) > STT_FUNC)
+					continue;
+				if (sym->st_shndx == SHN_UNDEF && caller_type != copyrel)
+					continue;
+				if (_dl_strcmp(strtab + sym->st_name, name) != 0)
+					continue;
+
+				switch (ELF32_ST_BIND(sym->st_info)) {
+				case STB_WEAK:
+//Disable this to match current glibc behavior.  Of course,
+//this doesn't actually work yet and will cause segfaults...
+#if 1
+					if (!weak_result)
+						weak_result = (char *)tpnt->loadaddr + sym->st_value;
+					break;
 #endif
 #endif
+				case STB_GLOBAL:
+					return (char*)tpnt->loadaddr + sym->st_value;
+				default:	/* Local symbols not handled here */
+					break;
 				}
 				}
 			}
 			}
 		}
 		}
 	}
 	}
-	if (data_result)
-		return data_result;		/* nakao */
 	return weak_result;
 	return weak_result;
 }
 }

+ 45 - 110
ldso/ldso/hash.c

@@ -1,12 +1,12 @@
 /* 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) 1994-2000 Eric Youngdale, Peter MacDonald, 
+ * Copyright (C) 2004 by Joakim Tjernlund <joakim.tjernlund@lumentis.se>
+ * Copyright (C) 2000-2004 by Erik Andersen <andersen@codpoet.org>
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
  *				David Engel, Hongjiu Lu and Mitch D'Souza
  *				David Engel, Hongjiu Lu and Mitch D'Souza
- * Copyright (C) 2001-2002, Erik Andersen
- *
- * All rights reserved.
  *
  *
  * Redistribution and use in source and binary forms, with or without
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * modification, are permitted provided that the following conditions
@@ -35,10 +35,9 @@
 
 
 /*
 /*
  * This is the start of the linked list that describes all of the files present
  * This is the start of the linked list that describes all of the files present
- * in the system with pointers to all of the symbol, string, and hash tables, 
+ * in the system with pointers to all of the symbol, string, and hash tables,
  * as well as all of the other good stuff in the binary.
  * as well as all of the other good stuff in the binary.
  */
  */
-
 struct elf_resolve *_dl_loaded_modules = NULL;
 struct elf_resolve *_dl_loaded_modules = NULL;
 
 
 /*
 /*
@@ -55,12 +54,9 @@ struct dyn_elf *_dl_symbol_tables = NULL;
 struct dyn_elf *_dl_handles = NULL;
 struct dyn_elf *_dl_handles = NULL;
 
 
 
 
-/*
- * This is the hash function that is used by the ELF linker to generate
- * the hash table that each executable and library is required to
- * have.  We need it to decode the hash table.
- */
-
+/* This is the hash function that is used by the ELF linker to generate the
+ * hash table that each executable and library is required to have.  We need
+ * it to decode the hash table.  */
 unsigned long _dl_elf_hash(const char *name)
 unsigned long _dl_elf_hash(const char *name)
 {
 {
 	unsigned long hash = 0;
 	unsigned long hash = 0;
@@ -75,9 +71,7 @@ unsigned long _dl_elf_hash(const char *name)
 	return hash;
 	return hash;
 }
 }
 
 
-/*
- * Check to see if a library has already been added to the hash chain.
- */
+/* Check to see if a library has already been added to the hash chain.  */
 struct elf_resolve *_dl_check_hashed_files(const char *libname)
 struct elf_resolve *_dl_check_hashed_files(const char *libname)
 {
 {
 	struct elf_resolve *tpnt;
 	struct elf_resolve *tpnt;
@@ -97,9 +91,8 @@ struct elf_resolve *_dl_check_hashed_files(const char *libname)
  * We add the relevant info to the symbol chain, so that we can resolve all
  * We add the relevant info to the symbol chain, so that we can resolve all
  * externals properly.
  * externals properly.
  */
  */
-
-struct elf_resolve *_dl_add_elf_hash_table(const char *libname, 
-	char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr, 
+struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
+	char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,
 	unsigned long dynamic_size)
 	unsigned long dynamic_size)
 {
 {
 	unsigned long *hash_addr;
 	unsigned long *hash_addr;
@@ -107,8 +100,7 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
 	int i;
 	int i;
 
 
 	if (!_dl_loaded_modules) {
 	if (!_dl_loaded_modules) {
-		tpnt = _dl_loaded_modules = 
-		    (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));
+		tpnt = _dl_loaded_modules = (struct elf_resolve *) _dl_malloc(sizeof(struct elf_resolve));
 		_dl_memset(tpnt, 0, sizeof(struct elf_resolve));
 		_dl_memset(tpnt, 0, sizeof(struct elf_resolve));
 	} else {
 	} else {
 		tpnt = _dl_loaded_modules;
 		tpnt = _dl_loaded_modules;
@@ -161,21 +153,18 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
  * This function resolves externals, and this is either called when we process
  * This function resolves externals, and this is either called when we process
  * relocations or when we call an entry in the PLT table for the first time.
  * relocations or when we call an entry in the PLT table for the first time.
  */
  */
-
-char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1, 
+char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,
 	struct elf_resolve *f_tpnt, enum caller_type caller_type)
 	struct elf_resolve *f_tpnt, enum caller_type caller_type)
 {
 {
 	struct elf_resolve *tpnt;
 	struct elf_resolve *tpnt;
 	int si;
 	int si;
-	char *pnt;
 	int pass;
 	int pass;
 	char *strtab;
 	char *strtab;
 	Elf32_Sym *symtab;
 	Elf32_Sym *symtab;
 	unsigned long elf_hash_number, hn;
 	unsigned long elf_hash_number, hn;
 	char *weak_result;
 	char *weak_result;
-	struct elf_resolve *first_def;
 	struct dyn_elf *rpnt, first;
 	struct dyn_elf *rpnt, first;
-	char *data_result = 0;		/* nakao */
+	const ElfW(Sym) *sym;
 
 
 	weak_result = 0;
 	weak_result = 0;
 	elf_hash_number = _dl_elf_hash(name);
 	elf_hash_number = _dl_elf_hash(name);
@@ -185,7 +174,7 @@ char *_dl_find_hash(const 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 (_dl_symbol_tables && !caller_type && rpnt1) {
+	if (_dl_symbol_tables && rpnt1) {
 		first = (*_dl_symbol_tables);
 		first = (*_dl_symbol_tables);
 		first.next = rpnt1;
 		first.next = rpnt1;
 		rpnt1 = (&first);
 		rpnt1 = (&first);
@@ -222,24 +211,16 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,
 		if (pass != 0) {
 		if (pass != 0) {
 			if (rpnt1 == NULL)
 			if (rpnt1 == NULL)
 				break;
 				break;
-			if ((rpnt1->flags & RTLD_GLOBAL) == 0)
-				continue;
+			//if ((rpnt1->flags & RTLD_GLOBAL) == 0)
+				//continue;
 		}
 		}
 
 
 		for (rpnt = (rpnt1 ? rpnt1 : _dl_symbol_tables); rpnt; rpnt = rpnt->next) {
 		for (rpnt = (rpnt1 ? rpnt1 : _dl_symbol_tables); rpnt; rpnt = rpnt->next) {
 			tpnt = rpnt->dyn;
 			tpnt = rpnt->dyn;
 
 
-			/*
-			 * The idea here is that if we are using dlsym, we want to
-			 * first search the entire chain loaded from dlopen, and
-			 * return a result from that if we found anything.  If this
-			 * fails, then we continue the search into the stuff loaded
-			 * when the image was activated.  For normal lookups, we start
-			 * with rpnt == NULL, so we should never hit this.  
-			 */
-			if (tpnt->libtype == elf_executable && weak_result != 0) {
-				break;
-			}
+			/* Don't search the executable when resolving a copy reloc. */
+			if (tpnt->libtype == elf_executable && caller_type == copyrel)
+				continue;
 
 
 			/*
 			/*
 			 * Avoid calling .urem here.
 			 * Avoid calling .urem here.
@@ -247,81 +228,35 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt1,
 			do_rem(hn, elf_hash_number, tpnt->nbucket);
 			do_rem(hn, elf_hash_number, tpnt->nbucket);
 			symtab = (Elf32_Sym *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
 			symtab = (Elf32_Sym *) (intptr_t) (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);
-			/*
-			 * This crap is required because the first instance of a
-			 * symbol on the chain will be used for all symbol references.
-			 * Thus this instance must be resolved to an address that
-			 * contains the actual function, 
-			 */
-
-			first_def = NULL;
-
-			for (si = tpnt->elf_buckets[hn]; si; si = tpnt->chains[si]) {
-				pnt = strtab + symtab[si].st_name;
-
-				if (_dl_strcmp(pnt, name) == 0 &&
-				    symtab[si].st_value != 0)
-				{
-				  if ((ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
-				       ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
-				       ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
-				      symtab[si].st_shndx != SHN_UNDEF) {
-
-					/* Here we make sure that we find a module where the symbol is
-					 * actually defined.
-					 */
-
-					if (f_tpnt) {
-						if (!first_def)
-							first_def = tpnt;
-						if (first_def == f_tpnt
-							&& symtab[si].st_shndx == 0)
-							continue;
-					}
 
 
-					switch (ELF32_ST_BIND(symtab[si].st_info)) {
-					case STB_GLOBAL:
-						if (tpnt->libtype != elf_executable && 
-							ELF32_ST_TYPE(symtab[si].st_info) 
-							== STT_NOTYPE) 
-						{	/* nakao */
-							data_result = (char *)tpnt->loadaddr + 
-							    symtab[si].st_value;	/* nakao */
-							break;	/* nakao */
-						} else	/* nakao */
-							return (char*)tpnt->loadaddr + symtab[si].st_value;
-					case STB_WEAK:
-						if (!weak_result)
-							weak_result = (char *)tpnt->loadaddr + symtab[si].st_value;
-						break;
-					default:	/* Do local symbols need to be examined? */
-						break;
-					}
-				  }
-#ifndef __mips__
-				  /*
-				   * 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;
-				  }
+			for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) {
+				sym = &symtab[si];
+
+				if (sym->st_value == 0)
+					continue;
+				if (ELF32_ST_TYPE(sym->st_info) > STT_FUNC)
+					continue;
+				if (sym->st_shndx == SHN_UNDEF && caller_type != copyrel)
+					continue;
+				if (_dl_strcmp(strtab + sym->st_name, name) != 0)
+					continue;
+
+				switch (ELF32_ST_BIND(sym->st_info)) {
+				case STB_WEAK:
+//Disable this to match current glibc behavior.  Of course,
+//this doesn't actually work yet and will cause segfaults...
+#if 1
+					if (!weak_result)
+						weak_result = (char *)tpnt->loadaddr + sym->st_value;
+					break;
 #endif
 #endif
+				case STB_GLOBAL:
+					return (char*)tpnt->loadaddr + sym->st_value;
+				default:	/* Local symbols not handled here */
+					break;
 				}
 				}
 			}
 			}
 		}
 		}
 	}
 	}
-	if (data_result)
-		return data_result;		/* nakao */
 	return weak_result;
 	return weak_result;
 }
 }