From b11b2969a9a507d9e42c8029cfeb06b9bc41fceb Mon Sep 17 00:00:00 2001
From: Cl?ment Chigot <clement.chigot@atos.net>
Date: Thu, 22 Apr 2021 12:28:50 +0100
Subject: [PATCH] Harmonize and improve auxiliary entries support for XCOFF

bfd/ChangeLog:
	* coff-rs6000.c (_bfd_xcoff_swap_aux_in): Add errors for
	unsupported storage class or auxialiry entries.
	Improve and adapt to new aux structures.
	Add C_DWARF support.
	(_bfd_xcoff_swap_aux_out): Likewise.
	* coff64-rs6000.c (_bfd_xcoff64_swap_aux_in): Likewise.
	(_bfd_xcoff64_swap_aux_out): Likewise.

binutils/ChangeLog:
	* od-xcoff.c (dump_xcoff32_symbols): Adapt to new
	aux structures.

include/ChangeLog:
	* coff/internal.h (union internal_auxent):
	 Add x_sect structure.
	* coff/rs6000.h (union external_auxent): Rework to
	match official documentation.
	* coff/rs6k64.h (union external_auxent): Likewise.
	(_AUX_SECT): New define.
---
 bfd/ChangeLog           |  10 ++
 bfd/coff-rs6000.c       | 196 +++++++++++++++-----------------------
 bfd/coff64-rs6000.c     | 203 ++++++++++++++++++++++++----------------
 binutils/ChangeLog      |   5 +
 binutils/od-xcoff.c     |  10 +-
 include/ChangeLog       |   9 ++
 include/coff/internal.h |   6 ++
 include/coff/rs6000.h   |  93 +++++++++---------
 include/coff/rs6k64.h   |  96 ++++++++++---------
 9 files changed, 326 insertions(+), 302 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index db31bdb2669..abb9d5f34d7 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,13 @@
+2021-04-22  Clément Chigot  <clement.chigot@atos.net>
+
+	* coff-rs6000.c (_bfd_xcoff_swap_aux_in): Add errors for
+	unsupported storage class or auxialiry entries.
+	Improve and adapt to new aux structures.
+	Add C_DWARF support.
+	(_bfd_xcoff_swap_aux_out): Likewise.
+	* coff64-rs6000.c (_bfd_xcoff64_swap_aux_in): Likewise.
+	(_bfd_xcoff64_swap_aux_out): Likewise.
+
 2021-04-21  Eli Zaretskii  <eliz@gnu.org>
 
 	PR 27760
diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c
index 7cfe4040fb7..491efbae80c 100644
--- a/bfd/coff-rs6000.c
+++ b/bfd/coff-rs6000.c
@@ -470,14 +470,22 @@ _bfd_xcoff_swap_sym_out (bfd *abfd, void * inp, void * extp)
 }
 
 void
