OSDN Git Service

2011-05-16 Tristan Gingold <gingold@adacore.com>
authorgingold <gingold>
Mon, 16 May 2011 12:22:10 +0000 (12:22 +0000)
committergingold <gingold>
Mon, 16 May 2011 12:22:10 +0000 (12:22 +0000)
* 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.

binutils/Makefile.am
binutils/Makefile.in
binutils/configure
binutils/configure.in
binutils/doc/binutils.texi
binutils/objdump.c
binutils/objdump.h [new file with mode: 0644]
binutils/od-xcoff.c [new file with mode: 0644]

index 6546087..6f9e4a8 100644 (file)
@@ -85,7 +85,7 @@ AM_CPPFLAGS = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) \
 HFILES = \
        arsup.h binemul.h bucomm.h budbg.h \
        coffgrok.h debug.h dlltool.h dwarf.h elfcomm.h nlmconv.h \
-       sysdep.h unwind-ia64.h windres.h winduni.h windint.h \
+       objdump.h sysdep.h unwind-ia64.h windres.h winduni.h windint.h \
        windmc.h
 
 GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h rcparse.h mcparse.h
@@ -99,6 +99,7 @@ CFILES = \
        ieee.c is-ranlib.c is-strip.c maybe-ranlib.c maybe-strip.c \
        nlmconv.c nm.c not-ranlib.c not-strip.c \
        objcopy.c objdump.c prdbg.c \
+       od-xcoff.c \
        rclex.c rdcoff.c rddbg.c readelf.c rename.c \
        resbin.c rescoff.c resrc.c resres.c \
        size.c srconv.c stabs.c strings.c sysdump.c \
@@ -113,6 +114,9 @@ GENERATED_CFILES = \
 DEBUG_SRCS = rddbg.c debug.c stabs.c ieee.c rdcoff.c
 WRITE_DEBUG_SRCS = $(DEBUG_SRCS) wrstabs.c
 
+# Extra object files for objdump
+OBJDUMP_PRIVATE_OFILES = @OBJDUMP_PRIVATE_OFILES@
+
 # Code shared by all the binutils.
 BULIBS = bucomm.c version.c filemode.c
 
@@ -167,7 +171,7 @@ installcheck-local:
 # which depends on libintl, since we don't know whether LIBINTL_DEP will be
 # non-empty until configure time.  Ugh!
 size_DEPENDENCIES =      $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
-objdump_DEPENDENCIES =   $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) $(OPCODES)
+objdump_DEPENDENCIES =   $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) $(OPCODES) $(OBJDUMP_PRIVATE_OFILES)
 nm_new_DEPENDENCIES =    $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 ar_DEPENDENCIES =        $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 strings_DEPENDENCIES =   $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
@@ -206,7 +210,8 @@ strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
 nm_new_SOURCES = nm.c $(BULIBS)
 
 objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS) $(ELFLIBS)
-objdump_LDADD = $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
+EXTRA_objdump_SOURCES = od-xcoff.c
+objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
 
 objdump.@OBJEXT@:objdump.c
 if am__fastdepCC
index 8e3d7f2..10b9e3f 100644 (file)
@@ -200,9 +200,10 @@ SOURCES = $(addr2line_SOURCES) $(ar_SOURCES) $(EXTRA_ar_SOURCES) \
        $(coffdump_SOURCES) $(cxxfilt_SOURCES) $(dlltool_SOURCES) \
        $(dllwrap_SOURCES) $(elfedit_SOURCES) $(nlmconv_SOURCES) \
        $(nm_new_SOURCES) $(objcopy_SOURCES) $(objdump_SOURCES) \
