* readelf.c (BYTE_GET8): Delete. Replace uses with BYTE_GET.

(byte_get_little_endian): Don't handle size of -8.
	(byte_get_signed, byte_get_big_endian): Likewise.
	(print_dec_vma, print_hex_vma): New functions.
	(print_vma): Use them.  Return chars output.
	(get_dynamic_data): Return a bfd_vma array.  Add ent_size parm.
	(process_symbol_table): Handle alpha and s390 .hash.
This commit is contained in:
Alan Modra 2005-02-21 02:55:56 +00:00
parent 942fd9fe45
commit 665435215e
2 changed files with 179 additions and 154 deletions

View File

@ -1,3 +1,13 @@
2005-02-21 Alan Modra <amodra@bigpond.net.au>
* readelf.c (BYTE_GET8): Delete. Replace uses with BYTE_GET.
(byte_get_little_endian): Don't handle size of -8.
(byte_get_signed, byte_get_big_endian): Likewise.
(print_dec_vma, print_hex_vma): New functions.
(print_vma): Use them. Return chars output.
(get_dynamic_data): Return a bfd_vma array. Add ent_size parm.
(process_symbol_table): Handle alpha and s390 .hash.
2005-02-18 H.J. Lu <hongjiu.lu@intel.com>
* readelf.c (display_debug_loc): Print out offset for end of

View File