-_bfd_xcoff_swap_aux_in (bfd *abfd, void * ext1, int type, int in_class,
-			int indx, int numaux, void * in1)
+_bfd_xcoff_swap_aux_in (bfd *abfd, void * ext1, int type ATTRIBUTE_UNUSED,
+			int in_class, int indx, int numaux, void * in1)
 {
   AUXENT * ext = (AUXENT *)ext1;
   union internal_auxent *in = (union internal_auxent *)in1;
 
   switch (in_class)
     {
+    default:
+      _bfd_error_handler
+	/* xgettext: c-format */
+	(_("%pB: unsupported swap_aux_in for storage class %#x"),
+	 abfd, (unsigned int) in_class);
+      bfd_set_error (bfd_error_bad_value);
+      break;
+
     case C_FILE:
       if (ext->x_file.x_n.x_fname[0] == 0)
 	{
@@ -486,21 +494,13 @@ _bfd_xcoff_swap_aux_in (bfd *abfd, void * ext1, int type, int in_class,
 	    H_GET_32 (abfd, ext->x_file.x_n.x_n.x_offset);
 	}
       else
-	{
-	  if (numaux > 1)
-	    {
-	      if (indx == 0)
-		memcpy (in->x_file.x_fname, ext->x_file.x_n.x_fname,
-			numaux * sizeof (AUXENT));
-	    }
-	  else
-	    {
-	      memcpy (in->x_file.x_fname, ext->x_file.x_n.x_fname, FILNMLEN);
-	    }
-	}
-      goto end;
+	memcpy (in->x_file.x_fname, ext->x_file.x_n.x_fname, FILNMLEN);
+      break;
 
-      /* RS/6000 "csect" auxents */
+      /* RS/6000 "csect" auxents.
+         There is always a CSECT auxiliary entry. But functions can
+         have FCN ones too. In this case, CSECT is always the last
+         one. */
     case C_EXT:
     case C_AIX_WEAKEXT:
     case C_HIDEXT:
@@ -516,74 +516,47 @@ _bfd_xcoff_swap_aux_in (bfd *abfd, void * ext1, int type, int in_class,
 	  in->x_csect.x_smclas   = H_GET_8 (abfd, ext->x_csect.x_smclas);
 	  in->x_csect.x_stab     = H_GET_32 (abfd, ext->x_csect.x_stab);
 	  in->x_csect.x_snstab   = H_GET_16 (abfd, ext->x_csect.x_snstab);
-	  goto end;
+	}
+      else
+	{
+	  /* x_exptr isn't supported.  */
+	  in->x_sym.x_misc.x_fsize
+	    = H_GET_32 (abfd, ext->x_fcn.x_fsize);
+	  in->x_sym.x_fcnary.x_fcn.x_lnnoptr
+	    = H_GET_32 (abfd, ext->x_fcn.x_lnnoptr);
+	  in->x_sym.x_fcnary.x_fcn.x_endndx.l
+	    = H_GET_32 (abfd, ext->x_fcn.x_endndx);
 	}
       break;
 
     case C_STAT:
-    case C_LEAFSTAT:
-    case C_HIDDEN:
-      if (type == T_NULL)
-	{
-	  in->x_scn.x_scnlen = H_GET_32 (abfd, ext->x_scn.x_scnlen);
-	  in->x_scn.x_nreloc = H_GET_16 (abfd, ext->x_scn.x_nreloc);
-	  in->x_scn.x_nlinno = H_GET_16 (abfd, ext->x_scn.x_nlinno);
-	  /* PE defines some extra fields; we zero them out for
-	     safety.  */
-	  in->x_scn.x_checksum = 0;
-	  in->x_scn.x_associated = 0;
-	  in->x_scn.x_comdat = 0;
-
-	  goto end;
-	}
+      in->x_scn.x_scnlen = H_GET_32 (abfd, ext->x_scn.x_scnlen);
+      in->x_scn.x_nreloc = H_GET_16 (abfd, ext->x_scn.x_nreloc);
+      in->x_scn.x_nlinno = H_GET_16 (abfd, ext->x_scn.x_nlinno);
+      /* PE defines some extra fields; we zero them out for
+	 safety.  */
+      in->x_scn.x_checksum = 0;
+      in->x_scn.x_associated = 0;
+      in->x_scn.x_comdat = 0;
       break;
-    }
 
-  in->x_sym.x_tagndx.l = H_GET_32 (abfd, ext->x_sym.x_tagndx);
-  in->x_sym.x_tvndx = H_GET_16 (abfd, ext->x_sym.x_tvndx);
+    case C_BLOCK:
+    case C_FCN:
+      in->x_sym.x_misc.x_lnsz.x_lnno
+	= H_GET_32 (abfd, ext->x_sym.x_lnno);
+      break;
 
-  if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type)
-      || ISTAG (in_class))
-    {
-      in->x_sym.x_fcnary.x_fcn.x_lnnoptr =
-	H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
-      in->x_sym.x_fcnary.x_fcn.x_endndx.l =
-	H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_endndx);
-    }
-  else
-    {
-      in->x_sym.x_fcnary.x_ary.x_dimen[0] =
-	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
-      in->x_sym.x_fcnary.x_ary.x_dimen[1] =
-	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
-      in->x_sym.x_fcnary.x_ary.x_dimen[2] =
-	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
-      in->x_sym.x_fcnary.x_ary.x_dimen[3] =
-	H_GET_16 (abfd, ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
-    }
+    case C_DWARF:
+      in->x_sect.x_scnlen = H_GET_32 (abfd, ext->x_sect.x_scnlen);
+      in->x_sect.x_nreloc = H_GET_32 (abfd, ext->x_sect.x_nreloc);
+      break;
 
-  if (ISFCN (type))
-    {
-      in->x_sym.x_misc.x_fsize = H_GET_32 (abfd, ext->x_sym.x_misc.x_fsize);
     }
-  else
-    {
-      in->x_sym.x_misc.x_lnsz.x_lnno =
-	H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_lnno);
-      in->x_sym.x_misc.x_lnsz.x_size =
-	H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_size);
-    }
-
- end: ;
-  /* The semicolon is because MSVC doesn't like labels at
-     end of block.  */
 }
 
 unsigned int
