* configure.ac (build_tools): Remove build-byacc.
[deliverable/binutils-gdb.git] / bfd / coff-rs6000.c
index 8e54c6a135a36a81c0cd7f9128c9c356d7f1fbc4..7fb20d8518e5b6ae483f333687cd048ec3973e06 100644 (file)
@@ -1,33 +1,30 @@
 /* BFD back-end for IBM RS/6000 "XCOFF" files.
 /* BFD back-end for IBM RS/6000 "XCOFF" files.
-   Copyright 1990-1999, 2000, 2001, 2002, 2003, 2004, 2005
+   Copyright 1990-1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+   2008, 2009, 2010
    Free Software Foundation, Inc.
    Free Software Foundation, Inc.
-   FIXME: Can someone provide a transliteration of this name into ASCII?
-   Using the following chars caused a compiler warning on HIUX (so I replaced
-   them with octal escapes), and isn't useful without an understanding of what
-   character set it is.
-   Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365,
-     and John Gilmore.
+   Written by Metin G. Ozisik, Mimi Phuong-Thao Vo, and John Gilmore.
    Archive support from Damon A. Permezel.
    Contributed by IBM Corporation and Cygnus Support.
 
    Archive support from Damon A. Permezel.
    Contributed by IBM Corporation and Cygnus Support.
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
 
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 
-#include "bfd.h"
 #include "sysdep.h"
 #include "sysdep.h"
+#include "bfd.h"
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "coff/internal.h"
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "coff/internal.h"
@@ -59,7 +56,7 @@ extern bfd_boolean _bfd_xcoff_write_armap
 extern bfd_boolean _bfd_xcoff_write_archive_contents
   PARAMS ((bfd *));
 extern int _bfd_xcoff_sizeof_headers
 extern bfd_boolean _bfd_xcoff_write_archive_contents
   PARAMS ((bfd *));
 extern int _bfd_xcoff_sizeof_headers
-  PARAMS ((bfd *, bfd_boolean));
+  PARAMS ((bfd *, struct bfd_link_info *));
 extern void _bfd_xcoff_swap_sym_in
   PARAMS ((bfd *, PTR, PTR));
 extern unsigned int _bfd_xcoff_swap_sym_out
 extern void _bfd_xcoff_swap_sym_in
   PARAMS ((bfd *, PTR, PTR));
 extern unsigned int _bfd_xcoff_swap_sym_out
@@ -98,6 +95,7 @@ void xcoff_rtype2howto
 #define coff_bfd_copy_private_bfd_data _bfd_xcoff_copy_private_bfd_data
 #define coff_bfd_is_local_label_name _bfd_xcoff_is_local_label_name
 #define coff_bfd_reloc_type_lookup _bfd_xcoff_reloc_type_lookup
 #define coff_bfd_copy_private_bfd_data _bfd_xcoff_copy_private_bfd_data
 #define coff_bfd_is_local_label_name _bfd_xcoff_is_local_label_name
 #define coff_bfd_reloc_type_lookup _bfd_xcoff_reloc_type_lookup
+#define coff_bfd_reloc_name_lookup _bfd_xcoff_reloc_name_lookup
 #ifdef AIX_CORE
 extern const bfd_target * rs6000coff_core_p
   PARAMS ((bfd *abfd));
 #ifdef AIX_CORE
 extern const bfd_target * rs6000coff_core_p
   PARAMS ((bfd *abfd));
@@ -114,6 +112,8 @@ extern int rs6000coff_core_file_failing_signal
   rs6000coff_core_file_failing_signal
 #define coff_core_file_matches_executable_p \
   rs6000coff_core_file_matches_executable_p
   rs6000coff_core_file_failing_signal
 #define coff_core_file_matches_executable_p \
   rs6000coff_core_file_matches_executable_p
+#define coff_core_file_pid \
+  _bfd_nocore_core_file_pid
 #else
 #define CORE_FILE_P _bfd_dummy_target
 #define coff_core_file_failing_command \
 #else
 #define CORE_FILE_P _bfd_dummy_target
 #define coff_core_file_failing_command \
@@ -122,6 +122,8 @@ extern int rs6000coff_core_file_failing_signal
   _bfd_nocore_core_file_failing_signal
 #define coff_core_file_matches_executable_p \
   _bfd_nocore_core_file_matches_executable_p
   _bfd_nocore_core_file_failing_signal
 #define coff_core_file_matches_executable_p \
   _bfd_nocore_core_file_matches_executable_p
+#define coff_core_file_pid \
+  _bfd_nocore_core_file_pid
 #endif
 #define coff_SWAP_sym_in _bfd_xcoff_swap_sym_in
 #define coff_SWAP_sym_out _bfd_xcoff_swap_sym_out
 #endif
 #define coff_SWAP_sym_in _bfd_xcoff_swap_sym_in
 #define coff_SWAP_sym_out _bfd_xcoff_swap_sym_out
@@ -131,6 +133,10 @@ extern int rs6000coff_core_file_failing_signal
 #define coff_swap_reloc_out xcoff_swap_reloc_out
 #define NO_COFF_RELOCS
 
 #define coff_swap_reloc_out xcoff_swap_reloc_out
 #define NO_COFF_RELOCS
 
+#ifndef bfd_pe_print_pdata
+#define bfd_pe_print_pdata     NULL
+#endif
+
 #include "coffcode.h"
 
 /* The main body of code is in coffcode.h.  */
 #include "coffcode.h"
 
 /* The main body of code is in coffcode.h.  */
@@ -179,8 +185,6 @@ static bfd_boolean do_pad
   PARAMS ((bfd *, unsigned int));
 static bfd_boolean do_copy
   PARAMS ((bfd *, bfd *));
   PARAMS ((bfd *, unsigned int));
 static bfd_boolean do_copy
   PARAMS ((bfd *, bfd *));
-static bfd_boolean do_shared_object_padding
-  PARAMS ((bfd *, bfd *, file_ptr *, int));
 
 /* Relocation functions */
 static bfd_boolean xcoff_reloc_type_br
 
 /* Relocation functions */
 static bfd_boolean xcoff_reloc_type_br
@@ -237,6 +241,119 @@ bfd_boolean (*xcoff_complain_overflow[XCOFF_MAX_COMPLAIN_OVERFLOW])
   xcoff_complain_overflow_unsigned_func,
 };
 
   xcoff_complain_overflow_unsigned_func,
 };
 
+/* Information about one member of an archive.  */
+struct member_layout {
+  /* The archive member that this structure describes.  */
+  bfd *member;
+
+  /* The number of bytes of padding that must be inserted before the
+     start of the member in order to ensure that the section contents
+     are correctly aligned.  */
+  unsigned int leading_padding;
+
+  /* The offset of MEMBER from the start of the archive (i.e. the end
+     of the leading padding).  */
+  file_ptr offset;
+
+  /* The normalized name of MEMBER.  */
+  const char *name;
+
+  /* The length of NAME, without padding.  */
+  bfd_size_type namlen;
+
+  /* The length of NAME, with padding.  */
+  bfd_size_type padded_namlen;
+
+  /* The size of MEMBER's header, including the name and magic sequence.  */
+  bfd_size_type header_size;
+
+  /* The size of the MEMBER's contents.  */
+  bfd_size_type contents_size;
+
+  /* The number of bytes of padding that must be inserted after MEMBER
+     in order to preserve even alignment.  */
+  bfd_size_type trailing_padding;
+};
+
+/* A structure used for iterating over the members of an archive.  */
+struct archive_iterator {
+  /* The archive itself.  */
+  bfd *archive;
+
+  /* Information about the current archive member.  */
+  struct member_layout current;
+
+  /* Information about the next archive member.  MEMBER is null if there
+     are no more archive members, in which case OFFSET is the offset of
+     the first unused byte.  */
+  struct member_layout next;
+};
+
+/* Initialize INFO so that it describes member MEMBER of archive ARCHIVE.
+   OFFSET is the even-padded offset of MEMBER, not including any leading
+   padding needed for section alignment.  */
+
+static void
+member_layout_init (struct member_layout *info, bfd *archive,
+                   bfd *member, file_ptr offset)
+{
+  info->member = member;
+  info->leading_padding = 0;
+  if (member)
+    {
+      info->name = normalize_filename (member);
+      info->namlen = strlen (info->name);
+      info->padded_namlen = info->namlen + (info->namlen & 1);
+      if (xcoff_big_format_p (archive))
+       info->header_size = SIZEOF_AR_HDR_BIG;
+      else
+       info->header_size = SIZEOF_AR_HDR;
+      info->header_size += info->padded_namlen + SXCOFFARFMAG;
+      info->contents_size = arelt_size (member);
+      info->trailing_padding = info->contents_size & 1;
+
+      if (bfd_check_format (member, bfd_object)
+         && bfd_get_flavour (member) == bfd_target_xcoff_flavour
+         && (member->flags & DYNAMIC) != 0)
+       info->leading_padding
+         = (-(offset + info->header_size)
+            & ((1 << bfd_xcoff_text_align_power (member)) - 1));
+    }
+  info->offset = offset + info->leading_padding;
+}
+
+/* Set up ITERATOR to iterate through archive ARCHIVE.  */
+
+static void
+archive_iterator_begin (struct archive_iterator *iterator,
+                       bfd *archive)
+{
+  iterator->archive = archive;
+  member_layout_init (&iterator->next, archive, archive->archive_head,
+                     xcoff_big_format_p (archive)
+                     ? SIZEOF_AR_FILE_HDR_BIG
+                     : SIZEOF_AR_FILE_HDR);
+}
+
+/* Make ITERATOR visit the first unvisited archive member.  Return true
+   on success; return false if all members have been visited.  */
+
+static bfd_boolean
+archive_iterator_next (struct archive_iterator *iterator)
+{
+  if (!iterator->next.member)
+    return FALSE;
+
+  iterator->current = iterator->next;
+  member_layout_init (&iterator->next, iterator->archive,
+                     iterator->current.member->archive_next,
+                     iterator->current.offset
+                     + iterator->current.header_size
+                     + iterator->current.contents_size
+                     + iterator->current.trailing_padding);
+  return TRUE;
+}
+
 /* We use our own tdata type.  Its first field is the COFF tdata type,
    so the COFF routines are compatible.  */
 
 /* We use our own tdata type.  Its first field is the COFF tdata type,
    so the COFF routines are compatible.  */
 