-       $(ranlib_SOURCES) $(readelf_SOURCES) $(size_SOURCES) \
-       $(srconv_SOURCES) $(strings_SOURCES) $(strip_new_SOURCES) \
-       $(sysdump_SOURCES) $(windmc_SOURCES) $(windres_SOURCES)
+       $(EXTRA_objdump_SOURCES) $(ranlib_SOURCES) $(readelf_SOURCES) \
+       $(size_SOURCES) $(srconv_SOURCES) $(strings_SOURCES) \
+       $(strip_new_SOURCES) $(sysdump_SOURCES) $(windmc_SOURCES) \
+       $(windres_SOURCES)
 RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
        html-recursive info-recursive install-data-recursive \
        install-dvi-recursive install-exec-recursive \
@@ -298,6 +299,9 @@ NMEDIT = @NMEDIT@
 NO_WERROR = @NO_WERROR@
 OBJDUMP = @OBJDUMP@
 OBJDUMP_DEFS = @OBJDUMP_DEFS@
+
+# Extra object files for objdump
+OBJDUMP_PRIVATE_OFILES = @OBJDUMP_PRIVATE_OFILES@
 OBJEXT = @OBJEXT@
 OTOOL = @OTOOL@
 OTOOL64 = @OTOOL64@
@@ -429,7 +433,7 @@ AM_CPPFLAGS = -I. -I$(srcdir) -I../bfd -I$(BFDDIR) -I$(INCDIR) \
 HFILES = \
        arsup.h binemul.h bucomm.h budbg.h \
        coffgrok.h debug.h dlltool.h dwarf.h elfcomm.h nlmconv.h \
-       sysdep.h unwind-ia64.h windres.h winduni.h windint.h \
+       objdump.h sysdep.h unwind-ia64.h windres.h winduni.h windint.h \
        windmc.h
 
 GENERATED_HFILES = arparse.h sysroff.h sysinfo.h defparse.h rcparse.h mcparse.h
@@ -442,6 +446,7 @@ CFILES = \
        ieee.c is-ranlib.c is-strip.c maybe-ranlib.c maybe-strip.c \
        nlmconv.c nm.c not-ranlib.c not-strip.c \
        objcopy.c objdump.c prdbg.c \
+       od-xcoff.c \
        rclex.c rdcoff.c rddbg.c readelf.c rename.c \
        resbin.c rescoff.c resrc.c resres.c \
        size.c srconv.c stabs.c strings.c sysdump.c \
