This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PATCH: PR binutils/4476: readelf -s -D doesn't support --hash-style=gnu


On Wed, May 09, 2007 at 03:54:23PM -0700, H. J. Lu wrote:
> This patch adds -s -D support for .gnu.hash.
> 
> 

Small update to check if DT_HASH or DT_GNU_HASH exist first.


H.J.
----
binutils/

2007-05-09  H.J. Lu  <hongjiu.lu@intel.com>

	PR binutils/4476
	* readelf.c (print_dynamic_symbol): New.
	(process_symbol_table): Handle DT_GNU_HASH for dynamic symbols.

ld/testsuite/

2007-05-09  H.J. Lu  <hongjiu.lu@intel.com>

	PR binutils/4476
	* ld-elf/hash.d: Check "-s -D" for readelf.

--- binutils/binutils/readelf.c.hash	2007-05-09 10:54:22.000000000 -0700
+++ binutils/binutils/readelf.c	2007-05-09 17:24:46.000000000 -0700
@@ -7033,6 +7033,39 @@ get_dynamic_data (FILE *file, unsigned i
   return i_data;
 }
 
+static void
+print_dynamic_symbol (bfd_vma si, unsigned long hn)
+{
+  Elf_Internal_Sym *psym;
+  int n;
+
+  psym = dynamic_symbols + si;
+
+  n = print_vma (si, DEC_5);
+  if (n < 5)
+    fputs ("     " + n, stdout);
+  printf (" %3lu: ", hn);
+  print_vma (psym->st_value, LONG_HEX);
+  putchar (' ');
+  print_vma (psym->st_size, DEC_5);
+
+  printf ("  %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
+  printf (" %6s",  get_symbol_binding (ELF_ST_BIND (psym->st_info)));
+  printf (" %3s",  get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
+  /* Check to see if any other bits in the st_other field are set.
+     Note - displaying this information disrupts the layout of the
+     table being generated, but for the moment this case is very
+     rare.  */
+  if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))
+    printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)));
+  printf (" %3.3s ", get_symbol_index_type (psym->st_shndx));
+  if (VALID_DYNAMIC_NAME (psym->st_name))
+    print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
+  else
+    printf (" <corrupt: %14ld>", psym->st_name);
+  putchar ('\n');
+}
+
 /* Dump the symbol table.  */
 static int
 process_symbol_table (FILE *file)
@@ -7045,12 +7078,14 @@ process_symbol_table (FILE *file)
   bfd_vma ngnubuckets = 0;
   bfd_vma *gnubuckets = NULL;
   bfd_vma *gnuchains = NULL;
+  bfd_vma gnusymidx = 0;
 
   if (! do_syms && !do_histogram)
     return 1;
 
-  if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
-				|| do_histogram))
+  if (dynamic_info[DT_HASH]
+      && (do_histogram
+	  || (do_using_dynamic && dynamic_strings != NULL)))
     {
       unsigned char nb[8];
       unsigned char nc[8];
@@ -7094,54 +7129,157 @@ process_symbol_table (FILE *file)
 	return 0;
     }
 
