* elf/readelf.c (process_dynamic_segment): Print DT_* value only if
authorUlrich Drepper <drepper@redhat.com>
Wed, 2 Sep 1998 21:55:37 +0000 (21:55 +0000)
committerUlrich Drepper <drepper@redhat.com>
Wed, 2 Sep 1998 21:55:37 +0000 (21:55 +0000)
do_dynamic.
(do_histogram): New variable.
(options): New long option histogram.  Set do_histogram if this
option is used.
(usage): Document --histogram.
(parse_args): Handle 0 return value from getopt_long.  Enable
do_histogram for -a.
(process_symbol_table): Read hash table also if only do_histogram.
Add code to print hash table histogram.

binutils/ChangeLog
binutils/readelf.c

index 17f5856..80aa314 100644 (file)
@@ -1,3 +1,16 @@
+1998-09-02 14:50  Ulrich Drepper  <drepper@cygnus.com>
+
+       * elf/readelf.c (process_dynamic_segment): Print DT_* value only if
+       do_dynamic.
+       (do_histogram): New variable.
+       (options): New long option histogram.  Set do_histogram if this
+       option is used.
+       (usage): Document --histogram.
+       (parse_args): Handle 0 return value from getopt_long.  Enable
+       do_histogram for -a.
+       (process_symbol_table): Read hash table also if only do_histogram.
+       Add code to print hash table histogram.
+
 1998-08-25 16:45  Ulrich Drepper  <drepper@cygnus.com>
 
        * readelf.c (process_dynamic_segment): Read syminfo section if
index e5263e7..698cdb4 100644 (file)
@@ -93,6 +93,7 @@ int                   do_using_dynamic;
 int                    do_header;
 int                    do_dump;
 int                    do_version;
+int                    do_histogram;
 
 static unsigned long int (* byte_get) PARAMS ((unsigned char *, int));
 
@@ -1017,6 +1018,7 @@ struct option options [] =
   {"file-header", no_argument, 0, 'h'},
   {"program-headers", no_argument, 0, 'l'},
   {"headers", no_argument, 0, 'e'},
+  {"histogram", no_argument, &do_histogram, 1},
   {"segments", no_argument, 0, 'l'},
   {"sections", no_argument, 0, 'S'},
   {"section-headers", no_argument, 0, 'S'},