@@ -383,11 +500,11 @@ _bfd_xcoff_swap_sym_out (abfd, inp, extp)
 }
 
 void
 }
 
 void
-_bfd_xcoff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
+_bfd_xcoff_swap_aux_in (abfd, ext1, type, in_class, indx, numaux, in1)
      bfd *abfd;
      PTR ext1;
      int type;
      bfd *abfd;
      PTR ext1;
      int type;
-     int class;
+     int in_class;
      int indx;
      int numaux;
      PTR in1;
      int indx;
      int numaux;
      PTR in1;
@@ -395,7 +512,7 @@ _bfd_xcoff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
   AUXENT * ext = (AUXENT *)ext1;
   union internal_auxent *in = (union internal_auxent *)in1;
 
   AUXENT * ext = (AUXENT *)ext1;
   union internal_auxent *in = (union internal_auxent *)in1;
 
-  switch (class)
+  switch (in_class)
     {
     case C_FILE:
       if (ext->x_file.x_fname[0] == 0)
     {
     case C_FILE:
       if (ext->x_file.x_fname[0] == 0)
@@ -421,6 +538,7 @@ _bfd_xcoff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
 
       /* RS/6000 "csect" auxents */
     case C_EXT:
 
       /* RS/6000 "csect" auxents */
     case C_EXT:
+    case C_AIX_WEAKEXT:
     case C_HIDEXT:
       if (indx + 1 == numaux)
        {
     case C_HIDEXT:
       if (indx + 1 == numaux)
        {
@@ -460,7 +578,8 @@ _bfd_xcoff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
   in->x_sym.x_tagndx.l = H_GET_32 (abfd, ext->x_sym.x_tagndx);
   in->x_sym.x_tvndx = H_GET_16 (abfd, ext->x_sym.x_tvndx);
 
   in->x_sym.x_tagndx.l = H_GET_32 (abfd, ext->x_sym.x_tagndx);
   in->x_sym.x_tvndx = H_GET_16 (abfd, ext->x_sym.x_tvndx);
 
-  if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
+  if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type)
+      || ISTAG (in_class))
     {
       in->x_sym.x_fcnary.x_fcn.x_lnnoptr =
        H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
     {
       in->x_sym.x_fcnary.x_fcn.x_lnnoptr =
        H_GET_32 (abfd, ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
@@ -501,11 +620,11 @@ unsigned int _bfd_xcoff_swap_aux_out
   PARAMS ((bfd *, PTR, int, int, int, int, PTR));
 
 unsigned int
   PARAMS ((bfd *, PTR, int, int, int, int, PTR));
 
 unsigned int
-_bfd_xcoff_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
+_bfd_xcoff_swap_aux_out (abfd, inp, type, in_class, indx, numaux, extp)
      bfd * abfd;
      PTR   inp;
      int   type;
      bfd * abfd;
      PTR   inp;
      int   type;
-     int   class;
+     int   in_class;
      int   indx ATTRIBUTE_UNUSED;
      int   numaux ATTRIBUTE_UNUSED;
      PTR   extp;
      int   indx ATTRIBUTE_UNUSED;
      int   numaux ATTRIBUTE_UNUSED;
      PTR   extp;
@@ -514,7 +633,7 @@ _bfd_xcoff_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
   AUXENT *ext = (AUXENT *)extp;
 
   memset ((PTR)ext, 0, bfd_coff_auxesz (abfd));
   AUXENT *ext = (AUXENT *)extp;
 
   memset ((PTR)ext, 0, bfd_coff_auxesz (abfd));
-  switch (class)
+  switch (in_class)
     {
     case C_FILE:
       if (in->x_file.x_fname[0] == 0)
     {
     case C_FILE:
       if (in->x_file.x_fname[0] == 0)
@@ -530,6 +649,7 @@ _bfd_xcoff_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
 
       /* RS/6000 "csect" auxents */
     case C_EXT:
 
       /* RS/6000 "csect" auxents */
     case C_EXT:
+    case C_AIX_WEAKEXT:
     case C_HIDEXT:
       if (indx + 1 == numaux)
        {
     case C_HIDEXT:
       if (indx + 1 == numaux)
        {
@@ -563,7 +683,8 @@ _bfd_xcoff_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
   H_PUT_32 (abfd, in->x_sym.x_tagndx.l, ext->x_sym.x_tagndx);
   H_PUT_16 (abfd, in->x_sym.x_tvndx, ext->x_sym.x_tvndx);
 
   H_PUT_32 (abfd, in->x_sym.x_tagndx.l, ext->x_sym.x_tagndx);
   H_PUT_16 (abfd, in->x_sym.x_tvndx, ext->x_sym.x_tvndx);
 
-  if (class == C_BLOCK || class == C_FCN || ISFCN (type) || ISTAG (class))
+  if (in_class == C_BLOCK || in_class == C_FCN || ISFCN (type)
+      || ISTAG (in_class))
     {
       H_PUT_32 (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr,
                ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
     {
       H_PUT_32 (abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr,
                ext->x_sym.x_fcnary.x_fcn.x_lnnoptr);
@@ -780,11 +901,11 @@ reloc_howto_type xcoff_howto_table[] =
 
   EMPTY_HOWTO (0xe),
 
 
   EMPTY_HOWTO (0xe),
 
-  /* Non-relocating reference.  */
+  /* Non-relocating reference.  Bitsize is 1 so that r_rsize is 0.  */
   HOWTO (R_REF,                        /* type */
         0,                     /* rightshift */
   HOWTO (R_REF,                        /* type */
         0,                     /* rightshift */
-        2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        32,                    /* bitsize */
+        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        1,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont, /* complain_on_overflow */
@@ -1046,11 +1167,28 @@ _bfd_xcoff_reloc_type_lookup (abfd, code)
     case BFD_RELOC_32:
     case BFD_RELOC_CTOR:
       return &xcoff_howto_table[0];
     case BFD_RELOC_32:
     case BFD_RELOC_CTOR:
       return &xcoff_howto_table[0];
+    case BFD_RELOC_NONE:
+      return &xcoff_howto_table[0xf];
     default:
       return NULL;
     }
 }
 
     default:
       return NULL;
     }
 }
 
+static reloc_howto_type *
+_bfd_xcoff_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+                             const char *r_name)
+{
+  unsigned int i;
+
+  for (i = 0;
+       i < sizeof (xcoff_howto_table) / sizeof (xcoff_howto_table[0]);
+       i++)
+    if (xcoff_howto_table[i].name != NULL
+       && strcasecmp (xcoff_howto_table[i].name, r_name) == 0)
+      return &xcoff_howto_table[i];
+
+  return NULL;
+}
 \f
 /* XCOFF archive support.  The original version of this code was by
    Damon A. Permezel.  It was enhanced to permit cross support, and
 \f
 /* XCOFF archive support.  The original version of this code was by
    Damon A. Permezel.  It was enhanced to permit cross support, and
@@ -1585,11 +1723,10 @@ xcoff_write_armap_old (abfd, elength, map, orl_count, stridx)
      unsigned int orl_count;
      int stridx;
 {
      unsigned int orl_count;
      int stridx;
 {
+  struct archive_iterator iterator;
   struct xcoff_ar_hdr hdr;
   char *p;
   unsigned char buf[4];
   struct xcoff_ar_hdr hdr;
   char *p;
   unsigned char buf[4];
-  bfd *sub;
-  file_ptr fileoff;
   unsigned int i;
 
   memset (&hdr, 0, sizeof hdr);
   unsigned int i;
 
   memset (&hdr, 0, sizeof hdr);
@@ -1617,29 +1754,16 @@ xcoff_write_armap_old (abfd, elength, map, orl_count, stridx)
   if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4)
     return FALSE;
 
   if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4)
     return FALSE;
 
-  sub = abfd->archive_head;
-  fileoff = SIZEOF_AR_FILE_HDR;
   i = 0;
   i = 0;
-  while (sub != NULL && i < orl_count)
-    {
-      size_t namlen;
-
-      while (map[i].u.abfd == sub)
-       {
-         H_PUT_32 (abfd, fileoff, buf);
-         if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4)
-           return FALSE;
-         ++i;
-       }
-      namlen = strlen (normalize_filename (sub));
-      namlen = (namlen + 1) &~ (size_t) 1;
-      fileoff += (SIZEOF_AR_HDR
-                 + namlen
-                 + SXCOFFARFMAG
-                 + arelt_size (sub));
-      fileoff = (fileoff + 1) &~ 1;
-      sub = sub->next;
-    }
+  archive_iterator_begin (&iterator, abfd);
+  while (i < orl_count && archive_iterator_next (&iterator))
+    while (map[i].u.abfd == iterator.current.member)
+      {
+       H_PUT_32 (abfd, iterator.current.offset, buf);
+       if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4)
+         return FALSE;
+       ++i;
+      }
 
   for (i = 0; i < orl_count; i++)
     {
 
   for (i = 0; i < orl_count; i++)
     {
@@ -1740,34 +1864,6 @@ do_copy (out_bfd, in_bfd)
   return TRUE;
 }
 
   return TRUE;
 }
 
-static bfd_boolean
-do_shared_object_padding (out_bfd, in_bfd, offset, ar_header_size)
-     bfd *out_bfd;
-     bfd *in_bfd;
-     file_ptr *offset;
-     int ar_header_size;
-{
-  if (bfd_check_format (in_bfd, bfd_object)
-      && bfd_get_flavour (in_bfd) == bfd_target_xcoff_flavour
-      && (in_bfd->flags & DYNAMIC) != 0)
-    {
-      bfd_size_type pad = 0;
-      int text_align_power;
-
-      text_align_power = bfd_xcoff_text_align_power (in_bfd);
-
-      pad = 1 << text_align_power;
-      pad -= (*offset + ar_header_size) & (pad - 1);
-
-      if (! do_pad (out_bfd, pad))
-       return FALSE;
-
-      *offset += pad;
-    }
-
-  return TRUE;
-}
-
 static bfd_boolean
 xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
      bfd *abfd;
 static bfd_boolean
 xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
      bfd *abfd;
@@ -1776,9 +1872,10 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
      unsigned int orl_count;
      int stridx;
 {
      unsigned int orl_count;
      int stridx;
 {
+  struct archive_iterator iterator;
   struct xcoff_ar_file_hdr_big *fhdr;
   bfd_vma i, sym_32, sym_64, str_32, str_64;
   struct xcoff_ar_file_hdr_big *fhdr;
   bfd_vma i, sym_32, sym_64, str_32, str_64;
-  const bfd_arch_info_type *arch_info = NULL;
+  const bfd_arch_info_type *arch_info;
   bfd *current_bfd;
   size_t string_length;
   file_ptr nextoff, prevoff;
   bfd *current_bfd;
   size_t string_length;
   file_ptr nextoff, prevoff;
@@ -1787,16 +1884,15 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
      from 32-bit objects and which from 64-bit ones.  */
   sym_32 = sym_64 = str_32 = str_64 = 0;
 
      from 32-bit objects and which from 64-bit ones.  */
   sym_32 = sym_64 = str_32 = str_64 = 0;
 
-  current_bfd = abfd->archive_head;
-  if (current_bfd != NULL)
-    arch_info = bfd_get_arch_info (current_bfd);
-    i = 0;
-    while (current_bfd != NULL && i < orl_count)
+  i = 0;
+  for (current_bfd = abfd->archive_head;
+       current_bfd != NULL && i < orl_count;
+       current_bfd = current_bfd->archive_next)
     {
     {
+      arch_info = bfd_get_arch_info (current_bfd);
       while (map[i].u.abfd == current_bfd)
        {
          string_length = strlen (*map[i].name) + 1;
       while (map[i].u.abfd == current_bfd)
        {
          string_length = strlen (*map[i].name) + 1;
-
          if (arch_info->bits_per_address == 64)
            {
              sym_64++;
          if (arch_info->bits_per_address == 64)
            {
              sym_64++;
@@ -1809,9 +1905,6 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
            }
          i++;
        }
            }
          i++;
        }
-      current_bfd = current_bfd->next;
-      if (current_bfd != NULL)
-       arch_info = bfd_get_arch_info (current_bfd);
     }
 
   /* A quick sanity check... */
     }
 
   /* A quick sanity check... */
@@ -1853,7 +1946,6 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
       struct xcoff_ar_hdr_big *hdr;
       char *symbol_table;
       char *st;
       struct xcoff_ar_hdr_big *hdr;
       char *symbol_table;
       char *st;
-      file_ptr fileoff;
 
       bfd_vma symbol_table_size =
        SIZEOF_AR_HDR_BIG
 
       bfd_vma symbol_table_size =
        SIZEOF_AR_HDR_BIG
@@ -1890,41 +1982,29 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
       st += 8;
 
       /* loop over the 32 bit offsets */
       st += 8;
 
       /* loop over the 32 bit offsets */
-      current_bfd = abfd->archive_head;
-      if (current_bfd != NULL)
-       arch_info = bfd_get_arch_info (current_bfd);
-      fileoff = SIZEOF_AR_FILE_HDR_BIG;
       i = 0;
       i = 0;
-      while (current_bfd != NULL && i < orl_count)
+      archive_iterator_begin (&iterator, abfd);
+      while (i < orl_count && archive_iterator_next (&iterator))
        {
        {
-         while (map[i].u.abfd == current_bfd)
+         arch_info = bfd_get_arch_info (iterator.current.member);
+         while (map[i].u.abfd == iterator.current.member)
            {
              if (arch_info->bits_per_address == 32)
                {
            {
              if (arch_info->bits_per_address == 32)
                {
-                 bfd_h_put_64 (abfd, fileoff, st);
+                 bfd_h_put_64 (abfd, iterator.current.offset, st);
                  st += 8;
                }
              i++;
            }
                  st += 8;
                }
              i++;
            }
-         string_length = strlen (normalize_filename (current_bfd));
-         string_length += string_length & 1;
-         fileoff += (SIZEOF_AR_HDR_BIG
-                     + string_length
-                     + SXCOFFARFMAG
-                     + arelt_size (current_bfd));
-         fileoff += fileoff & 1;
-         current_bfd = current_bfd->next;
-         if (current_bfd != NULL)
-           arch_info = bfd_get_arch_info (current_bfd);
        }
 
       /* loop over the 32 bit symbol names */
        }
 
       /* loop over the 32 bit symbol names */
-      current_bfd = abfd->archive_head;
-      if (current_bfd != NULL)
-       arch_info = bfd_get_arch_info (current_bfd);
       i = 0;
       i = 0;
-      while (current_bfd != NULL && i < orl_count)
+      for (current_bfd = abfd->archive_head;
+          current_bfd != NULL && i < orl_count;
+          current_bfd = current_bfd->archive_next)
        {
        {
+         arch_info = bfd_get_arch_info (current_bfd);
          while (map[i].u.abfd == current_bfd)
            {
              if (arch_info->bits_per_address == 32)
          while (map[i].u.abfd == current_bfd)
            {
              if (arch_info->bits_per_address == 32)
@@ -1934,9 +2014,6 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
                }
              i++;
            }
                }
              i++;
            }
-         current_bfd = current_bfd->next;
-         if (current_bfd != NULL)
-           arch_info = bfd_get_arch_info (current_bfd);
        }
 
       bfd_bwrite (symbol_table, symbol_table_size, abfd);
        }
 
       bfd_bwrite (symbol_table, symbol_table_size, abfd);
@@ -1954,7 +2031,6 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
       struct xcoff_ar_hdr_big *hdr;
       char *symbol_table;
       char *st;
       struct xcoff_ar_hdr_big *hdr;
       char *symbol_table;
       char *st;
-      file_ptr fileoff;
 
       bfd_vma symbol_table_size =
        SIZEOF_AR_HDR_BIG
 
       bfd_vma symbol_table_size =
        SIZEOF_AR_HDR_BIG
@@ -1986,41 +2062,29 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
       st += 8;
 
       /* loop over the 64 bit offsets */
       st += 8;
 
       /* loop over the 64 bit offsets */
-      current_bfd = abfd->archive_head;
-      if (current_bfd != NULL)
-       arch_info = bfd_get_arch_info (current_bfd);
-      fileoff = SIZEOF_AR_FILE_HDR_BIG;
       i = 0;
       i = 0;
-      while (current_bfd != NULL && i < orl_count)
+      archive_iterator_begin (&iterator, abfd);
+      while (i < orl_count && archive_iterator_next (&iterator))
        {
        {
-         while (map[i].u.abfd == current_bfd)
+         arch_info = bfd_get_arch_info (iterator.current.member);
+         while (map[i].u.abfd == iterator.current.member)
            {
              if (arch_info->bits_per_address == 64)
                {
            {
              if (arch_info->bits_per_address == 64)
                {
-                 bfd_h_put_64 (abfd, fileoff, st);
+                 bfd_h_put_64 (abfd, iterator.current.offset, st);
                  st += 8;
                }
              i++;
            }
                  st += 8;
                }
              i++;
            }
-         string_length = strlen (normalize_filename (current_bfd));
-         string_length += string_length & 1;
-         fileoff += (SIZEOF_AR_HDR_BIG
-                     + string_length
-                     + SXCOFFARFMAG
-                     + arelt_size (current_bfd));
-         fileoff += fileoff & 1;
-         current_bfd = current_bfd->next;
-         if (current_bfd != NULL)
-           arch_info = bfd_get_arch_info (current_bfd);
        }
 
       /* loop over the 64 bit symbol names */
        }
 
       /* loop over the 64 bit symbol names */
-      current_bfd = abfd->archive_head;
-      if (current_bfd != NULL)
-       arch_info = bfd_get_arch_info (current_bfd);
       i = 0;
       i = 0;
-      while (current_bfd != NULL && i < orl_count)
+      for (current_bfd = abfd->archive_head;
+          current_bfd != NULL && i < orl_count;
+          current_bfd = current_bfd->archive_next)
        {
        {
+         arch_info = bfd_get_arch_info (current_bfd);
          while (map[i].u.abfd == current_bfd)
            {
              if (arch_info->bits_per_address == 64)
          while (map[i].u.abfd == current_bfd)
            {
              if (arch_info->bits_per_address == 64)
@@ -2030,9 +2094,6 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
                }
              i++;
            }
                }
              i++;
            }
-         current_bfd = current_bfd->next;
-         if (current_bfd != NULL)
-           arch_info = bfd_get_arch_info (current_bfd);
        }
 
       bfd_bwrite (symbol_table, symbol_table_size, abfd);
        }
 
       bfd_bwrite (symbol_table, symbol_table_size, abfd);
@@ -2068,6 +2129,7 @@ static bfd_boolean
 xcoff_write_archive_contents_old (abfd)
      bfd *abfd;
 {
 xcoff_write_archive_contents_old (abfd)
      bfd *abfd;
 {
+  struct archive_iterator iterator;
   struct xcoff_ar_file_hdr fhdr;
   bfd_size_type count;
   bfd_size_type total_namlen;
   struct xcoff_ar_file_hdr fhdr;
   bfd_size_type count;
   bfd_size_type total_namlen;
@@ -2083,126 +2145,102 @@ xcoff_write_archive_contents_old (abfd)
   char decbuf[XCOFFARMAG_ELEMENT_SIZE + 1];
 
   memset (&fhdr, 0, sizeof fhdr);
   char decbuf[XCOFFARMAG_ELEMENT_SIZE + 1];
 
   memset (&fhdr, 0, sizeof fhdr);
-  strncpy (fhdr.magic, XCOFFARMAG, SXCOFFARMAG);
+  (void) strncpy (fhdr.magic, XCOFFARMAG, SXCOFFARMAG);
   sprintf (fhdr.firstmemoff, "%d", SIZEOF_AR_FILE_HDR);
   sprintf (fhdr.freeoff, "%d", 0);
 
   count = 0;
   total_namlen = 0;
   sprintf (fhdr.firstmemoff, "%d", SIZEOF_AR_FILE_HDR);
   sprintf (fhdr.freeoff, "%d", 0);
 
   count = 0;
   total_namlen = 0;
-  for (sub = abfd->archive_head; sub != NULL; sub = sub->next)
+  for (sub = abfd->archive_head; sub != NULL; sub = sub->archive_next)
     {
       ++count;
       total_namlen += strlen (normalize_filename (sub)) + 1;
     {
       ++count;
       total_namlen += strlen (normalize_filename (sub)) + 1;
-    }
-  offsets = (file_ptr *) bfd_alloc (abfd, count * sizeof (file_ptr));
-  if (offsets == NULL)
-    return FALSE;
-
-  if (bfd_seek (abfd, (file_ptr) SIZEOF_AR_FILE_HDR, SEEK_SET) != 0)
-    return FALSE;
-
-  makemap = bfd_has_map (abfd);
-  hasobjects = FALSE;
-  prevoff = 0;
-  nextoff = SIZEOF_AR_FILE_HDR;
-  for (sub = abfd->archive_head, i = 0; sub != NULL; sub = sub->next, i++)
-    {
-      const char *name;
-      bfd_size_type namlen;
-      struct xcoff_ar_hdr *ahdrp;
-      bfd_size_type remaining;
-
-      if (makemap && ! hasobjects)
+      if (sub->arelt_data == NULL)
        {
        {
-         if (bfd_check_format (sub, bfd_object))
-           hasobjects = TRUE;
+         sub->arelt_data = bfd_zalloc (sub, sizeof (struct areltdata));
+         if (sub->arelt_data == NULL)
+           return FALSE;
        }
        }
-
-      name = normalize_filename (sub);
-      namlen = strlen (name);
-
-      if (sub->arelt_data != NULL)
-       ahdrp = arch_xhdr (sub);
-      else
-       ahdrp = NULL;
-
-      if (ahdrp == NULL)
+      if (arch_xhdr (sub) == NULL)
        {
        {
+         struct xcoff_ar_hdr *ahdrp;
          struct stat s;
 
          struct stat s;
 
-         memset (&ahdr, 0, sizeof ahdr);
-         ahdrp = &ahdr;
          if (stat (bfd_get_filename (sub), &s) != 0)
            {
              bfd_set_error (bfd_error_system_call);
              return FALSE;
            }
 
          if (stat (bfd_get_filename (sub), &s) != 0)
            {
              bfd_set_error (bfd_error_system_call);
              return FALSE;
            }
 
+         ahdrp = bfd_zalloc (sub, sizeof (*ahdrp));
+         if (ahdrp == NULL)
+           return FALSE;
+
          sprintf (ahdrp->size, "%ld", (long) s.st_size);
          sprintf (ahdrp->date, "%ld", (long) s.st_mtime);
          sprintf (ahdrp->uid, "%ld", (long) s.st_uid);
          sprintf (ahdrp->gid, "%ld", (long) s.st_gid);
          sprintf (ahdrp->mode, "%o", (unsigned int) s.st_mode);
 
          sprintf (ahdrp->size, "%ld", (long) s.st_size);
          sprintf (ahdrp->date, "%ld", (long) s.st_mtime);
          sprintf (ahdrp->uid, "%ld", (long) s.st_uid);
          sprintf (ahdrp->gid, "%ld", (long) s.st_gid);
          sprintf (ahdrp->mode, "%o", (unsigned int) s.st_mode);
 
-         if (sub->arelt_data == NULL)
-           {
-             size = sizeof (struct areltdata);
-             sub->arelt_data = bfd_alloc (sub, size);
-             if (sub->arelt_data == NULL)
-               return FALSE;
-           }
-
+         arch_eltdata (sub)->arch_header = (char *) ahdrp;
          arch_eltdata (sub)->parsed_size = s.st_size;
        }
          arch_eltdata (sub)->parsed_size = s.st_size;
        }
+    }
+  offsets = (file_ptr *) bfd_alloc (abfd, count * sizeof (file_ptr));
+  if (offsets == NULL)
+    return FALSE;
 
 
-      sprintf (ahdrp->prevoff, "%ld", (long) prevoff);
-      sprintf (ahdrp->namlen, "%ld", (long) namlen);
-
-      /* If the length of the name is odd, we write out the null byte
-        after the name as well.  */
-      namlen = (namlen + 1) &~ (bfd_size_type) 1;
-
-      remaining = arelt_size (sub);
-      size = (SIZEOF_AR_HDR
-             + namlen
-             + SXCOFFARFMAG
-             + remaining);
-
-      BFD_ASSERT (nextoff == bfd_tell (abfd));
+  if (bfd_seek (abfd, (file_ptr) SIZEOF_AR_FILE_HDR, SEEK_SET) != 0)
+    return FALSE;
 
 
-      offsets[i] = nextoff;
+  makemap = bfd_has_map (abfd);
+  hasobjects = FALSE;
+  prevoff = 0;
+  for (archive_iterator_begin (&iterator, abfd), i = 0;
+       archive_iterator_next (&iterator);
+       i++)
+    {
+      bfd_size_type namlen;
+      struct xcoff_ar_hdr *ahdrp;
 
 
-      prevoff = nextoff;
-      nextoff += size + (size & 1);
+      if (makemap && ! hasobjects)
+       {
+         if (bfd_check_format (iterator.current.member, bfd_object))
+           hasobjects = TRUE;
+       }
 
 
-      sprintf (ahdrp->nextoff, "%ld", (long) nextoff);
+      ahdrp = arch_xhdr (iterator.current.member);
+      sprintf (ahdrp->prevoff, "%ld", (long) prevoff);
+      sprintf (ahdrp->namlen, "%ld", (long) iterator.current.namlen);
+      sprintf (ahdrp->nextoff, "%ld", (long) iterator.next.offset);
 
       /* We need spaces, not null bytes, in the header.  */
       for (p = (char *) ahdrp; p < (char *) ahdrp + SIZEOF_AR_HDR; p++)
        if (*p == '\0')
          *p = ' ';
 
 
       /* We need spaces, not null bytes, in the header.  */
       for (p = (char *) ahdrp; p < (char *) ahdrp + SIZEOF_AR_HDR; p++)
        if (*p == '\0')
          *p = ' ';
 
-      if ((bfd_bwrite ((PTR) ahdrp, (bfd_size_type) SIZEOF_AR_HDR, abfd)
-          != SIZEOF_AR_HDR)
-         || bfd_bwrite ((PTR) name, namlen, abfd) != namlen
-         || bfd_bwrite ((PTR) XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG,
-                        abfd) != SXCOFFARFMAG)
+      if (!do_pad (abfd, iterator.current.leading_padding))
        return FALSE;
 
        return FALSE;
 
-      if (bfd_seek (sub, (file_ptr) 0, SEEK_SET) != 0)
+      BFD_ASSERT (iterator.current.offset == bfd_tell (abfd));
+      namlen = iterator.current.padded_namlen;
+      if (bfd_bwrite (ahdrp, SIZEOF_AR_HDR, abfd) != SIZEOF_AR_HDR
+         || bfd_bwrite (iterator.current.name, namlen, abfd) != namlen
+         || bfd_bwrite (XCOFFARFMAG, SXCOFFARFMAG, abfd) != SXCOFFARFMAG
+         || bfd_seek (iterator.current.member, 0, SEEK_SET) != 0
+         || !do_copy (abfd, iterator.current.member)
+         || !do_pad (abfd, iterator.current.trailing_padding))
        return FALSE;
 
        return FALSE;
 
-      if (! do_copy (abfd, sub))
-       return FALSE;
-
-      if (! do_pad (abfd, size & 1))
-       return FALSE;
+      offsets[i] = iterator.current.offset;
+      prevoff = iterator.current.offset;
     }
 
   sprintf (fhdr.lastmemoff, "%ld", (long) prevoff);
 
   /* Write out the member table.  */
 
     }
 
   sprintf (fhdr.lastmemoff, "%ld", (long) prevoff);
 
   /* Write out the member table.  */
 
+  nextoff = iterator.next.offset;
   BFD_ASSERT (nextoff == bfd_tell (abfd));
   sprintf (fhdr.memoff, "%ld", (long) nextoff);
 
   BFD_ASSERT (nextoff == bfd_tell (abfd));
   sprintf (fhdr.memoff, "%ld", (long) nextoff);
 
@@ -2253,7 +2291,7 @@ xcoff_write_archive_contents_old (abfd)
                      abfd) != XCOFFARMAG_ELEMENT_SIZE)
        return FALSE;
     }
                      abfd) != XCOFFARMAG_ELEMENT_SIZE)
        return FALSE;
     }
-  for (sub = abfd->archive_head; sub != NULL; sub = sub->next)
+  for (sub = abfd->archive_head; sub != NULL; sub = sub->archive_next)
     {
       const char *name;
       bfd_size_type namlen;
     {
       const char *name;
       bfd_size_type namlen;
@@ -2307,10 +2345,11 @@ xcoff_write_archive_contents_big (abfd)
   file_ptr prevoff, nextoff;
   bfd *current_bfd;
   size_t i;
   file_ptr prevoff, nextoff;
   bfd *current_bfd;
   size_t i;
-  struct xcoff_ar_hdr_big *hdr, ahdr;
+  struct xcoff_ar_hdr_big *hdr;
   bfd_size_type size;
   char *member_table, *mt;
   bfd_vma member_table_size;
   bfd_size_type size;
   char *member_table, *mt;
   bfd_vma member_table_size;
+  struct archive_iterator iterator;
 
   memset (&fhdr, 0, SIZEOF_AR_FILE_HDR_BIG);
   memcpy (fhdr.magic, XCOFFARMAGBIG, SXCOFFARMAG);
 
   memset (&fhdr, 0, SIZEOF_AR_FILE_HDR_BIG);
   memcpy (fhdr.magic, XCOFFARMAGBIG, SXCOFFARMAG);
@@ -2323,7 +2362,7 @@ xcoff_write_archive_contents_big (abfd)
   hasobjects = FALSE;
   for (current_bfd = abfd->archive_head, count = 0, total_namlen = 0;
        current_bfd != NULL;
   hasobjects = FALSE;
   for (current_bfd = abfd->archive_head, count = 0, total_namlen = 0;
        current_bfd != NULL;
-       current_bfd = current_bfd->next, count++)
+       current_bfd = current_bfd->archive_next, count++)
     {
       total_namlen += strlen (normalize_filename (current_bfd)) + 1;
 
     {
       total_namlen += strlen (normalize_filename (current_bfd)) + 1;
 
@@ -2331,40 +2370,20 @@ xcoff_write_archive_contents_big (abfd)
          && ! hasobjects
          && bfd_check_format (current_bfd, bfd_object))
        hasobjects = TRUE;
          && ! hasobjects
          && bfd_check_format (current_bfd, bfd_object))
        hasobjects = TRUE;
-    }
-
-  offsets = NULL;
-  if (count)
-    {
-      offsets = (file_ptr *) bfd_malloc (count * sizeof (file_ptr));
-      if (offsets == NULL)
-       return FALSE;
-    }
-
-  prevoff = 0;
-  nextoff = SIZEOF_AR_FILE_HDR_BIG;
-  for (current_bfd = abfd->archive_head, i = 0;
-       current_bfd != NULL;
-       current_bfd = current_bfd->next, i++)
-    {
-      const char *name;
-      bfd_size_type namlen;
-      struct xcoff_ar_hdr_big *ahdrp;
-      bfd_size_type remaining;
 
 
-      name = normalize_filename (current_bfd);
-      namlen = strlen (name);
-
-      if (current_bfd->arelt_data != NULL)
-       ahdrp = arch_xhdr_big (current_bfd);
-      else
-       ahdrp = NULL;
+      if (current_bfd->arelt_data == NULL)
+       {
+         size = sizeof (struct areltdata);
+         current_bfd->arelt_data = bfd_zalloc (current_bfd, size);
+         if (current_bfd->arelt_data == NULL)
+           return FALSE;
+       }
 
 
-      if (ahdrp == NULL)
+      if (arch_xhdr_big (current_bfd) == NULL)
        {
        {
+         struct xcoff_ar_hdr_big *ahdrp;
          struct stat s;
 
          struct stat s;
 
-         ahdrp = &ahdr;
          /* XXX This should actually be a call to stat64 (at least on
             32-bit machines).
             XXX This call will fail if the original object is not found.  */
          /* XXX This should actually be a call to stat64 (at least on
             32-bit machines).
             XXX This call will fail if the original object is not found.  */
@@ -2374,68 +2393,57 @@ xcoff_write_archive_contents_big (abfd)
              return FALSE;
            }
 
              return FALSE;
            }
 
+         ahdrp = bfd_zalloc (current_bfd, sizeof (*ahdrp));
+         if (ahdrp == NULL)
+           return FALSE;
+
          PRINT20 (ahdrp->size, s.st_size);
          PRINT12 (ahdrp->date, s.st_mtime);
          PRINT12 (ahdrp->uid,  s.st_uid);
          PRINT12 (ahdrp->gid,  s.st_gid);
          PRINT12_OCTAL (ahdrp->mode, s.st_mode);
 
          PRINT20 (ahdrp->size, s.st_size);
          PRINT12 (ahdrp->date, s.st_mtime);
          PRINT12 (ahdrp->uid,  s.st_uid);
          PRINT12 (ahdrp->gid,  s.st_gid);
          PRINT12_OCTAL (ahdrp->mode, s.st_mode);
 
-         if (current_bfd->arelt_data == NULL)
-           {
-             size = sizeof (struct areltdata);
-             current_bfd->arelt_data = bfd_alloc (current_bfd, size);
-             if (current_bfd->arelt_data == NULL)
-               return FALSE;
-           }
-
+         arch_eltdata (current_bfd)->arch_header = (char *) ahdrp;
          arch_eltdata (current_bfd)->parsed_size = s.st_size;
        }
          arch_eltdata (current_bfd)->parsed_size = s.st_size;
        }
+    }
 
 
-      PRINT20 (ahdrp->prevoff, prevoff);
-      PRINT4 (ahdrp->namlen, namlen);
-
-      /* If the length of the name is odd, we write out the null byte
-        after the name as well.  */
-      namlen = (namlen + 1) &~ (bfd_size_type) 1;
-
-      remaining = arelt_size (current_bfd);
-      size = (SIZEOF_AR_HDR_BIG
-             + namlen
-             + SXCOFFARFMAG
-             + remaining);
-
-      BFD_ASSERT (nextoff == bfd_tell (abfd));
-
-      /* Check for xcoff shared objects.
-        Their text section needs to be aligned wrt the archive file position.
-        This requires extra padding before the archive header.  */
-      if (! do_shared_object_padding (abfd, current_bfd, & nextoff,
-                                     SIZEOF_AR_HDR_BIG + namlen
-                                     + SXCOFFARFMAG))
+  offsets = NULL;
+  if (count)
+    {
+      offsets = (file_ptr *) bfd_malloc (count * sizeof (file_ptr));
+      if (offsets == NULL)
        return FALSE;
        return FALSE;
+    }
 
 
-      offsets[i] = nextoff;
-
-      prevoff = nextoff;
-      nextoff += size + (size & 1);
-
-      PRINT20 (ahdrp->nextoff, nextoff);
+  prevoff = 0;
+  for (archive_iterator_begin (&iterator, abfd), i = 0;
+       archive_iterator_next (&iterator);
+       i++)
+    {
+      bfd_size_type namlen;
+      struct xcoff_ar_hdr_big *ahdrp;
 
 
-      if ((bfd_bwrite ((PTR) ahdrp, (bfd_size_type) SIZEOF_AR_HDR_BIG, abfd)
-          != SIZEOF_AR_HDR_BIG)
-         || bfd_bwrite ((PTR) name, (bfd_size_type) namlen, abfd) != namlen
-         || (bfd_bwrite ((PTR) XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG,
-                         abfd) != SXCOFFARFMAG))
-       return FALSE;
+      ahdrp = arch_xhdr_big (iterator.current.member);
+      PRINT20 (ahdrp->prevoff, prevoff);
+      PRINT4 (ahdrp->namlen, iterator.current.namlen);
+      PRINT20 (ahdrp->nextoff, iterator.next.offset);
 
 
-      if (bfd_seek (current_bfd, (file_ptr) 0, SEEK_SET) != 0)
+      if (!do_pad (abfd, iterator.current.leading_padding))
        return FALSE;
 
        return FALSE;
 
-      if (! do_copy (abfd, current_bfd))
+      BFD_ASSERT (iterator.current.offset == bfd_tell (abfd));
+      namlen = iterator.current.padded_namlen;
+      if (bfd_bwrite (ahdrp, SIZEOF_AR_HDR_BIG, abfd) != SIZEOF_AR_HDR_BIG
+         || bfd_bwrite (iterator.current.name, namlen, abfd) != namlen
+         || bfd_bwrite (XCOFFARFMAG, SXCOFFARFMAG, abfd) != SXCOFFARFMAG
+         || bfd_seek (iterator.current.member, 0, SEEK_SET) != 0
+         || !do_copy (abfd, iterator.current.member)
+         || !do_pad (abfd, iterator.current.trailing_padding))
        return FALSE;
 
        return FALSE;
 
-      if (! do_pad (abfd, size & 1))
-       return FALSE;
+      offsets[i] = iterator.current.offset;
+      prevoff = iterator.current.offset;
     }
 
   if (count)
     }
 
   if (count)
