[PATCH] Fix readelf -sI (or -a)

Jakub Jelinek jakub@redhat.com
Thu Jun 11 19:24:00 GMT 2009


Hi!

Recently I've noticed that while readelf -WS shows .symtab/.dynsym just
fine, for certain executables readelf -Wa doesn't print any symbol
information at all.  The problem is that if histogram is supposed to
be printed as well and readelf encounters empty .gnu.hash section (or some
errors while looking at .hash/.gnu.hash), process_symbol_table just returns
without printing any symbol information, even when not using -D (i.e. when
.hash/.gnu.hash isn't relevant to symbol table printing at all).

Fixed thusly, tested on x86_64-linux.  Ok for trunk?

2009-06-11  Jakub Jelinek  <jakub@redhat.com>

	* readelf.c (process_symbol_table): Don't return early if
	.hash/.gnu.hash is empty/unusable and not -D.

--- binutils/readelf.c.jj	2009-05-28 19:35:03.000000000 +0200
+++ binutils/readelf.c	2009-06-10 19:57:20.000000000 +0200
@@ -7152,19 +7152,19 @@ process_symbol_table (FILE * file)
 		 SEEK_SET))
 	{
 	  error (_("Unable to seek to start of dynamic information\n"));
-	  return 0;
+	  goto no_hash;
 	}
 
       if (fread (nb, hash_ent_size, 1, file) != 1)
 	{
 	  error (_("Failed to read in number of buckets\n"));
-	  return 0;
+	  goto no_hash;
 	}
 
       if (fread (nc, hash_ent_size, 1, file) != 1)
 	{
 	  error (_("Failed to read in number of chains\n"));
-	  return 0;
+	  goto no_hash;
 	}
 
       nbuckets = byte_get (nb, hash_ent_size);
@@ -7173,8 +7173,18 @@ process_symbol_table (FILE * file)
       buckets = get_dynamic_data (file, nbuckets, hash_ent_size);
       chains  = get_dynamic_data (file, nchains, hash_ent_size);
 
+    no_hash:
       if (buckets == NULL || chains == NULL)
-	return 0;
+	{
+	  if (do_using_dynamic)
+	    return 0;
+	  free (buckets);
+	  free (chains);
+	  buckets = NULL;
+	  chains = NULL;
+	  nbuckets = 0;
+	  nchains = 0;
+	}
     }
 
   if (dynamic_info_DT_GNU_HASH
@@ -7192,13 +7202,13 @@ process_symbol_table (FILE * file)
 		 SEEK_SET))
 	{
 	  error (_("Unable to seek to start of dynamic information\n"));
-	  return 0;
+	  goto no_gnu_hash;
 	}
 
       if (fread (nb, 16, 1, file) != 1)
 	{
 	  error (_("Failed to read in number of buckets\n"));
-	  return 0;
+	  goto no_gnu_hash;
 	}
 
       ngnubuckets = byte_get (nb, 4);
@@ -7216,13 +7226,13 @@ process_symbol_table (FILE * file)
 		 SEEK_SET))
 	{
 	  error (_("Unable to seek to start of dynamic information\n"));
-	  return 0;
+	  goto no_gnu_hash;
 	}
 
       gnubuckets = get_dynamic_data (file, ngnubuckets, 4);
 
       if (gnubuckets == NULL)
-	return 0;
+	goto no_gnu_hash;
 
       for (i = 0; i < ngnubuckets; i++)
 	if (gnubuckets[i] != 0)
@@ -7235,7 +7245,7 @@ process_symbol_table (FILE * file)
 	  }
 
       if (maxchain == 0xffffffff)
-	return 0;
+	goto no_gnu_hash;
 
       maxchain -= gnusymidx;
 
@@ -7246,7 +7256,7 @@ process_symbol_table (FILE * file)
 		 SEEK_SET))
 	{
 	  error (_("Unable to seek to start of dynamic information\n"));
-	  return 0;
+	  goto no_gnu_hash;
 	}
 
       do
@@ -7254,11 +7264,11 @@ process_symbol_table (FILE * file)
 	  if (fread (nb, 4, 1, file) != 1)
 	    {
 	      error (_("Failed to determine last chain length\n"));
-	      return 0;
+	      goto no_gnu_hash;
 	    }
 
 	  if (maxchain + 1 == 0)
-	    return 0;
+	    goto no_gnu_hash;
 
 	  ++maxchain;
 	}
@@ -7270,13 +7280,20 @@ process_symbol_table (FILE * file)
 		 SEEK_SET))
 	{
 	  error (_("Unable to seek to start of dynamic information\n"));
-	  return 0;
+	  goto no_gnu_hash;
 	}
 
       gnuchains = get_dynamic_data (file, maxchain, 4);
 
+    no_gnu_hash:
       if (gnuchains == NULL)
-	return 0;
+	{
+	  free (gnubuckets);
+	  if (do_using_dynamic)
+	    return 0;
+	  gnubuckets = NULL;
+	  ngnubuckets = 0;
+	}
     }
 
   if ((dynamic_info[DT_HASH] || dynamic_info_DT_GNU_HASH)
@@ -7608,7 +7625,7 @@ process_symbol_table (FILE * file)
       free (chains);
     }
 
-  if (do_histogram && dynamic_info_DT_GNU_HASH)
+  if (do_histogram && gnubuckets != NULL)
     {
       unsigned long * lengths;
       unsigned long * counts;

	Jakub



More information about the Binutils mailing list