-_bfd_xcoff_swap_aux_out (bfd *abfd, void * inp, int type, int in_class,
-			 int indx ATTRIBUTE_UNUSED,
-			 int numaux ATTRIBUTE_UNUSED,
-			 void * extp)
+_bfd_xcoff_swap_aux_out (bfd *abfd, void * inp, int type ATTRIBUTE_UNUSED,
+			 int in_class, int indx, int numaux, void * extp)
 {
   union internal_auxent *in = (union internal_auxent *)inp;
   AUXENT *ext = (AUXENT *)extp;
@@ -591,6 +564,14 @@ _bfd_xcoff_swap_aux_out (bfd *abfd, void * inp, int type, int in_class,
   memset (ext, 0, bfd_coff_auxesz (abfd));
   switch (in_class)
     {
+    default:
+      _bfd_error_handler
+	/* xgettext: c-format */
+	(_("%pB: unsupported swap_aux_out for storage class %#x"),
+	 abfd, (unsigned int) in_class);
+      bfd_set_error (bfd_error_bad_value);
+      break;
+
     case C_FILE:
       if (in->x_file.x_fname[0] == 0)
 	{
@@ -599,10 +580,8 @@ _bfd_xcoff_swap_aux_out (bfd *abfd, void * inp, int type, int in_class,
 		    ext->x_file.x_n.x_n.x_offset);
 	}
       else
-	{
-	  memcpy (ext->x_file.x_n.x_fname, in->x_file.x_fname, FILNMLEN);
-	}
-      goto end;
+	memcpy (ext->x_file.x_n.x_fname, in->x_file.x_fname, FILNMLEN);
+      break;
 
       /* RS/6000 "csect" auxents */
     case C_EXT:
@@ -620,57 +599,34 @@ _bfd_xcoff_swap_aux_out (bfd *abfd, void * inp, int type, int in_class,
 	  H_PUT_8 (abfd, in->x_csect.x_smclas, ext->x_csect.x_smclas);
 	  H_PUT_32 (abfd, in->x_csect.x_stab, ext->x_csect.x_stab);
 	  H_PUT_16 (abfd, in->x_csect.x_snstab, ext->x_csect.x_snstab);
-	  goto end;
+	}
+      else
+	{
+	  H_PUT_32 (abfd, in->x_sym.x_misc.x_fsize, ext->x_fcn.x_fsize);
+	  H_PUT_32 (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr,
+		    ext->x_fcn.x_lnnoptr);
+	  H_PUT_32 (abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l,
+		    ext->x_fcn.x_endndx);
 	}
       break;
 
     case C_STAT:
-    case C_LEAFSTAT:
-    case C_HIDDEN:
-      if (type == T_NULL)
-	{
-	  H_PUT_32 (abfd, in->x_scn.x_scnlen, ext->x_scn.x_scnlen);
-	  H_PUT_16 (abfd, in->x_scn.x_nreloc, ext->x_scn.x_nreloc);
-	  H_PUT_16 (abfd, in->x_scn.x_nlinno, ext->x_scn.x_nlinno);
-	  goto end;
-	}
+      H_PUT_32 (abfd, in->x_scn.x_scnlen, ext->x_scn.x_scnlen);
+      H_PUT_16 (abfd, in->x_scn.x_nreloc, ext->x_scn.x_nreloc);
+      H_PUT_16 (abfd, in->x_scn.x_nlinno, ext->x_scn.x_nlinno);
+      break;
+
+    case C_BLOCK:
+    case C_FCN:
+      H_PUT_32 (abfd, in->x_sym.x_misc.x_lnsz.x_lnno, ext->x_sym.x_lnno);
+      break;
+
+    case C_DWARF:
+      H_PUT_32 (abfd, in->x_sect.x_scnlen, ext->x_sect.x_scnlen);
+      H_PUT_32 (abfd, in->x_sect.x_nreloc, ext->x_sect.x_nreloc);
       break;
     }
 
-  H_PUT_32 (abfd, in->x_sym.x_tagndx.l, ext->x_sym.x_tagndx);
-  H_PUT_16 (abfd, in->x_sym.x_tvndx, ext->x_sym.x_tvndx);
-
-  if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type)
-      || ISTAG (in_class))
-    {
-      H_PUT_32 (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr,
-		ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
-      H_PUT_32 (abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l,
-		ext->x_sym.x_fcnary.x_fcn.x_endndx);
-    }
-  else
-    {
-      H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[0],
-		ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
-      H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[1],
-		ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
-      H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[2],
-		ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
-      H_PUT_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[3],
-		ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
-    }
-
-  if (ISFCN (type))
-    H_PUT_32 (abfd, in->x_sym.x_misc.x_fsize, ext->x_sym.x_misc.x_fsize);
-  else
-    {
-      H_PUT_16 (abfd, in->x_sym.x_misc.x_lnsz.x_lnno,
-		ext->x_sym.x_misc.x_lnsz.x_lnno);
-      H_PUT_16 (abfd, in->x_sym.x_misc.x_lnsz.x_size,
-		ext->x_sym.x_misc.x_lnsz.x_size);
-    }
-
- end:
   return bfd_coff_auxesz (abfd);
 }
 
diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c
index 889534088f0..9e9f9c2992f 100644
--- a/bfd/coff64-rs6000.c
+++ b/bfd/coff64-rs6000.c
@@ -362,15 +362,28 @@ _bfd_xcoff64_swap_sym_out (bfd *abfd, void *inp, void *extp)
 }
 
 static void
-_bfd_xcoff64_swap_aux_in (bfd *abfd, void *ext1, int type, int in_class,
-			  int indx, int numaux, void *in1)
+_bfd_xcoff64_swap_aux_in (bfd *abfd, void *ext1, int type ATTRIBUTE_UNUSED,
+			  int in_class, int indx, int numaux, void *in1)
 {
   union external_auxent *ext = (union external_auxent *) ext1;
   union internal_auxent *in = (union internal_auxent *) in1;
+  unsigned char auxtype;
 
   switch (in_class)
     {
+    default:
+      _bfd_error_handler
+	/* xgettext: c-format */
+	(_("%pB: unsupported swap_aux_in for storage class %#x"),
+	 abfd, (unsigned int) in_class);
+      bfd_set_error (bfd_error_bad_value);
+      break;
+
     case C_FILE:
+      auxtype = H_GET_8 (abfd, ext->x_file.x_auxtype);
+      if (auxtype != _AUX_FILE)
+	goto error;
+
       if (ext->x_file.x_n.x_n.x_zeroes[0] == 0)
 	{
 	  in->x_file.x_n.x_zeroes = 0;
@@ -378,17 +391,25 @@ _bfd_xcoff64_swap_aux_in (bfd *abfd, void *ext1, int type, int in_class,
 	    H_GET_32 (abfd, ext->x_file.x_n.x_n.x_offset);
 	}
       else
-	{
-	  memcpy (in->x_file.x_fname, ext->x_file.x_n.x_fname, FILNMLEN);
-	}
-      goto end;
+	memcpy (in->x_file.x_fname, ext->x_file.x_n.x_fname, FILNMLEN);
+      break;
 
-      /* RS/6000 "csect" auxents */
+      /* RS/6000 "csect" auxents.
+         There is always a CSECT auxiliary entry. But functions can
+         have FCN and EXCEPT ones too. In this case, CSECT is always the last
+         one.
+         For now, we only support FCN types.  */
     case C_EXT:
     case C_AIX_WEAKEXT:
     case C_HIDEXT:
       if (indx + 1 == numaux)
 	{
+	  /* C_EXT can have several aux enties. But the _AUX_CSECT is always
+	     the last one.  */
+	  auxtype = H_GET_8 (abfd, ext->x_csect.x_auxtype);
+	  if (auxtype != _AUX_CSECT)
+	    goto error;
+
 	  bfd_signed_vma h = 0;
 	  bfd_vma l = 0;
 
@@ -404,55 +425,67 @@ _bfd_xcoff64_swap_aux_in (bfd *abfd, void *ext1, int type, int in_class,
 	     byte orders.  */
 	  in->x_csect.x_smtyp = H_GET_8 (abfd, ext->x_csect.x_smtyp);
 	  in->x_csect.x_smclas = H_GET_8 (abfd, ext->x_csect.x_smclas);
-	  goto end;
+	}
+      else
+	{
+	  /* It can also be a _AUX_EXCEPT entry. But it's not supported
+	     for now. */
+	  auxtype = H_GET_8 (abfd, ext->x_fcn.x_auxtype);
+	  if (auxtype != _AUX_FCN)
+	    goto error;
+
+	  in->x_sym.x_fcnary.x_fcn.x_lnnoptr
+	    = H_GET_64 (abfd, ext->x_fcn.x_lnnoptr);
+	  in->x_sym.x_misc.x_fsize
+	    = H_GET_32 (abfd, ext->x_fcn.x_fsize);
+	  in->x_sym.x_fcnary.x_fcn.x_endndx.l
+	    = H_GET_32 (abfd, ext->x_fcn.x_endndx);
 	}
       break;
 
     case C_STAT:
-    case C_LEAFSTAT:
-    case C_HIDDEN:
-      if (type == T_NULL)
-	{
-	  /* PE defines some extra fields; we zero them out for
-	     safety.  */
-	  in->x_scn.x_checksum = 0;
-	  in->x_scn.x_associated = 0;
-	  in->x_scn.x_comdat = 0;
+      _bfd_error_handler
+	/* xgettext: c-format */
+	(_("%pB: C_STAT isn't supported by XCOFF64"),
+	 abfd);
+      bfd_set_error (bfd_error_bad_value);
+      break;
 
-	  goto end;
-	}
+    case C_BLOCK:
+    case C_FCN:
+      auxtype = H_GET_8 (abfd, ext->x_sym.x_auxtype);
+      if (auxtype != _AUX_SYM)
+	goto error;
+
+      in->x_sym.x_misc.x_lnsz.x_lnno
+	= H_GET_32 (abfd, ext->x_sym.x_lnno);
+      break;
+
+    case C_DWARF:
+      auxtype = H_GET_8 (abfd, ext->x_sect.x_auxtype);
+      if (auxtype != _AUX_SECT)
+	goto error;
+
+      in->x_sect.x_scnlen = H_GET_64 (abfd, ext->x_sect.x_scnlen);
+      in->x_sect.x_nreloc = H_GET_64 (abfd, ext->x_sect.x_nreloc);
       break;
     }
 
-  if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type)
-      || ISTAG (in_class))
-    {
-      in->x_sym.x_fcnary.x_fcn.x_lnnoptr
-	= H_GET_64 (abfd, ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
-      in->x_sym.x_fcnary.x_fcn.x_endndx.l
-	= H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_endndx);
-    }
-  if (ISFCN (type))
-    {
-      in->x_sym.x_misc.x_fsize
-	= H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_fsize);
-    }
-  else
-    {
-      in->x_sym.x_misc.x_lnsz.x_lnno
-	= H_GET_32 (abfd, ext->x_sym.x_fcnary.x_lnsz.x_lnno);
-      in->x_sym.x_misc.x_lnsz.x_size
-	= H_GET_16 (abfd, ext->x_sym.x_fcnary.x_lnsz.x_size);
-    }
+  return;
+
+ error:
+  _bfd_error_handler
+    /* xgettext: c-format */
+    (_("%pB: wrong auxtype %#x for storage class %#x"),
+     abfd, auxtype, (unsigned int) in_class);
+  bfd_set_error (bfd_error_bad_value);
+
 
