about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--elf/dl-addr.c15
-rw-r--r--sysdeps/generic/ldsodefs.h10
-rw-r--r--sysdeps/ieee754/flt-32/e_hypotf.c4
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h77
5 files changed, 109 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 0b7cca868d..b872277998 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2005-08-30  Ulrich Drepper  <drepper@redhat.com>
+
+	* sysdeps/ieee754/flt-32/e_hypotf.c [!__STDC__]: Fix function name.
+
+2005-08-01  Bob Wilson  <bob.wilson@acm.org>
+        Richard Sandiford  <richard@codesourcery.com>
+
+	* sysdeps/ieee754/flt-32/e_hypotf.c (__ieee754_hypotf): Add missing
+	exponent bias to the value for 2^126.
+
+2005-08-30  Jakub Jelinek  <jakub@redhat.com>
+	    Alan Modra  <amodra@bigpond.net.au>
+
+	* elf/dl-addr.c (_dl_addr): Use DL_ADDR_SYM_MATCH macro.
+	* sysdeps/generic/ldsodefs.h (DL_ADDR_SYM_MATCH): Define.
+	* sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h: New file.
+
 2005-08-23  Ulrich Drepper  <drepper@redhat.com>
 
 	* nscd/nscd.c (main): Use error while process isn't running in the
diff --git a/elf/dl-addr.c b/elf/dl-addr.c
index 6bd7f7b69c..fa62e40840 100644
--- a/elf/dl-addr.c
+++ b/elf/dl-addr.c
@@ -85,22 +85,15 @@ _dl_addr (const void *address, Dl_info *info,
 	   the string table which generally follows the symbol table.  */
 	symtabend = (const ElfW(Sym) *) strtab;
 
-      /* We assume that the string table follows the symbol table,
-	 because there is no way in ELF to know the size of the
-	 dynamic symbol table!!  */
       const ElfW(Sym) *matchsym;
       for (matchsym = NULL; (void *) symtab < (void *) symtabend; ++symtab)
-	if (addr >= match->l_addr + symtab->st_value
+	if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
+	     || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
 #if defined USE_TLS
 	    && ELFW(ST_TYPE) (symtab->st_info) != STT_TLS
 #endif
-	    && ((symtab->st_size == 0
-		 && addr == match->l_addr + symtab->st_value)
-		|| addr < match->l_addr + symtab->st_value + symtab->st_size)
-	    && symtab->st_name < strtabsize
-	    && (matchsym == NULL || matchsym->st_value < symtab->st_value)
-	    && (ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
-		|| ELFW(ST_BIND) (symtab->st_info) == STB_WEAK))
+	    && DL_ADDR_SYM_MATCH (match, symtab, matchsym, addr)
+	    && symtab->st_name < strtabsize)
 	  matchsym = (ElfW(Sym) *) symtab;
 
       if (mapp)
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index a24c2ff58e..191ae4d4fb 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -62,7 +62,7 @@ typedef struct link_map *lookup_t;
 # define LOOKUP_VALUE(map) map
 # define LOOKUP_VALUE_ADDRESS(map) ((map) ? (map)->l_addr : 0)
 
-/* on some architectures a pointer to a function is not just a pointer
+/* On some architectures a pointer to a function is not just a pointer
    to the actual code of the function but rather an architecture
    specific descriptor. */
 #ifndef ELF_FUNCTION_PTR_IS_SPECIAL
@@ -73,6 +73,14 @@ typedef struct link_map *lookup_t;
 # define DL_DT_FINI_ADDRESS(map, start) (start)
 #endif
 
+/* On some architectures dladdr can't use st_size of all symbols this way.  */
+#define DL_ADDR_SYM_MATCH(L, SYM, MATCHSYM, ADDR) \
+  ((ADDR) >= (L)->l_addr + (SYM)->st_value				\
+   && (((SYM)->st_size == 0						\
+	&& (ADDR) == (L)->l_addr + (SYM)->st_value)			\
+       || (ADDR) < (L)->l_addr + (SYM)->st_value + (SYM)->st_size)	\
+   && ((MATCHSYM) == NULL || (MATCHSYM)->st_value < (SYM)->st_value))
+
 /* Unmap a loaded object, called by _dl_close (). */
 #ifndef DL_UNMAP_IS_SPECIAL
 # define DL_UNMAP(map) \
