+ vers_data = byte_get (data, 2);
+
+ is_nobits = (psym->st_shndx < elf_header.e_shnum
+ && section_headers[psym->st_shndx].sh_type
+ == SHT_NOBITS);
+
+ check_def = (psym->st_shndx != SHN_UNDEF);
+
+ if ((vers_data & VERSYM_HIDDEN) || vers_data > 1)
+ {
+ if (version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
+ && (is_nobits || ! check_def))
+ {
+ Elf_External_Verneed evn;
+ Elf_Internal_Verneed ivn;
+ Elf_Internal_Vernaux ivna;
+
+ /* We must test both. */
+ offset = offset_from_vma
+ (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
+ sizeof evn);
+
+ do
+ {
+ unsigned long vna_off;
+
+ if (get_data (&evn, file, offset, sizeof (evn), 1,
+ _("version need")) == NULL)
+ {
+ ivna.vna_next = 0;
+ ivna.vna_other = 0;
+ ivna.vna_name = 0;
+ break;
+ }
+
+ ivn.vn_aux = BYTE_GET (evn.vn_aux);
+ ivn.vn_next = BYTE_GET (evn.vn_next);
+
+ vna_off = offset + ivn.vn_aux;
+
+ do
+ {
+ Elf_External_Vernaux evna;
+
+ if (get_data (&evna, file, vna_off,
+ sizeof (evna), 1,
+ _("version need aux (3)")) == NULL)
+ {
+ ivna.vna_next = 0;
+ ivna.vna_other = 0;
+ ivna.vna_name = 0;
+ }
+ else
+ {
+ ivna.vna_other = BYTE_GET (evna.vna_other);
+ ivna.vna_next = BYTE_GET (evna.vna_next);
+ ivna.vna_name = BYTE_GET (evna.vna_name);
+ }
+
+ vna_off += ivna.vna_next;
+ }
+ while (ivna.vna_other != vers_data
+ && ivna.vna_next != 0);
+
+ if (ivna.vna_other == vers_data)
+ break;
+
+ offset += ivn.vn_next;
+ }
+ while (ivn.vn_next != 0);
+
+ if (ivna.vna_other == vers_data)
+ {
+ *sym_info = symbol_undefined;
+ *vna_other = ivna.vna_other;
+ version_string = (ivna.vna_name < strtab_size
+ ? strtab + ivna.vna_name
+ : _("<corrupt>"));
+ check_def = 0;
+ }
+ else if (! is_nobits)
+ error (_("bad dynamic symbol\n"));
+ else
+ check_def = 1;
+ }
+
+ if (check_def)
+ {
+ if (vers_data != 0x8001
+ && version_info[DT_VERSIONTAGIDX (DT_VERDEF)])
+ {
+ Elf_Internal_Verdef ivd;
+ Elf_Internal_Verdaux ivda;
+ Elf_External_Verdaux evda;
+ unsigned long off;
+
+ off = offset_from_vma
+ (file,
+ version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
+ sizeof (Elf_External_Verdef));
+
+ do
+ {
+ Elf_External_Verdef evd;
+
+ if (get_data (&evd, file, off, sizeof (evd),
+ 1, _("version def")) == NULL)
+ {
+ ivd.vd_ndx = 0;
+ ivd.vd_aux = 0;
+ ivd.vd_next = 0;
+ }
+ else
+ {
+ ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
+ ivd.vd_aux = BYTE_GET (evd.vd_aux);
+ ivd.vd_next = BYTE_GET (evd.vd_next);
+ }
+
+ off += ivd.vd_next;
+ }
+ while (ivd.vd_ndx != (vers_data & VERSYM_VERSION)
+ && ivd.vd_next != 0);
+
+ off -= ivd.vd_next;
+ off += ivd.vd_aux;
+
+ if (get_data (&evda, file, off, sizeof (evda),
+ 1, _("version def aux")) == NULL)
+ return version_string;
+
+ ivda.vda_name = BYTE_GET (evda.vda_name);
+
+ if (psym->st_name != ivda.vda_name)
+ {
+ *sym_info = ((vers_data & VERSYM_HIDDEN) != 0
+ ? symbol_hidden : symbol_public);
+ version_string = (ivda.vda_name < strtab_size
+ ? strtab + ivda.vda_name
+ : _("<corrupt>"));
+ }
+ }
+ }
+ }
+ }
+ return version_string;
+}
+
+/* Dump the symbol table. */
+static int
+process_symbol_table (FILE * file)
+{
+ Elf_Internal_Shdr * section;
+ bfd_size_type nbuckets = 0;
+ bfd_size_type nchains = 0;
+ bfd_vma * buckets = NULL;
+ bfd_vma * chains = NULL;
+ bfd_vma ngnubuckets = 0;
+ bfd_vma * gnubuckets = NULL;
+ bfd_vma * gnuchains = NULL;
+ bfd_vma gnusymidx = 0;
+ bfd_size_type ngnuchains = 0;
+
+ if (!do_syms && !do_dyn_syms && !do_histogram)
+ return 1;
+
+ if (dynamic_info[DT_HASH]
+ && (do_histogram
+ || (do_using_dynamic
+ && !do_dyn_syms
+ && dynamic_strings != NULL)))
+ {
+ unsigned char nb[8];
+ unsigned char nc[8];
+ unsigned 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],
+ sizeof nb + sizeof nc)),
+ SEEK_SET))
+ {
+ error (_("Unable to seek to start of dynamic information\n"));
+ goto no_hash;
+ }
+
+ if (fread (nb, hash_ent_size, 1, file) != 1)
+ {