- end: ;
 }
 
 static unsigned int
-_bfd_xcoff64_swap_aux_out (bfd *abfd, void *inp, int type, int in_class,
-			   int indx ATTRIBUTE_UNUSED,
-			   int numaux ATTRIBUTE_UNUSED,
-			   void *extp)
+_bfd_xcoff64_swap_aux_out (bfd *abfd, void *inp, int type ATTRIBUTE_UNUSED,
+			   int in_class, int indx, int numaux, void *extp)
 {
   union internal_auxent *in = (union internal_auxent *) inp;
   union external_auxent *ext = (union external_auxent *) extp;
@@ -460,6 +493,14 @@ _bfd_xcoff64_swap_aux_out (bfd *abfd, void *inp, int type, int in_class,
   memset (ext, 0, bfd_coff_auxesz (abfd));
   switch (in_class)
     {
+    default:
+      _bfd_error_handler
+	/* xgettext: c-format */
+	(_("%pB: unsupported swap_aux_out for storage class %#x"),
+	 abfd, (unsigned int) in_class);
+      bfd_set_error (bfd_error_bad_value);
+      break;
+
     case C_FILE:
       if (in->x_file.x_n.x_zeroes == 0)
 	{
@@ -468,13 +509,15 @@ _bfd_xcoff64_swap_aux_out (bfd *abfd, void *inp, int type, int in_class,
 		    ext->x_file.x_n.x_n.x_offset);
 	}
       else
-	{
-	  memcpy (ext->x_file.x_n.x_fname, in->x_file.x_fname, FILNMLEN);
-	}
-      H_PUT_8 (abfd, _AUX_FILE, ext->x_auxtype.x_auxtype);
-      goto end;
+	memcpy (ext->x_file.x_n.x_fname, in->x_file.x_fname, FILNMLEN);
+      H_PUT_8 (abfd, _AUX_FILE, ext->x_file.x_auxtype);
+      break;
 
-      /* RS/6000 "csect" auxents */
+      /* RS/6000 "csect" auxents.
+         There is always a CSECT auxiliary entry. But functions can
+         have FCN and EXCEPT ones too. In this case, CSECT is always the last
+         one.
+         For now, we only support FCN types.  */
     case C_EXT:
     case C_AIX_WEAKEXT:
     case C_HIDEXT:
@@ -493,46 +536,40 @@ _bfd_xcoff64_swap_aux_out (bfd *abfd, void *inp, int type, int in_class,
 	     byte orders.  */
 	  H_PUT_8 (abfd, in->x_csect.x_smtyp, ext->x_csect.x_smtyp);
 	  H_PUT_8 (abfd, in->x_csect.x_smclas, ext->x_csect.x_smclas);
-	  H_PUT_8 (abfd, _AUX_CSECT, ext->x_auxtype.x_auxtype);
-	  goto end;
+	  H_PUT_8 (abfd, _AUX_CSECT, ext->x_csect.x_auxtype);
+	}
+      else
+	{
+	  H_PUT_64 (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr,
+		    ext->x_fcn.x_lnnoptr);
+	  H_PUT_32 (abfd, in->x_sym.x_misc.x_fsize, ext->x_fcn.x_fsize);
+	  H_PUT_32 (abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l,
+		    ext->x_fcn.x_endndx);
+	  H_PUT_8 (abfd, _AUX_FCN, ext->x_csect.x_auxtype);
 	}
       break;
 
     case C_STAT:
-    case C_LEAFSTAT:
-    case C_HIDDEN:
-      if (type == T_NULL)
-	{
-	  goto end;
-	}
+      _bfd_error_handler
+	/* xgettext: c-format */
+	(_("%pB: C_STAT isn't supported by XCOFF64"),
+	 abfd);
+      bfd_set_error (bfd_error_bad_value);
+      break;
+
+    case C_BLOCK:
+    case C_FCN:
+      H_PUT_32 (abfd, in->x_sym.x_misc.x_lnsz.x_lnno, ext->x_sym.x_lnno);
+      H_PUT_8 (abfd, _AUX_SYM, ext->x_sym.x_auxtype);
+      break;
+
+    case C_DWARF:
+      H_PUT_64 (abfd, in->x_sect.x_scnlen, ext->x_sect.x_scnlen);
+      H_PUT_64 (abfd, in->x_sect.x_nreloc, ext->x_sect.x_nreloc);
+      H_PUT_8 (abfd, _AUX_SECT, ext->x_sect.x_auxtype);
       break;
     }
 
-  if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type)
-      || ISTAG (in_class))
-    {
-      H_PUT_64 (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr,
-	       ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
-      H_PUT_8 (abfd, _AUX_FCN,
-	       ext->x_auxtype.x_auxtype);
-      H_PUT_32 (abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l,
-	       ext->x_sym.x_fcnary.x_fcn.x_endndx);
-    }
-  if (ISFCN (type))
-    {
-      H_PUT_32 (abfd, in->x_sym.x_misc.x_fsize,
-	       ext->x_sym.x_fcnary.x_fcn.x_fsize);
-    }
-  else
-    {
-      H_PUT_32 (abfd, in->x_sym.x_misc.x_lnsz.x_lnno,
-	       ext->x_sym.x_fcnary.x_lnsz.x_lnno);
-      H_PUT_16 (abfd, in->x_sym.x_misc.x_lnsz.x_size,
-	       ext->x_sym.x_fcnary.x_lnsz.x_size);
-    }
-
- end:
-
   return bfd_coff_auxesz (abfd);
 }
 
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index e15d0361236..9a1fd5dae09 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,8 @@
+2021-04-22  Clément Chigot  <clement.chigot@atos.net>
+
+	* od-xcoff.c (dump_xcoff32_symbols): Adapt to new
+	aux structures.
+
 2021-04-21  Nick Lott  <nick.lott@gmail.com>
 
 	PR 27672
