static int do_debugging;
static int do_arch;
static int do_notes;
+static int do_archive_index;
static int is_32bit_elf;
struct group_list
}
}
-#if defined BFD64 && !BFD_HOST_64BIT_LONG
+#if defined BFD64 && !BFD_HOST_64BIT_LONG && !BFD_HOST_64BIT_LONG_LONG
static int
print_dec_vma (bfd_vma vma, int is_signed)
{
case HEX:
#if BFD_HOST_64BIT_LONG
return nc + printf ("%lx", vma);
+#elif BFD_HOST_64BIT_LONG_LONG
+ return nc + printf ("%llx", vma);
#else
return nc + print_hex_vma (vma);
#endif
case DEC:
#if BFD_HOST_64BIT_LONG
return printf ("%ld", vma);
+#elif BFD_HOST_64BIT_LONG_LONG
+ return printf ("%lld", vma);
#else
return print_dec_vma (vma, 1);
#endif
return printf ("%5ld", vma);
else
return printf ("%#lx", vma);
+#elif BFD_HOST_64BIT_LONG_LONG
+ if (vma <= 99999)
+ return printf ("%5lld", vma);
+ else
+ return printf ("%#llx", vma);
#else
if (vma <= 99999)
return printf ("%5ld", _bfd_int64_low (vma));
case UNSIGNED:
#if BFD_HOST_64BIT_LONG
return printf ("%lu", vma);
+#elif BFD_HOST_64BIT_LONG_LONG
+ return printf ("%llu", vma);
#else
return print_dec_vma (vma, 0);
#endif
if (is_32bit_elf)
{
-#ifdef _bfd_int64_low
- printf ("%8.8lx %8.8lx ", _bfd_int64_low (offset), _bfd_int64_low (info));
-#else
- printf ("%8.8lx %8.8lx ", offset, info);
-#endif
+ printf ("%8.8lx %8.8lx ",
+ (unsigned long) offset & 0xffffffff,
+ (unsigned long) info & 0xffffffff);
}
else
{
-#ifdef _bfd_int64_low
+#if BFD_HOST_64BIT_LONG
+ printf (do_wide
+ ? "%16.16lx %16.16lx "
+ : "%12.12lx %12.12lx ",
+ offset, info);
+#elif BFD_HOST_64BIT_LONG_LONG
+ printf (do_wide
+ ? "%16.16llx %16.16llx "
+ : "%12.12llx %12.12llx ",
+ offset, info);
+#else
printf (do_wide
? "%8.8lx%8.8lx %8.8lx%8.8lx "
: "%4.4lx%8.8lx %4.4lx%8.8lx ",
_bfd_int64_low (offset),
_bfd_int64_high (info),
_bfd_int64_low (info));
-#else
- printf (do_wide
- ? "%16.16lx %16.16lx "
- : "%12.12lx %12.12lx ",
- offset, info);
#endif
}
}
if (rtype == NULL)
-#ifdef _bfd_int64_low
- printf (_("unrecognized: %-7lx"), _bfd_int64_low (type));
-#else
- printf (_("unrecognized: %-7lx"), type);
-#endif
+ printf (_("unrecognized: %-7lx"), (unsigned long) type & 0xffffffff);
else
printf (do_wide ? "%-22.22s" : "%-17.17s", rtype);
printf (" Type2: ");
if (rtype2 == NULL)
-#ifdef _bfd_int64_low
- printf (_("unrecognized: %-7lx"), _bfd_int64_low (type2));
-#else
- printf (_("unrecognized: %-7lx"), type2);
-#endif
+ printf (_("unrecognized: %-7lx"),
+ (unsigned long) type2 & 0xffffffff);
else
printf ("%-17.17s", rtype2);
printf ("\n Type3: ");
if (rtype3 == NULL)
-#ifdef _bfd_int64_low
- printf (_("unrecognized: %-7lx"), _bfd_int64_low (type3));
-#else
- printf (_("unrecognized: %-7lx"), type3);
-#endif
+ printf (_("unrecognized: %-7lx"),
+ (unsigned long) type3 & 0xffffffff);
else
printf ("%-17.17s", rtype3);
{"version-info", no_argument, 0, 'V'},
{"use-dynamic", no_argument, 0, 'D'},
{"unwind", no_argument, 0, 'u'},
+ {"archive-index", no_argument, 0, 'c'},
{"hex-dump", required_argument, 0, 'x'},
{"debug-dump", optional_argument, 0, OPTION_DEBUG_DUMP},
{"string-dump", required_argument, 0, 'p'},
-d --dynamic Display the dynamic section (if present)\n\
-V --version-info Display the version sections (if present)\n\
-A --arch-specific Display architecture specific information (if any).\n\
+ -c --archive-index Display the symbol/file index in an archive\n\
-D --use-dynamic Use the dynamic section info when displaying symbols\n\
-x --hex-dump=<number|name>\n\
Dump the contents of section <number|name> as bytes\n\
usage (stderr);
while ((c = getopt_long
- (argc, argv, "ersuahnldSDAINtgw::x:i:vVWHp:", options, NULL)) != EOF)
+ (argc, argv, "ADHINSVWacdeghi:lnp:rstuvw::x:", options, NULL)) != EOF)
{
char *cp;
int section;
case 'n':
do_notes++;
break;
+ case 'c':
+ do_archive_index++;
+ break;
case 'x':
do_dump++;
section = strtoul (optarg, & cp, 0);
if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections
&& !do_segments && !do_header && !do_dump && !do_version
&& !do_histogram && !do_debugging && !do_arch && !do_notes
- && !do_section_groups)
+ && !do_section_groups && !do_archive_index)
usage (stderr);
else if (argc < 3)
{
if (dynamic_addr)
error (_("more than one dynamic segment\n"));
+ /* By default, assume that the .dynamic section is the first
+ section in the DYNAMIC segment. */
+ dynamic_addr = segment->p_offset;
+ dynamic_size = segment->p_filesz;
+
/* Try to locate the .dynamic section. If there is
a section header table, we can easily locate it. */
if (section_headers != NULL)
}
if (sec->sh_type == SHT_NOBITS)
- break;
+ {
+ dynamic_size = 0;
+ break;
+ }
dynamic_addr = sec->sh_offset;
dynamic_size = sec->sh_size;
if (dynamic_addr < segment->p_offset
|| dynamic_addr > segment->p_offset + segment->p_filesz)
- warn (_("the .dynamic section is not contained within the dynamic segment\n"));
+ warn (_("the .dynamic section is not contained"
+ " within the dynamic segment\n"));
else if (dynamic_addr > segment->p_offset)
- warn (_("the .dynamic section is not the first section in the dynamic segment.\n"));
- }
- else
- {
- /* Otherwise, we can only assume that the .dynamic
- section is the first section in the DYNAMIC segment. */
- dynamic_addr = segment->p_offset;
- dynamic_size = segment->p_filesz;
+ warn (_("the .dynamic section is not the first section"
+ " in the dynamic segment.\n"));
}
break;
Elf_External_Verdef *edefs;
unsigned int idx;
unsigned int cnt;
+ char *endbuf;
found = 1;
edefs = get_data (NULL, file, section->sh_offset, 1,
section->sh_size,
_("version definition section"));
+ endbuf = (char *) edefs + section->sh_size;
if (!edefs)
break;
int isum;
vstart = ((char *) edefs) + idx;
+ if (vstart + sizeof (*edef) > endbuf)
+ break;
edef = (Elf_External_Verdef *) vstart;
vstart += aux.vda_next;
eaux = (Elf_External_Verdaux *) vstart;
+ if (vstart + sizeof (*eaux) > endbuf)
+ break;
aux.vda_name = BYTE_GET (eaux->vda_name);
aux.vda_next = BYTE_GET (eaux->vda_next);
printf (_(" %#06x: Parent %d, name index: %ld\n"),
isum, j, aux.vda_name);
}
+ if (j < ent.vd_cnt)
+ printf (_(" Version def aux past end of section\n"));
idx += ent.vd_next;
}
+ if (cnt < section->sh_info)
+ printf (_(" Version definition past end of section\n"));
free (edefs);
}
Elf_External_Verneed *eneed;
unsigned int idx;
unsigned int cnt;
+ char *endbuf;
found = 1;
eneed = get_data (NULL, file, section->sh_offset, 1,
section->sh_size,
_("version need section"));
+ endbuf = (char *) eneed + section->sh_size;
if (!eneed)
break;
char *vstart;
vstart = ((char *) eneed) + idx;
+ if (vstart + sizeof (*entry) > endbuf)
+ break;
entry = (Elf_External_Verneed *) vstart;
Elf_External_Vernaux *eaux;
Elf_Internal_Vernaux aux;
+ if (vstart + sizeof (*eaux) > endbuf)
+ break;
eaux = (Elf_External_Vernaux *) vstart;
aux.vna_hash = BYTE_GET (eaux->vna_hash);
isum += aux.vna_next;
vstart += aux.vna_next;
}
+ if (j < ent.vn_cnt)
+ printf (_(" Version need aux past end of section\n"));
idx += ent.vn_next;
}
+ if (cnt < section->sh_info)
+ printf (_(" Version need past end of section\n"));
free (eneed);
}
{
ivna.vna_name = BYTE_GET (evna.vna_name);
- name = strtab + ivna.vna_name;
+ if (ivna.vna_name >= string_sec->sh_size)
+ name = _("*invalid*");
+ else
+ name = strtab + ivna.vna_name;
nn += printf ("(%s%-*s",
name,
12 - (int) strlen (name),
ivda.vda_name = BYTE_GET (evda.vda_name);
- name = strtab + ivda.vda_name;
+ if (ivda.vda_name >= string_sec->sh_size)
+ name = _("*invalid*");
+ else
+ name = strtab + ivda.vda_name;
nn += printf ("(%s%-*s",
name,
12 - (int) strlen (name),
return i_data;
}
+static void
+print_dynamic_symbol (bfd_vma si, unsigned long hn)
+{
+ Elf_Internal_Sym *psym;
+ int n;
+
+ psym = dynamic_symbols + si;
+
+ n = print_vma (si, DEC_5);
+ if (n < 5)
+ fputs (" " + n, stdout);
+ printf (" %3lu: ", hn);
+ print_vma (psym->st_value, LONG_HEX);
+ putchar (' ');
+ print_vma (psym->st_size, DEC_5);
+
+ printf (" %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
+ printf (" %6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));
+ printf (" %3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
+ /* Check to see if any other bits in the st_other field are set.
+ Note - displaying this information disrupts the layout of the
+ table being generated, but for the moment this case is very
+ rare. */
+ if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))
+ printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)));
+ printf (" %3.3s ", get_symbol_index_type (psym->st_shndx));
+ if (VALID_DYNAMIC_NAME (psym->st_name))
+ print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
+ else
+ printf (" <corrupt: %14ld>", psym->st_name);
+ putchar ('\n');
+}
+
/* Dump the symbol table. */
static int
process_symbol_table (FILE *file)
bfd_vma ngnubuckets = 0;
bfd_vma *gnubuckets = NULL;
bfd_vma *gnuchains = NULL;
+ bfd_vma gnusymidx = 0;
if (! do_syms && !do_histogram)
return 1;
- if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
- || do_histogram))
+ if (dynamic_info[DT_HASH]
+ && (do_histogram
+ || (do_using_dynamic && dynamic_strings != NULL)))
{
unsigned char nb[8];
unsigned char nc[8];
return 0;
}
- if (do_syms
- && dynamic_info[DT_HASH] && do_using_dynamic && dynamic_strings != NULL)
+ if (dynamic_info_DT_GNU_HASH
+ && (do_histogram
+ || (do_using_dynamic && dynamic_strings != NULL)))
{
- unsigned long hn;
- bfd_vma si;
+ unsigned char nb[16];
+ bfd_vma i, maxchain = 0xffffffff, bitmaskwords;
+ bfd_vma buckets_vma;
+
+ if (fseek (file,
+ (archive_file_offset
+ + offset_from_vma (file, dynamic_info_DT_GNU_HASH,
+ sizeof nb)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ return 0;
+ }
- printf (_("\nSymbol table for image:\n"));
+ if (fread (nb, 16, 1, file) != 1)
+ {
+ error (_("Failed to read in number of buckets\n"));
+ return 0;
+ }
+
+ ngnubuckets = byte_get (nb, 4);
+ gnusymidx = byte_get (nb + 4, 4);
+ bitmaskwords = byte_get (nb + 8, 4);
+ buckets_vma = dynamic_info_DT_GNU_HASH + 16;
if (is_32bit_elf)
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
+ buckets_vma += bitmaskwords * 4;
else
- printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
+ buckets_vma += bitmaskwords * 8;
- for (hn = 0; hn < nbuckets; hn++)
+ if (fseek (file,
+ (archive_file_offset
+ + offset_from_vma (file, buckets_vma, 4)),
+ SEEK_SET))
{
- if (! buckets[hn])
- continue;
+ error (_("Unable to seek to start of dynamic information\n"));
+ return 0;
+ }
+
+ gnubuckets = get_dynamic_data (file, ngnubuckets, 4);
+
+ if (gnubuckets == NULL)
+ return 0;
+
+ for (i = 0; i < ngnubuckets; i++)
+ if (gnubuckets[i] != 0)
+ {
+ if (gnubuckets[i] < gnusymidx)
+ return 0;
+
+ if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
+ maxchain = gnubuckets[i];
+ }
+
+ if (maxchain == 0xffffffff)
+ return 0;
+
+ maxchain -= gnusymidx;
- for (si = buckets[hn]; si < nchains && si > 0; si = chains[si])
+ if (fseek (file,
+ (archive_file_offset
+ + offset_from_vma (file, buckets_vma
+ + 4 * (ngnubuckets + maxchain), 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ return 0;
+ }
+
+ do
+ {
+ if (fread (nb, 4, 1, file) != 1)
{
- Elf_Internal_Sym *psym;
- int n;
+ error (_("Failed to determine last chain length\n"));
+ return 0;
+ }
- psym = dynamic_symbols + si;
+ if (maxchain + 1 == 0)
+ return 0;
- n = print_vma (si, DEC_5);
- if (n < 5)
- fputs (" " + n, stdout);
- printf (" %3lu: ", hn);
- print_vma (psym->st_value, LONG_HEX);
- putchar (' ');
- print_vma (psym->st_size, DEC_5);
+ ++maxchain;
+ }
+ while ((byte_get (nb, 4) & 1) == 0);
- printf (" %6s", get_symbol_type (ELF_ST_TYPE (psym->st_info)));
- printf (" %6s", get_symbol_binding (ELF_ST_BIND (psym->st_info)));
- printf (" %3s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other)));
- /* Check to see if any other bits in the st_other field are set.
- Note - displaying this information disrupts the layout of the
- table being generated, but for the moment this case is very rare. */
- if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))
- printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)));
- printf (" %3.3s ", get_symbol_index_type (psym->st_shndx));
- if (VALID_DYNAMIC_NAME (psym->st_name))
- print_symbol (25, GET_DYNAMIC_NAME (psym->st_name));
- else
- printf (" <corrupt: %14ld>", psym->st_name);
- putchar ('\n');
+ if (fseek (file,
+ (archive_file_offset
+ + offset_from_vma (file, buckets_vma + 4 * ngnubuckets, 4)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ return 0;
+ }
+
+ gnuchains = get_dynamic_data (file, maxchain, 4);
+
+ if (gnuchains == NULL)
+ return 0;
+ }
+
+ if ((dynamic_info[DT_HASH] || dynamic_info_DT_GNU_HASH)
+ && do_syms
+ && do_using_dynamic
+ && dynamic_strings != NULL)
+ {
+ unsigned long hn;
+
+ if (dynamic_info[DT_HASH])
+ {
+ bfd_vma si;
+
+ printf (_("\nSymbol table for image:\n"));
+ if (is_32bit_elf)
+ printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
+ else
+ printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
+
+ for (hn = 0; hn < nbuckets; hn++)
+ {
+ if (! buckets[hn])
+ continue;
+
+ for (si = buckets[hn]; si < nchains && si > 0; si = chains[si])
+ print_dynamic_symbol (si, hn);
}
}
+
+ if (dynamic_info_DT_GNU_HASH)
+ {
+ printf (_("\nSymbol table of `.gnu.hash' for image:\n"));
+ if (is_32bit_elf)
+ printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
+ else
+ printf (_(" Num Buc: Value Size Type Bind Vis Ndx Name\n"));
+
+ for (hn = 0; hn < ngnubuckets; ++hn)
+ if (gnubuckets[hn] != 0)
+ {
+ bfd_vma si = gnubuckets[hn];
+ bfd_vma off = si - gnusymidx;
+
+ do
+ {
+ print_dynamic_symbol (si, hn);
+ si++;
+ }
+ while ((gnuchains[off++] & 1) == 0);
+ }
+ }
}
else if (do_syms && !do_using_dynamic)
{
if (do_histogram && dynamic_info_DT_GNU_HASH)
{
- unsigned char nb[16];
- bfd_vma i, maxchain = 0xffffffff, symidx, bitmaskwords;
unsigned long *lengths;
unsigned long *counts;
unsigned long hn;
unsigned long maxlength = 0;
unsigned long nzero_counts = 0;
unsigned long nsyms = 0;
- bfd_vma buckets_vma;
-
- if (fseek (file,
- (archive_file_offset
- + offset_from_vma (file, dynamic_info_DT_GNU_HASH,
- sizeof nb)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- return 0;
- }
-
- if (fread (nb, 16, 1, file) != 1)
- {
- error (_("Failed to read in number of buckets\n"));
- return 0;
- }
-
- ngnubuckets = byte_get (nb, 4);
- symidx = byte_get (nb + 4, 4);
- bitmaskwords = byte_get (nb + 8, 4);
- buckets_vma = dynamic_info_DT_GNU_HASH + 16;
- if (is_32bit_elf)
- buckets_vma += bitmaskwords * 4;
- else
- buckets_vma += bitmaskwords * 8;
-
- if (fseek (file,
- (archive_file_offset
- + offset_from_vma (file, buckets_vma, 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- return 0;
- }
-
- gnubuckets = get_dynamic_data (file, ngnubuckets, 4);
-
- if (gnubuckets == NULL)
- return 0;
-
- for (i = 0; i < ngnubuckets; i++)
- if (gnubuckets[i] != 0)
- {
- if (gnubuckets[i] < symidx)
- return 0;
-
- if (maxchain == 0xffffffff || gnubuckets[i] > maxchain)
- maxchain = gnubuckets[i];
- }
-
- if (maxchain == 0xffffffff)
- return 0;
-
- maxchain -= symidx;
-
- if (fseek (file,
- (archive_file_offset
- + offset_from_vma (file, buckets_vma
- + 4 * (ngnubuckets + maxchain), 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- return 0;
- }
-
- do
- {
- if (fread (nb, 4, 1, file) != 1)
- {
- error (_("Failed to determine last chain length\n"));
- return 0;
- }
-
- if (maxchain + 1 == 0)
- return 0;
-
- ++maxchain;
- }
- while ((byte_get (nb, 4) & 1) == 0);
-
- if (fseek (file,
- (archive_file_offset
- + offset_from_vma (file, buckets_vma + 4 * ngnubuckets, 4)),
- SEEK_SET))
- {
- error (_("Unable to seek to start of dynamic information\n"));
- return 0;
- }
-
- gnuchains = get_dynamic_data (file, maxchain, 4);
-
- if (gnuchains == NULL)
- return 0;
lengths = calloc (ngnubuckets, sizeof (*lengths));
if (lengths == NULL)
{
bfd_vma off, length = 1;
- for (off = gnubuckets[hn] - symidx;
+ for (off = gnubuckets[hn] - gnusymidx;
(gnuchains[off] & 1) == 0; ++off)
++length;
lengths[hn] = length;
if (data < end)
{
- printf (" [%6zx] %s\n", data - start, data);
+ printf (" [%6tx] %s\n", data - start, data);
data += strlen (data);
some_strings_shown = TRUE;
}
return p;
}
+ if (tag == Tag_GNU_Power_ABI_Vector)
+ {
+ val = read_uleb128 (p, &len);
+ p += len;
+ printf (" Tag_GNU_Power_ABI_Vector: ");
+ switch (val)
+ {
+ case 0:
+ printf ("Any\n");
+ break;
+ case 1:
+ printf ("Generic\n");
+ break;
+ case 2:
+ printf ("AltiVec\n");
+ break;
+ case 3:
+ printf ("SPE\n");
+ break;
+ default:
+ printf ("??? (%d)\n", val);
+ break;
+ }
+ return p;
+ }
+
if (tag & 1)
type = 1; /* String. */
else
return _("NT_TASKSTRUCT (task structure)");
case NT_PRXFPREG:
return _("NT_PRXFPREG (user_xfpregs structure)");
+ case NT_PPC_VMX:
+ return _("NT_PPC_VMX (ppc Altivec registers)");
case NT_PSTATUS:
return _("NT_PSTATUS (pstatus structure)");
case NT_FPREGS:
return 0;
}
-/* Process an ELF archive. The file is positioned just after the
- ARMAG string. */
+/* Process an ELF archive.
+ On entry the file is positioned just after the ARMAG string. */
static int
process_archive (char *file_name, FILE *file)
struct ar_hdr arhdr;
size_t got;
unsigned long size;
+ unsigned long index_num = 0;
+ unsigned long *index_array = NULL;
+ char *sym_table = NULL;
+ unsigned long sym_size = 0;
char *longnames = NULL;
unsigned long longnames_size = 0;
size_t file_name_size;
return 1;
}
+ /* See if this is the archive symbol table. */
if (const_strneq (arhdr.ar_name, "/ ")
|| const_strneq (arhdr.ar_name, "/SYM64/ "))
{
- /* This is the archive symbol table. Skip it.
- FIXME: We should have an option to dump it. */
size = strtoul (arhdr.ar_size, NULL, 10);
- if (fseek (file, size + (size & 1), SEEK_CUR) != 0)
+ size = size + (size & 1);
+
+ if (do_archive_index)
+ {
+ unsigned long i;
+ /* A buffer used to hold numbers read in from an archive index.
+ These are always 4 bytes long and stored in big-endian format. */
+#define SIZEOF_AR_INDEX_NUMBERS 4
+ unsigned char integer_buffer[SIZEOF_AR_INDEX_NUMBERS];
+ unsigned char * index_buffer;
+
+ /* Check the size of the archive index. */
+ if (size < SIZEOF_AR_INDEX_NUMBERS)
+ {
+ error (_("%s: the archive index is empty\n"), file_name);
+ return 1;
+ }
+
+ /* Read the numer of entries in the archive index. */
+ got = fread (integer_buffer, 1, sizeof integer_buffer, file);
+ if (got != sizeof (integer_buffer))
+ {
+ error (_("%s: failed to read archive index\n"), file_name);
+ return 1;
+ }
+ index_num = byte_get_big_endian (integer_buffer, sizeof integer_buffer);
+ size -= SIZEOF_AR_INDEX_NUMBERS;
+
+ /* Read in the archive index. */
+ if (size < index_num * SIZEOF_AR_INDEX_NUMBERS)
+ {
+ error (_("%s: the archive index is supposed to have %ld entries, but the size in the header is too small\n"),
+ file_name, index_num);
+ return 1;
+ }
+ index_buffer = malloc (index_num * SIZEOF_AR_INDEX_NUMBERS);
+ if (index_buffer == NULL)
+ {
+ error (_("Out of memory whilst trying to read archive symbol index\n"));
+ return 1;
+ }
+ got = fread (index_buffer, SIZEOF_AR_INDEX_NUMBERS, index_num, file);
+ if (got != index_num)
+ {
+ free (index_buffer);
+ error (_("%s: failed to read archive index\n"), file_name);
+ ret = 1;
+ goto out;
+ }
+ size -= index_num * SIZEOF_AR_INDEX_NUMBERS;
+
+ /* Convert the index numbers into the host's numeric format. */
+ index_array = malloc (index_num * sizeof (* index_array));
+ if (index_array == NULL)
+ {
+ free (index_buffer);
+ error (_("Out of memory whilst trying to convert the archive symbol index\n"));
+ return 1;
+ }
+
+ for (i = 0; i < index_num; i++)
+ index_array[i] = byte_get_big_endian ((unsigned char *)(index_buffer + (i * SIZEOF_AR_INDEX_NUMBERS)),
+ SIZEOF_AR_INDEX_NUMBERS);
+ free (index_buffer);
+
+ /* The remaining space in the header is taken up by the symbol table. */
+ if (size < 1)
+ {
+ error (_("%s: the archive has an index but no symbols\n"), file_name);
+ ret = 1;
+ goto out;
+ }
+ sym_table = malloc (size);
+ sym_size = size;
+ if (sym_table == NULL)
+ {
+ error (_("Out of memory whilst trying to read archive index symbol table\n"));
+ ret = 1;
+ goto out;
+ }
+ got = fread (sym_table, 1, size, file);
+ if (got != size)
+ {
+ error (_("%s: failed to read archive index symbol table\n"), file_name);
+ ret = 1;
+ goto out;
+ }
+ }
+ else
{
- error (_("%s: failed to skip archive symbol table\n"), file_name);
- return 1;
+ if (fseek (file, size, SEEK_CUR) != 0)
+ {
+ error (_("%s: failed to skip archive symbol table\n"), file_name);
+ return 1;
+ }
}
- got = fread (&arhdr, 1, sizeof arhdr, file);
+ got = fread (& arhdr, 1, sizeof arhdr, file);
if (got != sizeof arhdr)
{
if (got == 0)
- return 0;
+ {
+ ret = 0;
+ goto out;
+ }
- error (_("%s: failed to read archive header\n"), file_name);
- return 1;
+ error (_("%s: failed to read archive header following archive index\n"), file_name);
+ ret = 1;
+ goto out;
}
}
+ else if (do_archive_index)
+ printf (_("%s has no archive index\n"), file_name);
if (const_strneq (arhdr.ar_name, "// "))
{
names. */
longnames_size = strtoul (arhdr.ar_size, NULL, 10);
-
longnames = malloc (longnames_size);
if (longnames == NULL)
{
- error (_("Out of memory\n"));
- return 1;
+ error (_("Out of memory reading long symbol names in archive\n"));
+ ret = 1;
+ goto out;
}
if (fread (longnames, longnames_size, 1, file) != 1)
{
free (longnames);
- error (_("%s: failed to read string table\n"), file_name);
- return 1;
+ error (_("%s: failed to read long symbol name string table\n"), file_name);
+ ret = 1;
+ goto out;
}
if ((longnames_size & 1) != 0)
getc (file);
- got = fread (&arhdr, 1, sizeof arhdr, file);
+ got = fread (& arhdr, 1, sizeof arhdr, file);
if (got != sizeof arhdr)
{
- free (longnames);
-
if (got == 0)
- return 0;
+ ret = 0;
+ else
+ {
+ error (_("%s: failed to read archive header following long symbol names\n"), file_name);
+ ret = 1;
+ }
+ goto out;
+ }
+ }
- error (_("%s: failed to read archive header\n"), file_name);
- return 1;
+ if (do_archive_index)
+ {
+ if (sym_table == NULL)
+ error (_("%s: unable to dump the index as none was found\n"), file_name);
+ else
+ {
+ unsigned int i, j, k, l;
+ char elf_name[16];
+ unsigned long current_pos;
+
+ printf (_("Index of archive %s: (%ld entries, 0x%lx bytes in the symbol table)\n"),
+ file_name, index_num, sym_size);
+ current_pos = ftell (file);
+
+ for (i = l = 0; i < index_num; i++)
+ {
+ if ((i == 0) || ((i > 0) && (index_array[i] != index_array[i - 1])))
+ {
+ if (fseek (file, index_array[i], SEEK_SET) != 0)
+ {
+ error (_("%s: failed to seek to next file name\n"), file_name);
+ ret = 1;
+ goto out;
+ }
+ got = fread (elf_name, 1, 16, file);
+ if (got != 16)
+ {
+ error (_("%s: failed to read file name\n"), file_name);
+ ret = 1;
+ goto out;
+ }
+
+ if (elf_name[0] == '/')
+ {
+ /* We have a long name. */
+ k = j = strtoul (elf_name + 1, NULL, 10);
+ while ((j < longnames_size) && (longnames[j] != '/'))
+ j++;
+ longnames[j] = '\0';
+ printf (_("Binary %s contains:\n"), longnames + k);
+ longnames[j] = '/';
+ }
+ else
+ {
+ j = 0;
+ while ((elf_name[j] != '/') && (j < 16))
+ j++;
+ elf_name[j] = '\0';
+ printf(_("Binary %s contains:\n"), elf_name);
+ }
+ }
+ if (l >= sym_size)
+ {
+ error (_("%s: end of the symbol table reached before the end of the index\n"),
+ file_name);
+ break;
+ }
+ printf ("\t%s\n", sym_table + l);
+ l += strlen (sym_table + l) + 1;
+ }
+
+ if (l < sym_size)
+ error (_("%s: symbols remain in the index symbol table, but without corresponding entries in the index table\n"),
+ file_name);
+
+ free (index_array);
+ index_array = NULL;
+ free (sym_table);
+ sym_table = NULL;
+ if (fseek (file, current_pos, SEEK_SET) != 0)
+ {
+ error (_("%s: failed to seek back to start of object files in the archive\n"), file_name);
+ return 1;
+ }
}
+
+ if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections
+ && !do_segments && !do_header && !do_dump && !do_version
+ && !do_histogram && !do_debugging && !do_arch && !do_notes
+ && !do_section_groups)
+ return 0; /* Archive index only. */
}
file_name_size = strlen (file_name);
}
}
- if (longnames != 0)
+ out:
+ if (index_array != NULL)
+ free (index_array);
+ if (sym_table != NULL)
+ free (sym_table);
+ if (longnames != NULL)
free (longnames);
return ret;
if (fread (armag, SARMAG, 1, file) != 1)
{
- error (_("%s: Failed to read file header\n"), file_name);
+ error (_("%s: Failed to read file's magic number\n"), file_name);
fclose (file);
return 1;
}
ret = process_archive (file_name, file);
else
{
+ if (do_archive_index)
+ error (_("File %s is not an archive so its index cannot be displayed.\n"),
+ file_name);
+
rewind (file);
archive_file_size = archive_file_offset = 0;
ret = process_object (file_name, file);