Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / coff64-rs6000.c
index 4db61e5706428d22d0e2c67795b599bbd1dbafe6..9e9f9c2992fe3d1ec969e82c0e7e2bb66b3683b0 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD back-end for IBM RS/6000 "XCOFF64" files.
-   Copyright (C) 2000-2019 Free Software Foundation, Inc.
+   Copyright (C) 2000-2021 Free Software Foundation, Inc.
    Written Clinton Popetz.
    Contributed by Cygnus Support.
 
@@ -86,10 +86,10 @@ static void _bfd_xcoff64_swap_lineno_in
   (bfd *, void *, void *);
 static unsigned int _bfd_xcoff64_swap_lineno_out
   (bfd *, void *, void *);
-static bfd_boolean _bfd_xcoff64_put_symbol_name
+static bool _bfd_xcoff64_put_symbol_name
   (struct bfd_link_info *, struct bfd_strtab_hash *,
    struct internal_syment *, const char *);
-static bfd_boolean _bfd_xcoff64_put_ldsymbol_name
+static bool _bfd_xcoff64_put_ldsymbol_name
   (bfd *, struct xcoff_loader_info *, struct internal_ldsym *, const char *);
 static void _bfd_xcoff64_swap_sym_in
   (bfd *, void *, void *);
@@ -103,17 +103,17 @@ static void xcoff64_swap_reloc_in
   (bfd *, void *, void *);
 static unsigned int xcoff64_swap_reloc_out
   (bfd *, void *, void *);
-extern bfd_boolean _bfd_xcoff_mkobject
+extern bool _bfd_xcoff_mkobject
   (bfd *);
-extern bfd_boolean _bfd_xcoff_copy_private_bfd_data
+extern bool _bfd_xcoff_copy_private_bfd_data
   (bfd *, bfd *);
-extern bfd_boolean _bfd_xcoff_is_local_label_name
+extern bool _bfd_xcoff_is_local_label_name
   (bfd *, const char *);
 extern void xcoff64_rtype2howto
   (arelent *, struct internal_reloc *);
 extern reloc_howto_type * xcoff64_reloc_type_lookup
   (bfd *, bfd_reloc_code_real_type);
-extern bfd_boolean _bfd_xcoff_slurp_armap
+extern bool _bfd_xcoff_slurp_armap
   (bfd *);
 extern void *_bfd_xcoff_read_ar_hdr
   (bfd *);
@@ -121,9 +121,9 @@ extern bfd *_bfd_xcoff_openr_next_archived_file
   (bfd *, bfd *);
 extern int _bfd_xcoff_stat_arch_elt
   (bfd *, struct stat *);
-extern bfd_boolean _bfd_xcoff_write_armap
+extern bool _bfd_xcoff_write_armap
   (bfd *, unsigned int, struct orl *, unsigned int, int);
-extern bfd_boolean _bfd_xcoff_write_archive_contents
+extern bool _bfd_xcoff_write_archive_contents
   (bfd *);
 extern int _bfd_xcoff_sizeof_headers
   (bfd *, struct bfd_link_info *);
@@ -147,15 +147,13 @@ static void xcoff64_swap_ldrel_in
   (bfd *, const void *, struct internal_ldrel *);
 static void xcoff64_swap_ldrel_out
   (bfd *, const struct internal_ldrel *, void *d);
-static bfd_boolean xcoff64_write_object_contents
-  (bfd *);
-static bfd_boolean xcoff64_ppc_relocate_section
+static bool xcoff64_ppc_relocate_section
   (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
    struct internal_reloc *, struct internal_syment *,
    asection **);
-static bfd_boolean xcoff64_slurp_armap
+static bool xcoff64_slurp_armap
   (bfd *);
-static const bfd_target *xcoff64_archive_p
+static bfd_cleanup xcoff64_archive_p
   (bfd *);
 static bfd *xcoff64_openr_next_archived_file
   (bfd *, bfd *);
@@ -163,54 +161,75 @@ static int xcoff64_sizeof_headers
   (bfd *, struct bfd_link_info *);
 static asection *xcoff64_create_csect_from_smclas
   (bfd *, union internal_auxent *, const char *);
-static bfd_boolean xcoff64_is_lineno_count_overflow
+static bool xcoff64_is_lineno_count_overflow
   (bfd *, bfd_vma);
-static bfd_boolean xcoff64_is_reloc_count_overflow
+static bool xcoff64_is_reloc_count_overflow
   (bfd *, bfd_vma);
 static bfd_vma xcoff64_loader_symbol_offset
   (bfd *, struct internal_ldhdr *);
 static bfd_vma xcoff64_loader_reloc_offset
   (bfd *, struct internal_ldhdr *);
-static bfd_boolean xcoff64_generate_rtinit
-  (bfd *, const char *, const char *, bfd_boolean);
-static bfd_boolean xcoff64_bad_format_hook
+static bool xcoff64_generate_rtinit
+  (bfd *, const char *, const char *, bool);
+static bool xcoff64_bad_format_hook
   (bfd *, void *);
 
 /* Relocation functions */
-static bfd_boolean xcoff64_reloc_type_br
-  (XCOFF_RELOC_FUNCTION_ARGS);
+static xcoff_reloc_function xcoff64_reloc_type_br;
 
-bfd_boolean (*xcoff64_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION])
-  (XCOFF_RELOC_FUNCTION_ARGS) =
+xcoff_reloc_function *const
+xcoff64_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION] =
 {
-  xcoff_reloc_type_pos,         /* R_POS   (0x00) */
-  xcoff_reloc_type_neg,         /* R_NEG   (0x01) */
-  xcoff_reloc_type_rel,         /* R_REL   (0x02) */
-  xcoff_reloc_type_toc,         /* R_TOC   (0x03) */
-  xcoff_reloc_type_fail, /* R_RTB   (0x04) */
-  xcoff_reloc_type_toc,         /* R_GL    (0x05) */
-  xcoff_reloc_type_toc,         /* R_TCL   (0x06) */
-  xcoff_reloc_type_fail, /*        (0x07) */
-  xcoff_reloc_type_ba,  /* R_BA    (0x08) */
-  xcoff_reloc_type_fail, /*        (0x09) */
-  xcoff64_reloc_type_br, /* R_BR    (0x0a) */
-  xcoff_reloc_type_fail, /*        (0x0b) */
-  xcoff_reloc_type_pos,         /* R_RL    (0x0c) */
-  xcoff_reloc_type_pos,         /* R_RLA   (0x0d) */
-  xcoff_reloc_type_fail, /*        (0x0e) */
-  xcoff_reloc_type_noop, /* R_REF   (0x0f) */
-  xcoff_reloc_type_fail, /*        (0x10) */
-  xcoff_reloc_type_fail, /*        (0x11) */
-  xcoff_reloc_type_toc,         /* R_TRL   (0x12) */
-  xcoff_reloc_type_toc,         /* R_TRLA  (0x13) */
-  xcoff_reloc_type_fail, /* R_RRTBI (0x14) */
-  xcoff_reloc_type_fail, /* R_RRTBA (0x15) */
-  xcoff_reloc_type_ba,  /* R_CAI   (0x16) */
-  xcoff_reloc_type_crel, /* R_CREL  (0x17) */
-  xcoff_reloc_type_ba,  /* R_RBA   (0x18) */
-  xcoff_reloc_type_ba,  /* R_RBAC  (0x19) */
-  xcoff64_reloc_type_br, /* R_RBR   (0x1a) */
-  xcoff_reloc_type_ba,  /* R_RBRC  (0x1b) */
+  xcoff_reloc_type_pos,  /* R_POS     (0x00) */
+  xcoff_reloc_type_neg,  /* R_NEG     (0x01) */
+  xcoff_reloc_type_rel,  /* R_REL     (0x02) */
+  xcoff_reloc_type_toc,  /* R_TOC     (0x03) */
+  xcoff_reloc_type_toc,  /* R_TRL     (0x04) */
+  xcoff_reloc_type_toc,  /* R_GL      (0x05) */
+  xcoff_reloc_type_toc,  /* R_TCL     (0x06) */
+  xcoff_reloc_type_fail, /*           (0x07) */
+  xcoff_reloc_type_ba,   /* R_BA      (0x08) */
+  xcoff_reloc_type_fail, /*           (0x09) */
+  xcoff64_reloc_type_br, /* R_BR      (0x0a) */
+  xcoff_reloc_type_fail, /*           (0x0b) */
+  xcoff_reloc_type_pos,  /* R_RL      (0x0c) */
+  xcoff_reloc_type_pos,  /* R_RLA     (0x0d) */
+  xcoff_reloc_type_fail, /*           (0x0e) */
+  xcoff_reloc_type_noop, /* R_REF     (0x0f) */
+  xcoff_reloc_type_fail, /*           (0x10) */
+  xcoff_reloc_type_fail, /*           (0x11) */
+  xcoff_reloc_type_fail, /*           (0x12) */
+  xcoff_reloc_type_toc,  /* R_TRLA    (0x13) */
+  xcoff_reloc_type_fail, /* R_RRTBI   (0x14) */
+  xcoff_reloc_type_fail, /* R_RRTBA   (0x15) */
+  xcoff_reloc_type_ba,   /* R_CAI     (0x16) */
+  xcoff_reloc_type_crel, /* R_CREL    (0x17) */
+  xcoff_reloc_type_ba,   /* R_RBA     (0x18) */
+  xcoff_reloc_type_ba,   /* R_RBAC    (0x19) */
+  xcoff64_reloc_type_br, /* R_RBR     (0x1a) */
+  xcoff_reloc_type_ba,   /* R_RBRC    (0x1b) */
+  xcoff_reloc_type_fail, /*           (0x1c) */
+  xcoff_reloc_type_fail, /*           (0x1d) */
+  xcoff_reloc_type_fail, /*           (0x1e) */
+  xcoff_reloc_type_fail, /*           (0x1f) */
+  xcoff_reloc_type_tls,  /* R_TLS     (0x20) */
+  xcoff_reloc_type_tls,  /* R_TLS_IE  (0x21) */
+  xcoff_reloc_type_tls,  /* R_TLS_LD  (0x22) */
+  xcoff_reloc_type_tls,  /* R_TLS_LE  (0x23) */
+  xcoff_reloc_type_tls,  /* R_TLSM    (0x24) */
+  xcoff_reloc_type_tls,  /* R_TLSML   (0x25) */
+  xcoff_reloc_type_fail, /*           (0x26) */
+  xcoff_reloc_type_fail, /*           (0x27) */
+  xcoff_reloc_type_fail, /*           (0x28) */
+  xcoff_reloc_type_fail, /*           (0x29) */
+  xcoff_reloc_type_fail, /*           (0x2a) */
+  xcoff_reloc_type_fail, /*           (0x2b) */
+  xcoff_reloc_type_fail, /*           (0x2c) */
+  xcoff_reloc_type_fail, /*           (0x2d) */
+  xcoff_reloc_type_fail, /*           (0x2e) */
+  xcoff_reloc_type_fail, /*           (0x2f) */
+  xcoff_reloc_type_toc, /* R_TOCU    (0x30) */
+  xcoff_reloc_type_toc, /* R_TOCL    (0x31) */
 };
 
 /* coffcode.h needs these to be defined.  */
@@ -238,9 +257,9 @@ bfd_boolean (*xcoff64_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION])
 #define coff_bfd_reloc_type_lookup xcoff64_reloc_type_lookup
 #define coff_bfd_reloc_name_lookup xcoff64_reloc_name_lookup
 #ifdef AIX_CORE
-extern const bfd_target * rs6000coff_core_p
+extern bfd_cleanup rs6000coff_core_p
   (bfd *abfd);
-extern bfd_boolean rs6000coff_core_file_matches_executable_p
+extern bool rs6000coff_core_file_matches_executable_p
   (bfd *cbfd, bfd *ebfd);
 extern char *rs6000coff_core_file_failing_command
   (bfd *abfd);
@@ -343,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;
@@ -359,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;
 
@@ -385,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;
-
-         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;
-    }
 
-  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
-    {
+    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_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);
+       = 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;
     }
 
- end: ;
+  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);
+
+
 }
 
 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;
@@ -441,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)
        {
@@ -449,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:
@@ -474,71 +536,65 @@ _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;
-    }
 
-  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);
-    }
+    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;
 
- end:
+    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;
+    }
 
   return bfd_coff_auxesz (abfd);
 }
 
-static bfd_boolean
+static bool
 _bfd_xcoff64_put_symbol_name (struct bfd_link_info *info,
                              struct bfd_strtab_hash *strtab,
                              struct internal_syment *sym,
                              const char *name)
 {
-  bfd_boolean hash;
+  bool hash;
   bfd_size_type indx;
 
   hash = !info->traditional_format;
-  indx = _bfd_stringtab_add (strtab, name, hash, FALSE);
+  indx = _bfd_stringtab_add (strtab, name, hash, false);
 
   if (indx == (bfd_size_type) -1)
-    return FALSE;
+    return false;
 
   sym->_n._n_n._n_zeroes = 0;
   sym->_n._n_n._n_offset = STRING_SIZE_SIZE + indx;
 
-  return TRUE;
+  return true;
 }
 