@@ -487,7 +492,7 @@ CC_FOR_TARGET = ` \
 # which depends on libintl, since we don't know whether LIBINTL_DEP will be
 # non-empty until configure time.  Ugh!
 size_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
-objdump_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) $(OPCODES)
+objdump_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB) $(OPCODES) $(OBJDUMP_PRIVATE_OFILES)
 nm_new_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 ar_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
 strings_DEPENDENCIES = $(LIBINTL_DEP) $(LIBIBERTY) $(BFDLIB)
@@ -517,7 +522,8 @@ elfedit_LDADD = $(LIBINTL) $(LIBIBERTY)
 strip_new_SOURCES = objcopy.c is-strip.c rename.c $(WRITE_DEBUG_SRCS) $(BULIBS)
 nm_new_SOURCES = nm.c $(BULIBS)
 objdump_SOURCES = objdump.c dwarf.c prdbg.c $(DEBUG_SRCS) $(BULIBS) $(ELFLIBS)
-objdump_LDADD = $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
+EXTRA_objdump_SOURCES = od-xcoff.c
+objdump_LDADD = $(OBJDUMP_PRIVATE_OFILES) $(OPCODES) $(BFDLIB) $(LIBIBERTY) $(LIBINTL)
 cxxfilt_SOURCES = cxxfilt.c $(BULIBS)
 ar_SOURCES = arparse.y arlex.l ar.c not-ranlib.c arsup.c rename.c binemul.c \
        emul_$(EMULATION).c $(BULIBS)
@@ -796,6 +802,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/not-strip.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/objcopy.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/objdump.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/od-xcoff.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prdbg.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rclex.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rcparse.Po@am__quote@
index b191a61..003b6f1 100755 (executable)
@@ -604,6 +604,7 @@ LTLIBOBJS
 LIBOBJS
 EMULATION_VECTOR
 EMULATION
+OBJDUMP_PRIVATE_OFILES
 OBJDUMP_DEFS
 BUILD_INSTALL_MISC
 BUILD_MISC
@@ -11198,7 +11199,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11201 "configure"
+#line 11202 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11304,7 +11305,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11307 "configure"
+#line 11308 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13779,6 +13780,9 @@ BUILD_DLLWRAP=
 BUILD_MISC=
 BUILD_INSTALL_MISC=
 OBJDUMP_DEFS=
+OBJDUMP_PRIVATE_VECTORS=
+OBJDUMP_PRIVATE_OFILES=
+od_vectors=
 
 for targ in $target $canon_targets
 do
@@ -13796,6 +13800,7 @@ do
        fi
        DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386"
        BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
+        od_vectors="$od_vectors objdump_private_desc_xcoff"
     else
        case $targ in
        i[3-7]86*-*-netware*)
          NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_SPARC"
          ;;
        esac
+
        case $targ in
        *-*-hms*) BUILD_SRCONV='$(SRCONV_PROG)' ;;
        esac
+
        case $targ in
        arm-epoc-pe*)
          BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
          OBJDUMP_DEFS="-DSKIP_ZEROES=256 -DSKIP_ZEROES_AT_END=0"
          ;;
        esac
+
+       # Add objdump private vectors.
+       case $targ in
+       powerpc-*-aix*)
+       od_vectors="$od_vectors objdump_private_desc_xcoff"
+         ;;
+       esac
     fi
 done
 
+# Uniq objdump private vector, build objdump target ofiles.
+od_files=
+f=""
+for i in $od_vectors ; do
+    case " $f " in
+    *" $i "*) ;;
+    *)
+       f="$f $i"
+       OBJDUMP_PRIVATE_VECTORS="$OBJDUMP_PRIVATE_VECTORS &$i,"
+       case $i in
+       objdump_private_desc_xcoff)
+           od_files="$od_files od-xcoff" ;;
+       *) as_fn_error "*** unknown private vector $i" "$LINENO" 5 ;;
+       esac
+       ;;
+    esac
+done
+
+# Uniq objdump target ofiles
+f=""
+for i in $od_files ; do
+    case " $f " in
+    *" $i "*) ;;
+    *)
+       f="$f $i"
+       OBJDUMP_PRIVATE_OFILES="$OBJDUMP_PRIVATE_OFILES $i.$objext"
+       ;;
+    esac
+done
+
 DLLTOOL_DEFS="$DLLTOOL_DEFS $DLLTOOL_DEFAULT"
 
 if test "${with_windres+set}" = set; then
@@ -13944,6 +13988,9 @@ if test "${with_windmc+set}" = set; then
          BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)'
 fi
 
+OBJDUMP_DEFS="${OBJDUMP_DEFS} -DOBJDUMP_PRIVATE_VECTORS=\"${OBJDUMP_PRIVATE_VECTORS}\""
+
+
 
 
 
index b1564bb..4a03c75 100644 (file)
@@ -179,6 +179,9 @@ BUILD_DLLWRAP=
 BUILD_MISC=
 BUILD_INSTALL_MISC=
 OBJDUMP_DEFS=
+OBJDUMP_PRIVATE_VECTORS=
+OBJDUMP_PRIVATE_OFILES=
+od_vectors=
 
 for targ in $target $canon_targets
 do
@@ -196,6 +199,7 @@ do
        fi
        DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_I386"
        BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
+       od_vectors="$od_vectors objdump_private_desc_xcoff"
     else
        case $targ in
 changequote(,)dnl
@@ -217,9 +221,11 @@ changequote([,])dnl
          NLMCONV_DEFS="$NLMCONV_DEFS -DNLMCONV_SPARC"
          ;;
        esac
+
        case $targ in
        *-*-hms*) BUILD_SRCONV='$(SRCONV_PROG)' ;;
        esac
+
        case $targ in
        arm-epoc-pe*)
          BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
@@ -341,9 +347,46 @@ changequote([,])dnl
          OBJDUMP_DEFS="-DSKIP_ZEROES=256 -DSKIP_ZEROES_AT_END=0"
          ;;
        esac
+
+       # Add objdump private vectors.
+       case $targ in
+       powerpc-*-aix*)
+       od_vectors="$od_vectors objdump_private_desc_xcoff"
+         ;;
+       esac
     fi
 done
 
+# Uniq objdump private vector, build objdump target ofiles.
+od_files=
+f=""
+for i in $od_vectors ; do
+    case " $f " in
+    *" $i "*) ;;
+    *)
+       f="$f $i"
+       OBJDUMP_PRIVATE_VECTORS="$OBJDUMP_PRIVATE_VECTORS &$i,"
+       case $i in
+       objdump_private_desc_xcoff)
+           od_files="$od_files od-xcoff" ;;
+       *) AC_MSG_ERROR(*** unknown private vector $i) ;;
+       esac
+       ;;
+    esac
+done
+
+# Uniq objdump target ofiles
+f=""
+for i in $od_files ; do
+    case " $f " in
+    *" $i "*) ;;
+    *)
+       f="$f $i"
+       OBJDUMP_PRIVATE_OFILES="$OBJDUMP_PRIVATE_OFILES $i.$objext"
+       ;;
+    esac
+done
+
 DLLTOOL_DEFS="$DLLTOOL_DEFS $DLLTOOL_DEFAULT"
 
 if test "${with_windres+set}" = set; then
@@ -354,6 +397,8 @@ if test "${with_windmc+set}" = set; then
          BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)'
 fi
 
+OBJDUMP_DEFS="${OBJDUMP_DEFS} -DOBJDUMP_PRIVATE_VECTORS=\"${OBJDUMP_PRIVATE_VECTORS}\""
+
 AC_SUBST(NLMCONV_DEFS)
 AC_SUBST(BUILD_NLMCONV)
 AC_SUBST(BUILD_SRCONV)
@@ -365,6 +410,7 @@ AC_SUBST(BUILD_DLLWRAP)
 AC_SUBST(BUILD_MISC)
 AC_SUBST(BUILD_INSTALL_MISC)
 AC_SUBST(OBJDUMP_DEFS)
+AC_SUBST(OBJDUMP_PRIVATE_OFILES)
 
 AC_DEFINE_UNQUOTED(TARGET, "${target}", [Configured target name.])
 
index 08e1c4e..fb3948f 100644 (file)
@@ -1744,6 +1744,7 @@ objdump [@option{-a}|@option{--archive-headers}]
         [@option{-m} @var{machine}|@option{--architecture=}@var{machine}]
         [@option{-M} @var{options}|@option{--disassembler-options=}@var{options}]
         [@option{-p}|@option{--private-headers}]
+        [@option{-P} @var{options}|@option{--private=}@var{options}]
         [@option{-r}|@option{--reloc}]
         [@option{-R}|@option{--dynamic-reloc}]
         [@option{-s}|@option{--full-contents}]
@@ -1787,7 +1788,7 @@ object files.
 
 The long and short forms of options, shown here as alternatives, are
 equivalent.  At least one option from the list
-@option{-a,-d,-D,-e,-f,-g,-G,-h,-H,-p,-r,-R,-s,-S,-t,-T,-V,-x} must be given.
+@option{-a,-d,-D,-e,-f,-g,-G,-h,-H,-p,-P,-r,-R,-s,-S,-t,-T,-V,-x} must be given.
 
 @table @env
 @item -a
@@ -2066,6 +2067,17 @@ Print information that is specific to the object file format.  The exact
 information printed depends upon the object file format.  For some
 object file formats, no additional information is printed.
 
+@item -P @var{options}
+@itemx --private=@var{options}
+Print information that is specific to the object file format.  The
+argument @var{options} is a comma separated list that depends on the
+format (the lists of options is displayed with the help).
+
+For XCOFF, the available options are: @option{header}, @option{aout},
+@option{sections}, @option{syms}, @option{relocs}, @option{lineno},
+@option{loader}, @option{except}, @option{typchk}, @option{traceback}
+and @option{toc}.
+
 @item -r
 @itemx --reloc
 @cindex relocation entries, in object file
index 231a668..784ead2 100644 (file)
@@ -65,6 +65,7 @@
 #include "filenames.h"
 #include "debug.h"
 #include "budbg.h"
+#include "objdump.h"
 
 #ifdef HAVE_MMAP
 #include <sys/mman.h>
@@ -93,6 +94,7 @@ static int dump_reloc_info;           /* -r */
 static int dump_dynamic_reloc_info;    /* -R */
 static int dump_ar_hdrs;               /* -a */
 static int dump_private_headers;       /* -p */
+static char *dump_private_options;     /* -P */
 static int prefix_addresses;           /* --prefix-addresses */
 static int with_line_numbers;          /* -l */
 static bfd_boolean with_source_code;   /* -S */
@@ -185,6 +187,13 @@ static char *strtab;
 static bfd_size_type stabstr_size;
 
 static bfd_boolean is_relocatable = FALSE;
+
+/* Handlers for -P/--private.  */
+static const struct objdump_private_desc * const objdump_private_vectors[] =
+  {
+    OBJDUMP_PRIVATE_VECTORS
+    NULL
+  };
 \f
 static void
 usage (FILE *stream, int status)
@@ -196,6 +205,7 @@ usage (FILE *stream, int status)
   -a, --archive-headers    Display archive header information\n\
   -f, --file-headers       Display the contents of the overall file header\n\
   -p, --private-headers    Display object format specific file header contents\n\
+  -P, --private=OPT,OPT... Display object format specific contents\n\
   -h, --[section-]headers  Display the contents of the section headers\n\
   -x, --all-headers        Display the contents of all headers\n\
   -d, --disassemble        Display assembler contents of executable sections\n\
@@ -221,6 +231,8 @@ usage (FILE *stream, int status)
 "));
   if (status != 2)
     {
+      const struct objdump_private_desc * const *desc;
+
       fprintf (stream, _("\n The following switches are optional:\n"));
       fprintf (stream, _("\
   -b, --target=BFDNAME           Specify the target object format as BFDNAME\n\
@@ -256,6 +268,14 @@ usage (FILE *stream, int status)
       list_supported_architectures (program_name, stream);
 
       disassembler_usage (stream);
+
+      if (objdump_private_vectors[0] != NULL)
+        {
+          fprintf (stream,
+                   _("\nOptions supported for -P/--private switch:\n"));
+          for (desc = objdump_private_vectors; *desc != NULL; desc++)
+            (*desc)->help (stream);
+        }
     }
   if (REPORT_BUGS_TO[0] && status == 0)
     fprintf (stream, _("Report bugs to %s.\n"), REPORT_BUGS_TO);
@@ -282,6 +302,7 @@ static struct option long_options[]=
   {"adjust-vma", required_argument, NULL, OPTION_ADJUST_VMA},
   {"all-headers", no_argument, NULL, 'x'},
   {"private-headers", no_argument, NULL, 'p'},
+  {"private", required_argument, NULL, 'P'},
   {"architecture", required_argument, NULL, 'm'},
   {"archive-headers", no_argument, NULL, 'a'},
   {"debugging", no_argument, NULL, 'g'},
@@ -2595,6 +2616,57 @@ dump_bfd_private_header (bfd *abfd)
   bfd_print_private_bfd_data (abfd, stdout);
 }
 
+static void
+dump_target_specific (bfd *abfd)
+{
+  const struct objdump_private_desc * const *desc;
+  struct objdump_private_option *opt;
+  char *e, *b;
+
+  /* Find the desc.  */
+  for (desc = objdump_private_vectors; *desc != NULL; desc++)
+    if ((*desc)->filter (abfd))
+      break;
+
+  if (desc == NULL)
+    {
+      non_fatal (_("option -P/--private not supported by this file"));
+      return;
+    }
+
+  /* Clear all options.  */
+  for (opt = (*desc)->options; opt->name; opt++)
+    opt->selected = FALSE;
+
+  /* Decode options.  */
+  b = dump_private_options;
+  do
+    {
+      e = strchr (b, ',');
+
+      if (e)
+        *e = 0;
+
+      for (opt = (*desc)->options; opt->name; opt++)
+        if (strcmp (opt->name, b) == 0)
+          {
+            opt->selected = TRUE;
+            break;
+          }
+      if (opt->name == NULL)
+        non_fatal (_("target specific dump '%s' not supported"), b);
+
+      if (e)
+        {
+          *e = ',';
+          b = e + 1;
+        }
+    }
+  while (e != NULL);
+
+  /* Dump.  */
+  (*desc)->dump (abfd);
+}
 \f
 /* Display a section in hexadecimal format with associated characters.
    Each line prefixed by the zero padded address.  */
@@ -3096,6 +3168,8 @@ dump_bfd (bfd *abfd)
     dump_bfd_header (abfd);
   if (dump_private_headers)
     dump_bfd_private_header (abfd);
+  if (dump_private_options != NULL)
+    dump_target_specific (abfd);
   if (! dump_debugging_tags && ! suppress_bfd_header)
     putchar ('\n');
   if (dump_section_headers)
@@ -3307,7 +3381,7 @@ main (int argc, char **argv)
   set_default_bfd_target ();
 
   while ((c = getopt_long (argc, argv,
-                          "pib:m:M:VvCdDlfFaHhrRtTxsSI:j:wE:zgeGW::",
+                          "pP:ib:m:M:VvCdDlfFaHhrRtTxsSI:j:wE:zgeGW::",
                           long_options, (int *) 0))
         != EOF)
     {
@@ -3424,6 +3498,10 @@ main (int argc, char **argv)
          dump_private_headers = TRUE;
          seenflag = TRUE;
          break;
+       case 'P':
+         dump_private_options = optarg;
+         seenflag = TRUE;
+         break;
        case 'x':
          dump_private_headers = TRUE;
          dump_symtab = TRUE;
diff --git a/binutils/objdump.h b/binutils/objdump.h
new file mode 100644 (file)
index 0000000..511898c
--- /dev/null
@@ -0,0 +1,50 @@
+/* objdump.h
+   Copyright 2011 Free Software Foundation, Inc.
+
+   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 <stdio.h>
+
+struct objdump_private_option
+{
+  /* Option name.  */
+  const char *name;
+
+  /* TRUE if the option is selected.  Automatically set and cleared by
+     objdump.  */
+  unsigned int selected;
+};
+
+struct objdump_private_desc
+{
+  /* Help displayed for --help.  */
+  void (*help)(FILE *stream);
+
+  /* Return TRUE if these options can be applied to ABFD.  */
+  int (*filter)(bfd *abfd);
+
+  /* Do the actual work: display whatever is requested according to the
+     options whose SELECTED field is set.  */
+  void (*dump)(bfd *abfd);
+
+  /* List of options.  Terminated by a NULL name.  */
+  struct objdump_private_option *options;
+};
+
+/* XCOFF specific target.  */
+extern const struct objdump_private_desc objdump_private_desc_xcoff;
diff --git a/binutils/od-xcoff.c b/binutils/od-xcoff.c
new file mode 100644 (file)
index 0000000..47d0248
--- /dev/null
@@ -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
+  };