@@ -2465,6 +2473,7 @@ xcoff_write_archive_contents_big (abfd)
      ??                              pad to even bytes.
    */
 
      ??                              pad to even bytes.
    */
 
+  nextoff = iterator.next.offset;
   BFD_ASSERT (nextoff == bfd_tell (abfd));
 
   member_table_size = (SIZEOF_AR_HDR_BIG
   BFD_ASSERT (nextoff == bfd_tell (abfd));
 
   member_table_size = (SIZEOF_AR_HDR_BIG
@@ -2512,8 +2521,9 @@ xcoff_write_archive_contents_big (abfd)
       offsets = NULL;
     }
 
       offsets = NULL;
     }
 
-  for (current_bfd = abfd->archive_head; current_bfd != NULL;
-       current_bfd = current_bfd->next)
+  for (current_bfd = abfd->archive_head;
+       current_bfd != NULL;
+       current_bfd = current_bfd->archive_next)
     {
       const char *name;
       size_t namlen;
     {
       const char *name;
       size_t namlen;
@@ -2573,9 +2583,8 @@ _bfd_xcoff_write_archive_contents (abfd)
    always uses an a.out header.  */
 
 int
    always uses an a.out header.  */
 
 int
-_bfd_xcoff_sizeof_headers (abfd, reloc)
-     bfd *abfd;
-     bfd_boolean reloc ATTRIBUTE_UNUSED;
+_bfd_xcoff_sizeof_headers (bfd *abfd,
+                          struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   int size;
 
 {
   int size;
 
@@ -2929,11 +2938,13 @@ xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto,
      bfd_byte *contents;
 {
   struct xcoff_link_hash_entry *h;
      bfd_byte *contents;
 {
   struct xcoff_link_hash_entry *h;
+  bfd_vma section_offset;
 
   if (0 > rel->r_symndx)
     return FALSE;
 
   h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx];
 
   if (0 > rel->r_symndx)
     return FALSE;
 
   h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx];
+  section_offset = rel->r_vaddr - input_section->vma;
 
   /* If we see an R_BR or R_RBR reloc which is jumping to global
      linkage code, and it is followed by an appropriate cror nop
 
   /* If we see an R_BR or R_RBR reloc which is jumping to global
      linkage code, and it is followed by an appropriate cror nop
@@ -2943,13 +2954,14 @@ xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto,
      going to global linkage code, we can replace the load with a
      cror.  */
   if (NULL != h
      going to global linkage code, we can replace the load with a
      cror.  */
   if (NULL != h
-      && bfd_link_hash_defined == h->root.type
-      && rel->r_vaddr - input_section->vma + 8 <= input_section->size)
+      && (bfd_link_hash_defined == h->root.type
+         || bfd_link_hash_defweak == h->root.type)
+      && section_offset + 8 <= input_section->size)
     {
       bfd_byte *pnext;
       unsigned long next;
 
     {
       bfd_byte *pnext;
       unsigned long next;
 
-      pnext = contents + (rel->r_vaddr - input_section->vma) + 4;
+      pnext = contents + section_offset + 4;
       next = bfd_get_32 (input_bfd, pnext);
 
       /* The _ptrgl function is magic.  It is used by the AIX
       next = bfd_get_32 (input_bfd, pnext);
 
       /* The _ptrgl function is magic.  It is used by the AIX
@@ -2959,12 +2971,12 @@ xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto,
          if (next == 0x4def7b82                        /* cror 15,15,15 */
              || next == 0x4ffffb82                     /* cror 31,31,31 */
              || next == 0x60000000)                    /* ori r0,r0,0 */
          if (next == 0x4def7b82                        /* cror 15,15,15 */
              || next == 0x4ffffb82                     /* cror 31,31,31 */
              || next == 0x60000000)                    /* ori r0,r0,0 */
-           bfd_put_32 (input_bfd, 0x80410014, pnext);  /* lwz r1,20(r1) */
+           bfd_put_32 (input_bfd, 0x80410014, pnext);  /* lwz r2,20(r1) */
 
        }
       else
        {
 
        }
       else
        {
-         if (next == 0x80410014)                       /* lwz r1,20(r1) */
+         if (next == 0x80410014)                       /* lwz r2,20(r1) */
            bfd_put_32 (input_bfd, 0x60000000, pnext);  /* ori r0,r0,0 */
        }
     }
            bfd_put_32 (input_bfd, 0x60000000, pnext);  /* ori r0,r0,0 */
        }
     }
@@ -2980,16 +2992,42 @@ xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto,
       howto->complain_on_overflow = complain_overflow_dont;
     }
 
       howto->complain_on_overflow = complain_overflow_dont;
     }
 
