aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binutils/ChangeLog13
-rw-r--r--binutils/readelf.c103
2 files changed, 96 insertions, 20 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 17f5856..80aa314 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -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
diff --git a/binutils/readelf.c b/binutils/readelf.c
index e5263e7..698cdb4 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -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;
}