-static bfd_boolean
+static bool
 _bfd_xcoff64_put_ldsymbol_name (bfd *abfd ATTRIBUTE_UNUSED,
                                struct xcoff_loader_info *ldinfo,
                                struct internal_ldsym *ldsym,
@@ -561,8 +617,8 @@ _bfd_xcoff64_put_ldsymbol_name (bfd *abfd ATTRIBUTE_UNUSED,
       newstrings = bfd_realloc (ldinfo->strings, newalc);
       if (newstrings == NULL)
        {
-         ldinfo->failed = TRUE;
-         return FALSE;
+         ldinfo->failed = true;
+         return false;
        }
       ldinfo->string_alc = newalc;
       ldinfo->strings = newstrings;
@@ -575,7 +631,7 @@ _bfd_xcoff64_put_ldsymbol_name (bfd *abfd ATTRIBUTE_UNUSED,
   ldsym->_l._l_l._l_offset = ldinfo->string_size + 2;
   ldinfo->string_size += len + 3;
 
-  return TRUE;
+  return true;
 }
 
 /* Routines to swap information in the XCOFF .loader section.  If we
@@ -712,354 +768,8 @@ xcoff64_swap_ldrel_out (bfd *abfd, const struct internal_ldrel *src, void *d)
   bfd_put_32 (abfd, src->l_symndx, dst->l_symndx);
 }
 
-static bfd_boolean
-xcoff64_write_object_contents (bfd *abfd)
-{
-  asection *current;
-  bfd_boolean hasrelocs = FALSE;
-  bfd_boolean haslinno = FALSE;
-  file_ptr scn_base;
-  file_ptr reloc_base;
-  file_ptr lineno_base;
-  file_ptr sym_base;
-  unsigned long reloc_size = 0;
-  unsigned long lnno_size = 0;
-  asection *text_sec = NULL;
-  asection *data_sec = NULL;
-  asection *bss_sec = NULL;
-  struct internal_filehdr internal_f;
-  struct internal_aouthdr internal_a;
-
-  bfd_set_error (bfd_error_system_call);
-
-  if (! abfd->output_has_begun)
-    {
-      if (! bfd_coff_compute_section_file_positions (abfd))
-       return FALSE;
-    }
-
-  /* Work out the size of the reloc and linno areas.  */
-  reloc_base = obj_relocbase (abfd);
-
-  for (current = abfd->sections; current != NULL; current = current->next)
-    reloc_size += current->reloc_count * bfd_coff_relsz (abfd);
-
-  lineno_base = reloc_base + reloc_size;
-
-  /* Make a pass through the symbol table to count line number entries and
-     put them into the correct asections.  */
-  lnno_size = coff_count_linenumbers (abfd) * bfd_coff_linesz (abfd);
-
-  sym_base = lineno_base + lnno_size;
-
-  /* Indicate in each section->line_filepos its actual file address.  */
-  for (current = abfd->sections; current != NULL; current =  current->next)
-    {
-      if (current->lineno_count)
-       {
-         current->line_filepos = lineno_base;
-         current->moving_line_filepos = lineno_base;
-         lineno_base += current->lineno_count * bfd_coff_linesz (abfd);
-       }
-      else
-       {
-         current->line_filepos = 0;
-       }
-
-      if (current->reloc_count)
-       {
-         current->rel_filepos = reloc_base;
-         reloc_base += current->reloc_count * bfd_coff_relsz (abfd);
-       }
-      else
-       {
-         current->rel_filepos = 0;
-       }
-    }
-
-  if ((abfd->flags & EXEC_P) != 0)
-    {
-      scn_base = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd);
-      internal_f.f_opthdr = bfd_coff_aoutsz (abfd);
-    }
-  else
-    {
-      scn_base = bfd_coff_filhsz (abfd);
-      internal_f.f_opthdr = 0;
-    }
-
-  internal_f.f_nscns = 0;
-
-  if (bfd_seek (abfd, scn_base, SEEK_SET) != 0)
-    return FALSE;
-
-  for (current = abfd->sections; current != NULL; current = current->next)
-    {
-      struct internal_scnhdr section;
-      struct external_scnhdr buff;
-      bfd_size_type amount;
-
-      internal_f.f_nscns++;
-
-      strncpy (section.s_name, current->name, SCNNMLEN);
-
-      section.s_vaddr = current->vma;
-      section.s_paddr = current->lma;
-      section.s_size =  current->size;
-
-      /* If this section has no size or is unloadable then the scnptr
-        will be 0 too.  */
-      if (current->size == 0
-         || (current->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
-       {
-         section.s_scnptr = 0;
-       }
-      else
-       {
-         section.s_scnptr = current->filepos;
-       }
-
-      section.s_relptr = current->rel_filepos;
-      section.s_lnnoptr = current->line_filepos;
-      section.s_nreloc = current->reloc_count;
-
-      section.s_nlnno = current->lineno_count;
-      if (current->reloc_count != 0)
-       hasrelocs = TRUE;
-      if (current->lineno_count != 0)
-       haslinno = TRUE;
-
-      section.s_flags = sec_to_styp_flags (current->name, current->flags);
-
-      if (!strcmp (current->name, _TEXT))
-       {
-         text_sec = current;
-       }
-      else if (!strcmp (current->name, _DATA))
-       {
-         data_sec = current;
-       }
-      else if (!strcmp (current->name, _BSS))
-       {
-         bss_sec = current;
-       }
-
-      amount = bfd_coff_scnhsz (abfd);
-      if (bfd_coff_swap_scnhdr_out (abfd, &section, &buff) == 0
-         || bfd_bwrite (&buff, amount, abfd) != amount)
-       return FALSE;
-    }
-
-  internal_f.f_timdat = 0;
-
-  internal_f.f_flags = 0;
-
-  if (!hasrelocs)
-    internal_f.f_flags |= F_RELFLG;
-  if (!haslinno)
-    internal_f.f_flags |= F_LNNO;
-  if (abfd->flags & EXEC_P)
-    internal_f.f_flags |= F_EXEC;
-
-  /* FIXME: this is wrong for PPC_PE!  */
-  if (bfd_little_endian (abfd))
-    internal_f.f_flags |= F_AR32WR;
-  else
-    internal_f.f_flags |= F_AR32W;
-
-  if ((abfd->flags & DYNAMIC) != 0)
-    internal_f.f_flags |= F_SHROBJ;
-  if (bfd_get_section_by_name (abfd, _LOADER) != NULL)
-    internal_f.f_flags |= F_DYNLOAD;
-
-  memset (&internal_a, 0, sizeof internal_a);
-
-  internal_f.f_magic = bfd_xcoff_magic_number (abfd);
-  internal_a.magic = (abfd->flags & D_PAGED
-                     ? RS6K_AOUTHDR_ZMAGIC
-                     : (abfd->flags & WP_TEXT
-                        ? RS6K_AOUTHDR_NMAGIC
-                        : RS6K_AOUTHDR_OMAGIC));
-
-  /* FIXME: Does anybody ever set this to another value?  */
-  internal_a.vstamp = 0;
-
-  /* Now should write relocs, strings, syms.  */
-  obj_sym_filepos (abfd) = sym_base;
-
-  internal_f.f_symptr = 0;
-  internal_f.f_nsyms = 0;
 
-  /* If bfd_get_symcount (abfd) != 0, then we are not using the COFF
-     backend linker, and obj_raw_syment_count is not valid until after
-     coff_write_symbols is called.  */
-  if (bfd_get_symcount (abfd) != 0)
-    {
-      int firstundef;
-
-      if (!coff_renumber_symbols (abfd, &firstundef))
-       return FALSE;
-      coff_mangle_symbols (abfd);
-      if (! coff_write_symbols (abfd))
-       return FALSE;
-      if (! coff_write_linenumbers (abfd))
-       return FALSE;
-      if (! coff_write_relocs (abfd, firstundef))
-       return FALSE;
-
-      internal_f.f_symptr = sym_base;
-      internal_f.f_nsyms = bfd_get_symcount (abfd);
-    }
-  else if (obj_raw_syment_count (abfd) != 0)
-    {
-      internal_f.f_symptr = sym_base;
-
-      /* AIX appears to require that F_RELFLG not be set if there are
-        local symbols but no relocations.  */
-      internal_f.f_flags &=~ F_RELFLG;
-    }
-  else
-    {
-      internal_f.f_flags |= F_LSYMS;
-    }
-
-  if (text_sec)
-    {
-      internal_a.tsize = text_sec->size;
-      internal_a.text_start = internal_a.tsize ? text_sec->vma : 0;
-    }
-
-  if (data_sec)
-    {
-      internal_a.dsize = data_sec->size;
-      internal_a.data_start = internal_a.dsize ? data_sec->vma : 0;
-    }
-
-  if (bss_sec)
-    {
-      internal_a.bsize = bss_sec->size;
-      if (internal_a.bsize && bss_sec->vma < internal_a.data_start)
-       internal_a.data_start = bss_sec->vma;
-    }
-
-  internal_a.entry = bfd_get_start_address (abfd);
-  internal_f.f_nsyms = obj_raw_syment_count (abfd);
-
-  if (xcoff_data (abfd)->full_aouthdr)
-    {
-      bfd_vma toc;
-      asection *loader_sec;
-
-      internal_a.vstamp = 1;
-
-      internal_a.o_snentry = xcoff_data (abfd)->snentry;
-      if (internal_a.o_snentry == 0)
-       internal_a.entry = (bfd_vma) -1;
-
-      if (text_sec != NULL)
-       {
-         internal_a.o_sntext = text_sec->target_index;
-         internal_a.o_algntext = bfd_section_alignment (text_sec);
-       }
-      else
-       {
-         internal_a.o_sntext = 0;
-         internal_a.o_algntext = 0;
-       }
-
-      if (data_sec != NULL)
-       {
-         internal_a.o_sndata = data_sec->target_index;
-         internal_a.o_algndata = bfd_section_alignment (data_sec);
-       }
-      else
-       {
-         internal_a.o_sndata = 0;
-         internal_a.o_algndata = 0;
-       }
-
-      loader_sec = bfd_get_section_by_name (abfd, ".loader");
-      if (loader_sec != NULL)
-       internal_a.o_snloader = loader_sec->target_index;
-      else
-       internal_a.o_snloader = 0;
-      if (bss_sec != NULL)
-       internal_a.o_snbss = bss_sec->target_index;
-      else
-       internal_a.o_snbss = 0;
-
-      toc = xcoff_data (abfd)->toc;
-      internal_a.o_toc = toc;
-      internal_a.o_sntoc = xcoff_data (abfd)->sntoc;
-
-      internal_a.o_modtype = xcoff_data (abfd)->modtype;
-      if (xcoff_data (abfd)->cputype != -1)
-       internal_a.o_cputype = xcoff_data (abfd)->cputype;
-      else
-       {
-         switch (bfd_get_arch (abfd))
-           {
-           case bfd_arch_rs6000:
-             internal_a.o_cputype = 4;
-             break;
-           case bfd_arch_powerpc:
-             if (bfd_get_mach (abfd) == bfd_mach_ppc)
-               internal_a.o_cputype = 3;
-             else if (bfd_get_mach (abfd) == bfd_mach_ppc_620)
-               internal_a.o_cputype = 2;
-             else
-               internal_a.o_cputype = 1;
-             break;
-           default:
-             abort ();
-           }
-       }
-      internal_a.o_maxstack = xcoff_data (abfd)->maxstack;
-      internal_a.o_maxdata = xcoff_data (abfd)->maxdata;
-    }
-
-  if (bfd_seek (abfd, (file_ptr) 0, 0) != 0)
-    return FALSE;
-
-  {
-    char * buff;
-    bfd_size_type amount = bfd_coff_filhsz (abfd);
-
-    buff = bfd_malloc (amount);
-    if (buff == NULL)
-      return FALSE;
-
-    bfd_coff_swap_filehdr_out (abfd, &internal_f, buff);
-    amount = bfd_bwrite (buff, amount, abfd);
-
-    free (buff);
-
-    if (amount != bfd_coff_filhsz (abfd))
-      return FALSE;
-  }
-
-  if (abfd->flags & EXEC_P)
-    {
-      char * buff;
-      bfd_size_type amount = bfd_coff_aoutsz (abfd);
-
-      buff = bfd_malloc (amount);
-      if (buff == NULL)
-       return FALSE;
-
-      bfd_coff_swap_aouthdr_out (abfd, &internal_a, buff);
-      amount = bfd_bwrite (buff, amount, abfd);
-
-      free (buff);
-
-      if (amount != bfd_coff_aoutsz (abfd))
-       return FALSE;
-    }
-
-  return TRUE;
-}
-
-static bfd_boolean
+static bool
 xcoff64_reloc_type_br (bfd *input_bfd,
                       asection *input_section,
                       bfd *output_bfd ATTRIBUTE_UNUSED,
@@ -1075,7 +785,7 @@ xcoff64_reloc_type_br (bfd *input_bfd,
   bfd_vma section_offset;
 
   if (0 > rel->r_symndx)
-    return FALSE;
+    return false;
 
   h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx];
   section_offset = rel->r_vaddr - input_section->vma;
@@ -1148,388 +858,198 @@ xcoff64_reloc_type_br (bfd *input_bfd,
       bfd_put_32 (input_bfd, insn, ptr);
 
       /* Make the howto absolute too.  */
-      howto->pc_relative = FALSE;
+      howto->pc_relative = false;
       howto->complain_on_overflow = complain_overflow_bitfield;
     }
   else
     {
       /* Use a PC-relative howto and subtract the instruction's address
         from the target address we calculated above.  */
-      howto->pc_relative = TRUE;
+      howto->pc_relative = true;
       *relocation -= (input_section->output_section->vma
                      + input_section->output_offset
                      + section_offset);
     }
-  return TRUE;
+  return true;
 }
 
-/* This is the relocation function for the PowerPC64.
-   See xcoff_ppc_relocation_section for more information. */
 
-bfd_boolean
-xcoff64_ppc_relocate_section (bfd *output_bfd,
-                             struct bfd_link_info *info,
-                             bfd *input_bfd,
-                             asection *input_section,
-                             bfd_byte *contents,
-                             struct internal_reloc *relocs,
-                             struct internal_syment *syms,
-                             asection **sections)
-{
-  struct internal_reloc *rel;
-  struct internal_reloc *relend;
+\f
+/* The XCOFF reloc table.
+   Cf xcoff_howto_table comments.  */
 
-  rel = relocs;
-  relend = rel + input_section->reloc_count;
-  for (; rel < relend; rel++)
-    {
-      long symndx;
-      struct xcoff_link_hash_entry *h;
-      struct internal_syment *sym;
-      bfd_vma addend;
-      bfd_vma val;
-      struct reloc_howto_struct howto;
-      bfd_vma relocation;
-      bfd_vma value_to_relocate;
-      bfd_vma address;
-      bfd_byte *location;
+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) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        0,                     /* special_function */
+        "R_POS_64",            /* name */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
 
-      /* Relocation type R_REF is a special relocation type which is
-        merely used to prevent garbage collection from occurring for
-        the csect including the symbol which it references.  */
-      if (rel->r_type == R_REF)
-       continue;
+  /* 0x01: 64 bit relocation, but store negative value.  */
+  HOWTO (R_NEG,                        /* type */
+        0,                     /* rightshift */
+        -4,                    /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        0,                     /* special_function */
+        "R_NEG",               /* name */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
 
-      /* howto */
-      howto.type = rel->r_type;
-      howto.rightshift = 0;
-      howto.bitsize = (rel->r_size & 0x3f) + 1;
-      howto.size = howto.bitsize > 16 ? (howto.bitsize > 32 ? 4 : 2) : 1;
-      howto.pc_relative = FALSE;
-      howto.bitpos = 0;
-      howto.complain_on_overflow = (rel->r_size & 0x80
-                                   ? complain_overflow_signed
-                                   : complain_overflow_bitfield);
-      howto.special_function = NULL;
-      howto.name = "internal";
-      howto.partial_inplace = TRUE;
-      howto.src_mask = howto.dst_mask = N_ONES (howto.bitsize);
-      howto.pcrel_offset = FALSE;
-
-      /* symbol */
-      val = 0;
-      addend = 0;
-      h = NULL;
-      sym = NULL;
-      symndx = rel->r_symndx;
-
-      if (-1 != symndx)
-       {
-         asection *sec;
-
-         h = obj_xcoff_sym_hashes (input_bfd)[symndx];
-         sym = syms + symndx;
-         addend = - sym->n_value;
-
-         if (NULL == h)
-           {
-             sec = sections[symndx];
-             /* Hack to make sure we use the right TOC anchor value
-                if this reloc is against the TOC anchor.  */
-             if (sec->name[3] == '0'
-                 && strcmp (sec->name, ".tc0") == 0)
-               val = xcoff_data (output_bfd)->toc;
-             else
-               val = (sec->output_section->vma
-                      + sec->output_offset
-                      + sym->n_value
-                      - sec->vma);
-           }
-         else
-           {
-             if (info->unresolved_syms_in_objects != RM_IGNORE
-                 && (h->flags & XCOFF_WAS_UNDEFINED) != 0)
-               (*info->callbacks->undefined_symbol)
-                 (info, h->root.root.string, input_bfd, input_section,
-                  rel->r_vaddr - input_section->vma,
-                  info->unresolved_syms_in_objects == RM_GENERATE_ERROR);
-
-             if (h->root.type == bfd_link_hash_defined
-                 || h->root.type == bfd_link_hash_defweak)
-               {
-                 sec = h->root.u.def.section;
-                 val = (h->root.u.def.value
-                        + sec->output_section->vma
-                        + sec->output_offset);
-               }
-             else if (h->root.type == bfd_link_hash_common)
-               {
-                 sec = h->root.u.c.p->section;
-                 val = (sec->output_section->vma
-                        + sec->output_offset);
-               }
-             else
-               {
-                 BFD_ASSERT (bfd_link_relocatable (info)
-                             || (h->flags & XCOFF_DEF_DYNAMIC) != 0
-                             || (h->flags & XCOFF_IMPORT) != 0);
-               }
-           }
-       }
-
-      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)))
-       return FALSE;
-
-      /* address */
-      address = rel->r_vaddr - input_section->vma;
-      location = contents + address;
-
-      if (address > input_section->size)
-       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);
-
-      /* overflow.
-
-        FIXME: We may drop bits during the addition
-        which we don't check for.  We must either check at every single
-        operation, which would be tedious, or we must do the computations
-        in a type larger than bfd_vma, which would be inefficient.  */
-
-      if (((*xcoff_complain_overflow[howto.complain_on_overflow])
-          (input_bfd, value_to_relocate, relocation, &howto)))
-       {
-         const char *name;
-         char buf[SYMNMLEN + 1];
-         char reloc_type_name[10];
-
-         if (symndx == -1)
-           {
-             name = "*ABS*";
-           }
-         else if (h != NULL)
-           {
-             name = NULL;
-           }
-         else
-           {
-             name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
-             if (name == NULL)
-               name = "UNKNOWN";
-           }
-         sprintf (reloc_type_name, "0x%02x", rel->r_type);
-
-         (*info->callbacks->reloc_overflow)
-           (info, (h ? &h->root : NULL), name, reloc_type_name,
-            (bfd_vma) 0, input_bfd, input_section,
-            rel->r_vaddr - input_section->vma);
-       }
-
-      /* Add RELOCATION to the right bits of VALUE_TO_RELOCATE.  */
-      value_to_relocate = ((value_to_relocate & ~howto.dst_mask)
-                          | (((value_to_relocate & howto.src_mask)
-                              + 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);
-
-    }
-  return TRUE;
-}
-
-\f
-/* The XCOFF reloc table.  Actually, XCOFF relocations specify the
-   bitsize and whether they are signed or not, along with a
-   conventional type.  This table is for the types, which are used for
-   different algorithms for putting in the reloc.  Many of these
-   relocs need special_function entries, which I have not written.  */
-
-reloc_howto_type xcoff64_howto_table[] =
-{
-  /* 0x00: Standard 64 bit relocation.  */
-  HOWTO (R_POS,                        /* type */
+  /* 0x02: 64 bit PC relative relocation.  */
+  HOWTO (R_REL,                        /* type */
         0,                     /* rightshift */
         4,                     /* size (0 = byte, 1 = short, 2 = long) */
         64,                    /* bitsize */
-        FALSE,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_bitfield, /* complain_on_overflow */
-        0,                     /* special_function */
-        "R_POS_64",            /* name */
-        TRUE,                  /* partial_inplace */
-        MINUS_ONE,             /* src_mask */
-        MINUS_ONE,             /* dst_mask */
-        FALSE),                /* pcrel_offset */
-
-  /* 0x01: 64 bit relocation, but store negative value.  */
-  HOWTO (R_NEG,                        /* type */
-        0,                     /* rightshift */
-        -4,                    /* size (0 = byte, 1 = short, 2 = long) */
-        64,                    /* bitsize */
-        FALSE,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_bitfield, /* complain_on_overflow */
-        0,                     /* special_function */
-        "R_NEG",               /* name */
-        TRUE,                  /* partial_inplace */
-        MINUS_ONE,             /* src_mask */
-        MINUS_ONE,             /* dst_mask */
-        FALSE),                /* pcrel_offset */
-
-  /* 0x02: 32 bit PC relative relocation.  */
-  HOWTO (R_REL,                        /* type */
-        0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        32,                    /* bitsize */
-        TRUE,                  /* pc_relative */
+        true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         0,                     /* special_function */
         "R_REL",               /* name */
-        TRUE,                  /* partial_inplace */
-        0xffffffff,            /* src_mask */
-        0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
 
   /* 0x03: 16 bit TOC relative relocation.  */
   HOWTO (R_TOC,                        /* type */
         0,                     /* rightshift */
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_TOC",               /* name */
-        TRUE,                  /* partial_inplace */
-        0xffff,                /* src_mask */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
-  /* 0x04: I don't really know what this is.   */
-  HOWTO (R_RTB,                        /* type */
-        1,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+  /* 0x04: Same as R_TOC.  */
+  HOWTO (R_TRL,                        /* type */
+        0,                     /* rightshift */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
-        "R_RTB",               /* name */
-        TRUE,                  /* partial_inplace */
-        0xffffffff,            /* src_mask */
-        0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        "R_TRL",               /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
 
   /* 0x05: External TOC relative symbol.  */
   HOWTO (R_GL,                 /* type */
         0,                     /* rightshift */
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_GL",                /* name */
-        TRUE,                  /* partial_inplace */
-        0xffff,                /* src_mask */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* 0x06: Local TOC relative symbol.   */
   HOWTO (R_TCL,                        /* type */
         0,                     /* rightshift */
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_TCL",               /* name */
-        TRUE,                  /* partial_inplace */
-        0xffff,                /* src_mask */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   EMPTY_HOWTO (7),
 
-  /* 0x08: Non modifiable absolute branch.  */
+  /* 0x08: Same as R_RBA.  */
   HOWTO (R_BA,                 /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         26,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_BA_26",             /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0x03fffffc,            /* src_mask */
         0x03fffffc,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   EMPTY_HOWTO (9),
 
-  /* 0x0a: Non modifiable relative branch.  */
+  /* 0x0a: Same as R_RBR.  */
   HOWTO (R_BR,                 /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         26,                    /* bitsize */
-        TRUE,                  /* pc_relative */
+        true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         0,                     /* special_function */
         "R_BR",                /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0x03fffffc,            /* src_mask */
         0x03fffffc,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   EMPTY_HOWTO (0xb),
 
-  /* 0x0c: Indirect load.  */
+  /* 0x0c: Same as R_POS.  */
   HOWTO (R_RL,                 /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
-        16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_RL",                /* name */
-        TRUE,                  /* partial_inplace */
-        0xffff,                /* src_mask */
-        0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
 
-  /* 0x0d: Load address.  */
+  /* 0x0d: Same as R_POS.  */
   HOWTO (R_RLA,                        /* type */
         0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
-        16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_RLA",               /* name */
-        TRUE,                  /* partial_inplace */
-        0xffff,                /* src_mask */
-        0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
 
   EMPTY_HOWTO (0xe),
 
@@ -1538,235 +1058,365 @@ reloc_howto_type xcoff64_howto_table[] =
         0,                     /* rightshift */
         0,                     /* size (0 = byte, 1 = short, 2 = long) */
         1,                     /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         0,                     /* special_function */
         "R_REF",               /* name */
-        FALSE,                 /* partial_inplace */
+        false,                 /* partial_inplace */
         0,                     /* src_mask */
         0,                     /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   EMPTY_HOWTO (0x10),
   EMPTY_HOWTO (0x11),
+  EMPTY_HOWTO (0x12),
 
-  /* 0x12: TOC relative indirect load.  */
-  HOWTO (R_TRL,                        /* type */
-        0,                     /* rightshift */
-        1,                     /* size (0 = byte, 1 = short, 2 = long) */
-        16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
-        0,                     /* bitpos */
-        complain_overflow_bitfield, /* complain_on_overflow */
-        0,                     /* special_function */
-        "R_TRL",               /* name */
-        TRUE,                  /* partial_inplace */
-        0xffff,                /* src_mask */
-        0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
-
-  /* 0x13: TOC relative load address.   */
+  /* 0x13: Same as R_TOC  */
   HOWTO (R_TRLA,               /* type */
         0,                     /* rightshift */
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_TRLA",              /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* 0x14: Modifiable relative branch.  */
   HOWTO (R_RRTBI,              /* type */
         1,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_RRTBI",             /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* 0x15: Modifiable absolute branch.  */
   HOWTO (R_RRTBA,              /* type */
         1,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_RRTBA",             /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
-  /* 0x16: Modifiable call absolute indirect.   */
+  /* 0x16: Modifiable call absolute indirect.  */
   HOWTO (R_CAI,                        /* type */
         0,                     /* rightshift */
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_CAI",               /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
-  /* 0x17: Modifiable call relative.   */
+  /* 0x17: Modifiable call relative.  */
   HOWTO (R_CREL,               /* type */
         0,                     /* rightshift */
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_CREL",              /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* 0x18: Modifiable branch absolute.  */
   HOWTO (R_RBA,                        /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         26,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_RBA",               /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0x03fffffc,            /* src_mask */
         0x03fffffc,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* 0x19: Modifiable branch absolute.  */
   HOWTO (R_RBAC,               /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_RBAC",              /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* 0x1a: Modifiable branch relative.  */
   HOWTO (R_RBR,                        /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         26,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         0,                     /* special_function */
         "R_RBR_26",            /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0x03fffffc,            /* src_mask */
         0x03fffffc,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* 0x1b: Modifiable branch absolute.  */
   HOWTO (R_RBRC,               /* type */
         0,                     /* rightshift */
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_RBRC",              /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* 0x1c: Standard 32 bit relocation.  */
   HOWTO (R_POS,                        /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         32,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_POS_32",            /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0xffffffff,            /* src_mask */
         0xffffffff,            /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* 0x1d: 16 bit Non modifiable absolute branch.  */
   HOWTO (R_BA,                 /* type */
         0,                     /* rightshift */
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_BA_16",             /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0xfffc,                /* src_mask */
         0xfffc,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* 0x1e: Modifiable branch relative.  */
   HOWTO (R_RBR,                        /* type */
         0,                     /* rightshift */
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        TRUE,                  /* pc_relative */
+        true,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed, /* complain_on_overflow */
         0,                     /* special_function */
         "R_RBR_16",            /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0xfffc,                /* src_mask */
         0xfffc,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
 
   /* 0x1f: Modifiable branch absolute.  */
   HOWTO (R_RBA,                        /* type */
         0,                     /* rightshift */
         1,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
-        FALSE,                 /* pc_relative */
+        false,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_bitfield, /* complain_on_overflow */
         0,                     /* special_function */
         "R_RBA_16",            /* name */
-        TRUE,                  /* partial_inplace */
+        true,                  /* partial_inplace */
         0xffff,                /* src_mask */
         0xffff,                /* dst_mask */
-        FALSE),                /* pcrel_offset */
+        false),                /* pcrel_offset */
+
+  /* 0x20: General-dynamic TLS relocation.  */
+  HOWTO (R_TLS,                        /* type */
+        0,                     /* rightshift */
+        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        0,                     /* special_function */
+        "R_TLS",               /* name */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 0x21: Initial-exec TLS relocation.  */
+  HOWTO (R_TLS_IE,             /* type */
+        0,                     /* rightshift */
+        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        0,                     /* special_function */
+        "R_TLS_IE",            /* name */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 0x22: Local-dynamic TLS relocation.  */
+  HOWTO (R_TLS_LD,             /* type */
+        0,                     /* rightshift */
+        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        0,                     /* special_function */
+        "R_TLS_LD",            /* name */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 0x23: Local-exec TLS relocation.  */
+  HOWTO (R_TLS_LE,             /* type */
+        0,                     /* rightshift */
+        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        0,                     /* special_function */
+        "R_TLS_LE",            /* name */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 0x24: TLS relocation.  */
+  HOWTO (R_TLSM,               /* type */
+        0,                     /* rightshift */
+        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        0,                     /* special_function */
+        "R_TLSM",              /* name */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 0x25: TLS module relocation.  */
+  HOWTO (R_TLSML,              /* type */
+        0,                     /* rightshift */
+        4,                     /* size (0 = byte, 1 = short, 2 = long) */
+        64,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        0,                     /* special_function */
+        "R_TLSM",              /* name */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 0x26: 32 bit relocation, but store negative value.  */
+  HOWTO (R_NEG,                        /* type */
+        0,                     /* rightshift */
+        -2,                    /* size (0 = byte, 1 = short, 2 = long) */
+        32,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        0,                     /* special_function */
+        "R_NEG_32",            /* name */
+        true,                  /* partial_inplace */
+        MINUS_ONE,             /* src_mask */
+        MINUS_ONE,             /* dst_mask */
+        false),                /* pcrel_offset */
+
+  EMPTY_HOWTO(0x27),
+  EMPTY_HOWTO(0x28),
+  EMPTY_HOWTO(0x29),
+  EMPTY_HOWTO(0x2a),
+  EMPTY_HOWTO(0x2b),
+  EMPTY_HOWTO(0x2c),
+  EMPTY_HOWTO(0x2d),
+  EMPTY_HOWTO(0x2e),
+  EMPTY_HOWTO(0x2f),
+
+  HOWTO (R_TOCU,               /* type */
+        16,                    /* rightshift */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_bitfield, /* complain_on_overflow */
+        0,                     /* special_function */
+        "R_TOCU",              /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
+
+  /* 0x31: Low-order 16 bit TOC relative relocation.  */
+  HOWTO (R_TOCL,               /* type */
+        0,                     /* rightshift */
+        1,                     /* size (0 = byte, 1 = short, 2 = long) */
+        16,                    /* bitsize */
+        false,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont, /* complain_on_overflow */
+        0,                     /* special_function */
+        "R_TOCL",              /* name */
+        true,                  /* partial_inplace */
+        0,                     /* src_mask */
+        0xffff,                /* dst_mask */
+        false),                /* pcrel_offset */
 
 };
 
 void
 xcoff64_rtype2howto (arelent *relent, struct internal_reloc *internal)
 {
-  if (internal->r_type > R_RBRC)
+  if (internal->r_type > R_TOCL)
     abort ();
 
   /* Default howto layout works most of the time */
@@ -1787,6 +1437,9 @@ xcoff64_rtype2howto (arelent *relent, struct internal_reloc *internal)
     {
       if (R_POS == internal->r_type)
        relent->howto = &xcoff64_howto_table[0x1c];
+
+      if (R_NEG == internal->r_type)
+       relent->howto = &xcoff64_howto_table[0x26];
     }
 
   /* The r_size field of an XCOFF reloc encodes the bitsize of the
@@ -1814,9 +1467,10 @@ xcoff64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       return &xcoff64_howto_table[8];
     case BFD_RELOC_PPC_TOC16:
       return &xcoff64_howto_table[3];
-    case BFD_RELOC_16:
-      /* Note that this relocation is only internally used by gas.  */
-      return &xcoff64_howto_table[0xc];
+    case BFD_RELOC_PPC_TOC16_HI:
+      return &xcoff64_howto_table[0x30];
+    case BFD_RELOC_PPC_TOC16_LO:
+      return &xcoff64_howto_table[0x31];
     case BFD_RELOC_PPC_B16:
       return &xcoff64_howto_table[0x1e];
     case BFD_RELOC_32:
@@ -1826,6 +1480,20 @@ xcoff64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
       return &xcoff64_howto_table[0];
     case BFD_RELOC_NONE:
       return &xcoff64_howto_table[0xf];
+    case BFD_RELOC_PPC_NEG:
+      return &xcoff64_howto_table[0x1];
+    case BFD_RELOC_PPC64_TLSGD:
+      return &xcoff64_howto_table[0x20];
+    case BFD_RELOC_PPC64_TLSIE:
+      return &xcoff64_howto_table[0x21];
+    case BFD_RELOC_PPC64_TLSLD:
+      return &xcoff64_howto_table[0x22];
+    case BFD_RELOC_PPC64_TLSLE:
+      return &xcoff64_howto_table[0x23];
+    case BFD_RELOC_PPC64_TLSM:
+      return &xcoff64_howto_table[0x24];
+    case BFD_RELOC_PPC64_TLSML:
+      return &xcoff64_howto_table[0x25];
     default:
       return NULL;
     }
@@ -1847,6 +1515,209 @@ xcoff64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   return NULL;
 }
 
+/* This is the relocation function for the PowerPC64.
+   See xcoff_ppc_relocation_section for more information. */
+
+bool
+xcoff64_ppc_relocate_section (bfd *output_bfd,
+                             struct bfd_link_info *info,
+                             bfd *input_bfd,
+                             asection *input_section,
+                             bfd_byte *contents,
+                             struct internal_reloc *relocs,
+                             struct internal_syment *syms,
+                             asection **sections)
+{
+  struct internal_reloc *rel;
+  struct internal_reloc *relend;
+
+  rel = relocs;
+  relend = rel + input_section->reloc_count;
+  for (; rel < relend; rel++)
+    {
+      long symndx;
+      struct xcoff_link_hash_entry *h;
+      struct internal_syment *sym;
+      bfd_vma addend;
+      bfd_vma val;
+      struct reloc_howto_struct howto;
+      bfd_vma relocation;
+      bfd_vma value_to_relocate;
+      bfd_vma address;
+      bfd_byte *location;
+
+      /* Relocation type R_REF is a special relocation type which is
+        merely used to prevent garbage collection from occurring for
+        the csect including the symbol which it references.  */
+      if (rel->r_type == R_REF)
+       continue;
+
+      /* Retrieve default value in HOWTO table and fix up according
+        to r_size field, if it can be different.
+        This should be made during relocation reading but the algorithms
+        are expecting constant howtos.  */
+      memcpy (&howto, &xcoff64_howto_table[rel->r_type], sizeof (howto));
+      if (howto.bitsize != (rel->r_size & 0x3f) + 1)
+       {
+         switch (rel->r_type)
+           {
+           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.src_mask = howto.dst_mask = N_ONES (howto.bitsize);
+             break;
+
+           default:
+             _bfd_error_handler
+               (_("%pB: relocatation (%d) at (0x%" BFD_VMA_FMT "x) has wrong"
+                  " r_rsize (0x%x)\n"),
+                input_bfd, rel->r_type, rel->r_vaddr, rel->r_size);
+             return false;
+           }
+       }
+
+      howto.complain_on_overflow = (rel->r_size & 0x80
+                                   ? complain_overflow_signed
+                                   : complain_overflow_bitfield);
+
+      /* symbol */
+      val = 0;
+      addend = 0;
+      h = NULL;
+      sym = NULL;
+      symndx = rel->r_symndx;
+
+      if (-1 != symndx)
+       {
+         asection *sec;
+
+         h = obj_xcoff_sym_hashes (input_bfd)[symndx];
+         sym = syms + symndx;
+         addend = - sym->n_value;
+
+         if (NULL == h)
+           {
+             sec = sections[symndx];
+             /* Hack to make sure we use the right TOC anchor value
+                if this reloc is against the TOC anchor.  */
+             if (sec->name[3] == '0'
+                 && strcmp (sec->name, ".tc0") == 0)
+               val = xcoff_data (output_bfd)->toc;
+             else
+               val = (sec->output_section->vma
+                      + sec->output_offset
+                      + sym->n_value
+                      - sec->vma);
+           }
+         else
+           {
+             if (info->unresolved_syms_in_objects != RM_IGNORE
+                 && (h->flags & XCOFF_WAS_UNDEFINED) != 0)
+               info->callbacks->undefined_symbol
+                 (info, h->root.root.string, input_bfd, input_section,
+                  rel->r_vaddr - input_section->vma,
+                  info->unresolved_syms_in_objects == RM_DIAGNOSE
+                  && !info->warn_unresolved_syms);
+
+             if (h->root.type == bfd_link_hash_defined
+                 || h->root.type == bfd_link_hash_defweak)
+               {
+                 sec = h->root.u.def.section;
+                 val = (h->root.u.def.value
+                        + sec->output_section->vma
+                        + sec->output_offset);
+               }
+             else if (h->root.type == bfd_link_hash_common)
+               {
+                 sec = h->root.u.c.p->section;
+                 val = (sec->output_section->vma
+                        + sec->output_offset);
+               }
+             else
+               {
+                 BFD_ASSERT (bfd_link_relocatable (info)
+                             || (h->flags & XCOFF_DEF_DYNAMIC) != 0
+                             || (h->flags & XCOFF_IMPORT) != 0);
+               }
+           }
+       }
+
+      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)))
+       return false;
+
+      /* address */
+      address = rel->r_vaddr - input_section->vma;
+      location = contents + address;
+
+      if (address > input_section->size)
+       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);
+
+      /* overflow.
+
+        FIXME: We may drop bits during the addition
+        which we don't check for.  We must either check at every single
+        operation, which would be tedious, or we must do the computations
+        in a type larger than bfd_vma, which would be inefficient.  */
+
+      if (((*xcoff_complain_overflow[howto.complain_on_overflow])
+          (input_bfd, value_to_relocate, relocation, &howto)))
+       {
+         const char *name;
+         char buf[SYMNMLEN + 1];
+         char reloc_type_name[10];
+
+         if (symndx == -1)
+           {
+             name = "*ABS*";
+           }
+         else if (h != NULL)
+           {
+             name = NULL;
+           }
+         else
+           {
+             name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
+             if (name == NULL)
+               name = "UNKNOWN";
+           }
+         sprintf (reloc_type_name, "0x%02x", rel->r_type);
+
+         (*info->callbacks->reloc_overflow)
+           (info, (h ? &h->root : NULL), name, reloc_type_name,
+            (bfd_vma) 0, input_bfd, input_section,
+            rel->r_vaddr - input_section->vma);
+       }
+
+      /* Add RELOCATION to the right bits of VALUE_TO_RELOCATE.  */
+      value_to_relocate = ((value_to_relocate & ~howto.dst_mask)
+                          | (((value_to_relocate & howto.src_mask)
+                              + 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);
+
+    }
+  return true;
+}
+
+
 /* PR 21786:  The PE/COFF standard does not require NUL termination for any of
    the ASCII fields in the archive headers.  So in order to be able to extract
    numerical values we provide our own versions of strtol and strtoll which
@@ -1889,7 +1760,7 @@ _bfd_strntoll (const char * nptr, int base, unsigned int maxlen)
 
 /* Read in the armap of an XCOFF archive.  */
 
-static bfd_boolean
+static bool
 xcoff64_slurp_armap (bfd *abfd)
 {
   file_ptr off;
@@ -1906,45 +1777,43 @@ xcoff64_slurp_armap (bfd *abfd)
 
   if (xcoff_ardata (abfd) == NULL)
     {
-      abfd->has_armap = FALSE;
-      return TRUE;
+      abfd->has_armap = false;
+      return true;
     }
 
   off = bfd_scan_vma (xcoff_ardata_big (abfd)->symoff64,
                      (const char **) NULL, 10);
   if (off == 0)
     {
-      abfd->has_armap = FALSE;
-      return TRUE;
+      abfd->has_armap = false;
+      return true;
     }
 
   if (bfd_seek (abfd, off, SEEK_SET) != 0)
-    return FALSE;
+    return false;
 
   /* The symbol table starts with a normal archive header.  */
   if (bfd_bread (&hdr, (bfd_size_type) SIZEOF_AR_HDR_BIG, abfd)
       != SIZEOF_AR_HDR_BIG)
-    return FALSE;
+    return false;
 
   /* Skip the name (normally empty).  */
   GET_VALUE_IN_FIELD (namlen, hdr.namlen, 10);
   pos = ((namlen + 1) & ~(size_t) 1) + SXCOFFARFMAG;
   if (bfd_seek (abfd, pos, SEEK_CUR) != 0)
-    return FALSE;
+    return false;
 
   sz = bfd_scan_vma (hdr.size, (const char **) NULL, 10);
-  if (sz == (bfd_size_type) -1)
+  if (sz + 1 < 9)
     {
-      bfd_set_error (bfd_error_no_memory);
-      return FALSE;
+      bfd_set_error (bfd_error_bad_value);
+      return false;
     }
 
   /* Read in the entire symbol table.  */
-  contents = (bfd_byte *) bfd_alloc (abfd, sz + 1);
+  contents = (bfd_byte *) _bfd_alloc_and_read (abfd, sz + 1, sz);
   if (contents == NULL)
-    return FALSE;
-  if (bfd_bread (contents, sz, abfd) != sz)
-    return FALSE;
+    return false;
 
   /* Ensure strings are NULL terminated so we don't wander off the end
      of the buffer.  */
@@ -1956,13 +1825,13 @@ xcoff64_slurp_armap (bfd *abfd)
   if (c >= sz / 8)
     {
       bfd_set_error (bfd_error_bad_value);
-      return FALSE;
+      return false;
     }
   amt = c;
   amt *= sizeof (carsym);
   bfd_ardata (abfd)->symdefs = (carsym *) bfd_alloc (abfd, amt);
   if (bfd_ardata (abfd)->symdefs == NULL)
-    return FALSE;
+    return false;
 
   /* After the count comes a list of eight byte file offsets.  */
   for (i = 0, arsym = bfd_ardata (abfd)->symdefs, p = contents + 8;
@@ -1979,28 +1848,28 @@ xcoff64_slurp_armap (bfd *abfd)
       if (p >= cend)
        {
          bfd_set_error (bfd_error_bad_value);
-         return FALSE;
+         return false;
        }
       arsym->name = (char *) p;
     }
 
   bfd_ardata (abfd)->symdef_count = c;
-  abfd->has_armap = TRUE;
+  abfd->has_armap = true;
 
-  return TRUE;
+  return true;
 }
 
 
 /* See if this is an NEW XCOFF archive.  */
 
-static const bfd_target *
+static bfd_cleanup
 xcoff64_archive_p (bfd *abfd)
 {
   struct artdata *tdata_hold;
   char magic[SXCOFFARMAG];
   /* This is the new format.  */
   struct xcoff_ar_file_hdr_big hdr;
-  bfd_size_type amt = SXCOFFARMAG;
+  size_t amt = SXCOFFARMAG;
 
   if (bfd_bread (magic, amt, abfd) != amt)
     {
@@ -2060,7 +1929,7 @@ xcoff64_archive_p (bfd *abfd)
       return NULL;
     }
 
-  return abfd->xvec;
+  return _bfd_no_cleanup;
 }
 
 
@@ -2132,14 +2001,14 @@ xcoff64_create_csect_from_smclas (bfd *abfd, union internal_auxent *aux,
   /* Changes from 32 :
      .sv == 8, is only for 32 bit programs
      .ti == 12 and .tb == 13 are now reserved.  */
-  static const char *names[19] =
+  static const char * const names[] =
   {
     ".pr", ".ro", ".db", ".tc", ".ua", ".rw", ".gl", ".xo",
     NULL, ".bs", ".ds", ".uc", NULL,  NULL,  NULL,  ".tc0",
-    ".td", ".sv64", ".sv3264"
+    ".td", ".sv64", ".sv3264", NULL, ".tl", ".ul", ".te"
   };
 
-  if ((19 >= aux->x_csect.x_smclas)
+  if ((aux->x_csect.x_smclas < ARRAY_SIZE (names))
       && (NULL != names[aux->x_csect.x_smclas]))
     {
 
@@ -2159,18 +2028,18 @@ xcoff64_create_csect_from_smclas (bfd *abfd, union internal_auxent *aux,
   return return_value;
 }
 
-static bfd_boolean
+static bool
 xcoff64_is_lineno_count_overflow (bfd *abfd ATTRIBUTE_UNUSED,
                                  bfd_vma value ATTRIBUTE_UNUSED)
 {
-  return FALSE;
+  return false;
 }
 
-static bfd_boolean
+static bool
 xcoff64_is_reloc_count_overflow (bfd *abfd ATTRIBUTE_UNUSED,
                                 bfd_vma value ATTRIBUTE_UNUSED)
 {
-  return FALSE;
+  return false;
 }
 
 static bfd_vma
@@ -2187,24 +2056,24 @@ xcoff64_loader_reloc_offset (bfd *abfd ATTRIBUTE_UNUSED,
   return (ldhdr->l_rldoff);
 }
 
-static bfd_boolean
+static bool
 xcoff64_bad_format_hook (bfd * abfd, void *filehdr)
 {
   struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
 
   /* Check flavor first.  */
   if (bfd_get_flavour (abfd) != bfd_target_xcoff_flavour)
-    return FALSE;
+    return false;
 
   if (bfd_xcoff_magic_number (abfd) != internal_f->f_magic)
-    return FALSE;
+    return false;
 
-  return TRUE;
+  return true;
 }
 
-static bfd_boolean
+static bool
 xcoff64_generate_rtinit (bfd *abfd, const char *init, const char *fini,
-                        bfd_boolean rtld)
+                        bool rtld)
 {
   bfd_byte filehdr_ext[FILHSZ];
   bfd_byte scnhdr_ext[SCNHSZ * 3];
@@ -2231,7 +2100,7 @@ xcoff64_generate_rtinit (bfd *abfd, const char *init, const char *fini,
   char *rtld_name = "__rtld";
 
   if (! bfd_xcoff_rtinit_size (abfd))
-    return FALSE;
+    return false;
 
   initsz = (init == NULL ? 0 : 1 + strlen (init));
   finisz = (fini == NULL ? 0 : 1 + strlen (fini));
@@ -2320,7 +2189,7 @@ xcoff64_generate_rtinit (bfd *abfd, const char *init, const char *fini,
   data_buffer = NULL;
   data_buffer = (bfd_byte *) bfd_zmalloc (data_buffer_size);
   if (data_buffer == NULL)
-    return FALSE;
+    return false;
 
   if (initsz)
     {
@@ -2356,7 +2225,7 @@ xcoff64_generate_rtinit (bfd *abfd, const char *init, const char *fini,
 
   string_table = (bfd_byte *) bfd_zmalloc (string_table_size);
   if (string_table == NULL)
-    return FALSE;
+    return false;
 
   val = string_table_size;
   bfd_put_32 (abfd, val, &string_table[0]);
@@ -2520,7 +2389,7 @@ xcoff64_generate_rtinit (bfd *abfd, const char *init, const char *fini,
   free (data_buffer);
   data_buffer = NULL;
 
-  return TRUE;
+  return true;
 }
 
 /* The typical dynamic reloc.  */
@@ -2530,17 +2399,17 @@ HOWTO (0,                       /* type */
        0,                      /* rightshift */
        4,                      /* size (0 = byte, 1 = short, 2 = long) */
        64,                     /* bitsize */
-       FALSE,                  /* pc_relative */
+       false,                  /* pc_relative */
        0,                      /* bitpos */
        complain_overflow_bitfield, /* complain_on_overflow */
        0,                      /* special_function */
        "R_POS",                        /* name */
-       TRUE,                   /* partial_inplace */
+       true,                   /* partial_inplace */
        MINUS_ONE,              /* src_mask */
        MINUS_ONE,              /* dst_mask */
-       FALSE);                 /* pcrel_offset */
+       false);                 /* pcrel_offset */
 
-static unsigned long xcoff64_glink_code[10] =
+static const unsigned long xcoff64_glink_code[10] =
 {
   0xe9820000,  /* ld r12,0(r2) */
   0xf8410028,  /* std r2,40(r1) */
@@ -2575,10 +2444,10 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
       RELSZ,
       LINESZ,
       FILNMLEN,
-      TRUE,                    /* _bfd_coff_long_filenames */
+      true,                    /* _bfd_coff_long_filenames */
       XCOFF_NO_LONG_SECTION_NAMES,  /* _bfd_coff_long_section_names */
       3,                       /* _bfd_coff_default_section_alignment_power */
-      TRUE,                    /* _bfd_coff_force_symnames_in_strings */
+      true,                    /* _bfd_coff_force_symnames_in_strings */
       4,                       /* _bfd_coff_debug_string_prefix_length */
       32768,                   /* _bfd_coff_max_nscns */
       coff_swap_filehdr_in,
@@ -2667,6 +2536,7 @@ const bfd_target rs6000_xcoff64_vec =
     '/',                       /* ar_pad_char */
     15,                                /* ar_max_namelen */
     0,                         /* match priority.  */
+    TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
 
     /* data */
     bfd_getb64,
@@ -2706,7 +2576,7 @@ const bfd_target rs6000_xcoff64_vec =
 
     {/* bfd_write_contents */
       _bfd_bool_bfd_false_error,
-      xcoff64_write_object_contents,
+      coff_write_object_contents,
       _bfd_xcoff_write_archive_contents,
       _bfd_bool_bfd_false_error
     },
@@ -2807,9 +2677,9 @@ const bfd_target rs6000_xcoff64_vec =
     &bfd_xcoff_backend_data,
   };
 
-extern const bfd_target *xcoff64_core_p
+extern bfd_cleanup xcoff64_core_p
   (bfd *);
-extern bfd_boolean xcoff64_core_file_matches_executable_p
+extern bool xcoff64_core_file_matches_executable_p
   (bfd *, bfd *);
 extern char *xcoff64_core_file_failing_command
   (bfd *);
@@ -2839,10 +2709,10 @@ static const struct xcoff_backend_data_rec bfd_xcoff_aix5_backend_data =
       RELSZ,
       LINESZ,
       FILNMLEN,
-      TRUE,                    /* _bfd_coff_long_filenames */
+      true,                    /* _bfd_coff_long_filenames */
       XCOFF_NO_LONG_SECTION_NAMES,  /* _bfd_coff_long_section_names */
       3,                       /* _bfd_coff_default_section_alignment_power */
-      TRUE,                    /* _bfd_coff_force_symnames_in_strings */
+      true,                    /* _bfd_coff_force_symnames_in_strings */
       4,                       /* _bfd_coff_debug_string_prefix_length */
       32768,                   /* _bfd_coff_max_nscns */
       coff_swap_filehdr_in,
@@ -2930,6 +2800,7 @@ const bfd_target rs6000_xcoff64_aix_vec =
     '/',                       /* ar_pad_char */
     15,                                /* ar_max_namelen */
     0,                         /* match priority.  */
+    TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
 
     /* data */
     bfd_getb64,
@@ -2969,7 +2840,7 @@ const bfd_target rs6000_xcoff64_aix_vec =
 
     {/* bfd_write_contents */
       _bfd_bool_bfd_false_error,
-      xcoff64_write_object_contents,
+      coff_write_object_contents,
       _bfd_xcoff_write_archive_contents,
       _bfd_bool_bfd_false_error
     },
This page took 0.054635 seconds and 4 git commands to generate.