-  if (do_syms
-      && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
+  if (dynamic_info_DT_GNU_HASH
+      && (do_histogram
+	  || (do_using_dynamic && dynamic_strings != NULL)))
     {
-      unsigned long hn;
-      bfd_vma si;
+      unsigned char nb[16];
+      bfd_vma i, maxchain = 0xffffffff, bitmaskwords;
+      bfd_vma buckets_vma;
+
+      if (fseek (file,
+		 (archive_file_offset
+		  + offset_from_vma (file, dynamic_info_DT_GNU_HASH,
+				     sizeof nb)),
+		 SEEK_SET))
+	{
+	  error (_("Unable to seek to start of dynamic information\n"));
+	  return 0;
+	}
+
+      if (fread (nb, 16, 1, file) != 1)
+	{
+	  error (_("Failed to read in number of buckets\n"));
+	  return 0;
+	}
 
-      printf (_("\nSymbol table for image:\n"));
+      ngnubuckets = byte_get (nb, 4);
+      gnusymidx = byte_get (nb + 4, 4);
+      bitmaskwords = byte_get (nb + 8, 4);
+      buckets_vma = dynamic_info_DT_GNU_HASH + 16;
       if (is_32bit_elf)
-	printf (_("  Num Buc:    Value  Size   Type   Bind Vis      Ndx Name\n"));
+	buckets_vma += bitmaskwords * 4;
       else
-	printf (_("  Num Buc:    Value          Size   Type   Bind Vis      Ndx Name\n"));
+	buckets_vma += bitmaskwords * 8;
 
-      for (hn = 0; hn < nbuckets; hn++)
+      if (fseek (file,
+		 (archive_file_offset
+		  + offset_from_vma (file, buckets_vma, 4)),
+		 SEEK_SET))
 	{
-	  if (! buckets[hn])
-	    continue;
+	  error (_("Unable to seek to start of dynamic information\n"));
+	  return 0;
+	}
+
+      gnubuckets = get_dynamic_data (file, ngnubuckets, 4);
+
+      if (gnubuckets == NULL)
+	return 0;
+
+      for (i = 0; i < ngnubuckets; i++)
+	if (gnubuckets[i] != 0)
+	  {
+	    if (gnubuckets[i] < gnusymidx)
+	      return 0;
+
+	    if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
+	      maxchain = gnubuckets[i];
+	  }
+
+      if (maxchain == 0xffffffff)
+	return 0;
 
-	  for (si = buckets[hn]; si < nchains && si > 0; si = chains[si])
+      maxchain -= gnusymidx;
+
+      if (fseek (file,
+		 (archive_file_offset
+		  + offset_from_vma (file, buckets_vma
+					   + 4 * (ngnubuckets + maxchain), 4)),
+		 SEEK_SET))
+	{
+	  error (_("Unable to seek to start of dynamic information\n"));
+	  return 0;
+	}
+
+      do
+	{
+	  if (fread (nb, 4, 1, file) != 1)
 	    {
-	      Elf_Internal_Sym *psym;
-	      int n;
+	      error (_("Failed to determine last chain length\n"));
+	      return 0;
+	    }
 
-	      psym = dynamic_symbols + si;
+	  if (maxchain + 1 == 0)
+	    return 0;
 
-	      n = print_vma (si, DEC_5);
-	      if (n < 5)
-		fputs ("     " + n, stdout);
-	      printf (" %3lu: ", hn);
-	      print_vma (psym->st_value, LONG_HEX);
-	      putchar (' ');
-	      print_vma (psym->st_size, DEC_5);
+	  ++maxchain;
+	}
+      while ((byte_get (nb, 4) & 1) == 0);
 
-	      printf ("  %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
-	      printf (" %6s",  get_symbol_binding (ELF_ST_BIND (psym->st_info)));
-	      printf (" %3s",  get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
-	      /* Check to see if any other bits in the st_other field are set.
-	         Note - displaying this information disrupts the layout of the
-	         table being generated, but for the moment this case is very rare.  */
-	      if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))
-		printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)));
-	      printf (" %3.3s ", get_symbol_index_type (psym->st_shndx));
-	      if (VALID_DYNAMIC_NAME (psym->st_name))
-		print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
-	      else
-		printf (" <corrupt: %14ld>", psym->st_name);
-	      putchar ('\n');
+      if (fseek (file,
+		 (archive_file_offset
+		  + offset_from_vma (file, buckets_vma + 4 * ngnubuckets, 4)),
+		 SEEK_SET))
+	{
+	  error (_("Unable to seek to start of dynamic information\n"));
+	  return 0;
+	}
+
+      gnuchains = get_dynamic_data (file, maxchain, 4);
+
+      if (gnuchains == NULL)
+	return 0;
+    }
+
+  if ((dynamic_info[DT_HASH] || dynamic_info_DT_GNU_HASH)
+      && do_syms
+      && do_using_dynamic
+      && dynamic_strings != NULL)
+    {
+      unsigned long hn;
+
+      if (dynamic_info[DT_HASH])
+	{
+	  bfd_vma si;
+
+	  printf (_("\nSymbol table for image:\n"));
+	  if (is_32bit_elf)
+	    printf (_("  Num Buc:    Value  Size   Type   Bind Vis      Ndx Name\n"));
+	  else
+	    printf (_("  Num Buc:    Value          Size   Type   Bind Vis      Ndx Name\n"));
+
+	  for (hn = 0; hn < nbuckets; hn++)
+	    {
+	      if (! buckets[hn])
+		continue;
+
+	      for (si = buckets[hn]; si < nchains && si > 0; si = chains[si])
+		print_dynamic_symbol (si, hn);
 	    }
 	}
+
+      if (dynamic_info_DT_GNU_HASH)
+	{
+	  printf (_("\nSymbol table of `.gnu.hash' for image:\n"));
+	  if (is_32bit_elf)
+	    printf (_("  Num Buc:    Value  Size   Type   Bind Vis      Ndx Name\n"));
+	  else
+	    printf (_("  Num Buc:    Value          Size   Type   Bind Vis      Ndx Name\n"));
+
+	  for (hn = 0; hn < ngnubuckets; ++hn)
+	    if (gnubuckets[hn] != 0)
+	      {
+		bfd_vma si = gnubuckets[hn];
+		bfd_vma off = si - gnusymidx;
+
+		do
+		  {
+		    print_dynamic_symbol (si, hn);
+		    si++;
+		  }
+		while ((gnuchains[off++] & 1) == 0);
+	      }
+	}
     }
   else if (do_syms && !do_using_dynamic)
     {
@@ -7426,108 +7564,12 @@ process_symbol_table (FILE *file)
 
   if (do_histogram && dynamic_info_DT_GNU_HASH)
     {
-      unsigned char nb[16];
-      bfd_vma i, maxchain = 0xffffffff, symidx, bitmaskwords;
       unsigned long *lengths;
       unsigned long *counts;
       unsigned long hn;
       unsigned long maxlength = 0;
       unsigned long nzero_counts = 0;
       unsigned long nsyms = 0;
-      bfd_vma buckets_vma;
-
-      if (fseek (file,
-		 (archive_file_offset
-		  + offset_from_vma (file, dynamic_info_DT_GNU_HASH,
-				     sizeof nb)),
-		 SEEK_SET))
-	{
-	  error (_("Unable to seek to start of dynamic information\n"));
-	  return 0;
-	}
-
-      if (fread (nb, 16, 1, file) != 1)
-	{
-	  error (_("Failed to read in number of buckets\n"));
-	  return 0;
-	}
-
-      ngnubuckets = byte_get (nb, 4);
-      symidx = byte_get (nb + 4, 4);
-      bitmaskwords = byte_get (nb + 8, 4);
-      buckets_vma = dynamic_info_DT_GNU_HASH + 16;
-      if (is_32bit_elf)
-	buckets_vma += bitmaskwords * 4;
-      else
-	buckets_vma += bitmaskwords * 8;
-
-      if (fseek (file,
-		 (archive_file_offset
-		  + offset_from_vma (file, buckets_vma, 4)),
-		 SEEK_SET))
-	{
-	  error (_("Unable to seek to start of dynamic information\n"));
-	  return 0;
-	}
-
-      gnubuckets = get_dynamic_data (file, ngnubuckets, 4);
-
-      if (gnubuckets == NULL)
-	return 0;
-
-      for (i = 0; i < ngnubuckets; i++)
-	if (gnubuckets[i] != 0)
-	  {
-	    if (gnubuckets[i] < symidx)
-	      return 0;
-
-	    if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
-	      maxchain = gnubuckets[i];
-	  }
-
-      if (maxchain == 0xffffffff)
-	return 0;
-
-      maxchain -= symidx;
-
-      if (fseek (file,
-		 (archive_file_offset
-		  + offset_from_vma (file, buckets_vma
-					   + 4 * (ngnubuckets + maxchain), 4)),
-		 SEEK_SET))
-	{
-	  error (_("Unable to seek to start of dynamic information\n"));
-	  return 0;
-	}
-
-      do
-	{
-	  if (fread (nb, 4, 1, file) != 1)
-	    {
-	      error (_("Failed to determine last chain length\n"));
-	      return 0;
-	    }
-
-	  if (maxchain + 1 == 0)
-	    return 0;
-
-	  ++maxchain;
-	}
-      while ((byte_get (nb, 4) & 1) == 0);
-
-      if (fseek (file,
-		 (archive_file_offset
-		  + offset_from_vma (file, buckets_vma + 4 * ngnubuckets, 4)),
-		 SEEK_SET))
-	{
-	  error (_("Unable to seek to start of dynamic information\n"));
-	  return 0;
-	}
-
-      gnuchains = get_dynamic_data (file, maxchain, 4);
-
-      if (gnuchains == NULL)
-	return 0;
 
       lengths = calloc (ngnubuckets, sizeof (*lengths));
       if (lengths == NULL)
@@ -7545,7 +7587,7 @@ process_symbol_table (FILE *file)
 	  {
 	    bfd_vma off, length = 1;
 
-	    for (off = gnubuckets[hn] - symidx;
+	    for (off = gnubuckets[hn] - gnusymidx;
 		 (gnuchains[off] & 1) == 0; ++off)
 	      ++length;
 	    lengths[hn] = length;
--- binutils/ld/testsuite/ld-elf/hash.d.hash	2006-09-15 07:55:42.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/hash.d	2007-05-09 15:46:56.000000000 -0700
@@ -1,5 +1,5 @@
 #source: start.s
-#readelf: -d 
+#readelf: -d -s -D
 #ld: -shared --hash-style=gnu
 #target: *-*-linux*
 #notarget: mips*-*-*
@@ -7,3 +7,11 @@
 #...
 [ 	]*0x[0-9a-z]+[ 	]+\(GNU_HASH\)[ 	]+0x[0-9a-z]+
 #...
+[ 	]+[0-9]+[ 	]+[0-9]+:[ 	]+[0-9a-f]+[ 	]+[0-9]+[ 	]+NOTYPE[	 ]+GLOBAL DEFAULT[ 	]+[1-9] _start
+#...
+[ 	]+[0-9]+[ 	]+[0-9]+:[ 	]+[0-9a-f]+[ 	]+[0-9]+[ 	]+NOTYPE[	 ]+GLOBAL DEFAULT[ 	]+[1-9] main
+#...
+[ 	]+[0-9]+[ 	]+[0-9]+:[ 	]+[0-9a-f]+[ 	]+[0-9]+[ 	]+NOTYPE[	 ]+GLOBAL DEFAULT[ 	]+[1-9] start
+#...
+[ 	]+[0-9]+[ 	]+[0-9]+:[ 	]+[0-9a-f]+[ 	]+[0-9]+[ 	]+NOTYPE[	 ]+GLOBAL DEFAULT[ 	]+[1-9] __start
+#...


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]