diff --git a/sysdeps/ieee754/flt-32/e_hypotf.c b/sysdeps/ieee754/flt-32/e_hypotf.c
index d6b1520cb8..ddcd8ee208 100644
--- a/sysdeps/ieee754/flt-32/e_hypotf.c
+++ b/sysdeps/ieee754/flt-32/e_hypotf.c
@@ -23,7 +23,7 @@ static char rcsid[] = "$NetBSD: e_hypotf.c,v 1.5 1995/05/12 04:57:30 jtc Exp $";
 #ifdef __STDC__
 	float __ieee754_hypotf(float x, float y)
 #else
-	float __ieee754_hypot(x,y)
+	float __ieee754_hypotf(x,y)
 	float x, y;
 #endif
 {
@@ -54,7 +54,7 @@ static char rcsid[] = "$NetBSD: e_hypotf.c,v 1.5 1995/05/12 04:57:30 jtc Exp $";
 	if(hb < 0x26800000) {	/* b < 2**-50 */
 	    if(hb <= 0x007fffff) {	/* subnormal b or 0 */
 	        if(hb==0) return a;
-		SET_FLOAT_WORD(t1,0x3f000000);	/* t1=2^126 */
+		SET_FLOAT_WORD(t1,0x7e800000);	/* t1=2^126 */
 		b *= t1;
 		a *= t1;
 		k -= 126;
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h
new file mode 100644
index 0000000000..1ead3dd63d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h
@@ -0,0 +1,77 @@
+/* Run-time dynamic linker data structures for loaded ELF shared objects.
+   Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef	_LDSODEFS_H
+
+/* Get the real definitions.  */
+#include_next <ldsodefs.h>
+
+/* Now define our stuff.  */
+
+static __always_inline bool
+_dl_ppc64_is_opd_sym (const struct link_map *l, const ElfW(Sym) *sym)
+{
+  return (ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
+	  && l->l_addr + sym->st_value >= (ElfW(Addr)) l->l_ld
+	  && l->l_addr + sym->st_value < l->l_map_end
+	  && sym->st_size != 0);
+}
+
+static __always_inline bool
+_dl_ppc64_addr_sym_match (const struct link_map *l, const ElfW(Sym) *sym,
+			  const ElfW(Sym) *matchsym, ElfW(Addr) addr)
+{
+  ElfW(Addr) value = l->l_addr + sym->st_value;
+  if (_dl_ppc64_is_opd_sym (l, sym))
+    {
+      if (addr < value || addr >= value + 24)
+	{
+	  value = *(ElfW(Addr) *) value;
+	  if (addr < value || addr >= value + sym->st_size)
+	    return false;
+	}
+    }
+  else if (sym->st_size == 0)
+    {
+      if (addr != value)
+	return false;
+    }
+  else if (addr < value || addr >= value + sym->st_size)
+    return false;
+
+  if (matchsym == NULL)
+    return true;
+
+  ElfW(Addr) matchvalue = l->l_addr + matchsym->st_value;
+  if (_dl_ppc64_is_opd_sym (l, matchsym)
+      && (addr < matchvalue || addr > matchvalue + 24))
+    matchvalue = *(ElfW(Addr) *) matchvalue;
+
+  return matchvalue < value;
+}
+
+/* If this is a function symbol defined past the end of our dynamic
+   section, then it must be a function descriptor.  Allow these symbols
+   to match their associated function code range as well as the
+   descriptor addresses.  */
+#undef DL_ADDR_SYM_MATCH
+#define DL_ADDR_SYM_MATCH(L, SYM, MATCHSYM, ADDR) \
+  _dl_ppc64_addr_sym_match (L, SYM, MATCHSYM, ADDR)
+
+#endif /* ldsodefs.h */