-  howto->pc_relative = TRUE;
+  /* 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;
+
   howto->src_mask &= ~3;
   howto->dst_mask = howto->src_mask;
 
   howto->src_mask &= ~3;
   howto->dst_mask = howto->src_mask;
 
-  /* A PC relative reloc includes the section address.  */
-  addend += input_section->vma;
-
-  *relocation = val + addend;
-  *relocation -= (input_section->output_section->vma
-                 + input_section->output_offset);
+  if (h != NULL
+      && (h->root.type == bfd_link_hash_defined
+         || h->root.type == bfd_link_hash_defweak)
+      && bfd_is_abs_section (h->root.u.def.section)
+      && section_offset + 4 <= input_section->size)
+    {
+      bfd_byte *ptr;
+      bfd_vma insn;
+
+      /* Turn the relative branch into an absolute one by setting the
+        AA bit.  */
+      ptr = contents + section_offset;
+      insn = bfd_get_32 (input_bfd, ptr);
+      insn |= 2;
+      bfd_put_32 (input_bfd, insn, ptr);
+
+      /* Make the howto absolute too.  */
+      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;
+      *relocation -= (input_section->output_section->vma
+                     + input_section->output_offset
+                     + section_offset);
+    }
   return TRUE;
 }
 
   return TRUE;
 }
 
