about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2006-08-02 16:45:53 +0000
committerUlrich Drepper <drepper@redhat.com>2006-08-02 16:45:53 +0000
commit82ee37c5104b12116f14fb6b00b1dce06dcd3344 (patch)
tree3a8de9b0cfa290e9d52ca6f825ceddf29cd0853a
parent5632cd20609a6d52f108d745b77830eddf7d3af7 (diff)
downloadglibc-82ee37c5104b12116f14fb6b00b1dce06dcd3344.tar.gz
glibc-82ee37c5104b12116f14fb6b00b1dce06dcd3344.tar.xz
glibc-82ee37c5104b12116f14fb6b00b1dce06dcd3344.zip
2006-06-23  Joseph Myers  <joseph@codesourcery.com>
	[BZ #2980]
	* posix/Makefile (CFLAGS-waitid.c): Add
	-fasynchronous-unwind-tables.

2006-08-02  Ulrich Drepper  <drepper@redhat.com>

	* elf/dl-addr.c (_dl_addr): If GNU-style hash tables are present,
	walk them instead of the symbol table.
-rw-r--r--ChangeLog11
-rw-r--r--elf/dl-addr.c74
-rw-r--r--nptl/sysdeps/unix/sysv/linux/smp.h30
-rw-r--r--posix/Makefile2
4 files changed, 69 insertions, 48 deletions
diff --git a/ChangeLog b/ChangeLog
index a4bb3e8c34..6d8eea5ae4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2006-06-23  Joseph Myers  <joseph@codesourcery.com>
+
+	[BZ #2980]
+	* posix/Makefile (CFLAGS-waitid.c): Add
+	-fasynchronous-unwind-tables.
+
+2006-08-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf/dl-addr.c (_dl_addr): If GNU-style hash tables are present,
+	walk them instead of the symbol table.
+
 2006-08-01  Ulrich Drepper  <drepper@redhat.com>
 
 	* nscd/initgrcache.c (addinitgroupsX): Judge successful lookups by
diff --git a/elf/dl-addr.c b/elf/dl-addr.c
index ced8978eb3..535977ca5e 100644
--- a/elf/dl-addr.c
+++ b/elf/dl-addr.c
@@ -74,28 +74,62 @@ _dl_addr (const void *address, Dl_info *info,
 
       ElfW(Word) strtabsize = match->l_info[DT_STRSZ]->d_un.d_val;
 
-      const ElfW(Sym) *symtabend;
-      if (match->l_info[DT_HASH] != NULL)
-	symtabend = (symtab
-		     + ((Elf_Symndx *) D_PTR (match, l_info[DT_HASH]))[1]);
+      const ElfW(Sym) *matchsym = NULL;
+      if (match->l_info[DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM
+			+ DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] != NULL)
+	{
+	  /* We look at all symbol table entries referenced by the
+	     hash table.  */
+	  for (Elf_Symndx bucket = 0; bucket < match->l_nbuckets; ++bucket)
+	    {
+	      Elf32_Word symndx = match->l_gnu_buckets[bucket];
+	      if (bucket != 0)
+		{
+		  const Elf32_Word *hasharr = &match->l_gnu_chain_zero[symndx];
+
+		  do
+		    {
+		      /* The hash table never references local symbols
+			 so we can omit that test here.  */
+		      if (symtab[symndx].st_shndx != SHN_UNDEF
+#ifdef USE_TLS
+			  && ELFW(ST_TYPE) (symtab[symndx].st_info) != STT_TLS
+#endif
+			  && DL_ADDR_SYM_MATCH (match, &symtab[symndx],
+						matchsym, addr)
+			  && symtab[symndx].st_name < strtabsize)
+			matchsym = (ElfW(Sym) *) &symtab[symndx];
+
+		      ++symndx;
+		    }
+		  while ((*hasharr++ & 1u) == 0);
+		}
+	    }
+	}
       else
-	/* There is no direct way to determine the number of symbols in the
-	   dynamic symbol table and no hash table is present.  The ELF
-	   binary is ill-formed but what shall we do?  Use the beginning of
-	   the string table which generally follows the symbol table.  */
-	symtabend = (const ElfW(Sym) *) strtab;
-
-      const ElfW(Sym) *matchsym;
-      for (matchsym = NULL; (void *) symtab < (void *) symtabend; ++symtab)
-	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
+	{
+	  const ElfW(Sym) *symtabend;
+	  if (match->l_info[DT_HASH] != NULL)
+	    symtabend = (symtab
+			 + ((Elf_Symndx *) D_PTR (match, l_info[DT_HASH]))[1]);
+	  else
+	    /* There is no direct way to determine the number of symbols in the
+	       dynamic symbol table and no hash table is present.  The ELF
+	       binary is ill-formed but what shall we do?  Use the beginning of
+	       the string table which generally follows the symbol table.  */
+	    symtabend = (const ElfW(Sym) *) strtab;
+
+	  for (; (void *) symtab < (void *) symtabend; ++symtab)
+	    if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
+		 || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
+#ifdef USE_TLS
+		&& ELFW(ST_TYPE) (symtab->st_info) != STT_TLS
 #endif
-	    && symtab->st_shndx != SHN_UNDEF
-	    && DL_ADDR_SYM_MATCH (match, symtab, matchsym, addr)
-	    && symtab->st_name < strtabsize)
-	  matchsym = (ElfW(Sym) *) symtab;
+		&& symtab->st_shndx != SHN_UNDEF
+		&& DL_ADDR_SYM_MATCH (match, symtab, matchsym, addr)
+		&& symtab->st_name < strtabsize)
+	      matchsym = (ElfW(Sym) *) symtab;
+	}
 
       if (mapp)
 	*mapp = match;
diff --git a/nptl/sysdeps/unix/sysv/linux/smp.h b/nptl/sysdeps/unix/sysv/linux/smp.h
index 4f4d358d32..fcc34f7681 100644
--- a/nptl/sysdeps/unix/sysv/linux/smp.h
+++ b/nptl/sysdeps/unix/sysv/linux/smp.h
@@ -1,5 +1,5 @@
 /* Determine whether the host has multiple processors.  Linux version.
-   Copyright (C) 1996, 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1996, 2002, 2004, 2006 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
@@ -17,36 +17,12 @@
    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
 
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/sysctl.h>
-#include <not-cancel.h>
-
 /* Test whether the machine has more than one processor.  This is not the
    best test but good enough.  More complicated tests would require `malloc'
    which is not available at that time.  */
 static inline int
 is_smp_system (void)
 {
-  static const int sysctl_args[] = { CTL_KERN, KERN_VERSION };
-  char buf[512];
-  size_t reslen = sizeof (buf);
-
-  /* Try reading the number using `sysctl' first.  */
-  if (__sysctl ((int *) sysctl_args,
-		sizeof (sysctl_args) / sizeof (sysctl_args[0]),
-		buf, &reslen, NULL, 0) < 0)
-    {
-      /* This was not successful.  Now try reading the /proc filesystem.  */
-      int fd = open_not_cancel_2 ("/proc/sys/kernel/version", O_RDONLY);
-      if (__builtin_expect (fd, 0) == -1
-	  || (reslen = read_not_cancel (fd, buf, sizeof (buf))) <= 0)
-	/* This also didn't work.  We give up and say it's a UP machine.  */
-	buf[0] = '\0';
-
-      close_not_cancel_no_status (fd);
-    }
-
-  return strstr (buf, "SMP") != NULL;
+  /* Assume all machines are SMP and/or CMT and/or SMT.  */
+  return 1;
 }
diff --git a/posix/Makefile b/posix/Makefile
index a9d99102ae..3b97ff013e 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -141,7 +141,7 @@ CFLAGS-pwrite.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-pwrite64.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-sleep.c = -fexceptions
 CFLAGS-wait.c = -fexceptions -fasynchronous-unwind-tables
-CFLAGS-waitid.c = -fexceptions
+CFLAGS-waitid.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-waitpid.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-getopt.c = -fexceptions
 CFLAGS-wordexp.c = -fexceptions