diff options
author | Tristan Gingold <gingold@adacore.com> | 2011-05-16 12:22:13 +0000 |
---|---|---|
committer | Tristan Gingold <gingold@adacore.com> | 2011-05-16 12:22:13 +0000 |
commit | 6abcee9042f9603cf9fdeb62fa55335a6aa974e9 (patch) | |
tree | b39c076736f3af34bd9e1bb7a766598a3c6a96d1 /binutils/od-xcoff.c | |
parent | f37a7048a8608dcc4465a4b425cc4fd3b0f9e1cd (diff) | |
download | gdb-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.c | 1670 |
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 + }; |