aboutsummaryrefslogtreecommitdiff
path: root/binutils/od-xcoff.c
diff options
context:
space:
mode:
authorTristan Gingold <gingold@adacore.com>2011-05-16 12:22:13 +0000
committerTristan Gingold <gingold@adacore.com>2011-05-16 12:22:13 +0000
commit6abcee9042f9603cf9fdeb62fa55335a6aa974e9 (patch)
treeb39c076736f3af34bd9e1bb7a766598a3c6a96d1 /binutils/od-xcoff.c
parentf37a7048a8608dcc4465a4b425cc4fd3b0f9e1cd (diff)
downloadgdb-6abcee9042f9603cf9fdeb62fa55335a6aa974e9.zip
gdb-6abcee9042f9603cf9fdeb62fa55335a6aa974e9.tar.gz
gdb-6abcee9042f9603cf9fdeb62fa55335a6aa974e9.tar.bz2
2011-05-16 Tristan Gingold <gingold@adacore.com>
* od-xcoff.c: New file. * objdump.h: New file. * objdump.c: Include objdump.h (dump_private_options, objdump_private_vectors): New variables. (usage): Mention -P/--private. Display handled options. (long_options): Add -P/--private. (dump_target_specific): New function. (dump_bfd): Handle dump_private_options. (main): Handle -P. * doc/binutils.texi (objdump): Document -P/--private. * configure.in (OBJDUMP_PRIVATE_VECTORS, OBJDUMP_PRIVATE_OFILES): New variables, compute them. (od_vectors): Add vectors for private dumpers. Make them uniq. (OBJDUMP_DEFS): Add OBJDUMP_PRIVATE_VECTORS. * Makefile.am (HFILES): Add objdump.h (CFILES): Add od-xcoff.c (OBJDUMP_PRIVATE_OFILES): New variable. (objdump_DEPENDENCIES): Append OBJDUMP_PRIVATE_OFILES. (objdump_LDADD): Ditto. (EXTRA_objdump_SOURCES): Define. * Makefile.in: Regenerate. * configure: Regenerate.
Diffstat (limited to 'binutils/od-xcoff.c')
-rw-r--r--binutils/od-xcoff.c1670
1 files changed, 1670 insertions, 0 deletions
diff --git a/binutils/od-xcoff.c b/binutils/od-xcoff.c
new file mode 100644
index 0000000..47d0248
--- /dev/null
+++ b/binutils/od-xcoff.c
@@ -0,0 +1,1670 @@
+/* od-xcoff.c -- dump information about an xcoff object file.
+ Copyright 2011 Free Software Foundation, Inc.
+ Written by Tristan Gingold, Adacore.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include <stddef.h>
+#include <time.h>
+#include "sysdep.h"
+#include "safe-ctype.h"
+#include "bfd.h"
+#include "objdump.h"
+#include "bucomm.h"
+#include "bfdlink.h"
+/* Force the support of weak symbols. */
+#ifndef AIX_WEAK_SUPPORT
+#define AIX_WEAK_SUPPORT 1
+#endif
+#include "coff/internal.h"
+#include "coff/rs6000.h"
+#include "coff/xcoff.h"
+#include "libcoff.h"
+#include "libxcoff.h"
+
+/* Index of the options in the options[] array. */
+#define OPT_FILE_HEADER 0
+#define OPT_AOUT 1
+#define OPT_SECTIONS 2
+#define OPT_SYMS 3
+#define OPT_RELOCS 4
+#define OPT_LINENO 5
+#define OPT_LOADER 6
+#define OPT_EXCEPT 7
+#define OPT_TYPCHK 8
+#define OPT_TRACEBACK 9
+#define OPT_TOC 10
+
+/* List of actions. */
+static struct objdump_private_option options[] =
+ {
+ { "header", 0 },
+ { "aout", 0 },
+ { "sections", 0 },
+ { "syms", 0 },
+ { "relocs", 0 },
+ { "lineno", 0 },
+ { "loader", 0 },
+ { "except", 0 },
+ { "typchk", 0 },
+ { "traceback", 0 },
+ { "toc", 0 },
+ { NULL, 0 }
+ };
+
+/* Display help. */
+
+static void
+xcoff_help (FILE *stream)
+{
+ fprintf (stream, _("\
+For XCOFF files:\n\
+ header Display the file header\n\
+ aout Display the auxiliary header\n\
+ sections Display the section headers\n\
+ syms Display the symbols table\n\
+ relocs Display the relocation entries\n\
+ lineno Display the line number entries\n\
+ loader Display loader section\n\
+ except Display exception table\n\
+ typchk Display type-check section\n\
+ traceback Display traceback tags\n\
+ toc Display toc symbols\n\
+"));
+}
+
+/* Return TRUE if ABFD is handled. */
+
+static int
+xcoff_filter (bfd *abfd)
+{
+ return bfd_get_flavour (abfd) == bfd_target_xcoff_flavour;
+}
+
+/* Translation entry type. The last entry must be {0, NULL}. */
+
+struct xlat_table {
+ unsigned int val;
+ const char *name;
+};
+
+/* Display the list of name (from TABLE) for FLAGS, using comma to separate
+ them. A name is displayed if FLAGS & VAL is not 0. */
+
+static void
+dump_flags (const struct xlat_table *table, unsigned int flags)
+{
+ unsigned int r = flags;
+ int first = 1;
+ const struct xlat_table *t;
+
+ for (t = table; t->name; t++)
+ if ((flags & t->val) != 0)
+ {
+ r &= ~t->val;
+
+ if (first)
+ first = 0;
+ else
+ putchar (',');
+ fputs (t->name, stdout);
+ }
+
+ /* Not decoded flags. */
+ if (r != 0)
+ {
+ if (!first)
+ putchar (',');
+ printf ("0x%x", r);
+ }
+}
+
+/* Display the name corresponding to VAL from TABLE, using at most
+ MAXLEN char (possibly passed with spaces). */
+
+static void
+dump_value (const struct xlat_table *table, unsigned int val, int maxlen)
+{
+ const struct xlat_table *t;
+
+ for (t = table; t->name; t++)
+ if (t->val == val)
+ {
+ printf ("%-*s", maxlen, t->name);
+ return;
+ }
+ printf ("(%*x)", maxlen - 2, val);
+}
+
+/* Names of f_flags. */
+static const struct xlat_table f_flag_xlat[] =
+ {
+ { F_RELFLG, "no-rel" },
+ { F_EXEC, "exec" },
+ { F_LNNO, "lineno" },
+ { F_LSYMS, "lsyms" },
+
+ { F_FDPR_PROF, "fdpr-prof" },
+ { F_FDPR_OPTI, "fdpr-opti" },
+ { F_DSA, "dsa" },
+
+ { F_VARPG, "varprg" },
+
+ { F_DYNLOAD, "dynload" },
+ { F_SHROBJ, "shrobj" },
+ { F_NONEXEC, "nonexec" },
+
+ { 0, NULL }
+ };
+
+/* Names of s_flags. */
+static const struct xlat_table s_flag_xlat[] =
+ {
+ { STYP_PAD, "pad" },
+ { STYP_DWARF, "dwarf" },
+ { STYP_TEXT, "text" },
+ { STYP_DATA, "data" },
+ { STYP_BSS, "bss" },
+
+ { STYP_EXCEPT, "except" },
+ { STYP_INFO, "info" },
+ { STYP_TDATA, "tdata" },
+ { STYP_TBSS, "tbss" },
+
+ { STYP_LOADER, "loader" },
+ { STYP_DEBUG, "debug" },
+ { STYP_TYPCHK, "typchk" },
+ { STYP_OVRFLO, "ovrflo" },
+ { 0, NULL }
+ };
+
+/* Names of storage class. */
+static const struct xlat_table sc_xlat[] =
+ {
+#define SC_ENTRY(X) { C_##X, #X }
+ SC_ENTRY(NULL),
+ SC_ENTRY(AUTO),
+ SC_ENTRY(EXT),
+ SC_ENTRY(STAT),
+ SC_ENTRY(REG),
+ SC_ENTRY(EXTDEF),
+ SC_ENTRY(LABEL),
+ SC_ENTRY(ULABEL),
+ SC_ENTRY(MOS),
+ SC_ENTRY(ARG),
+ /* SC_ENTRY(STRARG), */
+ SC_ENTRY(MOU),
+ SC_ENTRY(UNTAG),
+ SC_ENTRY(TPDEF),
+ SC_ENTRY(USTATIC),
+ SC_ENTRY(ENTAG),
+ SC_ENTRY(MOE),
+ SC_ENTRY(REGPARM),
+ SC_ENTRY(FIELD),
+ SC_ENTRY(BLOCK),
+ SC_ENTRY(FCN),
+ SC_ENTRY(EOS),
+ SC_ENTRY(FILE),
+ SC_ENTRY(LINE),
+ SC_ENTRY(ALIAS),
+ SC_ENTRY(HIDDEN),
+ SC_ENTRY(HIDEXT),
+ SC_ENTRY(BINCL),
+ SC_ENTRY(EINCL),
+ SC_ENTRY(INFO),
+ SC_ENTRY(WEAKEXT),
+ SC_ENTRY(DWARF),
+
+ /* Stabs. */
+ SC_ENTRY (GSYM),
+ SC_ENTRY (LSYM),
+ SC_ENTRY (PSYM),
+ SC_ENTRY (RSYM),
+ SC_ENTRY (RPSYM),
+ SC_ENTRY (STSYM),
+ SC_ENTRY (TCSYM),
+ SC_ENTRY (BCOMM),
+ SC_ENTRY (ECOML),
+ SC_ENTRY (ECOMM),
+ SC_ENTRY (DECL),
+ SC_ENTRY (ENTRY),
+ SC_ENTRY (FUN),
+ SC_ENTRY (BSTAT),
+ SC_ENTRY (ESTAT),
+
+ { 0, NULL }
+#undef SC_ENTRY
+ };
+
+/* Names for symbol type. */
+static const struct xlat_table smtyp_xlat[] =
+ {
+ { XTY_ER, "ER" },
+ { XTY_SD, "SD" },
+ { XTY_LD, "LD" },
+ { XTY_CM, "CM" },
+ { XTY_EM, "EM" },
+ { XTY_US, "US" },
+ { 0, NULL }
+ };
+
+/* Names for storage-mapping class. */
+static const struct xlat_table smclas_xlat[] =
+ {
+#define SMCLAS_ENTRY(X) { XMC_##X, #X }
+ SMCLAS_ENTRY (PR),
+ SMCLAS_ENTRY (RO),
+ SMCLAS_ENTRY (DB),
+ SMCLAS_ENTRY (TC),
+ SMCLAS_ENTRY (UA),
+ SMCLAS_ENTRY (RW),
+ SMCLAS_ENTRY (GL),
+ SMCLAS_ENTRY (XO),
+ SMCLAS_ENTRY (SV),
+ SMCLAS_ENTRY (BS),
+ SMCLAS_ENTRY (DS),
+ SMCLAS_ENTRY (UC),
+ SMCLAS_ENTRY (TI),
+ SMCLAS_ENTRY (TB),
+ SMCLAS_ENTRY (TC0),
+ SMCLAS_ENTRY (TD),
+ SMCLAS_ENTRY (SV64),
+ SMCLAS_ENTRY (SV3264),
+ { 0, NULL }
+#undef SMCLAS_ENTRY
+ };
+
+/* Names for relocation type. */
+static const struct xlat_table rtype_xlat[] =
+ {
+#define RTYPE_ENTRY(X) { R_##X, #X }
+ RTYPE_ENTRY (POS),
+ RTYPE_ENTRY (NEG),
+ RTYPE_ENTRY (REL),
+ RTYPE_ENTRY (TOC),
+ RTYPE_ENTRY (RTB),
+ RTYPE_ENTRY (GL),
+ RTYPE_ENTRY (TCL),
+ RTYPE_ENTRY (BA),
+ RTYPE_ENTRY (BR),
+ RTYPE_ENTRY (RL),
+ RTYPE_ENTRY (RLA),
+ RTYPE_ENTRY (REF),
+ RTYPE_ENTRY (TRL),
+ RTYPE_ENTRY (TRLA),
+ RTYPE_ENTRY (RRTBI),
+ RTYPE_ENTRY (RRTBA),
+ RTYPE_ENTRY (CAI),
+ RTYPE_ENTRY (CREL),
+ RTYPE_ENTRY (RBA),
+ RTYPE_ENTRY (RBAC),
+ RTYPE_ENTRY (RBR),
+ RTYPE_ENTRY (RBRC),
+ RTYPE_ENTRY (TLS),
+ RTYPE_ENTRY (TLS_IE),
+ RTYPE_ENTRY (TLS_LD),
+ RTYPE_ENTRY (TLS_LE),
+ RTYPE_ENTRY (TLSM),
+ RTYPE_ENTRY (TLSML),
+ RTYPE_ENTRY (TOCU),
+ RTYPE_ENTRY (TOCL),
+ { 0, NULL }
+ };
+
+/* Simplified section header. */
+struct xcoff32_section
+{
+ /* NUL terminated name. */
+ char name[9];
+
+ /* Section flags. */
+ unsigned int flags;
+
+ /* Offsets in file. */
+ ufile_ptr scnptr;
+ ufile_ptr relptr;
+ ufile_ptr lnnoptr;
+
+ /* Number of relocs and line numbers. */
+ unsigned int nreloc;
+ unsigned int nlnno;
+};
+
+/* Simplified symbol. */
+
+union xcoff32_symbol
+{
+ union external_auxent aux;
+
+ struct sym
+ {
+ /* Pointer the the NUL-terminated name. */
+ char *name;
+
+ /* XCOFF symbol fields. */
+ unsigned int val;
+ unsigned short scnum;
+ unsigned short ntype;
+ unsigned char sclass;
+ unsigned char numaux;
+
+ /* Buffer in case the name is local. */
+ union
+ {
+ char name[9];
+ unsigned int off;
+ } raw;
+ } sym;
+};
+
+/* Important fields to dump the file. */
+
+struct xcoff_dump
+{
+ /* From file header. */
+ unsigned short nscns;
+ unsigned int symptr;
+ unsigned int nsyms;
+ unsigned short opthdr;
+
+ /* Sections. */
+ struct xcoff32_section *sects;
+
+ /* Symbols. */
+ union xcoff32_symbol *syms;
+ char *strings;
+ unsigned int strings_size;
+};
+
+/* Print a symbol (if possible). */
+
+static void
+xcoff32_print_symbol (struct xcoff_dump *data, unsigned int symndx)
+{
+ if (data->syms != NULL
+ && symndx < data->nsyms
+ && data->syms[symndx].sym.name != NULL)
+ printf ("%s", data->syms[symndx].sym.name);
+ else
+ printf ("%u", symndx);
+}
+
+/* Dump the file header. */
+
+static void
+dump_xcoff32_file_header (bfd *abfd, struct external_filehdr *fhdr,
+ struct xcoff_dump *data)
+{
+ unsigned int timdat = bfd_h_get_32 (abfd, fhdr->f_timdat);
+ unsigned short flags = bfd_h_get_16 (abfd, fhdr->f_flags);
+
+ printf (_(" nbr sections: %d\n"), data->nscns);
+ printf (_(" time and date: 0x%08x - "), timdat);
+ if (timdat == 0)
+ printf (_("not set\n"));
+ else
+ {
+ /* Not correct on all platforms, but works on unix. */
+ time_t t = timdat;
+ fputs (ctime (&t), stdout);
+ }
+ printf (_(" symbols off: 0x%08x\n"), data->symptr);
+ printf (_(" nbr symbols: %d\n"), data->nsyms);
+ printf (_(" opt hdr sz: %d\n"), data->opthdr);
+ printf (_(" flags: 0x%04x "), flags);
+ dump_flags (f_flag_xlat, flags);
+ putchar ('\n');
+}
+
+/* Dump the a.out header. */
+
+static void
+dump_xcoff32_aout_header (bfd *abfd, struct xcoff_dump *data)
+{
+ AOUTHDR auxhdr;
+ unsigned short magic;
+ unsigned int sz = data->opthdr;
+
+ printf (_("Auxiliary header:\n"));
+ if (data->opthdr == 0)
+ {
+ printf (_(" No aux header\n"));
+ return;
+ }
+ if (data->opthdr > sizeof (auxhdr))
+ {
+ printf (_("warning: optionnal header size too large (> %d)\n"),
+ (int)sizeof (auxhdr));
+ sz = sizeof (auxhdr);
+ }
+ if (bfd_bread (&auxhdr, sz, abfd) != sz)
+ {
+ non_fatal (_("cannot read auxhdr"));
+ return;
+ }
+
+ magic = bfd_h_get_16 (abfd, auxhdr.magic);
+ printf (_(" o_mflag (magic): 0x%04x 0%04o\n"), magic, magic);
+ printf (_(" o_vstamp: 0x%04x\n"),
+ (unsigned short)bfd_h_get_16 (abfd, auxhdr.vstamp));
+ printf (_(" o_tsize: 0x%08x\n"),
+ (unsigned int)bfd_h_get_32 (abfd, auxhdr.tsize));
+ printf (_(" o_dsize: 0x%08x\n"),
+ (unsigned int)bfd_h_get_32 (abfd, auxhdr.dsize));
+ printf (_(" o_entry: 0x%08x\n"),
+ (unsigned int)bfd_h_get_32 (abfd, auxhdr.entry));
+ printf (_(" o_text_start: 0x%08x\n"),
+ (unsigned int)bfd_h_get_32 (abfd, auxhdr.text_start));
+ printf (_(" o_data_start: 0x%08x\n"),
+ (unsigned int)bfd_h_get_32 (abfd, auxhdr.data_start));
+ if (sz == offsetof (AOUTHDR, o_toc))
+ return;
+ printf (_(" o_toc: 0x%08x\n"),
+ (unsigned int)bfd_h_get_32 (abfd, auxhdr.o_toc));
+ printf (_(" o_snentry: 0x%04x\n"),
+ (unsigned int)bfd_h_get_16 (abfd, auxhdr.o_snentry));
+ printf (_(" o_sntext: 0x%04x\n"),
+ (unsigned int)bfd_h_get_16 (abfd, auxhdr.o_sntext));
+ printf (_(" o_sndata: 0x%04x\n"),
+ (unsigned int)bfd_h_get_16 (abfd, auxhdr.o_sndata));
+ printf (_(" o_sntoc: 0x%04x\n"),
+ (unsigned int)bfd_h_get_16 (abfd, auxhdr.o_sntoc));
+ printf (_(" o_snloader: 0x%04x\n"),
+ (unsigned int)bfd_h_get_16 (abfd, auxhdr.o_snloader));
+ printf (_(" o_snbss: 0x%04x\n"),
+ (unsigned int)bfd_h_get_16 (abfd, auxhdr.o_snbss));
+ printf (_(" o_algntext: %u\n"),
+ (unsigned int)bfd_h_get_16 (abfd, auxhdr.o_algntext));
+ printf (_(" o_algndata: %u\n"),
+ (unsigned int)bfd_h_get_16 (abfd, auxhdr.o_algndata));
+ printf (_(" o_modtype: 0x%04x"),
+ (unsigned int)bfd_h_get_16 (abfd, auxhdr.o_modtype));
+ if (ISPRINT (auxhdr.o_modtype[0]) && ISPRINT (auxhdr.o_modtype[1]))
+ printf (" (%c%c)", auxhdr.o_modtype[0], auxhdr.o_modtype[1]);
+ putchar ('\n');
+ printf (_(" o_cputype: 0x%04x\n"),
+ (unsigned int)bfd_h_get_16 (abfd, auxhdr.o_cputype));
+ printf (_(" o_maxstack: 0x%08x\n"),
+ (unsigned int)bfd_h_get_32 (abfd, auxhdr.o_maxstack));
+ printf (_(" o_maxdata: 0x%08x\n"),
+ (unsigned int)bfd_h_get_32 (abfd, auxhdr.o_maxdata));
+#if 0
+ printf (_(" o_debugger: 0x%08x\n"),
+ (unsigned int)bfd_h_get_32 (abfd, auxhdr.o_debugger));
+#endif
+}
+
+/* Dump the sections header. */
+
+static void
+dump_xcoff32_sections_header (bfd *abfd, struct xcoff_dump *data)
+{
+ unsigned int i;
+ unsigned int off;
+
+ off = sizeof (struct external_filehdr) + data->opthdr;
+ printf (_("Section headers (at %u+%u=0x%08x to 0x%08x):\n"),
+ (unsigned int)sizeof (struct external_filehdr), data->opthdr, off,
+ off + (unsigned int)sizeof (struct external_scnhdr) * data->nscns);
+ if (data->nscns == 0)
+ {
+ printf (_(" No section header\n"));
+ return;
+ }
+ if (bfd_seek (abfd, off, SEEK_SET) != 0)
+ {
+ non_fatal (_("cannot read section header"));
+ return;
+ }
+ printf (_(" # Name paddr vaddr size scnptr relptr lnnoptr nrel nlnno\n"));
+ for (i = 0; i < data->nscns; i++)
+ {
+ struct external_scnhdr scn;
+ unsigned int flags;
+
+ if (bfd_bread (&scn, sizeof (scn), abfd) != sizeof (scn))
+ {
+ non_fatal (_("cannot read section header"));
+ return;
+ }
+ flags = bfd_h_get_32 (abfd, scn.s_flags);
+ printf (_("%2d %-8.8s %08x %08x %08x %08x %08x %08x "
+ "%-5d %-5d\n"),
+ i + 1, scn.s_name,
+ (unsigned int)bfd_h_get_32 (abfd, scn.s_paddr),
+ (unsigned int)bfd_h_get_32 (abfd, scn.s_vaddr),
+ (unsigned int)bfd_h_get_32 (abfd, scn.s_size),
+ (unsigned int)bfd_h_get_32 (abfd, scn.s_scnptr),
+ (unsigned int)bfd_h_get_32 (abfd, scn.s_relptr),
+ (unsigned int)bfd_h_get_32 (abfd, scn.s_lnnoptr),
+ (unsigned int)bfd_h_get_16 (abfd, scn.s_nreloc),
+ (unsigned int)bfd_h_get_16 (abfd, scn.s_nlnno));
+ printf (_(" Flags: %08x "), flags);
+
+ if (~flags == 0)
+ {
+ /* Stripped executable ? */
+ putchar ('\n');
+ }
+ else if (flags & STYP_OVRFLO)
+ printf (_("overflow - nreloc: %u, nlnno: %u\n"),
+ (unsigned int)bfd_h_get_32 (abfd, scn.s_paddr),
+ (unsigned int)bfd_h_get_32 (abfd, scn.s_vaddr));
+ else
+ {
+ dump_flags (s_flag_xlat, flags);
+ putchar ('\n');
+ }
+ }
+}
+
+/* Read section table. */
+
+static void
+xcoff32_read_sections (bfd *abfd, struct xcoff_dump *data)
+{
+ int i;
+
+ if (bfd_seek (abfd, sizeof (struct external_filehdr) + data->opthdr,
+ SEEK_SET) != 0)
+ {
+ non_fatal (_("cannot read section headers"));
+ return;
+ }
+
+ data->sects = xmalloc (data->nscns * sizeof (struct xcoff32_section));
+ for (i = 0; i < data->nscns; i++)
+ {
+ struct external_scnhdr scn;
+ struct xcoff32_section *s = &data->sects[i];
+
+ if (bfd_bread (&scn, sizeof (scn), abfd) != sizeof (scn))
+ {
+ non_fatal (_("cannot read section header"));
+ free (data->sects);
+ data->sects = NULL;
+ return;
+ }
+ memcpy (s->name, scn.s_name, 8);
+ s->name[8] = 0;
+ s->flags = bfd_h_get_32 (abfd, scn.s_flags);
+
+ s->scnptr = bfd_h_get_32 (abfd, scn.s_scnptr);
+ s->relptr = bfd_h_get_32 (abfd, scn.s_relptr);
+ s->lnnoptr = bfd_h_get_32 (abfd, scn.s_lnnoptr);
+
+ s->nreloc = bfd_h_get_16 (abfd, scn.s_nreloc);
+ s->nlnno = bfd_h_get_16 (abfd, scn.s_nlnno);
+
+ if (s->flags == STYP_OVRFLO)
+ {
+ if (s->nreloc > 0 && s->nreloc <= data->nscns)
+ data->sects[s->nreloc - 1].nreloc =
+ bfd_h_get_32 (abfd, scn.s_paddr);
+ if (s->nlnno > 0 && s->nlnno <= data->nscns)
+ data->sects[s->nlnno - 1].nlnno =
+ bfd_h_get_32 (abfd, scn.s_vaddr);
+ }
+ }
+}
+
+/* Read symbols. */
+
+static void
+xcoff32_read_symbols (bfd *abfd, struct xcoff_dump *data)
+{
+ unsigned int i;
+ char stsz_arr[4];
+ unsigned int stptr;
+
+ if (data->nsyms == 0)
+ return;
+
+ stptr = data->symptr
+ + data->nsyms * (unsigned)sizeof (struct external_syment);
+
+ /* Read string table. */
+ if (bfd_seek (abfd, stptr, SEEK_SET) != 0)
+ {
+ data->strings_size = 0;
+ }
+ else
+ {
+ if (bfd_bread (&stsz_arr, sizeof (stsz_arr), abfd) != sizeof (stsz_arr))
+ {
+ non_fatal (_("cannot read strings table len"));
+ return;
+ }
+ data->strings_size = bfd_h_get_32 (abfd, stsz_arr);
+ if (data->strings_size > sizeof (stsz_arr))
+ {
+ unsigned int remsz = data->strings_size - sizeof (stsz_arr);
+
+ data->strings = xmalloc (data->strings_size);
+
+ memcpy (data->strings, stsz_arr, sizeof (stsz_arr));
+ if (bfd_bread (data->strings + sizeof (stsz_arr), remsz, abfd)
+ != remsz)
+ {
+ non_fatal (_("cannot read strings table"));
+ goto clean;
+ }
+ }
+ }
+
+ if (bfd_seek (abfd, data->symptr, SEEK_SET) != 0)
+ {
+ non_fatal (_("cannot read symbol table"));
+ goto clean;
+ }
+
+ data->syms = (union xcoff32_symbol *)
+ xmalloc (data->nsyms * sizeof (union xcoff32_symbol));
+
+ for (i = 0; i < data->nsyms; i++)
+ {
+ struct external_syment sym;
+ int j;
+ union xcoff32_symbol *s = &data->syms[i];
+
+ if (bfd_bread (&sym, sizeof (sym), abfd) != sizeof (sym))
+ {
+ non_fatal (_("cannot read symbol entry"));
+ goto clean;
+ }
+
+ s->sym.val = bfd_h_get_32 (abfd, sym.e_value);
+ s->sym.scnum = bfd_h_get_16 (abfd, sym.e_scnum);
+ s->sym.ntype = bfd_h_get_16 (abfd, sym.e_type);
+ s->sym.sclass = bfd_h_get_8 (abfd, sym.e_sclass);
+ s->sym.numaux = bfd_h_get_8 (abfd, sym.e_numaux);
+
+ if (sym.e.e_name[0])
+ {
+ memcpy (s->sym.raw.name, sym.e.e_name, sizeof (sym.e.e_name));
+ s->sym.raw.name[8] = 0;
+ s->sym.name = s->sym.raw.name;
+ }
+ else
+ {
+ unsigned int soff = bfd_h_get_32 (abfd, sym.e.e.e_offset);
+
+ if ((s->sym.sclass & DBXMASK) == 0 && soff < data->strings_size)
+ s->sym.name = data->strings + soff;
+ else
+ {
+ s->sym.name = NULL;
+ s->sym.raw.off = soff;
+ }
+ }
+
+ for (j = 0; j < s->sym.numaux; j++, i++)
+ {
+ if (bfd_bread (&s[j + 1].aux,
+ sizeof (union external_auxent), abfd)
+ != sizeof (union external_auxent))
+ {
+ non_fatal (_("cannot read symbol aux entry"));
+ goto clean;
+ }
+ }
+ }
+ return;
+ clean:
+ free (data->syms);
+ data->syms = NULL;
+ free (data->strings);
+ data->strings = NULL;
+}
+
+/* Dump xcoff symbols. */
+
+static void
+dump_xcoff32_symbols (bfd *abfd, struct xcoff_dump *data)
+{
+ unsigned int i;
+ asection *debugsec;
+ char *debug = NULL;
+
+ printf (_("Symbols table (strtable at 0x%08x)"),
+ data->symptr
+ + data->nsyms * (unsigned)sizeof (struct external_syment));
+ if (data->nsyms == 0 || data->syms == NULL)
+ {
+ printf (_(":\n No symbols\n"));
+ return;
+ }
+
+ /* Read string table. */
+ if (data->strings_size == 0)
+ printf (_(" (no strings):\n"));
+ else
+ printf (_(" (strings size: %08x):\n"), data->strings_size);
+
+ /* Read debug section. */
+ debugsec = bfd_get_section_by_name (abfd, ".debug");
+ if (debugsec != NULL)
+ {
+ bfd_size_type size;
+
+ size = bfd_get_section_size (debugsec);
+ debug = (char *) xmalloc (size);
+ bfd_get_section_contents (abfd, debugsec, debug, 0, size);
+ }
+
+ printf (_(" # sc value section type aux name/off\n"));
+ for (i = 0; i < data->nsyms; i++)
+ {
+ union xcoff32_symbol *s = &data->syms[i];
+ int j;
+
+ printf ("%3u ", i);
+ dump_value (sc_xlat, s->sym.sclass, 10);
+ printf (" %08x ", s->sym.val);
+ if (s->sym.scnum > 0 && s->sym.scnum <= data->nscns)
+ {
+ if (data->sects != NULL)
+ printf ("%-8s", data->sects[s->sym.scnum - 1].name);
+ else
+ printf ("%-8u", s->sym.scnum);
+ }
+ else
+ switch ((signed short)s->sym.scnum)
+ {
+ case N_DEBUG:
+ printf ("N_DEBUG ");
+ break;
+ case N_ABS:
+ printf ("N_ABS ");
+ break;
+ case N_UNDEF:
+ printf ("N_UNDEF ");
+ break;
+ default:
+ printf ("(%04x) ", s->sym.scnum);
+ }
+ printf (" %04x %3u ", s->sym.ntype, s->sym.numaux);
+ if (s->sym.name != NULL)
+ printf ("%s", s->sym.name);
+ else
+ {
+ if ((s->sym.sclass & DBXMASK) != 0 && debug != NULL)
+ printf ("%s", debug + s->sym.raw.off);
+ else
+ printf ("%08x", s->sym.raw.off);
+ }
+ putchar ('\n');
+
+ for (j = 0; j < s->sym.numaux; j++, i++)
+ {
+ union external_auxent *aux = &s[j + 1].aux;
+
+ printf (" %3u ", i + 1);
+ switch (s->sym.sclass)
+ {
+ case C_STAT:
+ printf (_(" scnlen: %08x nreloc: %-6u nlinno: %-6u\n"),
+ (unsigned)bfd_h_get_32 (abfd, aux->x_scn.x_scnlen),
+ (unsigned)bfd_h_get_16 (abfd, aux->x_scn.x_nreloc),
+ (unsigned)bfd_h_get_16 (abfd, aux->x_scn.x_nlinno));
+ break;
+ case C_DWARF:
+ printf (_(" scnlen: %08x nreloc: %-6u\n"),
+ (unsigned)bfd_h_get_32 (abfd, aux->x_scn.x_scnlen),
+ (unsigned)bfd_h_get_16 (abfd, aux->x_scn.x_nreloc));
+ break;
+ case C_EXT:
+ case C_WEAKEXT:
+ case C_HIDEXT:
+ if (j == 0 && s->sym.numaux > 1)
+ {
+ /* Function aux entry. */
+ printf (_(" exptr: %08x fsize: %08x lnnoptr: %08x endndx: %u\n"),
+ (unsigned)bfd_h_get_32 (abfd, aux->x_sym.x_tagndx),
+ (unsigned)bfd_h_get_32
+ (abfd, aux->x_sym.x_misc.x_fsize),
+ (unsigned)bfd_h_get_32
+ (abfd, aux->x_sym.x_fcnary.x_fcn.x_lnnoptr),
+ (unsigned)bfd_h_get_32
+ (abfd, aux->x_sym.x_fcnary.x_fcn.x_endndx));
+ }
+ else if (j == 1 || (j == 0 && s->sym.numaux == 1))
+ {
+ /* csect aux entry. */
+ unsigned char smtyp;
+ unsigned int scnlen;
+
+ smtyp = bfd_h_get_8 (abfd, aux->x_csect.x_smtyp);
+ scnlen = bfd_h_get_32 (abfd, aux->x_csect.x_scnlen);
+
+ if (smtyp == XTY_LD)
+ printf (_(" scnsym: %-8u"), scnlen);
+ else
+ printf (_(" scnlen: %08x"), scnlen);
+ printf (_(" h: parm=%08x sn=%04x al: 2**%u"),
+ (unsigned)bfd_h_get_32 (abfd, aux->x_csect.x_parmhash),
+ (unsigned)bfd_h_get_16 (abfd, aux->x_csect.x_snhash),
+ SMTYP_ALIGN (smtyp));
+ printf (_(" typ: "));
+ dump_value (smtyp_xlat, SMTYP_SMTYP (smtyp), 2);
+ printf (_(" cl: "));
+ dump_value
+ (smclas_xlat,
+ (unsigned)bfd_h_get_8 (abfd, aux->x_csect.x_smclas), 6);
+ putchar ('\n');
+ }
+ else
+ printf ("aux\n");
+ break;
+ case C_FILE:
+ {
+ unsigned int off;
+
+ printf (_(" ftype: %02x "),
+ (unsigned)bfd_h_get_8 (abfd, aux->x_file.x_ftype));
+ if (aux->x_file.x_n.x_fname[0] != 0)
+ printf (_("fname: %.14s"), aux->x_file.x_n.x_fname);
+ else
+ {
+ off = (unsigned)bfd_h_get_32
+ (abfd, aux->x_file.x_n.x_n.x_offset);
+ if (data->strings != NULL && off < data->strings_size)
+ printf (_(" %s"), data->strings + off);
+ else
+ printf (_("offset: %08x"), off);
+ }
+ putchar ('\n');
+ }
+ break;
+ case C_BLOCK:
+ case C_FCN:
+ printf (_(" lnno: %u\n"),
+ (unsigned)bfd_h_get_16
+ (abfd, aux->x_sym.x_misc.x_lnsz.x_lnno));
+ break;
+ default:
+ printf ("aux\n");
+ break;
+ }
+ }
+
+ }
+ free (debug);
+}
+
+/* Dump xcoff relocation entries. */
+
+static void
+dump_xcoff32_relocs (bfd *abfd, struct xcoff_dump *data)
+{
+ unsigned int i;
+
+ if (data->sects == NULL)
+ {
+ non_fatal (_("cannot read section headers"));
+ return;
+ }
+
+ for (i = 0; i < data->nscns; i++)
+ {
+ struct xcoff32_section *sect = &data->sects[i];
+ unsigned int nrel = sect->nreloc;
+ unsigned int j;
+
+ if (nrel == 0)
+ continue;
+ printf (_("Relocations for %s (%u)\n"), sect->name, nrel);
+ if (bfd_seek (abfd, sect->relptr, SEEK_SET) != 0)
+ {
+ non_fatal (_("cannot read relocations"));
+ continue;
+ }
+ printf (_("vaddr sgn mod sz type symndx symbol\n"));
+ for (j = 0; j < nrel; j++)
+ {
+ struct external_reloc rel;
+ unsigned char rsize;
+ unsigned int symndx;
+
+ if (bfd_bread (&rel, sizeof (rel), abfd) != sizeof (rel))
+ {
+ non_fatal (_("cannot read relocation entry"));
+ return;
+ }
+ rsize = bfd_h_get_8 (abfd, rel.r_size);
+ printf (_("%08x %c %c %-2u "),
+ (unsigned int)bfd_h_get_32 (abfd, rel.r_vaddr),
+ rsize & 0x80 ? 'S' : 'U',
+ rsize & 0x40 ? 'm' : ' ',
+ (rsize & 0x3f) + 1);
+ dump_value (rtype_xlat, bfd_h_get_8 (abfd, rel.r_type), 6);
+ symndx = bfd_h_get_32 (abfd, rel.r_symndx);
+ printf ("%-6u ", symndx);
+ xcoff32_print_symbol (data, symndx);
+ putchar ('\n');
+ }
+ putchar ('\n');
+ }
+}
+
+/* Dump xcoff line number entries. */
+
+static void
+dump_xcoff32_lineno (bfd *abfd, struct xcoff_dump *data)
+{
+ unsigned int i;
+
+ if (data->sects == NULL)
+ {
+ non_fatal (_("cannot read section headers"));
+ return;
+ }
+
+ for (i = 0; i < data->nscns; i++)
+ {
+ struct xcoff32_section *sect = &data->sects[i];
+ unsigned int nlnno = sect->nlnno;
+ unsigned int j;
+
+ if (nlnno == 0)
+ continue;
+ printf (_("Line numbers for %s (%u)\n"), sect->name, nlnno);
+ if (bfd_seek (abfd, sect->lnnoptr, SEEK_SET) != 0)
+ {
+ non_fatal (_("cannot read line numbers"));
+ continue;
+ }
+ printf (_("lineno symndx/paddr\n"));
+ for (j = 0; j < nlnno; j++)
+ {
+ struct external_lineno ln;
+ unsigned int no;
+
+ if (bfd_bread (&ln, sizeof (ln), abfd) != sizeof (ln))
+ {
+ non_fatal (_("cannot read line number entry"));
+ return;
+ }
+ no = bfd_h_get_16 (abfd, ln.l_lnno);
+ printf (_(" %-6u "), no);
+ if (no == 0)
+ {
+ unsigned int symndx = bfd_h_get_32 (abfd, ln.l_addr.l_symndx);
+ xcoff32_print_symbol (data, symndx);
+ }
+ else
+ printf ("0x%08x",
+ (unsigned int)bfd_h_get_32 (abfd, ln.l_addr.l_paddr));
+ putchar ('\n');
+ }
+ }
+}
+
+/* Dump xcoff loader section. */
+
+static void
+dump_xcoff32_loader (bfd *abfd)
+{
+ asection *loader;
+ bfd_size_type size = 0;
+ struct external_ldhdr *lhdr;
+ struct external_ldsym *ldsym;
+ struct external_ldrel *ldrel;
+ bfd_byte *ldr_data;
+ unsigned int version;
+ unsigned int ndsyms;
+ unsigned int ndrel;
+ unsigned int stlen;
+ unsigned int stoff;
+ unsigned int impoff;
+ unsigned int nimpid;
+ unsigned int i;
+ const char *p;
+
+ loader = bfd_get_section_by_name (abfd, ".loader");
+
+ if (loader == NULL)
+ {
+ printf (_("no .loader section in file\n"));
+ return;
+ }
+ size = bfd_get_section_size (loader);
+ if (size < sizeof (*lhdr))
+ {
+ printf (_("section .loader is too short\n"));
+ return;
+ }
+
+ ldr_data = (bfd_byte *) xmalloc (size);
+ bfd_get_section_contents (abfd, loader, ldr_data, 0, size);
+ lhdr = (struct external_ldhdr *)ldr_data;
+ printf (_("Loader header:\n"));
+ version = bfd_h_get_32 (abfd, lhdr->l_version);
+ printf (_(" version: %u\n"), version);
+ if (version != 1)
+ {
+ printf (_(" Unhandled version\n"));
+ free (ldr_data);
+ return;
+ }
+ ndsyms = bfd_h_get_32 (abfd, lhdr->l_nsyms);
+ printf (_(" nbr symbols: %u\n"), ndsyms);
+ ndrel = bfd_h_get_32 (abfd, lhdr->l_nreloc);
+ printf (_(" nbr relocs: %u\n"), ndrel);
+ printf (_(" import strtab len: %u\n"),
+ (unsigned) bfd_h_get_32 (abfd, lhdr->l_istlen));
+ nimpid = bfd_h_get_32 (abfd, lhdr->l_nimpid);
+ printf (_(" nbr import files: %u\n"), nimpid);
+ impoff = bfd_h_get_32 (abfd, lhdr->l_impoff);
+ printf (_(" import file off: %u\n"), impoff);
+ stlen = bfd_h_get_32 (abfd, lhdr->l_stlen);
+ printf (_(" string table len: %u\n"), stlen);
+ stoff = bfd_h_get_32 (abfd, lhdr->l_stoff);
+ printf (_(" string table off: %u\n"), stoff);
+
+ ldsym = (struct external_ldsym *)(ldr_data + sizeof (*lhdr));
+ printf (_("Dynamic symbols:\n"));
+ printf (_(" # value sc IFEW ty class file pa name\n"));
+ for (i = 0; i < ndsyms; i++, ldsym++)
+ {
+ unsigned char smtype;
+
+ printf (_(" %4u %08x %3u "), i,
+ (unsigned)bfd_h_get_32 (abfd, ldsym->l_value),
+ (unsigned)bfd_h_get_16 (abfd, ldsym->l_scnum));
+ smtype = bfd_h_get_8 (abfd, ldsym->l_smtype);
+ putchar (smtype & 0x40 ? 'I' : ' ');
+ putchar (smtype & 0x20 ? 'F' : ' ');
+ putchar (smtype & 0x10 ? 'E' : ' ');
+ putchar (smtype & 0x08 ? 'W' : ' ');
+ putchar (' ');
+ dump_value (smtyp_xlat, SMTYP_SMTYP (smtype), 2);
+ putchar (' ');
+ dump_value
+ (smclas_xlat, (unsigned)bfd_h_get_8 (abfd, ldsym->l_smclas), 6);
+ printf (_(" %3u %3u "),
+ (unsigned)bfd_h_get_32 (abfd, ldsym->l_ifile),
+ (unsigned)bfd_h_get_32 (abfd, ldsym->l_parm));
+ if (ldsym->_l._l_name[0] != 0)
+ printf ("%-.8s", ldsym->_l._l_name);
+ else
+ {
+ unsigned int off = bfd_h_get_32 (abfd, ldsym->_l._l_l._l_offset);
+ if (off > stlen)
+ printf (_("(bad offset: %u)"), off);
+ else
+ printf ("%s", ldr_data + stoff + off);
+ }
+ putchar ('\n');
+ }
+
+ printf (_("Dynamic relocs:\n"));
+ printf (_(" vaddr sec sz typ sym\n"));
+ ldrel = (struct external_ldrel *)(ldr_data + sizeof (*lhdr)
+ + ndsyms * sizeof (*ldsym));
+ for (i = 0; i < ndrel; i++, ldrel++)
+ {
+ unsigned int rsize;
+ unsigned int rtype;
+ unsigned int symndx;
+
+ rsize = bfd_h_get_8 (abfd, ldrel->l_rtype + 0);
+ rtype = bfd_h_get_8 (abfd, ldrel->l_rtype + 1);
+
+ printf (_(" %08x %3u %c%c %2u "),
+ (unsigned)bfd_h_get_32 (abfd, ldrel->l_vaddr),
+ (unsigned)bfd_h_get_16 (abfd, ldrel->l_rsecnm),
+ rsize & 0x80 ? 'S' : 'U',
+ rsize & 0x40 ? 'm' : ' ',
+ (rsize & 0x3f) + 1);
+ dump_value (rtype_xlat, rtype, 6);
+ symndx = bfd_h_get_32 (abfd, ldrel->l_symndx);
+ switch (symndx)
+ {
+ case 0:
+ printf (_(".text"));
+ break;
+ case 1:
+ printf (_(".data"));
+ break;
+ case 2:
+ printf (_(".bss"));
+ break;
+ default:
+ printf (_("%u"), symndx - 3);
+ break;
+ }
+ putchar ('\n');
+ }
+
+ printf (_("Import files:\n"));
+ p = (char *)ldr_data + impoff;
+ for (i = 0; i < nimpid; i++)
+ {
+ int n1, n2, n3;
+
+ n1 = strlen (p);
+ n2 = strlen (p + n1 + 1);
+ n3 = strlen (p + n1 + 1 + n2+ 1);
+ printf (" %2u: %s,%s,%s\n", i,
+ p, p + n1 + 1, p + n1 + n2 + 2);
+ p += n1 + n2 + n3 + 3;
+ }
+
+ free (ldr_data);
+}
+
+/* Dump xcoff exception section. */
+
+static void
+dump_xcoff32_except (bfd *abfd, struct xcoff_dump *data)
+{
+ asection *sec;
+ bfd_size_type size = 0;
+ bfd_byte *excp_data;
+ struct external_exceptab *exceptab;
+ unsigned int i;
+
+ sec = bfd_get_section_by_name (abfd, ".except");
+
+ if (sec == NULL)
+ {
+ printf (_("no .except section in file\n"));
+ return;
+ }
+ size = bfd_get_section_size (sec);
+ excp_data = (bfd_byte *) xmalloc (size);
+ bfd_get_section_contents (abfd, sec, excp_data, 0, size);
+ exceptab = (struct external_exceptab *)excp_data;
+
+ printf (_("Exception table:\n"));
+ printf (_("lang reason sym/addr\n"));
+ for (i = 0; i * sizeof (*exceptab) < size; i++, exceptab++)
+ {
+ unsigned int reason;
+ unsigned int addr;
+
+ addr = bfd_get_32 (abfd, exceptab->e_addr.e_paddr);
+ reason = bfd_get_8 (abfd, exceptab->e_reason);
+ printf (_(" %02x %02x "),
+ (unsigned) bfd_get_8 (abfd, exceptab->e_lang), reason);
+ if (reason == 0)
+ xcoff32_print_symbol (data, addr);
+ else
+ printf (_("@%08x"), addr);
+ putchar ('\n');
+ }
+ free (excp_data);
+}
+
+/* Dump xcoff type-check section. */
+
+static void
+dump_xcoff32_typchk (bfd *abfd)
+{
+ asection *sec;
+ bfd_size_type size = 0;
+ bfd_byte *data;
+ unsigned int i;
+
+ sec = bfd_get_section_by_name (abfd, ".typchk");
+
+ if (sec == NULL)
+ {
+ printf (_("no .typchk section in file\n"));
+ return;
+ }
+ size = bfd_get_section_size (sec);
+ data = (bfd_byte *) xmalloc (size);
+ bfd_get_section_contents (abfd, sec, data, 0, size);
+
+ printf (_("Type-check section:\n"));
+ printf (_("offset len lang-id general-hash language-hash\n"));
+ for (i = 0; i < size;)
+ {
+ unsigned int len;
+
+ len = bfd_get_16 (abfd, data + i);
+ printf ("%08x: %-4u ", i, len);
+ i += 2;
+
+ if (len == 10)
+ {
+ /* Expected format. */
+ printf ("%04x %08x %08x\n",
+ (unsigned) bfd_get_16 (abfd, data + i),
+ (unsigned) bfd_get_32 (abfd, data + i + 2),
+ (unsigned) bfd_get_32 (abfd, data + i + 2 + 4));
+ }
+ else
+ {
+ unsigned int j;
+
+ for (j = 0; j < len; j++)
+ {
+ if (j % 16 == 0)
+ printf ("\n ");
+ printf (" %02x", (unsigned char)data[i + j]);
+ }
+ putchar ('\n');
+ }
+ i += len;
+ }
+ free (data);
+}
+
+/* Dump xcoff traceback tags section. */
+
+static void
+dump_xcoff32_tbtags (bfd *abfd,
+ const char *text, bfd_size_type text_size,
+ unsigned int text_start, unsigned int func_start)
+{
+ unsigned int i;
+
+ if (func_start - text_start > text_size)
+ {
+ printf (_(" address beyond section size\n"));
+ return;
+ }
+ for (i = func_start - text_start; i < text_size; i+= 4)
+ if (bfd_get_32 (abfd, text + i) == 0)
+ {
+ unsigned int tb1;
+ unsigned int tb2;
+ unsigned int off;
+
+ printf (_(" tags at %08x\n"), i + 4);
+ if (i + 8 >= text_size)
+ goto truncated;
+
+ tb1 = bfd_get_32 (abfd, text + i + 4);
+ tb2 = bfd_get_32 (abfd, text + i + 8);
+ off = i + 12;
+ printf (_(" version: %u, lang: %u, global_link: %u, is_eprol: %u, has_tboff: %u, int_proc: %u\n"),
+ (tb1 >> 24) & 0xff,
+ (tb1 >> 16) & 0xff,
+ (tb1 >> 15) & 1,
+ (tb1 >> 14) & 1,
+ (tb1 >> 13) & 1,
+ (tb1 >> 12) & 1);
+ printf (_(" has_ctl: %u, tocless: %u, fp_pres: %u, log_abort: %u, int_hndl: %u\n"),
+ (tb1 >> 11) & 1,
+ (tb1 >> 10) & 1,
+ (tb1 >> 9) & 1,
+ (tb1 >> 8) & 1,
+ (tb1 >> 7) & 1);
+ printf (_(" name_pres: %u, uses_alloca: %u, cl_dis_inv: %u, saves_cr: %u, saves_lr: %u\n"),
+ (tb1 >> 6) & 1,
+ (tb1 >> 5) & 1,
+ (tb1 >> 2) & 7,
+ (tb1 >> 1) & 1,
+ (tb1 >> 0) & 1);
+ printf (_(" stores_bc: %u, fixup: %u, fpr_saved: %-2u, spare3: %u, gpr_saved: %-2u\n"),
+ (tb2 >> 31) & 1,
+ (tb2 >> 30) & 1,
+ (tb2 >> 24) & 63,
+ (tb2 >> 22) & 3,
+ (tb2 >> 16) & 63);
+ printf (_(" fixparms: %-3u floatparms: %-3u parm_on_stk: %u\n"),
+ (tb2 >> 8) & 0xff,
+ (tb2 >> 1) & 0x7f,
+ (tb2 >> 0) & 1);
+
+ if (((tb2 >> 1) & 0x7fff) != 0)
+ {
+ unsigned int parminfo;
+
+ if (off >= text_size)
+ goto truncated;
+ parminfo = bfd_get_32 (abfd, text + off);
+ off += 4;
+ printf (_(" parminfo: 0x%08x\n"), parminfo);
+ }
+
+ if ((tb1 >> 13) & 1)
+ {
+ unsigned int tboff;
+
+ if (off >= text_size)
+ goto truncated;
+ tboff = bfd_get_32 (abfd, text + off);
+ off += 4;
+ printf (_(" tb_offset: 0x%08x (start=0x%08x)\n"),
+ tboff, text_start + i - tboff);
+ }
+ if ((tb1 >> 7) & 1)
+ {
+ unsigned int hand_mask;
+
+ if (off >= text_size)
+ goto truncated;
+ hand_mask = bfd_get_32 (abfd, text + off);
+ off += 4;
+ printf (_(" hand_mask_offset: 0x%08x\n"), hand_mask);
+ }
+ if ((tb1 >> 11) & 1)
+ {
+ unsigned int ctl_info;
+ unsigned int j;
+
+ if (off >= text_size)
+ goto truncated;
+ ctl_info = bfd_get_32 (abfd, text + off);
+ off += 4;
+ printf (_(" number of CTL anchors: %u\n"), ctl_info);
+ for (j = 0; j < ctl_info; j++)
+ {
+ if (off >= text_size)
+ goto truncated;
+ printf (_(" CTL[%u]: %08x\n"),
+ j, (unsigned)bfd_get_32 (abfd, text + off));
+ off += 4;
+ }
+ }
+ if ((tb1 >> 6) & 1)
+ {
+ unsigned int name_len;
+ unsigned int j;
+
+ if (off >= text_size)
+ goto truncated;
+ name_len = bfd_get_16 (abfd, text + off);
+ off += 2;
+ printf (_(" Name (len: %u): "), name_len);
+ if (off + name_len >= text_size)
+ {
+ printf (_("[truncated]\n"));
+ goto truncated;
+ }
+ for (j = 0; j < name_len; j++)
+ if (ISPRINT (text[off + j]))
+ putchar (text[off + j]);
+ else
+ printf ("[%02x]", (unsigned char)text[off + j]);
+ putchar ('\n');
+ off += name_len;
+ }
+ if ((tb1 >> 5) & 1)
+ {
+ if (off >= text_size)
+ goto truncated;
+ printf (_(" alloca reg: %u\n"),
+ (unsigned) bfd_get_8 (abfd, text + off));
+ off++;
+ }
+ printf (_(" (end of tags at %08x)\n"), text_start + off);
+ return;
+ }
+ printf (_(" no tags found\n"));
+ return;
+
+ truncated:
+ printf (_(" Truncated .text section\n"));
+ return;
+}
+
+static void
+dump_xcoff32_traceback (bfd *abfd, struct xcoff_dump *data)
+{
+ unsigned int i;
+ unsigned int scnum_text = -1;
+ unsigned int text_vma;
+ asection *text_sec;
+ bfd_size_type text_size;
+ char *text;
+
+ if (data->syms == NULL || data->sects == NULL)
+ return;
+
+ /* Read text section. */
+ text_sec = bfd_get_section_by_name (abfd, ".text");
+ if (text_sec == NULL)
+ return;
+ text_vma = bfd_get_section_vma (abfd, text_sec);
+
+ text_size = bfd_get_section_size (text_sec);
+ text = (char *) xmalloc (text_size);
+ bfd_get_section_contents (abfd, text_sec, text, 0, text_size);
+
+ for (i = 0; i < data->nscns; i++)
+ if (data->sects[i].flags == STYP_TEXT)
+ {
+ scnum_text = i + 1;
+ break;
+ }
+ if (scnum_text == (unsigned int)-1)
+ return;
+
+ for (i = 0; i < data->nsyms; i++)
+ {
+ union xcoff32_symbol *s = &data->syms[i];
+
+ switch (s->sym.sclass)
+ {
+ case C_EXT:
+ case C_HIDEXT:
+ case C_WEAKEXT:
+ if (s->sym.scnum == scnum_text
+ && s->sym.numaux > 0)
+ {
+ union external_auxent *aux = &s[s->sym.numaux].aux;
+
+ unsigned int smtyp;
+ unsigned int smclas;
+
+ smtyp = bfd_h_get_8 (abfd, aux->x_csect.x_smtyp);
+ smclas = bfd_h_get_8 (abfd, aux->x_csect.x_smclas);
+ if (SMTYP_SMTYP (smtyp) == XTY_LD
+ && (smclas == XMC_PR
+ || smclas == XMC_GL
+ || smclas == XMC_XO))
+ {
+ printf ("%08x: ", s->sym.val);
+ xcoff32_print_symbol (data, i);
+ putchar ('\n');
+ dump_xcoff32_tbtags (abfd, text, text_size,
+ text_vma, s->sym.val);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ i += s->sym.numaux;
+ }
+ free (text);
+}
+
+/* Dump the TOC symbols. */
+
+static void
+dump_xcoff32_toc (bfd *abfd, struct xcoff_dump *data)
+{
+ unsigned int i;
+ unsigned int nbr_ent;
+ unsigned int size;
+
+ printf (_("TOC:\n"));
+
+ if (data->syms == NULL)
+ return;
+
+ nbr_ent = 0;
+ size = 0;
+
+ for (i = 0; i < data->nsyms; i++)
+ {
+ union xcoff32_symbol *s = &data->syms[i];
+
+ switch (s->sym.sclass)
+ {
+ case C_EXT:
+ case C_HIDEXT:
+ case C_WEAKEXT:
+ if (s->sym.numaux > 0)
+ {
+ union external_auxent *aux = &s[s->sym.numaux].aux;
+ unsigned int smclas;
+ unsigned int ent_sz;
+
+ smclas = bfd_h_get_8 (abfd, aux->x_csect.x_smclas);
+ if (smclas == XMC_TC
+ || smclas == XMC_TD
+ || smclas == XMC_TC0)
+ {
+ ent_sz = bfd_h_get_32 (abfd, aux->x_scn.x_scnlen);
+ printf ("%08x %08x ",
+ s->sym.val, ent_sz);
+ xcoff32_print_symbol (data, i);
+ putchar ('\n');
+ nbr_ent++;
+ size += ent_sz;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ i += s->sym.numaux;
+ }
+ printf (_("Nbr entries: %-8u Size: %08x (%u)\n"),
+ nbr_ent, size, size);
+}
+
+/* Handle an rs6000 xcoff file. */
+
+static void
+dump_xcoff32 (bfd *abfd, struct external_filehdr *fhdr)
+{
+ struct xcoff_dump data;
+
+ data.nscns = bfd_h_get_16 (abfd, fhdr->f_nscns);
+ data.symptr = bfd_h_get_32 (abfd, fhdr->f_symptr);
+ data.nsyms = bfd_h_get_32 (abfd, fhdr->f_nsyms);
+ data.opthdr = bfd_h_get_16 (abfd, fhdr->f_opthdr);
+ data.sects = NULL;
+ data.syms = NULL;
+ data.strings = NULL;
+ data.strings_size = 0;
+
+ if (options[OPT_FILE_HEADER].selected)
+ dump_xcoff32_file_header (abfd, fhdr, &data);
+
+ if (options[OPT_AOUT].selected)
+ dump_xcoff32_aout_header (abfd, &data);
+
+ if (options[OPT_SYMS].selected
+ || options[OPT_RELOCS].selected
+ || options[OPT_LINENO].selected
+ || options[OPT_TRACEBACK].selected)
+ xcoff32_read_sections (abfd, &data);
+
+ if (options[OPT_SECTIONS].selected)
+ dump_xcoff32_sections_header (abfd, &data);
+
+ if (options[OPT_SYMS].selected
+ || options[OPT_RELOCS].selected
+ || options[OPT_LINENO].selected
+ || options[OPT_EXCEPT].selected
+ || options[OPT_TRACEBACK].selected
+ || options[OPT_TOC].selected)
+ xcoff32_read_symbols (abfd, &data);
+
+ if (options[OPT_SYMS].selected)
+ dump_xcoff32_symbols (abfd, &data);
+
+ if (options[OPT_RELOCS].selected)
+ dump_xcoff32_relocs (abfd, &data);
+
+ if (options[OPT_LINENO].selected)
+ dump_xcoff32_lineno (abfd, &data);
+
+ if (options[OPT_LOADER].selected)
+ dump_xcoff32_loader (abfd);
+
+ if (options[OPT_EXCEPT].selected)
+ dump_xcoff32_except (abfd, &data);
+
+ if (options[OPT_TYPCHK].selected)
+ dump_xcoff32_typchk (abfd);
+
+ if (options[OPT_TRACEBACK].selected)
+ dump_xcoff32_traceback (abfd, &data);
+
+ if (options[OPT_TOC].selected)
+ dump_xcoff32_toc (abfd, &data);
+
+ free (data.sects);
+ free (data.strings);
+ free (data.syms);
+}
+
+/* Dump ABFD (according to the options[] array). */
+
+static void
+xcoff_dump (bfd *abfd)
+{
+ struct external_filehdr fhdr;
+ unsigned short magic;
+
+ /* Read file header. */
+ if (bfd_seek (abfd, 0, SEEK_SET) != 0
+ || bfd_bread (&fhdr, sizeof (fhdr), abfd) != sizeof (fhdr))
+ {
+ non_fatal (_("cannot read header"));
+ return;
+ }
+
+ /* Decoding. We don't use the bfd/coff function to get all the fields. */
+ magic = bfd_h_get_16 (abfd, fhdr.f_magic);
+ if (options[OPT_FILE_HEADER].selected)
+ {
+ printf (_("File header:\n"));
+ printf (_(" magic: 0x%04x (0%04o) "), magic, magic);
+ switch (magic)
+ {
+ case U802WRMAGIC:
+ printf (_("(WRMAGIC: writable text segments)"));
+ break;
+ case U802ROMAGIC:
+ printf (_("(ROMAGIC: readonly sharablee text segments)"));
+ break;
+ case U802TOCMAGIC:
+ printf (_("(TOCMAGIC: readonly text segments and TOC)"));
+ break;
+ default:
+ printf (_("unknown magic"));
+ }
+ putchar ('\n');
+ }
+ if (magic == U802ROMAGIC || magic == U802WRMAGIC || magic == U802TOCMAGIC)
+ dump_xcoff32 (abfd, &fhdr);
+ else
+ printf (_(" Unhandled magic\n"));
+}
+
+/* Vector for xcoff. */
+
+const struct objdump_private_desc objdump_private_desc_xcoff =
+ {
+ xcoff_help,
+ xcoff_filter,
+ xcoff_dump,
+ options
+ };