diff --git a/binutils/od-xcoff.c b/binutils/od-xcoff.c
index f0d566b1902..02264503b15 100644
--- a/binutils/od-xcoff.c
+++ b/binutils/od-xcoff.c
@@ -838,13 +838,13 @@ dump_xcoff32_symbols (bfd *abfd, struct xcoff_dump *data)
                 {
                   /* Function aux entry  (Do not translate).  */
                   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_fcn.x_exptr),
                           (unsigned)bfd_h_get_32
-                            (abfd, aux->x_sym.x_misc.x_fsize),
+                            (abfd, aux->x_fcn.x_fsize),
                           (unsigned)bfd_h_get_32
-                            (abfd, aux->x_sym.x_fcnary.x_fcn.x_lnnoptr),
+                            (abfd, aux->x_fcn.x_lnnoptr),
                           (unsigned)bfd_h_get_32
-                            (abfd, aux->x_sym.x_fcnary.x_fcn.x_endndx));
+                            (abfd, aux->x_fcn.x_endndx));
                 }
               else if (j == 1 || (j == 0 && s->sym.numaux == 1))
                 {
@@ -899,7 +899,7 @@ dump_xcoff32_symbols (bfd *abfd, struct xcoff_dump *data)
             case C_FCN:
               printf ("  lnno: %u\n",
                       (unsigned)bfd_h_get_16
-                      (abfd, aux->x_sym.x_misc.x_lnsz.x_lnno));
+                      (abfd, aux->x_sym.x_lnno));
               break;
             default:
               /* Do not translate - generic field name.  */