@@ -3037,7 +3075,7 @@ xcoff_complain_overflow_bitfield_func (input_bfd, val, relocation, howto)
      bfd_vma relocation;
      struct reloc_howto_struct *howto;
 {
      bfd_vma relocation;
      struct reloc_howto_struct *howto;
 {
-  bfd_vma addrmask, fieldmask, signmask, ss;
+  bfd_vma fieldmask, signmask, ss;
   bfd_vma a, b, sum;
 
   /* Get the values to be added together.  For signed and unsigned
   bfd_vma a, b, sum;
 
   /* Get the values to be added together.  For signed and unsigned
@@ -3045,7 +3083,6 @@ xcoff_complain_overflow_bitfield_func (input_bfd, val, relocation, howto)
      the size of an address.  For bitfields, all the bits matter.
      See also bfd_check_overflow.  */
   fieldmask = N_ONES (howto->bitsize);
      the size of an address.  For bitfields, all the bits matter.
      See also bfd_check_overflow.  */
   fieldmask = N_ONES (howto->bitsize);
-  addrmask = N_ONES (bfd_arch_bits_per_address (input_bfd)) | fieldmask;
   a = relocation;
   b = val & howto->src_mask;
 
   a = relocation;
   b = val & howto->src_mask;
 
@@ -3305,9 +3342,7 @@ xcoff_complain_overflow_unsigned_func (input_bfd, val, relocation, howto)
 
    R_RBR:
    A relative branch which may be modified to become an
 
    R_RBR:
    A relative branch which may be modified to become an
-   absolute branch.  FIXME: We don't implement this,
-   although we should for symbols of storage mapping class
-   XMC_XO.
+   absolute branch.
 
    R_RL:
    The PowerPC AIX ABI describes this as a load which may be
 
    R_RL:
    The PowerPC AIX ABI describes this as a load which may be
@@ -3404,6 +3439,17 @@ xcoff_ppc_relocate_section (output_bfd, info, input_bfd,
            }
          else
            {
            }
          else
            {
+             if (info->unresolved_syms_in_objects != RM_IGNORE
+                 && (h->flags & XCOFF_WAS_UNDEFINED) != 0)
+               {
+                 if (! ((*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))))
+                   return FALSE;
+               }
              if (h->root.type == bfd_link_hash_defined
                  || h->root.type == bfd_link_hash_defweak)
                {
              if (h->root.type == bfd_link_hash_defined
                  || h->root.type == bfd_link_hash_defweak)
                {
@@ -3419,17 +3465,13 @@ xcoff_ppc_relocate_section (output_bfd, info, input_bfd,
                         + sec->output_offset);
 
                }
                         + sec->output_offset);
 
                }
-             else if ((0 == (h->flags & (XCOFF_DEF_DYNAMIC | XCOFF_IMPORT)))
-                      && ! info->relocatable)
+             else
                {
                {
-                 if (! ((*info->callbacks->undefined_symbol)
-                        (info, h->root.root.string, input_bfd, input_section,
-                         rel->r_vaddr - input_section->vma, TRUE)))
-                   return FALSE;
-
-                 /* Don't try to process the reloc.  It can't help, and
-                    it may generate another error.  */
-                 continue;
+                 BFD_ASSERT (info->relocatable
+                             || (info->static_link
+                                 && (h->flags & XCOFF_WAS_UNDEFINED) != 0)
+                             || (h->flags & XCOFF_DEF_DYNAMIC) != 0
+                             || (h->flags & XCOFF_IMPORT) != 0);
                }
            }
        }
                }
            }
        }
@@ -3993,7 +4035,7 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
       LINESZ,
       FILNMLEN,
       TRUE,                    /* _bfd_coff_long_filenames */
       LINESZ,
       FILNMLEN,
       TRUE,                    /* _bfd_coff_long_filenames */
-      FALSE,                   /* _bfd_coff_long_section_names */
+      XCOFF_NO_LONG_SECTION_NAMES,  /* _bfd_coff_long_section_names */
       3,                       /* _bfd_coff_default_section_alignment_power */
       FALSE,                   /* _bfd_coff_force_symnames_in_strings */
       2,                       /* _bfd_coff_debug_string_prefix_length */
       3,                       /* _bfd_coff_default_section_alignment_power */
       FALSE,                   /* _bfd_coff_force_symnames_in_strings */
       2,                       /* _bfd_coff_debug_string_prefix_length */
@@ -4020,7 +4062,8 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
       NULL,                    /* _bfd_coff_adjust_symndx */
       _bfd_generic_link_add_one_symbol,
       coff_link_output_has_begun,
       NULL,                    /* _bfd_coff_adjust_symndx */
       _bfd_generic_link_add_one_symbol,
       coff_link_output_has_begun,
-      coff_final_link_postscript
+      coff_final_link_postscript,
+      NULL                     /* print_pdata.  */
     },
 
     0x01DF,                    /* magic number */
     },
 
     0x01DF,                    /* magic number */
@@ -4134,26 +4177,25 @@ const bfd_target rs6000coff_vec =
 
     /* Copy */
     _bfd_xcoff_copy_private_bfd_data,
 
     /* Copy */
     _bfd_xcoff_copy_private_bfd_data,
-    ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
+    _bfd_generic_bfd_merge_private_bfd_data,
     _bfd_generic_init_private_section_data,
     _bfd_generic_init_private_section_data,
-    ((bfd_boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true),
-    ((bfd_boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true),
-    ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
-    ((bfd_boolean (*) (bfd *, flagword)) bfd_true),
-    ((bfd_boolean (*) (bfd *, void * )) bfd_true),
+    _bfd_generic_bfd_copy_private_section_data,
+    _bfd_generic_bfd_copy_private_symbol_data,
+    _bfd_generic_bfd_copy_private_header_data,
+    _bfd_generic_bfd_set_private_flags,
+    _bfd_generic_bfd_print_private_bfd_data,
 
     /* Core */
 
     /* Core */
-    coff_core_file_failing_command,
-    coff_core_file_failing_signal,
-    coff_core_file_matches_executable_p,
+    BFD_JUMP_TABLE_CORE (coff),
 
     /* Archive */
     _bfd_xcoff_slurp_armap,
 
     /* Archive */
     _bfd_xcoff_slurp_armap,
-    bfd_false,
-    ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_false),
+    _bfd_noarchive_slurp_extended_name_table,
+    _bfd_noarchive_construct_extended_name_table,
     bfd_dont_truncate_arname,
     _bfd_xcoff_write_armap,
     _bfd_xcoff_read_ar_hdr,
     bfd_dont_truncate_arname,
     _bfd_xcoff_write_armap,
     _bfd_xcoff_read_ar_hdr,
+    _bfd_generic_write_ar_hdr,
     _bfd_xcoff_openr_next_archived_file,
     _bfd_generic_get_elt_at_index,
     _bfd_xcoff_stat_arch_elt,
     _bfd_xcoff_openr_next_archived_file,
     _bfd_generic_get_elt_at_index,
     _bfd_xcoff_stat_arch_elt,
@@ -4179,6 +4221,7 @@ const bfd_target rs6000coff_vec =
     coff_get_reloc_upper_bound,
     coff_canonicalize_reloc,
     _bfd_xcoff_reloc_type_lookup,
     coff_get_reloc_upper_bound,
     coff_canonicalize_reloc,
     _bfd_xcoff_reloc_type_lookup,
+    _bfd_xcoff_reloc_name_lookup,
 
     /* Write */
     coff_set_arch_mach,
 
     /* Write */
     coff_set_arch_mach,
@@ -4192,14 +4235,15 @@ const bfd_target rs6000coff_vec =
     _bfd_generic_link_hash_table_free,
     _bfd_xcoff_bfd_link_add_symbols,
     _bfd_generic_link_just_syms,
     _bfd_generic_link_hash_table_free,
     _bfd_xcoff_bfd_link_add_symbols,
     _bfd_generic_link_just_syms,
+    _bfd_generic_copy_link_hash_symbol_type,
     _bfd_xcoff_bfd_final_link,
     _bfd_generic_link_split_section,
     bfd_generic_gc_sections,
     bfd_generic_merge_sections,
     _bfd_xcoff_bfd_final_link,
     _bfd_generic_link_split_section,
     bfd_generic_gc_sections,
     bfd_generic_merge_sections,
-    _bfd_generic_match_sections_by_type,
     bfd_generic_is_group_section,
     bfd_generic_discard_group,
     _bfd_generic_section_already_linked,
     bfd_generic_is_group_section,
     bfd_generic_discard_group,
     _bfd_generic_section_already_linked,
+    _bfd_xcoff_define_common_symbol,
 
     /* Dynamic */
     _bfd_xcoff_get_dynamic_symtab_upper_bound,
 
     /* Dynamic */
     _bfd_xcoff_get_dynamic_symtab_upper_bound,
@@ -4244,7 +4288,7 @@ static const struct xcoff_backend_data_rec bfd_pmac_xcoff_backend_data =
       LINESZ,
       FILNMLEN,
       TRUE,                    /* _bfd_coff_long_filenames */
       LINESZ,
       FILNMLEN,
       TRUE,                    /* _bfd_coff_long_filenames */
-      FALSE,                   /* _bfd_coff_long_section_names */
+      XCOFF_NO_LONG_SECTION_NAMES,  /* _bfd_coff_long_section_names */
       3,                       /* _bfd_coff_default_section_alignment_power */
       FALSE,                   /* _bfd_coff_force_symnames_in_strings */
       2,                       /* _bfd_coff_debug_string_prefix_length */
       3,                       /* _bfd_coff_default_section_alignment_power */
       FALSE,                   /* _bfd_coff_force_symnames_in_strings */
       2,                       /* _bfd_coff_debug_string_prefix_length */
@@ -4271,7 +4315,8 @@ static const struct xcoff_backend_data_rec bfd_pmac_xcoff_backend_data =
       NULL,                    /* _bfd_coff_adjust_symndx */
       _bfd_generic_link_add_one_symbol,
       coff_link_output_has_begun,
       NULL,                    /* _bfd_coff_adjust_symndx */
       _bfd_generic_link_add_one_symbol,
       coff_link_output_has_begun,
-      coff_final_link_postscript
+      coff_final_link_postscript,
+      NULL                     /* print_pdata.  */
     },
 
     0x01DF,                    /* magic number */
     },
 
     0x01DF,                    /* magic number */