@ -248,20 +248,6 @@ static void (*byte_put) (unsigned char *, bfd_vma, int);
#define BYTE_GET(field) byte_get (field, sizeof (field))
/* If we can support a 64 bit data type then BFD64 should be defined
and sizeof (bfd_vma) == 8. In this case when translating from an
external 8 byte field to an internal field, we can assume that the
internal field is also 8 bytes wide and so we can extract all the data.
If, however, BFD64 is not defined, then we must assume that the
internal data structure only has 4 byte wide fields that are the
equivalent of the 8 byte wide external counterparts, and so we must
truncate the data. */
#ifdef BFD64
#define BYTE_GET8(field) byte_get (field, -8)
#else
#define BYTE_GET8(field) byte_get (field, 8)
#endif
#define NUM_ELEM(array) (sizeof (array) / sizeof ((array)[0]))
#define GET_ELF_SYMBOLS(file, section) \
@ -365,11 +351,6 @@ byte_get_little_endian (unsigned char *field, int size)
#ifdef BFD64
case 8:
case -8:
/* This is a special case, generated by the BYTE_GET8 macro.
It means that we are loading an 8 byte value from a field
in an external structure into an 8 byte value in a field
in an internal structure. */
return ((bfd_vma) (field[0]))
| (((bfd_vma) (field[1])) << 8)
| (((bfd_vma) (field[2])) << 16)
@ -399,7 +380,6 @@ byte_get_signed (unsigned char *field, int size)
case 4:
return (x ^ 0x80000000) - 0x80000000;
case 8:
case -8:
return x;
default:
abort ();
@ -434,8 +414,60 @@ byte_put_little_endian (unsigned char *field, bfd_vma value, int size)
}
}
#if defined BFD64 && !BFD_HOST_64BIT_LONG
static int
print_dec_vma (bfd_vma vma, int is_signed)
{
char buf[40];
char *bufp = buf;
int nc = 0;
if (is_signed && (bfd_signed_vma) vma < 0)
{
vma = -vma;
putchar ('-');
nc = 1;
}
do
{
*bufp++ = '0' + vma % 10;
vma /= 10;
}
while (vma != 0);
nc += bufp - buf;
while (bufp > buf)
putchar (*--bufp);
return nc;
}
static int
print_hex_vma (bfd_vma vma)
{
char buf[32];
char *bufp = buf;
int nc;
do
{
char digit = '0' + (vma & 0x0f);
if (digit > '9')
digit += 'a' - '0' - 10;
*bufp++ = digit;
vma >>= 4;
}
while (vma != 0);
nc = bufp - buf;
while (bufp > buf)
putchar (*--bufp);
return nc;
}
#endif
/* Print a VMA value. */
static void
static int
print_vma (bfd_vma vma, print_mode mode)
{
#ifdef BFD64
@ -445,106 +477,85 @@ print_vma (bfd_vma vma, print_mode mode)
switch (mode)
{
case FULL_HEX:
printf ("0x");
/* Drop through. */
return printf ("0x%8.8lx", (unsigned long) vma);
case LONG_HEX:
printf ("%8.8lx", (unsigned long) vma);
break;
return printf ("%8.8lx", (unsigned long) vma);
case DEC_5:
if (vma <= 99999)
{
printf ("%5ld", (long) vma);
break;
}
return printf ("%5ld", (long) vma);
/* Drop through. */
case PREFIX_HEX:
printf ("0x");
/* Drop through. */
return printf ("0x%lx", (unsigned long) vma);
case HEX:
printf ("%lx", (unsigned long) vma);
break;
return printf ("%lx", (unsigned long) vma);
case DEC:
printf ("%ld", (unsigned long) vma);
break;
return printf ("%ld", (unsigned long) vma);
case UNSIGNED:
printf ("%lu", (unsigned long) vma);
break;
return printf ("%lu", (unsigned long) vma);
}
}
#ifdef BFD64
else
{
int nc = 0;
switch (mode)
{
case FULL_HEX:
printf ("0x");
nc = printf ("0x");
/* Drop through. */
case LONG_HEX:
printf_vma (vma);
break;
return nc + 16;
case PREFIX_HEX:
printf ("0x");
nc = printf ("0x");
/* Drop through. */
case HEX:
#if BFD_HOST_64BIT_LONG
printf ("%lx", vma);
return nc + printf ("%lx", vma);
#else
if (_bfd_int64_high (vma))
printf ("%lx%8.8lx", _bfd_int64_high (vma), _bfd_int64_low (vma));
else
printf ("%lx", _bfd_int64_low (vma));
return nc + print_hex_vma (vma);
#endif
break;
case DEC:
#if BFD_HOST_64BIT_LONG
printf ("%ld", vma);
return printf ("%ld", vma);
#else
if (_bfd_int64_high (vma))
/* ugg */
printf ("++%ld", _bfd_int64_low (vma));
else
printf ("%ld", _bfd_int64_low (vma));
return print_dec_vma (vma, 1);
#endif
break;
case DEC_5:
#if BFD_HOST_64BIT_LONG
if (vma <= 99999)
printf ("%5ld", vma);
return printf ("%5ld", vma);
else
printf ("%#lx", vma);
return printf ("%#lx", vma);
#else
if (_bfd_int64_high (vma))
/* ugg */
printf ("++%ld", _bfd_int64_low (vma));
else if (vma <= 99999)
printf ("%5ld", _bfd_int64_low (vma));
if (vma <= 99999)
return printf ("%5ld", _bfd_int64_low (vma));
else
printf ("%#lx", _bfd_int64_low (vma));
return print_hex_vma (vma);
#endif
break;
case UNSIGNED:
#if BFD_HOST_64BIT_LONG
printf ("%lu", vma);
return printf ("%lu", vma);
#else
if (_bfd_int64_high (vma))
/* ugg */
printf ("++%lu", _bfd_int64_low (vma));
else
printf ("%lu", _bfd_int64_low (vma));
return print_dec_vma (vma, 0);
#endif
break;
}
}
#endif
return 0;
}
/* Display a symbol on stdout. If do_wide is not true then
@ -575,27 +586,21 @@ byte_get_big_endian (unsigned char *field, int size)
case 2:
return ((unsigned int) (field[1])) | (((int) (field[0])) << 8);
#ifndef BFD64
case 8:
/* Although we are extracing data from an 8 byte wide field,
we are returning only 4 bytes of data. */
field += 4;
/* Fall thru */
#endif
case 4:
return ((unsigned long) (field[3]))
| (((unsigned long) (field[2])) << 8)
| (((unsigned long) (field[1])) << 16)
| (((unsigned long) (field[0])) << 24);
#ifndef BFD64
#ifdef BFD64
case 8:
/* Although we are extracing data from an 8 byte wide field,
we are returning only 4 bytes of data. */
return ((unsigned long) (field[7]))
| (((unsigned long) (field[6])) << 8)
| (((unsigned long) (field[5])) << 16)
| (((unsigned long) (field[4])) << 24);
#else
case 8:
case -8:
/* This is a special case, generated by the BYTE_GET8 macro.
It means that we are loading an 8 byte value from a field
in an external structure into an 8 byte value in a field
in an internal structure. */
return ((bfd_vma) (field[7]))
| (((bfd_vma) (field[6])) << 8)
| (((bfd_vma) (field[5])) << 16)
@ -807,9 +812,9 @@ slurp_rela_relocs (FILE *file,
for (i = 0; i < nrelas; i++)
{
relas[i].r_offset = BYTE_GET8 (erelas[i].r_offset);
relas[i].r_info = BYTE_GET8 (erelas[i].r_info);
relas[i].r_addend = BYTE_GET8 (erelas[i].r_addend);
relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
relas[i].r_info = BYTE_GET (erelas[i].r_info);
relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
}
free (erelas);
@ -877,8 +882,8 @@ slurp_rel_relocs (FILE *file,
for (i = 0; i < nrels; i++)
{
rels[i].r_offset = BYTE_GET8 (erels[i].r_offset);
rels[i].r_info = BYTE_GET8 (erels[i].r_info);
rels[i].r_offset = BYTE_GET (erels[i].r_offset);
rels[i].r_info = BYTE_GET (erels[i].r_info);
rels[i].r_addend = 0;
}
@ -3108,12 +3113,12 @@ get_64bit_program_headers (FILE *file, Elf_Internal_Phdr *program_headers)
{
internal->p_type = BYTE_GET (external->p_type);
internal->p_flags = BYTE_GET (external->p_flags);
internal->p_offset = BYTE_GET8 (external->p_offset);
internal->p_vaddr = BYTE_GET8 (external->p_vaddr);
internal->p_paddr = BYTE_GET8 (external->p_paddr);
internal->p_filesz = BYTE_GET8 (external->p_filesz);
internal->p_memsz = BYTE_GET8 (external->p_memsz);
internal->p_align = BYTE_GET8 (external->p_align);
internal->p_offset = BYTE_GET (external->p_offset);
internal->p_vaddr = BYTE_GET (external->p_vaddr);
internal->p_paddr = BYTE_GET (external->p_paddr);
internal->p_filesz = BYTE_GET (external->p_filesz);
internal->p_memsz = BYTE_GET (external->p_memsz);
internal->p_align = BYTE_GET (external->p_align);
}
free (phdrs);
@ -3488,10 +3493,10 @@ get_64bit_section_headers (FILE *file, unsigned int num)
{
internal->sh_name = BYTE_GET (shdrs[i].sh_name);
internal->sh_type = BYTE_GET (shdrs[i].sh_type);
internal->sh_flags = BYTE_GET8 (shdrs[i].sh_flags);
internal->sh_addr = BYTE_GET8 (shdrs[i].sh_addr);
internal->sh_size = BYTE_GET8 (shdrs[i].sh_size);
internal->sh_entsize = BYTE_GET8 (shdrs[i].sh_entsize);
internal->sh_flags = BYTE_GET (shdrs[i].sh_flags);
internal->sh_addr = BYTE_GET (shdrs[i].sh_addr);
internal->sh_size = BYTE_GET (shdrs[i].sh_size);
internal->sh_entsize = BYTE_GET (shdrs[i].sh_entsize);
internal->sh_link = BYTE_GET (shdrs[i].sh_link);
internal->sh_info = BYTE_GET (shdrs[i].sh_info);
internal->sh_offset = BYTE_GET (shdrs[i].sh_offset);
@ -3618,8 +3623,8 @@ get_64bit_elf_symbols (FILE *file, Elf_Internal_Shdr *section)
if (psym->st_shndx == SHN_XINDEX && shndx != NULL)
psym->st_shndx
= byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j]));
psym->st_value = BYTE_GET8 (esyms[j].st_value);
psym->st_size = BYTE_GET8 (esyms[j].st_size);
psym->st_value = BYTE_GET (esyms[j].st_value);
psym->st_size = BYTE_GET (esyms[j].st_size);
}
if (shndx)
@ -4410,7 +4415,7 @@ dump_ia64_unwind (struct ia64_unw_aux_info *aux)
(unsigned long) (tp->info.offset - aux->seg_base));
head = aux->info + (tp->info.offset - aux->info_addr);
stamp = BYTE_GET8 ((unsigned char *) head);
stamp = BYTE_GET ((unsigned char *) head);
printf (" v%u, flags=0x%lx (%s%s), len=%lu bytes\n",
(unsigned) UNW_VER (stamp),
@ -4490,9 +4495,9 @@ slurp_ia64_unwind_table (FILE *file,
}
else
{
tep->start.offset = BYTE_GET8 ((unsigned char *) tp + 0);
tep->end.offset = BYTE_GET8 ((unsigned char *) tp + 8);
tep->info.offset = BYTE_GET8 ((unsigned char *) tp + 16);
tep->start.offset = BYTE_GET ((unsigned char *) tp + 0);
tep->end.offset = BYTE_GET ((unsigned char *) tp + 8);
tep->info.offset = BYTE_GET ((unsigned char *) tp + 16);
}
tep->start.offset += aux->seg_base;
tep->end.offset += aux->seg_base;
@ -4875,8 +4880,8 @@ slurp_hppa_unwind_table (FILE *file,
}
else
{
tep->start.offset = BYTE_GET8 ((unsigned char *) tp + 0);
tep->end.offset = BYTE_GET8 ((unsigned char *) tp + 8);
tep->start.offset = BYTE_GET ((unsigned char *) tp + 0);
tep->end.offset = BYTE_GET ((unsigned char *) tp + 8);
tmp1 = byte_get ((unsigned char *) tp + 16, 4);
tmp2 = byte_get ((unsigned char *) tp + 20, 4);
}
@ -5273,7 +5278,7 @@ get_64bit_dynamic_section (FILE *file)
ext++)
{
dynamic_nent++;
if (BYTE_GET8 (ext->d_tag) == DT_NULL)
if (BYTE_GET (ext->d_tag) == DT_NULL)
break;
}
@ -5289,8 +5294,8 @@ get_64bit_dynamic_section (FILE *file)
entry < dynamic_section + dynamic_nent;
ext++, entry++)
{
entry->d_tag = BYTE_GET8 (ext->d_tag);
entry->d_un.d_val = BYTE_GET8 (ext->d_un.d_val);
entry->d_tag = BYTE_GET (ext->d_tag);
entry->d_un.d_val = BYTE_GET (ext->d_un.d_val);
}
free (edyn);
@ -6430,13 +6435,13 @@ get_symbol_index_type (unsigned int type)
return buff;
}
static int *
get_dynamic_data (FILE *file, unsigned int number)
static bfd_vma *
get_dynamic_data (FILE *file, unsigned int number, unsigned int ent_size)
{
unsigned char *e_data;
int *i_data;
bfd_vma *i_data;
e_data = malloc (number * 4);
e_data = malloc (number * ent_size);
if (e_data == NULL)
{
@ -6444,7 +6449,7 @@ get_dynamic_data (FILE *file, unsigned int number)
return NULL;
}
if (fread (e_data, 4, number, file) != number)
if (fread (e_data, ent_size, number, file) != number)
{
error (_("Unable to read in dynamic data\n"));
return NULL;
@ -6460,7 +6465,7 @@ get_dynamic_data (FILE *file, unsigned int number)
}
while (number--)
i_data[number] = byte_get (e_data + number * 4, 4);
i_data[number] = byte_get (e_data + number * ent_size, ent_size);
free (e_data);
@ -6472,12 +6477,10 @@ static int
process_symbol_table (FILE *file)
{
Elf_Internal_Shdr *section;
unsigned char nb[4];
unsigned char nc[4];
int nbuckets = 0;
int nchains = 0;
int *buckets = NULL;
int *chains = NULL;
bfd_vma nbuckets = 0;
bfd_vma nchains = 0;
bfd_vma *buckets = NULL;
bfd_vma *chains = NULL;
if (! do_syms && !do_histogram)
return 1;
@ -6485,6 +6488,16 @@ process_symbol_table (FILE *file)
if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
|| do_histogram))
{
unsigned char nb[8];
unsigned char nc[8];
int hash_ent_size = 4;
if ((elf_header.e_machine == EM_ALPHA
|| elf_header.e_machine == EM_S390
|| elf_header.e_machine == EM_S390_OLD)
&& elf_header.e_ident[EI_CLASS] == ELFCLASS64)
hash_ent_size = 8;
if (fseek (file,
(archive_file_offset
+ offset_from_vma (file, dynamic_info[DT_HASH],
@ -6495,23 +6508,23 @@ process_symbol_table (FILE *file)
return 0;
}
if (fread (nb, sizeof (nb), 1, file) != 1)
if (fread (nb, hash_ent_size, 1, file) != 1)
{
error (_("Failed to read in number of buckets\n"));
return 0;
}
if (fread (nc, sizeof (nc), 1, file) != 1)
if (fread (nc, hash_ent_size, 1, file) != 1)
{
error (_("Failed to read in number of chains\n"));
return 0;
}
nbuckets = byte_get (nb, 4);
nchains = byte_get (nc, 4);
nbuckets = byte_get (nb, hash_ent_size);
nchains = byte_get (nc, hash_ent_size);
buckets = get_dynamic_data (file, nbuckets);
chains = get_dynamic_data (file, nchains);
buckets = get_dynamic_data (file, nbuckets, hash_ent_size);
chains = get_dynamic_data (file, nchains, hash_ent_size);
if (buckets == NULL || chains == NULL)
return 0;
@ -6520,8 +6533,8 @@ process_symbol_table (FILE *file)
if (do_syms
&& dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
{
int hn;
int si;
unsigned long hn;
bfd_vma si;
printf (_("\nSymbol table for image:\n"));
if (is_32bit_elf)
@ -6537,12 +6550,16 @@ process_symbol_table (FILE *file)
for (si = buckets[hn]; si < nchains && si > 0; si = chains[si])
{
Elf_Internal_Sym *psym;
int n;
psym = dynamic_symbols + si;
printf (" %3d %3d: ", si, hn);
n = print_vma (si, DEC_5);
if (n < 5)
fputs (" " + n, stdout);
printf (" %3lu: ", hn);
print_vma (psym->st_value, LONG_HEX);
putchar (' ' );
putchar (' ');
print_vma (psym->st_size, DEC_5);
printf (" %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
@ -6760,19 +6777,19 @@ process_symbol_table (FILE *file)
if (do_histogram && buckets != NULL)
{
int *lengths;
int *counts;
int hn;
int si;
int maxlength = 0;
int nzero_counts = 0;
int nsyms = 0;
unsigned long *lengths;
unsigned long *counts;
unsigned long hn;
bfd_vma si;
unsigned long maxlength = 0;
unsigned long nzero_counts = 0;
unsigned long nsyms = 0;
printf (_("\nHistogram for bucket list length (total of %d buckets):\n"),
nbuckets);
printf (_("\nHistogram for bucket list length (total of %lu buckets):\n"),
(unsigned long) nbuckets);
printf (_(" Length Number %% of total Coverage\n"));
lengths = calloc (nbuckets, sizeof (int));
lengths = calloc (nbuckets, sizeof (*lengths));
if (lengths == NULL)
{
error (_("Out of memory"));
@ -6780,9 +6797,6 @@ process_symbol_table (FILE *file)
}
for (hn = 0; hn < nbuckets; ++hn)
{
if (! buckets[hn])
continue;
for (si = buckets[hn]; si > 0 && si < nchains; si = chains[si])
{
++nsyms;
@ -6791,7 +6805,7 @@ process_symbol_table (FILE *file)
}
}
counts = calloc (maxlength + 1, sizeof (int));
counts = calloc (maxlength + 1, sizeof (*counts));
if (counts == NULL)
{
error (_("Out of memory"));
@ -6803,13 +6817,14 @@ process_symbol_table (FILE *file)
if (nbuckets > 0)
{
printf (" 0 %-10d (%5.1f%%)\n",
unsigned long i;
printf (" 0 %-10lu (%5.1f%%)\n",
counts[0], (counts[0] * 100.0) / nbuckets);
for (si = 1; si <= maxlength; ++si)
for (i = 1; i <= maxlength; ++i)
{
nzero_counts += counts[si] * si;
printf ("%7d %-10d (%5.1f%%) %5.1f%%\n",
si, counts[si], (counts[si] * 100.0) / nbuckets,
nzero_counts += counts[i] * i;
printf ("%7lu %-10lu (%5.1f%%) %5.1f%%\n",
i, counts[i], (counts[i] * 100.0) / nbuckets,
(nzero_counts * 100.0) / nsyms);
}
}
@ -11017,7 +11032,7 @@ process_mips_specific (FILE *file)
reginfo.ri_cprmask[1] = BYTE_GET (ereg->ri_cprmask[1]);
reginfo.ri_cprmask[2] = BYTE_GET (ereg->ri_cprmask[2]);
reginfo.ri_cprmask[3] = BYTE_GET (ereg->ri_cprmask[3]);
reginfo.ri_gp_value = BYTE_GET8 (ereg->ri_gp_value);
reginfo.ri_gp_value = BYTE_GET (ereg->ri_gp_value);
printf ("GPR %08lx GP 0x",
reginfo.ri_gprmask);
@ -11638,9 +11653,9 @@ get_file_header (FILE *file)
elf_header.e_type = BYTE_GET (ehdr64.e_type);
elf_header.e_machine = BYTE_GET (ehdr64.e_machine);
elf_header.e_version = BYTE_GET (ehdr64.e_version);
elf_header.e_entry = BYTE_GET8 (ehdr64.e_entry);
elf_header.e_phoff = BYTE_GET8 (ehdr64.e_phoff);
elf_header.e_shoff = BYTE_GET8 (ehdr64.e_shoff);
elf_header.e_entry = BYTE_GET (ehdr64.e_entry);
elf_header.e_phoff = BYTE_GET (ehdr64.e_phoff);
elf_header.e_shoff = BYTE_GET (ehdr64.e_shoff);
elf_header.e_flags = BYTE_GET (ehdr64.e_flags);
elf_header.e_ehsize = BYTE_GET (ehdr64.e_ehsize);
elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize);