* 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.
This commit is contained in:
Ulrich Drepper
1998-09-02 21:55:37 +00:00
parent a6ac3b6bb5
commit e5a32b1725
2 changed files with 95 additions and 19 deletions

View 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> 1998-08-25 16:45 Ulrich Drepper <drepper@cygnus.com>
* readelf.c (process_dynamic_segment): Read syminfo section if * readelf.c (process_dynamic_segment): Read syminfo section if

View File

@ -93,6 +93,7 @@ int do_using_dynamic;
int do_header; int do_header;
int do_dump; int do_dump;
int do_version; int do_version;
int do_histogram;
static unsigned long int (* byte_get) PARAMS ((unsigned char *, int)); static unsigned long int (* byte_get) PARAMS ((unsigned char *, int));
@ -1017,6 +1018,7 @@ struct option options [] =
{"file-header", no_argument, 0, 'h'}, {"file-header", no_argument, 0, 'h'},
{"program-headers", no_argument, 0, 'l'}, {"program-headers", no_argument, 0, 'l'},
{"headers", no_argument, 0, 'e'}, {"headers", no_argument, 0, 'e'},
{"histogram", no_argument, &do_histogram, 1},
{"segments", no_argument, 0, 'l'}, {"segments", no_argument, 0, 'l'},
{"sections", no_argument, 0, 'S'}, {"sections", no_argument, 0, 'S'},
{"section-headers", 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, _("Usage: readelf {options} elf-file(s)\n"));
fprintf (stdout, _(" Options are:\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, _(" -h or --file-header Display the ELF file header\n"));
fprintf (stdout, _(" -l or --program-headers or --segments\n")); fprintf (stdout, _(" -l or --program-headers or --segments\n"));
fprintf (stdout, _(" Display the program headers\n")); fprintf (stdout, _(" Display the program headers\n"));
@ -1060,6 +1062,7 @@ usage ()
fprintf (stdout, _(" -i <number> or --instruction-dump=<number>\n")); fprintf (stdout, _(" -i <number> or --instruction-dump=<number>\n"));
fprintf (stdout, _(" Disassemble the contents of section <number>\n")); fprintf (stdout, _(" Disassemble the contents of section <number>\n"));
#endif #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, _(" -v or --version Display the version number of readelf\n"));
fprintf (stdout, _(" -H or --help Display this information\n")); fprintf (stdout, _(" -H or --help Display this information\n"));
fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n")); fprintf (stdout, _("Report bugs to bug-gnu-utils@gnu.org\n"));
@ -1085,6 +1088,9 @@ parse_args (argc, argv)
switch (c) switch (c)
{ {
case 0:
/* Long options. */
break;
case 'H': case 'H':
usage (); usage ();
break; break;
@ -1097,6 +1103,7 @@ parse_args (argc, argv)
do_sections ++; do_sections ++;
do_segments ++; do_segments ++;
do_version ++; do_version ++;
do_histogram ++;
break; break;
case 'e': case 'e':
do_header ++; do_header ++;
@ -1161,7 +1168,8 @@ parse_args (argc, argv)
} }
if (!do_dynamic && !do_syms && !do_reloc && !do_sections 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 (); usage ();
else if (argc < 3) else if (argc < 3)
{ {
@ -2091,7 +2099,8 @@ process_dynamic_segment (file)
case DT_VERNEEDNUM: case DT_VERNEEDNUM:
case DT_RELACOUNT: case DT_RELACOUNT:
case DT_RELCOUNT: case DT_RELCOUNT:
printf ("%ld\n", entry->d_un.d_val); if (do_dynamic)
printf ("%ld\n", entry->d_un.d_val);
break; break;
case DT_SYMINSZ : case DT_SYMINSZ :
@ -2766,21 +2775,19 @@ process_symbol_table (file)
FILE * file; FILE * file;
{ {
Elf32_Internal_Shdr * section; Elf32_Internal_Shdr * section;
char nb [4];
char nc [4];
int nbuckets;
int nchains;
int * buckets = NULL;
int * chains = NULL;
if (! do_syms) if (! do_syms && !do_histogram)
return 1; 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)) if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET))
{ {
error (_("Unable to seek to start of dynamic information")); error (_("Unable to seek to start of dynamic information"));
@ -2807,6 +2814,13 @@ process_symbol_table (file)
if (buckets == NULL || chains == NULL) if (buckets == NULL || chains == NULL)
return 0; 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 (_("\nSymbol table for image:\n"));
printf (_(" Num Buc: Value Size Type Bind Ot Ndx Name\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); 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; unsigned int i;
@ -3036,10 +3047,62 @@ process_symbol_table (file)
free (strtab); free (strtab);
} }
} }
else else if (do_syms)
printf printf
(_("\nDynamic symbol information is not available for displaying symbols.\n")); (_("\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; return 1;
} }