summaryrefslogtreecommitdiff
path: root/binutils/readelf.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2005-02-21 02:55:56 +0000
committerAlan Modra <amodra@bigpond.net.au>2005-02-21 02:55:56 +0000
commit873545aa33705bfc15c8314fcaac9d759211d755 (patch)
treef62ad2f90d66055a80b19b45e278d3dc5b361241 /binutils/readelf.c
parenta10d138eb86e7cb3c5c5f6dd6427aa3fa63b4fde (diff)
downloadbinutils-redhat-873545aa33705bfc15c8314fcaac9d759211d755.tar.gz
* 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.
Diffstat (limited to 'binutils/readelf.c')
-rw-r--r--binutils/readelf.c323
1 files changed, 169 insertions, 154 deletions
diff --git a/binutils/readelf.c b/binutils/readelf.c
index e607e0f72d..877c04baad 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -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
- 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
+#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[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);