@@ -1042,7 +1044,7 @@ usage ()
 {
   fprintf (stdout, _("Usage: readelf {options} elf-file(s)\n"));
   fprintf (stdout, _("  Options are:\n"));
-  fprintf (stdout, _("  -a or --all               Equivalent to: -h -l -S -s -r -d -V\n"));
+  fprintf (stdout, _("  -a or --all               Equivalent to: -h -l -S -s -r -d -V --histogram\n"));
   fprintf (stdout, _("  -h or --file-header       Display the ELF file header\n"));
   fprintf (stdout, _("  -l or --program-headers or --segments\n"));
   fprintf (stdout, _("                            Display the program headers\n"));
@@ -1060,6 +1062,7 @@ usage ()
   fprintf (stdout, _("  -i <number> or --instruction-dump=<number>\n"));
   fprintf (stdout, _("                            Disassemble the contents of section <number>\n"));
 #endif
+  fprintf (stdout, _("        --histogram         Display histogram of bucket list lengths\n"));
   fprintf (stdout, _("  -v or --version           Display the version number of readelf\n"));
   fprintf (stdout, _("  -H or --help              Display this information\n"));
   fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n"));
@@ -1085,6 +1088,9 @@ parse_args (argc, argv)
 
       switch (c)
        {
+       case 0:
+         /* Long options.  */
+         break;
        case 'H':
          usage ();
          break;
@@ -1097,6 +1103,7 @@ parse_args (argc, argv)
          do_sections ++;
          do_segments ++;
          do_version ++;
+         do_histogram ++;
          break;
        case 'e':
          do_header ++;
@@ -1161,7 +1168,8 @@ parse_args (argc, argv)
     }
 
   if (!do_dynamic && !do_syms && !do_reloc && !do_sections
-      && !do_segments && !do_header && !do_dump && !do_version)
+      && !do_segments && !do_header && !do_dump && !do_version
+      && !do_histogram)
     usage ();
   else if (argc < 3)
     {
@@ -2091,7 +2099,8 @@ process_dynamic_segment (file)
        case DT_VERNEEDNUM:
        case DT_RELACOUNT:
        case DT_RELCOUNT:
-         printf ("%ld\n", entry->d_un.d_val);
+         if (do_dynamic)
+           printf ("%ld\n", entry->d_un.d_val);
          break;
 
        case DT_SYMINSZ :
@@ -2766,21 +2775,19 @@ process_symbol_table (file)
      FILE * file;
 {
   Elf32_Internal_Shdr *   section;
-
-  if (! do_syms)
+  char   nb [4];
+  char   nc [4];
+  int    nbuckets;
+  int    nchains;
+  int *  buckets = NULL;
+  int *  chains = NULL;
+
+  if (! do_syms && !do_histogram)
     return 1;
 
-  if (dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
+  if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
+                               || do_histogram))
     {
-      char   nb [4];
-      char   nc [4];
-      int    nbuckets;
-      int    nchains;
-      int *  buckets;
-      int *  chains;
-      int    hn;
-      int    si;
-
       if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET))
        {
          error (_("Unable to seek to start of dynamic information"));
@@ -2807,6 +2814,13 @@ process_symbol_table (file)
 
       if (buckets == NULL || chains == NULL)
        return 0;
+    }
+
+  if (do_syms
+      && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
+    {
+      int    hn;
+      int    si;
 
       printf (_("\nSymbol table for image:\n"));
       printf (_("  Num Buc:    Value  Size   Type   Bind Ot Ndx Name\n"));
@@ -2835,11 +2849,8 @@ process_symbol_table (file)
              printf (" %s\n", dynamic_strings + psym->st_name);
            }
        }
-
-      free (buckets);
-      free (chains);
     }
-  else if (!do_using_dynamic)
+  else if (do_syms && !do_using_dynamic)
     {
       unsigned int     i;
 
@@ -3036,10 +3047,62 @@ process_symbol_table (file)
            free (strtab);
        }
     }
-  else
+  else if (do_syms)
     printf
       (_("\nDynamic symbol information is not available for displaying symbols.\n"));
 
+  if (do_histogram)
+    {
+      int *lengths;
+      int *counts;
+      int hn;
+      int si;
+      int maxlength = 0;
+
+      printf (_("\nHistogram for bucket list length (total of %d buckets):\n"),
+             nbuckets);
+      printf (_(" Length  Number\n"));
+
+      lengths = (int *) calloc (nbuckets, sizeof (int));
+      if (lengths == NULL)
+       {
+         error (_("Out of memory"));
+         return 0;
+       }
+      for (hn = 0; hn < nbuckets; ++hn)
+       {
+         if (! buckets [hn])
+           continue;
+
+         for (si = buckets[hn]; si; si = chains[si])
+           if (maxlength < ++lengths[hn])
+             maxlength = lengths[hn];
+       }
+
+      counts = (int *) calloc (maxlength + 1, sizeof (int));
+      if (counts == NULL)
+       {
+         error (_("Out of memory"));
+         return 0;
+       }
+
+      for (hn = 0; hn < nbuckets; ++hn)
+       ++counts[lengths[hn]];
+
+      for (si = 0; si <= maxlength; ++si)
+       printf ("%7d  %-10d (%5.1f%%)\n",
+               si, counts[si], (counts[si] * 100.0) / nbuckets);
+
+      free (counts);
+      free (lengths);
+    }
+
+  if (buckets != NULL)
+    {
+      free (buckets);
+      free (chains);
+    }
+
   return 1;
 }