diff --git a/include/ChangeLog b/include/ChangeLog
index 20aefde3397..0f277f95a61 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,12 @@
+2021-04-22  Clément Chigot  <clement.chigot@atos.net>
+
+	* coff/internal.h (union internal_auxent):
+	 Add x_sect structure.
+	* coff/rs6000.h (union external_auxent): Rework to
+	match official documentation.
+	* coff/rs6k64.h (union external_auxent): Likewise.
+	(_AUX_SECT): New define.
+
 2021-04-21  Eli Zaretskii  <eliz@gnu.org>
 
 	PR 27760
diff --git a/include/coff/internal.h b/include/coff/internal.h
index b09bb0f469d..e79bf560c6e 100644
--- a/include/coff/internal.h
+++ b/include/coff/internal.h
@@ -659,6 +659,12 @@ union internal_auxent
 /* 		14	??? */
 #define	XMC_TC0	15		/* Read-write TOC anchor */
 #define XMC_TD	16		/* Read-write data in TOC */
+
+  struct
+  {
+    long x_scnlen;              /* Section length */
+    long x_nreloc;              /* Number of relocation entries */
+  } x_sect;
 };
 
 /********************** RELOCATION DIRECTIVES **********************/
diff --git a/include/coff/rs6000.h b/include/coff/rs6000.h
index ff2de530b8e..e60efff23b6 100644
--- a/include/coff/rs6000.h
+++ b/include/coff/rs6000.h
@@ -153,59 +153,54 @@ struct external_syment
   
 
 union external_auxent {
-	struct {
-		char x_tagndx[4];	/* str, un, or enum tag indx */
-		union {
-			struct {
-			    char  x_lnno[2]; /* declaration line number */
-			    char  x_size[2]; /* str/union/array size */
-			} x_lnsz;
-			char x_fsize[4];	/* size of function */
-		} x_misc;
-		union {
-			struct {		/* if ISFCN, tag, or .bb */
-			    char x_lnnoptr[4];	/* ptr to fcn line # */
-			    char x_endndx[4];	/* entry ndx past block end */
-			} x_fcn;
-			struct {		/* if ISARY, up to 4 dimen. */
-			    char x_dimen[E_DIMNUM][2];
-			} x_ary;
-		} x_fcnary;
-		char x_tvndx[2];		/* tv index */
-	} x_sym;
+  struct {
+    char x_pad1[2];
+    char x_lnno[4]; 	/* Source line number */
+    char x_pad[12];
+  } x_sym;
 
-        struct {
-                union {
-                        char x_fname[E_FILNMLEN];
-                        struct {
-                                char x_zeroes[4];
-                                char x_offset[4];
-                        } x_n;
-                } x_n;
-                char x_ftype[1];
-        } x_file;
+  struct {
+    char x_exptr[4];
+    char x_fsize[4];
+    char x_lnnoptr[4];
+    char x_endndx[4];
+    char x_pad[1];
+  } x_fcn;
 
-	struct {
-		char x_scnlen[4];			/* section length */
-		char x_nreloc[2];	/* # relocation entries */
-		char x_nlinno[2];	/* # line numbers */
-	} x_scn;
+  struct {
+    union {
+      char x_fname[E_FILNMLEN];
+      struct {
+	char x_zeroes[4];
+	char x_offset[4];
+      } x_n;
+    } x_n;
+    char x_ftype[1];
+  } x_file;
 
-        struct {
-		char x_tvfill[4];	/* tv fill value */
-		char x_tvlen[2];	/* length of .tv */
-		char x_tvran[2][2];	/* tv range */
-	} x_tv;		/* info about .tv section (in auxent of symbol .tv)) */
+  struct {
+    char x_scnlen[4];	/* section length */
+    char x_nreloc[2];	/* # relocation entries */
+    char x_nlinno[2];	/* # line numbers */
+    char x_pad[10];
+  } x_scn;
 
-	struct {
-		unsigned char x_scnlen[4];
-		unsigned char x_parmhash[4];
-		unsigned char x_snhash[2];
-		unsigned char x_smtyp[1];
-		unsigned char x_smclas[1];
-		unsigned char x_stab[4];
-		unsigned char x_snstab[2];
-	} x_csect;
+  struct {
+    char x_scnlen[4];
+    char x_parmhash[4];
+    char x_snhash[2];
+    char x_smtyp[1];
+    char x_smclas[1];
+    char x_stab[4];
+    char x_snstab[2];
+  } x_csect;
+
+  struct {
+    char x_scnlen[4];
+    char x_pad1[4];
+    char x_nreloc[4];
+    char x_pad2[6];
+  } x_sect;
 
 };
 
