diff options
-rw-r--r-- | binutils/ChangeLog | 13 | ||||
-rw-r--r-- | binutils/readelf.c | 103 |
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; } |