@@ -4385,26 +4430,25 @@ const bfd_target pmac_xcoff_vec =
 
     /* Copy */
     _bfd_xcoff_copy_private_bfd_data,
 
     /* Copy */
     _bfd_xcoff_copy_private_bfd_data,
-    ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
+    _bfd_generic_bfd_merge_private_bfd_data,
     _bfd_generic_init_private_section_data,
     _bfd_generic_init_private_section_data,
-    ((bfd_boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true),
-    ((bfd_boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true),
-    ((bfd_boolean (*) (bfd *, bfd *)) bfd_true),
-    ((bfd_boolean (*) (bfd *, flagword)) bfd_true),
-    ((bfd_boolean (*) (bfd *, void * )) bfd_true),
+    _bfd_generic_bfd_copy_private_section_data,
+    _bfd_generic_bfd_copy_private_symbol_data,
+    _bfd_generic_bfd_copy_private_header_data,
+    _bfd_generic_bfd_set_private_flags,
+    _bfd_generic_bfd_print_private_bfd_data,
 
     /* Core */
 
     /* Core */
-    coff_core_file_failing_command,
-    coff_core_file_failing_signal,
-    coff_core_file_matches_executable_p,
+    BFD_JUMP_TABLE_CORE (coff),
 
     /* Archive */
     _bfd_xcoff_slurp_armap,
 
     /* Archive */
     _bfd_xcoff_slurp_armap,
-    bfd_false,
-    ((bfd_boolean (*) (bfd *, char **, bfd_size_type *, const char **)) bfd_false),
+    _bfd_noarchive_slurp_extended_name_table,
+    _bfd_noarchive_construct_extended_name_table,
     bfd_dont_truncate_arname,
     _bfd_xcoff_write_armap,
     _bfd_xcoff_read_ar_hdr,
     bfd_dont_truncate_arname,
     _bfd_xcoff_write_armap,
     _bfd_xcoff_read_ar_hdr,
+    _bfd_generic_write_ar_hdr,
     _bfd_xcoff_openr_next_archived_file,
     _bfd_generic_get_elt_at_index,
     _bfd_xcoff_stat_arch_elt,
     _bfd_xcoff_openr_next_archived_file,
     _bfd_generic_get_elt_at_index,
     _bfd_xcoff_stat_arch_elt,
@@ -4430,6 +4474,7 @@ const bfd_target pmac_xcoff_vec =
     coff_get_reloc_upper_bound,
     coff_canonicalize_reloc,
     _bfd_xcoff_reloc_type_lookup,
     coff_get_reloc_upper_bound,
     coff_canonicalize_reloc,
     _bfd_xcoff_reloc_type_lookup,
+    _bfd_xcoff_reloc_name_lookup,
 
     /* Write */
     coff_set_arch_mach,
 
     /* Write */
     coff_set_arch_mach,
@@ -4443,14 +4488,15 @@ const bfd_target pmac_xcoff_vec =
     _bfd_generic_link_hash_table_free,
     _bfd_xcoff_bfd_link_add_symbols,
     _bfd_generic_link_just_syms,
     _bfd_generic_link_hash_table_free,
     _bfd_xcoff_bfd_link_add_symbols,
     _bfd_generic_link_just_syms,
+    _bfd_generic_copy_link_hash_symbol_type,
     _bfd_xcoff_bfd_final_link,
     _bfd_generic_link_split_section,
     bfd_generic_gc_sections,
     bfd_generic_merge_sections,
     _bfd_xcoff_bfd_final_link,
     _bfd_generic_link_split_section,
     bfd_generic_gc_sections,
     bfd_generic_merge_sections,
-    _bfd_generic_match_sections_by_type,
     bfd_generic_is_group_section,
     bfd_generic_discard_group,
     _bfd_generic_section_already_linked,
     bfd_generic_is_group_section,
     bfd_generic_discard_group,
     _bfd_generic_section_already_linked,
+    _bfd_xcoff_define_common_symbol,
 
     /* Dynamic */
     _bfd_xcoff_get_dynamic_symtab_upper_bound,
 
     /* Dynamic */
     _bfd_xcoff_get_dynamic_symtab_upper_bound,
This page took 0.046819 seconds and 4 git commands to generate.