diff --git a/include/coff/rs6k64.h b/include/coff/rs6k64.h
index 53adf4be49a..58ffd6eb2f4 100644
--- a/include/coff/rs6k64.h
+++ b/include/coff/rs6k64.h
@@ -144,54 +144,59 @@ struct external_syment
 
 union external_auxent
 {
-    struct {
-    	union {
-	    struct {
-		char x_lnno[4]; 	/* declaration line number */
-		char x_size[2]; 	/* str/union/array size */
-	    } x_lnsz;
-	    struct {
-		char x_lnnoptr[8];/* ptr to fcn line */
-		char x_fsize[4];	 /* size of function */
-		char x_endndx[4];	 /* entry ndx past block end */
-	    } x_fcn;
- 	} x_fcnary;
-    } x_sym;
-         
-    struct {
-        union {
-            char x_fname[E_FILNMLEN];
-            struct {
-	        char x_zeroes[4];
-                char x_offset[4];
-	        char x_pad[6];
-            } x_n;
-        } x_n;
-        unsigned char x_ftype[1];
-        unsigned char x_resv[2];
-    } x_file;
+  struct {
+    char x_lnno[4]; 	/* declaration line number */
+    char x_pad[13];
+    char x_auxtype[1];
+  } x_sym;
 
-    struct {
-	char x_exptr[8];
-	char x_fsize[4];
-	char x_endndx[4];
-	char x_pad[1];
-    } x_except;
+  struct {
+    char x_lnnoptr[8];/* ptr to fcn line */
+    char x_fsize[4];	 /* size of function */
+    char x_endndx[4];	 /* entry ndx past block end */
+    char x_pad[1];
+    char x_auxtype[1];
+  } x_fcn;
 
-    struct {
-	    unsigned char x_scnlen_lo[4];
-	    unsigned char x_parmhash[4];
-	    unsigned char x_snhash[2];
-	    unsigned char x_smtyp[1];
-	    unsigned char x_smclas[1];
-	    unsigned char x_scnlen_hi[4];
-	    unsigned char x_pad[1];
-    } x_csect;	
+  struct {
+    union {
+      char x_fname[E_FILNMLEN];
+      struct {
+	char x_zeroes[4];
+	char x_offset[4];
+	char x_pad[6];
+      } x_n;
+    } x_n;
+    unsigned char x_ftype[1];
+    unsigned char x_resv[2];
+    char x_auxtype[1];
+  } x_file;
 
-    struct {
-	char x_pad[17];
-	char x_auxtype[1];
-    } x_auxtype;
+  struct {
+    char x_exptr[8];
+    char x_fsize[4];
+    char x_endndx[4];
+    char x_pad[1];
+    char x_auxtype[1];
+  } x_except;
+
+  struct {
+    char x_scnlen_lo[4];
+    char x_parmhash[4];
+    char x_snhash[2];
+    char x_smtyp[1];
+    char x_smclas[1];
+    char x_scnlen_hi[4];
+    char x_pad[1];
+    char x_auxtype[1];
+  } x_csect;
+
+  struct {
+    char x_scnlen[8];
+    char x_nreloc[8];
+    char x_pad[1];
+    char x_auxtype[1];
+  } x_sect;
 };
 
 #define	SYMENT	struct external_syment
@@ -207,6 +212,7 @@ union external_auxent
 #define _AUX_SYM        253
 #define _AUX_FILE       252
 #define _AUX_CSECT      251
+#define _AUX_SECT       250
 
 /********************** RELOCATION DIRECTIVES **********************/