Make bfd_byte an int8_t, flagword a uint32_t
[binutils-gdb.git] / bfd / coff64-rs6000.c
index e66d75f3713edbe1b1d93de44f375641f9083f33..71d21583ee5dbcd55353434c1428855bd4c47e20 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD back-end for IBM RS/6000 "XCOFF64" files.
-   Copyright (C) 2000-2021 Free Software Foundation, Inc.
+   Copyright (C) 2000-2023 Free Software Foundation, Inc.
    Written Clinton Popetz.
    Contributed by Cygnus Support.
 
@@ -386,12 +386,13 @@ _bfd_xcoff64_swap_aux_in (bfd *abfd, void *ext1, int type ATTRIBUTE_UNUSED,
 
       if (ext->x_file.x_n.x_n.x_zeroes[0] == 0)
        {
-         in->x_file.x_n.x_zeroes = 0;
-         in->x_file.x_n.x_offset =
+         in->x_file.x_n.x_n.x_zeroes = 0;
+         in->x_file.x_n.x_n.x_offset =
            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);
+       memcpy (in->x_file.x_n.x_fname, ext->x_file.x_n.x_fname, FILNMLEN);
+      in->x_file.x_ftype = H_GET_8 (abfd, ext->x_file.x_ftype);
       break;
 
       /* RS/6000 "csect" auxents.
@@ -410,13 +411,10 @@ _bfd_xcoff64_swap_aux_in (bfd *abfd, void *ext1, int type ATTRIBUTE_UNUSED,
          if (auxtype != _AUX_CSECT)
            goto error;
 
-         bfd_signed_vma h = 0;
-         bfd_vma l = 0;
+         bfd_vma h = H_GET_32 (abfd, ext->x_csect.x_scnlen_hi);
+         bfd_vma l = H_GET_32 (abfd, ext->x_csect.x_scnlen_lo);
 
-         h = H_GET_S32 (abfd, ext->x_csect.x_scnlen_hi);
-         l = H_GET_32 (abfd, ext->x_csect.x_scnlen_lo);
-
-         in->x_csect.x_scnlen.l = h << 32 | (l & 0xffffffff);
+         in->x_csect.x_scnlen.u64 = h << 32 | (l & 0xffffffff);
 
          in->x_csect.x_parmhash = H_GET_32 (abfd, ext->x_csect.x_parmhash);
          in->x_csect.x_snhash = H_GET_16 (abfd, ext->x_csect.x_snhash);
@@ -438,7 +436,7 @@ _bfd_xcoff64_swap_aux_in (bfd *abfd, void *ext1, int type ATTRIBUTE_UNUSED,
            = 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
+         in->x_sym.x_fcnary.x_fcn.x_endndx.u32
            = H_GET_32 (abfd, ext->x_fcn.x_endndx);
        }
       break;
@@ -502,14 +500,15 @@ _bfd_xcoff64_swap_aux_out (bfd *abfd, void *inp, int type ATTRIBUTE_UNUSED,
       break;
 
     case C_FILE:
-      if (in->x_file.x_n.x_zeroes == 0)
+      if (in->x_file.x_n.x_n.x_zeroes == 0)
        {
          H_PUT_32 (abfd, 0, ext->x_file.x_n.x_n.x_zeroes);
-         H_PUT_32 (abfd, in->x_file.x_n.x_offset,
+         H_PUT_32 (abfd, in->x_file.x_n.x_n.x_offset,
                    ext->x_file.x_n.x_n.x_offset);
        }
       else
-       memcpy (ext->x_file.x_n.x_fname, in->x_file.x_fname, FILNMLEN);
+       memcpy (ext->x_file.x_n.x_fname, in->x_file.x_n.x_fname, FILNMLEN);
+      H_PUT_8 (abfd, in->x_file.x_ftype, ext->x_file.x_ftype);
       H_PUT_8 (abfd, _AUX_FILE, ext->x_file.x_auxtype);
       break;
 
@@ -525,9 +524,9 @@ _bfd_xcoff64_swap_aux_out (bfd *abfd, void *inp, int type ATTRIBUTE_UNUSED,
        {
          bfd_vma temp;
 
-         temp = in->x_csect.x_scnlen.l & 0xffffffff;
+         temp = in->x_csect.x_scnlen.u64 & 0xffffffff;
          H_PUT_32 (abfd, temp, ext->x_csect.x_scnlen_lo);
-         temp = in->x_csect.x_scnlen.l >> 32;
+         temp = in->x_csect.x_scnlen.u64 >> 32;
          H_PUT_32 (abfd, temp, ext->x_csect.x_scnlen_hi);
          H_PUT_32 (abfd, in->x_csect.x_parmhash, ext->x_csect.x_parmhash);
          H_PUT_16 (abfd, in->x_csect.x_snhash, ext->x_csect.x_snhash);
@@ -543,7 +542,7 @@ _bfd_xcoff64_swap_aux_out (bfd *abfd, void *inp, int type ATTRIBUTE_UNUSED,
          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,
+         H_PUT_32 (abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.u32,
                    ext->x_fcn.x_endndx);
          H_PUT_8 (abfd, _AUX_FCN, ext->x_csect.x_auxtype);
        }
@@ -624,8 +623,8 @@ _bfd_xcoff64_put_ldsymbol_name (bfd *abfd ATTRIBUTE_UNUSED,
       ldinfo->strings = newstrings;
     }
 
-  bfd_put_16 (ldinfo->output_bfd, (bfd_vma) (len + 1),
-             ldinfo->strings + ldinfo->string_size);
+  ldinfo->strings[ldinfo->string_size] = ((len + 1) >> 8) & 0xff;
+  ldinfo->strings[ldinfo->string_size + 1] = ((len + 1)) & 0xff;
   strcpy (ldinfo->strings + ldinfo->string_size + 2, name);
   ldsym->_l._l_l._l_zeroes = 0;
   ldsym->_l._l_l._l_offset = ldinfo->string_size + 2;
@@ -779,10 +778,13 @@ xcoff64_reloc_type_br (bfd *input_bfd,
                       bfd_vma val,
                       bfd_vma addend,
                       bfd_vma *relocation,
-                      bfd_byte *contents)
+                      bfd_byte *contents,
+                      struct bfd_link_info *info)
 {
   struct xcoff_link_hash_entry *h;
   bfd_vma section_offset;
+  struct xcoff_stub_hash_entry *stub_entry = NULL;
+  enum xcoff_stub_type stub_type;
 
   if (0 > rel->r_symndx)
     return false;
@@ -834,6 +836,27 @@ xcoff64_reloc_type_br (bfd *input_bfd,
       howto->complain_on_overflow = complain_overflow_dont;
     }
 
+  /* Check if a stub is needed.  */
+  stub_type = bfd_xcoff_type_of_stub (input_section, rel, val, h);
+  if (stub_type != xcoff_stub_none)
+    {
+      asection *stub_csect;
+
+      stub_entry = bfd_xcoff_get_stub_entry (input_section, h, info);
+      if (stub_entry == NULL)
+       {
+         _bfd_error_handler (_("Unable to find the stub entry targeting %s"),
+                             h->root.root.string);
+         bfd_set_error (bfd_error_bad_value);
+         return false;
+       }
+
+      stub_csect = stub_entry->hcsect->root.u.def.section;
+      val = (stub_entry->stub_offset
+            + stub_csect->output_section->vma
+            + stub_csect->output_offset);
+    }
+
   /* The original PC-relative relocation is biased by -r_vaddr, so adding
      the value below will give the absolute target address.  */
   *relocation = val + addend + rel->r_vaddr;
@@ -883,7 +906,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x00: Standard 64 bit relocation.  */
   HOWTO (R_POS,                        /* type */
         0,                     /* rightshift */
-        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        8,                     /* size */
         64,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -898,7 +921,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x01: 64 bit relocation, but store negative value.  */
   HOWTO (R_NEG,                        /* type */
         0,                     /* rightshift */
-        -4,                    /* size (0 = byte, 1 = short, 2 = long) */
+        -8,                    /* size */
         64,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -913,7 +936,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x02: 64 bit PC relative relocation.  */
   HOWTO (R_REL,                        /* type */
         0,                     /* rightshift */
-        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        8,                     /* size */
         64,                    /* bitsize */
         true,                  /* pc_relative */
         0,                     /* bitpos */
@@ -928,7 +951,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x03: 16 bit TOC relative relocation.  */
   HOWTO (R_TOC,                        /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -943,7 +966,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x04: Same as R_TOC.  */
   HOWTO (R_TRL,                        /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -958,7 +981,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x05: External TOC relative symbol.  */
   HOWTO (R_GL,                 /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -973,7 +996,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x06: Local TOC relative symbol.   */
   HOWTO (R_TCL,                        /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -990,7 +1013,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x08: Same as R_RBA.  */
   HOWTO (R_BA,                 /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         26,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1007,7 +1030,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x0a: Same as R_RBR.  */
   HOWTO (R_BR,                 /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         26,                    /* bitsize */
         true,                  /* pc_relative */
         0,                     /* bitpos */
@@ -1024,7 +1047,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x0c: Same as R_POS.  */
   HOWTO (R_RL,                 /* type */
         0,                     /* rightshift */
-        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        8,                     /* size */
         64,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1039,7 +1062,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x0d: Same as R_POS.  */
   HOWTO (R_RLA,                        /* type */
         0,                     /* rightshift */
-        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        8,                     /* size */
         64,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1056,7 +1079,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x0f: Non-relocating reference.  Bitsize is 1 so that r_rsize is 0.  */
   HOWTO (R_REF,                        /* type */
         0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        1,                     /* size */
         1,                     /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1075,7 +1098,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x13: Same as R_TOC  */
   HOWTO (R_TRLA,               /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1090,7 +1113,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x14: Modifiable relative branch.  */
   HOWTO (R_RRTBI,              /* type */
         1,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1105,7 +1128,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x15: Modifiable absolute branch.  */
   HOWTO (R_RRTBA,              /* type */
         1,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1120,7 +1143,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x16: Modifiable call absolute indirect.  */
   HOWTO (R_CAI,                        /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1135,7 +1158,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x17: Modifiable call relative.  */
   HOWTO (R_CREL,               /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1150,7 +1173,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x18: Modifiable branch absolute.  */
   HOWTO (R_RBA,                        /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         26,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1165,7 +1188,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x19: Modifiable branch absolute.  */
   HOWTO (R_RBAC,               /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1180,7 +1203,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x1a: Modifiable branch relative.  */
   HOWTO (R_RBR,                        /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         26,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1195,7 +1218,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x1b: Modifiable branch absolute.  */
   HOWTO (R_RBRC,               /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1210,7 +1233,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x1c: Standard 32 bit relocation.  */
   HOWTO (R_POS,                        /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        4,                     /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1225,7 +1248,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x1d: 16 bit Non modifiable absolute branch.  */
   HOWTO (R_BA,                 /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1240,7 +1263,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x1e: Modifiable branch relative.  */
   HOWTO (R_RBR,                        /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         true,                  /* pc_relative */
         0,                     /* bitpos */
@@ -1255,7 +1278,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x1f: Modifiable branch absolute.  */
   HOWTO (R_RBA,                        /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1270,7 +1293,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x20: General-dynamic TLS relocation.  */
   HOWTO (R_TLS,                        /* type */
         0,                     /* rightshift */
-        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        8,                     /* size */
         64,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1285,7 +1308,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x21: Initial-exec TLS relocation.  */
   HOWTO (R_TLS_IE,             /* type */
         0,                     /* rightshift */
-        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        8,                     /* size */
         64,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1300,7 +1323,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x22: Local-dynamic TLS relocation.  */
   HOWTO (R_TLS_LD,             /* type */
         0,                     /* rightshift */
-        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        8,                     /* size */
         64,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1315,7 +1338,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x23: Local-exec TLS relocation.  */
   HOWTO (R_TLS_LE,             /* type */
         0,                     /* rightshift */
-        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        8,                     /* size */
         64,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1330,7 +1353,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x24: TLS relocation.  */
   HOWTO (R_TLSM,               /* type */
         0,                     /* rightshift */
-        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        8,                     /* size */
         64,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1345,13 +1368,13 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x25: TLS module relocation.  */
   HOWTO (R_TLSML,              /* type */
         0,                     /* rightshift */
-        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        8,                     /* size */
         64,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
-        "R_TLSM",              /* name */
+        "R_TLSML",             /* name */
         true,                  /* partial_inplace */
         MINUS_ONE,             /* src_mask */
         MINUS_ONE,             /* dst_mask */
@@ -1360,7 +1383,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x26: 32 bit relocation, but store negative value.  */
   HOWTO (R_NEG,                        /* type */
         0,                     /* rightshift */
-        -2,                    /* size (0 = byte, 1 = short, 2 = long) */
+        -4,                    /* size */
         32,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1384,7 +1407,7 @@ reloc_howto_type xcoff64_howto_table[] =
 
   HOWTO (R_TOCU,               /* type */
         16,                    /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1399,7 +1422,7 @@ reloc_howto_type xcoff64_howto_table[] =
   /* 0x31: Low-order 16 bit TOC relative relocation.  */
   HOWTO (R_TOCL,               /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        2,                     /* size */
         16,                    /* bitsize */
         false,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1564,13 +1587,15 @@ xcoff64_ppc_relocate_section (bfd *output_bfd,
            case R_POS:
            case R_NEG:
              howto.bitsize = (rel->r_size & 0x3f) + 1;
-             howto.size = howto.bitsize > 16 ? (howto.bitsize > 32 ? 4 : 2) : 1;
+             howto.size = HOWTO_RSIZE (howto.bitsize <= 16
+                                       ? 2 : howto.bitsize <= 32
+                                       ? 4 : 8);
              howto.src_mask = howto.dst_mask = N_ONES (howto.bitsize);
              break;
 
            default:
              _bfd_error_handler
-               (_("%pB: relocation (%d) at (0x%" BFD_VMA_FMT "x) has wrong"
+               (_("%pB: relocation (%d) at (0x%" PRIx64 ") has wrong"
                   " r_rsize (0x%x)\n"),
                 input_bfd, rel->r_type, rel->r_vaddr, rel->r_size);
              return false;
@@ -1646,7 +1671,7 @@ xcoff64_ppc_relocate_section (bfd *output_bfd,
       if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION
          || !((*xcoff64_calculate_relocation[rel->r_type])
              (input_bfd, input_section, output_bfd, rel, sym, &howto, val,
-              addend, &relocation, contents)))
+              addend, &relocation, contents, info)))
        return false;
 
       /* address */
@@ -1657,12 +1682,18 @@ xcoff64_ppc_relocate_section (bfd *output_bfd,
        abort ();
 
       /* Get the value we are going to relocate.  */
-      if (1 == howto.size)
-       value_to_relocate = bfd_get_16 (input_bfd, location);
-      else if (2 == howto.size)
-       value_to_relocate = bfd_get_32 (input_bfd, location);
-      else
-       value_to_relocate = bfd_get_64 (input_bfd, location);
+      switch (bfd_get_reloc_size (&howto))
+       {
+       case 2:
+         value_to_relocate = bfd_get_16 (input_bfd, location);
+         break;
+       case 4:
+         value_to_relocate = bfd_get_32 (input_bfd, location);
+         break;
+       default:
+         value_to_relocate = bfd_get_64 (input_bfd, location);
+         break;
+       }
 
       /* overflow.
 
@@ -1706,13 +1737,18 @@ xcoff64_ppc_relocate_section (bfd *output_bfd,
                               + relocation) & howto.dst_mask));
 
       /* Put the value back in the object file.  */
-      if (1 == howto.size)
-       bfd_put_16 (input_bfd, value_to_relocate, location);
-      else if (2 == howto.size)
-       bfd_put_32 (input_bfd, value_to_relocate, location);
-      else
-       bfd_put_64 (input_bfd, value_to_relocate, location);
-
+      switch (bfd_get_reloc_size (&howto))
+       {
+       case 2:
+         bfd_put_16 (input_bfd, value_to_relocate, location);
+         break;
+       case 4:
+         bfd_put_32 (input_bfd, value_to_relocate, location);
+         break;
+       default:
+         bfd_put_64 (input_bfd, value_to_relocate, location);
+         break;
+       }
     }
   return true;
 }
@@ -1775,13 +1811,13 @@ xcoff64_slurp_armap (bfd *abfd)
   /* This is for the new format.  */
   struct xcoff_ar_hdr_big hdr;
 
-  if (xcoff_ardata (abfd) == NULL)
+  if (x_artdata (abfd) == NULL)
     {
       abfd->has_armap = false;
       return true;
     }
 
-  off = bfd_scan_vma (xcoff_ardata_big (abfd)->symoff64,
+  off = bfd_scan_vma (x_artdata (abfd)->u.bhdr.symoff64,
                      (const char **) NULL, 10);
   if (off == 0)
     {
@@ -1903,22 +1939,16 @@ xcoff64_archive_p (bfd *abfd)
   if (bfd_ardata (abfd) == (struct artdata *) NULL)
     goto error_ret_restore;
 
-  /* Already cleared by bfd_zalloc above.
-     bfd_ardata (abfd)->cache = NULL;
-     bfd_ardata (abfd)->archive_head = NULL;
-     bfd_ardata (abfd)->symdefs = NULL;
-     bfd_ardata (abfd)->extended_names = NULL;
-     bfd_ardata (abfd)->extended_names_size = 0;  */
   bfd_ardata (abfd)->first_file_filepos = bfd_scan_vma (hdr.firstmemoff,
                                                        (const char **) NULL,
                                                        10);
 
-  amt = SIZEOF_AR_FILE_HDR_BIG;
+  amt = sizeof (struct xcoff_artdata);
   bfd_ardata (abfd)->tdata = bfd_zalloc (abfd, amt);
   if (bfd_ardata (abfd)->tdata == NULL)
     goto error_ret;
 
-  memcpy (bfd_ardata (abfd)->tdata, &hdr, SIZEOF_AR_FILE_HDR_BIG);
+  memcpy (&x_artdata (abfd)->u.bhdr, &hdr, SIZEOF_AR_FILE_HDR_BIG);
 
   if (! xcoff64_slurp_armap (abfd))
     {
@@ -1938,36 +1968,14 @@ xcoff64_archive_p (bfd *abfd)
 static bfd *
 xcoff64_openr_next_archived_file (bfd *archive, bfd *last_file)
 {
-  bfd_vma filestart;
-
-  if ((xcoff_ardata (archive) == NULL)
+  if (x_artdata (archive) == NULL
       || ! xcoff_big_format_p (archive))
     {
       bfd_set_error (bfd_error_invalid_operation);
       return NULL;
     }
 
-  if (last_file == NULL)
-    {
-      filestart = bfd_ardata (archive)->first_file_filepos;
-    }
-  else
-    {
-      filestart = bfd_scan_vma (arch_xhdr_big (last_file)->nextoff,
-                               (const char **) NULL, 10);
-    }
-
-  if (filestart == 0
-      || filestart == bfd_scan_vma (xcoff_ardata_big (archive)->memoff,
-                                   (const char **) NULL, 10)
-      || filestart == bfd_scan_vma (xcoff_ardata_big (archive)->symoff,
-                                   (const char **) NULL, 10))
-    {
-      bfd_set_error (bfd_error_no_more_archived_files);
-      return NULL;
-    }
-
-  return _bfd_get_elt_at_filepos (archive, (file_ptr) filestart);
+  return _bfd_xcoff_openr_next_archived_file (archive, last_file);
 }
 
 /* We can't use the usual coff_sizeof_headers routine, because AIX
@@ -2251,7 +2259,7 @@ xcoff64_generate_rtinit (bfd *abfd, const char *init, const char *fini,
   syment.n_scnum = 2;
   syment.n_sclass = C_HIDEXT;
   syment.n_numaux = 1;
-  auxent.x_csect.x_scnlen.l = data_buffer_size;
+  auxent.x_csect.x_scnlen.u64 = data_buffer_size;
   auxent.x_csect.x_smtyp = 3 << 3 | XTY_SD;
   auxent.x_csect.x_smclas = XMC_RW;
   bfd_coff_swap_sym_out (abfd, &syment,
@@ -2397,7 +2405,7 @@ xcoff64_generate_rtinit (bfd *abfd, const char *init, const char *fini,
 static reloc_howto_type xcoff64_dynamic_reloc =
 HOWTO (0,                      /* type */
        0,                      /* rightshift */
-       4,                      /* size (0 = byte, 1 = short, 2 = long) */
+       8,                      /* size */
        64,                     /* bitsize */
        false,                  /* pc_relative */
        0,                      /* bitpos */
@@ -2409,12 +2417,32 @@ HOWTO (0,                       /* type */
        MINUS_ONE,              /* dst_mask */
        false);                 /* pcrel_offset */
 
+/* Indirect call stub */
+static const unsigned long xcoff64_stub_indirect_call_code[4] =
+  {
+    0xe9820000,        /* ld r12,0(r2) */
+    0xe80c0000,        /* ld r0,0(r12) */
+    0x7c0903a6,        /* mtctr r0 */
+    0x4e800420,        /* bctr */
+  };
+
+/* Shared call stub */
+static const unsigned long xcoff64_stub_shared_call_code[6] =
+  {
+    0xe9820000,        /* ld r12,0(r2) */
+    0xf8410028,        /* std r2,40(r1) */
+    0xe80c0000,        /* ld r0,0(r12) */
+    0xe84c0008,        /* ld r2,8(r12) */
+    0x7c0903a6,        /* mtctr r0 */
+    0x4e800420,        /* bctr */
+  };
+
 static const unsigned long xcoff64_glink_code[10] =
 {
   0xe9820000,  /* ld r12,0(r2) */
   0xf8410028,  /* std r2,40(r1) */
   0xe80c0000,  /* ld r0,0(r12) */
-  0xe84c0008,  /* ld r0,8(r12) */
+  0xe84c0008,  /* ld r2,8(r12) */
   0x7c0903a6,  /* mtctr r0 */
   0x4e800420,  /* bctr */
   0x00000000,  /* start of traceback table */
@@ -2518,6 +2546,14 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
     /* rtinit.  */
     88,                                /* _xcoff_rtinit_size */
     xcoff64_generate_rtinit,
+
+    /* Stub indirect call.  */
+    &xcoff64_stub_indirect_call_code[0],
+    16,                                /* _xcoff_stub_indirect_call_size */
+
+    /* Stub shared call.  */
+    &xcoff64_stub_shared_call_code[0],
+    24,                                /* _xcoff_stub_shared_call_size */
   };
 
 /* The transfer vector that leads the outside world to all of the above.  */
@@ -2582,7 +2618,7 @@ const bfd_target rs6000_xcoff64_vec =
     },
 
     /* Generic */
-    _bfd_archive_close_and_cleanup,
+    _bfd_coff_close_and_cleanup,
     _bfd_bool_bfd_true,
     coff_new_section_hook,
     _bfd_generic_get_section_contents,
@@ -2625,6 +2661,7 @@ const bfd_target rs6000_xcoff64_vec =
     coff_bfd_is_target_special_symbol,
     coff_get_lineno,
     coff_find_nearest_line,
+    coff_find_nearest_line_with_alt,
     coff_find_line,
     coff_find_inliner_info,
     coff_bfd_make_debug_symbol,
@@ -2782,6 +2819,14 @@ static const struct xcoff_backend_data_rec bfd_xcoff_aix5_backend_data =
     /* rtinit.  */
     88,                                /* _xcoff_rtinit_size */
     xcoff64_generate_rtinit,
+
+    /* Stub indirect call.  */
+    &xcoff64_stub_indirect_call_code[0],
+    16,                                /* _xcoff_stub_indirect_call_size */
+
+    /* Stub shared call.  */
+    &xcoff64_stub_shared_call_code[0],
+    24,                                /* _xcoff_stub_shared_call_size */
   };
 
 /* The transfer vector that leads the outside world to all of the above.  */
@@ -2846,7 +2891,7 @@ const bfd_target rs6000_xcoff64_aix_vec =
     },
 
     /* Generic */
-    _bfd_archive_close_and_cleanup,
+    _bfd_coff_close_and_cleanup,
     _bfd_bool_bfd_true,
     coff_new_section_hook,
     _bfd_generic_get_section_contents,
@@ -2889,6 +2934,7 @@ const bfd_target rs6000_xcoff64_aix_vec =
     coff_bfd_is_target_special_symbol,
     coff_get_lineno,
     coff_find_nearest_line,
+    coff_find_nearest_line_with_alt,
     coff_find_line,
     coff_find_inliner_info,
     coff_bfd_make_debug_symbol,