Support for xcoff64
[deliverable/binutils-gdb.git] / bfd / xcofflink.c
index 5580e9b35439119c13131e8e5325b86fcd639c09..4e25c595d453e4f617cb328942e1dda0634f06cc 100644 (file)
@@ -24,186 +24,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "coff/internal.h"
+#include "coff/xcoff.h"
 #include "libcoff.h"
+#include "libxcoff.h"
 
 /* This file holds the XCOFF linker code.  */
 
 #define STRING_SIZE_SIZE (4)
 
-/* Get the XCOFF hash table entries for a BFD.  */
-#define obj_xcoff_sym_hashes(bfd) \
-  ((struct xcoff_link_hash_entry **) obj_coff_sym_hashes (bfd))
-
-/* XCOFF relocation types.  These probably belong in a header file
-   somewhere.  The relocations are described in the function
-   _bfd_ppc_xcoff_relocate_section in this file.  */
-
-#define R_POS   (0x00)
-#define R_NEG   (0x01)
-#define R_REL   (0x02)
-#define R_TOC   (0x03)
-#define R_RTB   (0x04)
-#define R_GL    (0x05)
-#define R_TCL   (0x06)
-#define R_BA    (0x08)
-#define R_BR    (0x0a)
-#define R_RL    (0x0c)
-#define R_RLA   (0x0d)
-#define R_REF   (0x0f)
-#define R_TRL   (0x12)
-#define R_TRLA  (0x13)
-#define R_RRTBI (0x14)
-#define R_RRTBA (0x15)
-#define R_CAI   (0x16)
-#define R_CREL  (0x17)
-#define R_RBA   (0x18)
-#define R_RBAC  (0x19)
-#define R_RBR   (0x1a)
-#define R_RBRC  (0x1b)
-
-/* The first word of global linkage code.  This must be modified by
-   filling in the correct TOC offset.  */
-
-#define XCOFF_GLINK_FIRST (0x81820000) /* lwz r12,0(r2) */
-
-/* The remaining words of global linkage code.  */
-
-static unsigned long xcoff_glink_code[] = {
-  0x90410014,  /* stw r2,20(r1) */
-  0x800c0000,  /* lwz r0,0(r12) */
-  0x804c0004,  /* lwz r2,4(r12) */
-  0x7c0903a6,  /* mtctr r0 */
-  0x4e800420,  /* bctr */
-  0x0,         /* start of traceback table */
-  0x000c8000,  /* traceback table */
-  0x0          /* traceback table */
-};
-
-#define XCOFF_GLINK_SIZE \
-  (((sizeof xcoff_glink_code / sizeof xcoff_glink_code[0]) * 4) + 4)
-
 /* We reuse the SEC_ROM flag as a mark flag for garbage collection.
    This flag will only be used on input sections.  */
 
 #define SEC_MARK (SEC_ROM)
 
-/* The ldhdr structure.  This appears at the start of the .loader
-   section.  */
-
-struct internal_ldhdr {
-  /* The version number: currently always 1.  */
-  unsigned long l_version;
-  /* The number of symbol table entries.  */
-  bfd_size_type l_nsyms;
-  /* The number of relocation table entries.  */
-  bfd_size_type l_nreloc;
-  /* The length of the import file string table.  */
-  bfd_size_type l_istlen;
-  /* The number of import files.  */
-  bfd_size_type l_nimpid;
-  /* The offset from the start of the .loader section to the first
-     entry in the import file table.  */
-  bfd_size_type l_impoff;
-  /* The length of the string table.  */
-  bfd_size_type l_stlen;
-  /* The offset from the start of the .loader section to the first
-     entry in the string table.  */
-  bfd_size_type l_stoff;
-};
-
-struct external_ldhdr {
-  bfd_byte l_version[4];
-  bfd_byte l_nsyms[4];
-  bfd_byte l_nreloc[4];
-  bfd_byte l_istlen[4];
-  bfd_byte l_nimpid[4];
-  bfd_byte l_impoff[4];
-  bfd_byte l_stlen[4];
-  bfd_byte l_stoff[4];
-};
-
-#define LDHDRSZ (8 * 4)
-
-/* The ldsym structure.  This is used to represent a symbol in the
-   .loader section.  */
-
-struct internal_ldsym {
-  union {
-    /* The symbol name if <= SYMNMLEN characters.  */
-    char _l_name[SYMNMLEN];
-    struct {
-      /* Zero if the symbol name is more than SYMNMLEN characters.  */
-      long _l_zeroes;
-      /* The offset in the string table if the symbol name is more
-        than SYMNMLEN characters.  */
-      long _l_offset;
-    } _l_l;
-  } _l;
-  /* The symbol value.  */
-  bfd_vma l_value;
-  /* The symbol section number.  */
-  short l_scnum;
-  /* The symbol type and flags.  */
-  char l_smtype;
-  /* The symbol storage class.  */
-  char l_smclas;
-  /* The import file ID.  */
-  bfd_size_type l_ifile;
-  /* Offset to the parameter type check string.  */
-  bfd_size_type l_parm;
-};
-
-struct external_ldsym {
-  union {
-    bfd_byte _l_name[SYMNMLEN];
-    struct {
-      bfd_byte _l_zeroes[4];
-      bfd_byte _l_offset[4];
-    } _l_l;
-  } _l;
-  bfd_byte l_value[4];
-  bfd_byte l_scnum[2];
-  bfd_byte l_smtype[1];
-  bfd_byte l_smclas[1];
-  bfd_byte l_ifile[4];
-  bfd_byte l_parm[4];
-};
-
-#define LDSYMSZ (8 + 3 * 4 + 2 + 2)
-
-/* These flags are for the l_smtype field (the lower three bits are an
-   XTY_* value).  */
-
-/* Imported symbol.  */
-#define L_IMPORT (0x40)
-/* Entry point.  */
-#define L_ENTRY (0x20)
-/* Exported symbol.  */
-#define L_EXPORT (0x10)
-
-/* The ldrel structure.  This is used to represent a reloc in the
-   .loader section.  */
-
-struct internal_ldrel {
-  /* The reloc address.  */
-  bfd_vma l_vaddr;
-  /* The symbol table index in the .loader section symbol table.  */
-  bfd_size_type l_symndx;
-  /* The relocation type and size.  */
-  short l_rtype;
-  /* The section number this relocation applies to.  */
-  short l_rsecnm;
-};
-
-struct external_ldrel {
-  bfd_byte l_vaddr[4];
-  bfd_byte l_symndx[4];
-  bfd_byte l_rtype[2];
-  bfd_byte l_rsecnm[2];
-};
-
-#define LDRELSZ (2 * 4 + 2 * 2)
-
 /* The list of import files.  */
 
 struct xcoff_import_file {
@@ -217,134 +50,6 @@ struct xcoff_import_file {
   const char *member;
 };
 
-/* An entry in the XCOFF linker hash table.  */
-
-struct xcoff_link_hash_entry {
-  struct bfd_link_hash_entry root;
-
-  /* Symbol index in output file.  Set to -1 initially.  Set to -2 if
-     there is a reloc against this symbol.  */
-  long indx;
-
-  /* If we have created a TOC entry for this symbol, this is the .tc
-     section which holds it.  */
-  asection *toc_section;
-
-  union {
-    /* If we have created a TOC entry (the XCOFF_SET_TOC flag is set),
-       this is the offset in toc_section.  */
-    bfd_vma toc_offset;
-    /* If the TOC entry comes from an input file, this is set to the
-       symbol index of the C_HIDEXT XMC_TC or XMC_TD symbol.  */
-    long toc_indx;
-  } u;
-
-  /* If this symbol is a function entry point which is called, this
-     field holds a pointer to the function descriptor.  If this symbol
-     is a function descriptor, this field holds a pointer to the
-     function entry point.  */
-  struct xcoff_link_hash_entry *descriptor;
-
-  /* The .loader symbol table entry, if there is one.  */
-  struct internal_ldsym *ldsym;
-
-  /* If XCOFF_BUILT_LDSYM is set, this is the .loader symbol table
-     index.  If XCOFF_BUILD_LDSYM is clear, and XCOFF_IMPORT is set,
-     this is the l_ifile value.  */
-  long ldindx;
-
-  /* Some linker flags.  */
-  unsigned short flags;
-  /* Symbol is referenced by a regular object.  */
-#define XCOFF_REF_REGULAR (01)
-  /* Symbol is defined by a regular object.  */
-#define XCOFF_DEF_REGULAR (02)
-  /* Symbol is defined by a dynamic object.  */
-#define XCOFF_DEF_DYNAMIC (04)
-  /* Symbol is used in a reloc being copied into the .loader section.  */
-#define XCOFF_LDREL (010)
-  /* Symbol is the entry point.  */
-#define XCOFF_ENTRY (020)
-  /* Symbol is called; this is, it appears in a R_BR reloc.  */
-#define XCOFF_CALLED (040)
-  /* Symbol needs the TOC entry filled in.  */
-#define XCOFF_SET_TOC (0100)
-  /* Symbol is explicitly imported.  */
-#define XCOFF_IMPORT (0200)
-  /* Symbol is explicitly exported.  */
-#define XCOFF_EXPORT (0400)
-  /* Symbol has been processed by xcoff_build_ldsyms.  */
-#define XCOFF_BUILT_LDSYM (01000)
-  /* Symbol is mentioned by a section which was not garbage collected.  */
-#define XCOFF_MARK (02000)
-  /* Symbol size is recorded in size_list list from hash table.  */
-#define XCOFF_HAS_SIZE (04000)
-  /* Symbol is a function descriptor.  */
-#define XCOFF_DESCRIPTOR (010000)
-  /* Multiple definitions have been for the symbol.  */
-#define XCOFF_MULTIPLY_DEFINED (020000)
-
-  /* The storage mapping class.  */
-  unsigned char smclas;
-};
-
-/* The XCOFF linker hash table.  */
-
-struct xcoff_link_hash_table {
-  struct bfd_link_hash_table root;
-
-  /* The .debug string hash table.  We need to compute this while
-     reading the input files, so that we know how large the .debug
-     section will be before we assign section positions.  */
-  struct bfd_strtab_hash *debug_strtab;
-
-  /* The .debug section we will use for the final output.  */
-  asection *debug_section;
-
-  /* The .loader section we will use for the final output.  */
-  asection *loader_section;
-
-  /* A count of non TOC relative relocs which will need to be
-     allocated in the .loader section.  */
-  size_t ldrel_count;
-
-  /* The .loader section header.  */
-  struct internal_ldhdr ldhdr;
-
-  /* The .gl section we use to hold global linkage code.  */
-  asection *linkage_section;
-
-  /* The .tc section we use to hold toc entries we build for global
-     linkage code.  */
-  asection *toc_section;
-
-  /* The .ds section we use to hold function descriptors which we
-     create for exported symbols.  */
-  asection *descriptor_section;
-
-  /* The list of import files.  */
-  struct xcoff_import_file *imports;
-
-  /* Required alignment of sections within the output file.  */
-  unsigned long file_align;
-
-  /* Whether the .text section must be read-only.  */
-  boolean textro;
-
-  /* Whether garbage collection was done.  */
-  boolean gc;
-
-  /* A linked list of symbols for which we have size information.  */
-  struct xcoff_link_size_list {
-    struct xcoff_link_size_list *next;
-    struct xcoff_link_hash_entry *h;
-    bfd_size_type size;
-  } *size_list;
-
-  /* Magic sections: _text, _etext, _data, _edata, _end, end.  */
-  asection *special_sections[6];
-};
-
 /* Information we keep for each section in the output file during the
    final link phase.  */
 
@@ -384,9 +89,9 @@ struct xcoff_final_link_info {
   /* Symbol index of TOC symbol.  */
   long toc_symindx;
   /* Start of .loader symbols.  */
-  struct external_ldsym *ldsym;
+  bfd_byte *ldsym;
   /* Next .loader reloc to swap out.  */
-  struct external_ldrel *ldrel;
+  bfd_byte *ldrel;
   /* File position of start of line numbers.  */
   file_ptr line_filepos;
   /* Buffer large enough to hold swapped symbols of any input file.  */
@@ -405,18 +110,6 @@ struct xcoff_final_link_info {
   bfd_byte *external_relocs;
 };
 
-static void xcoff_swap_ldhdr_in
-  PARAMS ((bfd *, const struct external_ldhdr *, struct internal_ldhdr *));
-static void xcoff_swap_ldhdr_out
-  PARAMS ((bfd *, const struct internal_ldhdr *, struct external_ldhdr *));
-static void xcoff_swap_ldsym_in
-  PARAMS ((bfd *, const struct external_ldsym *, struct internal_ldsym *));
-static void xcoff_swap_ldsym_out
-  PARAMS ((bfd *, const struct internal_ldsym *, struct external_ldsym *));
-static void xcoff_swap_ldrel_in
-  PARAMS ((bfd *, const struct external_ldrel *, struct internal_ldrel *));
-static void xcoff_swap_ldrel_out
-  PARAMS ((bfd *, const struct internal_ldrel *, struct external_ldrel *));
 static struct bfd_hash_entry *xcoff_link_hash_newfunc
   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
 static boolean xcoff_get_section_contents PARAMS ((bfd *, asection *));
@@ -451,121 +144,7 @@ static boolean xcoff_reloc_link_order
           struct bfd_link_order *));
 static int xcoff_sort_relocs PARAMS ((const PTR, const PTR));
 \f
-/* Routines to swap information in the XCOFF .loader section.  If we
-   ever need to write an XCOFF loader, this stuff will need to be
-   moved to another file shared by the linker (which XCOFF calls the
-   ``binder'') and the loader.  */
-
-/* Swap in the ldhdr structure.  */
-
-static void
-xcoff_swap_ldhdr_in (abfd, src, dst)
-     bfd *abfd;
-     const struct external_ldhdr *src;
-     struct internal_ldhdr *dst;
-{
-  dst->l_version = bfd_get_32 (abfd, src->l_version);
-  dst->l_nsyms = bfd_get_32 (abfd, src->l_nsyms);
-  dst->l_nreloc = bfd_get_32 (abfd, src->l_nreloc);
-  dst->l_istlen = bfd_get_32 (abfd, src->l_istlen);
-  dst->l_nimpid = bfd_get_32 (abfd, src->l_nimpid);
-  dst->l_impoff = bfd_get_32 (abfd, src->l_impoff);
-  dst->l_stlen = bfd_get_32 (abfd, src->l_stlen);
-  dst->l_stoff = bfd_get_32 (abfd, src->l_stoff);
-}
-
-/* Swap out the ldhdr structure.  */
-
-static void
-xcoff_swap_ldhdr_out (abfd, src, dst)
-     bfd *abfd;
-     const struct internal_ldhdr *src;
-     struct external_ldhdr *dst;
-{
-  bfd_put_32 (abfd, src->l_version, dst->l_version);
-  bfd_put_32 (abfd, src->l_nsyms, dst->l_nsyms);
-  bfd_put_32 (abfd, src->l_nreloc, dst->l_nreloc);
-  bfd_put_32 (abfd, src->l_istlen, dst->l_istlen);
-  bfd_put_32 (abfd, src->l_nimpid, dst->l_nimpid);
-  bfd_put_32 (abfd, src->l_impoff, dst->l_impoff);
-  bfd_put_32 (abfd, src->l_stlen, dst->l_stlen);
-  bfd_put_32 (abfd, src->l_stoff, dst->l_stoff);
-}
-
-/* Swap in the ldsym structure.  */
-
-static void
-xcoff_swap_ldsym_in (abfd, src, dst)
-     bfd *abfd;
-     const struct external_ldsym *src;
-     struct internal_ldsym *dst;
-{
-  if (bfd_get_32 (abfd, src->_l._l_l._l_zeroes) != 0)
-    memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN);
-  else
-    {
-      dst->_l._l_l._l_zeroes = 0;
-      dst->_l._l_l._l_offset = bfd_get_32 (abfd, src->_l._l_l._l_offset);
-    }
-  dst->l_value = bfd_get_32 (abfd, src->l_value);
-  dst->l_scnum = bfd_get_16 (abfd, src->l_scnum);
-  dst->l_smtype = bfd_get_8 (abfd, src->l_smtype);
-  dst->l_smclas = bfd_get_8 (abfd, src->l_smclas);
-  dst->l_ifile = bfd_get_32 (abfd, src->l_ifile);
-  dst->l_parm = bfd_get_32 (abfd, src->l_parm);
-}
-
-/* Swap out the ldsym structure.  */
-
-static void
-xcoff_swap_ldsym_out (abfd, src, dst)
-     bfd *abfd;
-     const struct internal_ldsym *src;
-     struct external_ldsym *dst;
-{
-  if (src->_l._l_l._l_zeroes != 0)
-    memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN);
-  else
-    {
-      bfd_put_32 (abfd, 0, dst->_l._l_l._l_zeroes);
-      bfd_put_32 (abfd, src->_l._l_l._l_offset, dst->_l._l_l._l_offset);
-    }
-  bfd_put_32 (abfd, src->l_value, dst->l_value);
-  bfd_put_16 (abfd, src->l_scnum, dst->l_scnum);
-  bfd_put_8 (abfd, src->l_smtype, dst->l_smtype);
-  bfd_put_8 (abfd, src->l_smclas, dst->l_smclas);
-  bfd_put_32 (abfd, src->l_ifile, dst->l_ifile);
-  bfd_put_32 (abfd, src->l_parm, dst->l_parm);
-}
-
-/* Swap in the ldrel structure.  */
-
-static void
-xcoff_swap_ldrel_in (abfd, src, dst)
-     bfd *abfd;
-     const struct external_ldrel *src;
-     struct internal_ldrel *dst;
-{
-  dst->l_vaddr = bfd_get_32 (abfd, src->l_vaddr);
-  dst->l_symndx = bfd_get_32 (abfd, src->l_symndx);
-  dst->l_rtype = bfd_get_16 (abfd, src->l_rtype);
-  dst->l_rsecnm = bfd_get_16 (abfd, src->l_rsecnm);
-}
 
-/* Swap out the ldrel structure.  */
-
-static void
-xcoff_swap_ldrel_out (abfd, src, dst)
-     bfd *abfd;
-     const struct internal_ldrel *src;
-     struct external_ldrel *dst;
-{
-  bfd_put_32 (abfd, src->l_vaddr, dst->l_vaddr);
-  bfd_put_32 (abfd, src->l_symndx, dst->l_symndx);
-  bfd_put_16 (abfd, src->l_rtype, dst->l_rtype);
-  bfd_put_16 (abfd, src->l_rsecnm, dst->l_rsecnm);
-}
-\f
 /* Routines to read XCOFF dynamic information.  This don't really
    belong here, but we already have the ldsym manipulation routines
    here.  */
@@ -577,6 +156,7 @@ xcoff_get_section_contents (abfd, sec)
      bfd *abfd;
      asection *sec;
 {
+
   if (coff_section_data (abfd, sec) == NULL)
     {
       sec->used_by_bfd = bfd_zalloc (abfd,
@@ -628,7 +208,7 @@ _bfd_xcoff_get_dynamic_symtab_upper_bound (abfd)
     return -1;
   contents = coff_section_data (abfd, lsec)->contents;
 
-  xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
+  bfd_xcoff_swap_ldhdr_in (abfd, (PTR) contents, &ldhdr);
 
   return (ldhdr.l_nsyms + 1) * sizeof (asymbol *);
 }
@@ -644,7 +224,7 @@ _bfd_xcoff_canonicalize_dynamic_symtab (abfd, psyms)
   bfd_byte *contents;
   struct internal_ldhdr ldhdr;
   const char *strings;
-  struct external_ldsym *elsym, *elsymend;
+  bfd_byte *elsym, *elsymend;
   coff_symbol_type *symbuf;
 
   if ((abfd->flags & DYNAMIC) == 0)
@@ -666,7 +246,7 @@ _bfd_xcoff_canonicalize_dynamic_symtab (abfd, psyms)
 
   coff_section_data (abfd, lsec)->keep_contents = true;
 
-  xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
+  bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
 
   strings = (char *) contents + ldhdr.l_stoff;
 
@@ -675,13 +255,14 @@ _bfd_xcoff_canonicalize_dynamic_symtab (abfd, psyms)
   if (symbuf == NULL)
     return -1;
 
-  elsym = (struct external_ldsym *) (contents + LDHDRSZ);
-  elsymend = elsym + ldhdr.l_nsyms;
-  for (; elsym < elsymend; elsym++, symbuf++, psyms++)
+  elsym = contents + bfd_xcoff_loader_symbol_offset(abfd, &ldhdr);
+
+  elsymend = elsym + ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
+  for (; elsym < elsymend; elsym += bfd_xcoff_ldsymsz(abfd), symbuf++, psyms++)
     {
       struct internal_ldsym ldsym;
 
-      xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
+      bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
 
       symbuf->symbol.the_bfd = abfd;
 
@@ -689,24 +270,14 @@ _bfd_xcoff_canonicalize_dynamic_symtab (abfd, psyms)
        symbuf->symbol.name = strings + ldsym._l._l_l._l_offset;
       else
        {
-         int i;
-
-         for (i = 0; i < SYMNMLEN; i++)
-           if (ldsym._l._l_name[i] == '\0')
-             break;
-         if (i < SYMNMLEN)
-           symbuf->symbol.name = (char *) elsym->_l._l_name;
-         else
-           {
-             char *c;
-
-             c = bfd_alloc (abfd, SYMNMLEN + 1);
-             if (c == NULL)
-               return -1;
-             memcpy (c, ldsym._l._l_name, SYMNMLEN);
-             c[SYMNMLEN] = '\0';
-             symbuf->symbol.name = c;
-           }
+         char *c;
+
+         c = bfd_alloc (abfd, SYMNMLEN + 1);
+         if (c == NULL)
+           return -1;
+         memcpy (c, ldsym._l._l_name, SYMNMLEN);
+         c[SYMNMLEN] = '\0';
+         symbuf->symbol.name = c;
        }
 
       if (ldsym.l_smclas == XMC_XO)
@@ -758,28 +329,11 @@ _bfd_xcoff_get_dynamic_reloc_upper_bound (abfd)
     return -1;
   contents = coff_section_data (abfd, lsec)->contents;
 
-  xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
+  bfd_xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
 
   return (ldhdr.l_nreloc + 1) * sizeof (arelent *);
 }
 
-/* The typical dynamic reloc.  */
-
-static reloc_howto_type xcoff_dynamic_reloc =
-  HOWTO (0,                    /* 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_POS",               /* name */
-        true,                  /* partial_inplace */
-        0xffffffff,            /* src_mask */
-        0xffffffff,            /* dst_mask */
-        false);                /* pcrel_offset */
-
 /* Get the dynamic relocs.  */
 
 long
@@ -792,7 +346,7 @@ _bfd_xcoff_canonicalize_dynamic_reloc (abfd, prelocs, syms)
   bfd_byte *contents;
   struct internal_ldhdr ldhdr;
   arelent *relbuf;
-  struct external_ldrel *elrel, *elrelend;
+  bfd_byte *elrel, *elrelend;
 
   if ((abfd->flags & DYNAMIC) == 0)
     {
@@ -811,20 +365,21 @@ _bfd_xcoff_canonicalize_dynamic_reloc (abfd, prelocs, syms)
     return -1;
   contents = coff_section_data (abfd, lsec)->contents;
 
-  xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);
+  bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
 
   relbuf = (arelent *) bfd_alloc (abfd, ldhdr.l_nreloc * sizeof (arelent));
   if (relbuf == NULL)
     return -1;
 
-  elrel = ((struct external_ldrel *)
-          (contents + LDHDRSZ + ldhdr.l_nsyms * LDSYMSZ));
-  elrelend = elrel + ldhdr.l_nreloc;
-  for (; elrel < elrelend; elrel++, relbuf++, prelocs++)
+  elrel = contents + bfd_xcoff_loader_reloc_offset(abfd, &ldhdr);
+
+  elrelend = elrel + ldhdr.l_nreloc * bfd_xcoff_ldrelsz(abfd);
+  for (; elrel < elrelend; elrel += bfd_xcoff_ldrelsz(abfd), relbuf++, 
+          prelocs++)
     {
       struct internal_ldrel ldrel;
 
-      xcoff_swap_ldrel_in (abfd, elrel, &ldrel);
+      bfd_xcoff_swap_ldrel_in (abfd, elrel, &ldrel);
 
       if (ldrel.l_symndx >= 3)
        relbuf->sym_ptr_ptr = syms + (ldrel.l_symndx - 3);
@@ -865,7 +420,7 @@ _bfd_xcoff_canonicalize_dynamic_reloc (abfd, prelocs, syms)
       /* Most dynamic relocs have the same type.  FIXME: This is only
          correct if ldrel.l_rtype == 0.  In other cases, we should use
          a different howto.  */
-      relbuf->howto = &xcoff_dynamic_reloc;
+      relbuf->howto = bfd_xcoff_dynamic_reloc_howto(abfd);
 
       /* FIXME: We have no way to record the l_rsecnm field.  */
 
@@ -955,25 +510,6 @@ _bfd_xcoff_bfd_link_hash_table_create (abfd)
   return &ret->root;
 }
 
-/* Look up an entry in an XCOFF link hash table.  */
-
-#define xcoff_link_hash_lookup(table, string, create, copy, follow) \
-  ((struct xcoff_link_hash_entry *) \
-   bfd_link_hash_lookup (&(table)->root, (string), (create), (copy),\
-                        (follow)))
-
-/* Traverse an XCOFF link hash table.  */
-
-#define xcoff_link_hash_traverse(table, func, info)                    \
-  (bfd_link_hash_traverse                                              \
-   (&(table)->root,                                                    \
-    (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \
-    (info)))
-
-/* Get the XCOFF link hash table from the info structure.  This is
-   just a cast.  */
-
-#define xcoff_hash_table(p) ((struct xcoff_link_hash_table *) ((p)->hash))
 \f
 /* Read internal relocs for an XCOFF csect.  This is a wrapper around
    _bfd_coff_read_internal_relocs which tries to take advantage of any
@@ -989,6 +525,7 @@ xcoff_read_internal_relocs (abfd, sec, cache, external_relocs,
      boolean require_internal;
      struct internal_reloc *internal_relocs;
 {
+
   if (coff_section_data (abfd, sec) != NULL
       && coff_section_data (abfd, sec)->relocs == NULL
       && xcoff_section_data (abfd, sec) != NULL)
@@ -1018,6 +555,7 @@ xcoff_read_internal_relocs (abfd, sec, cache, external_relocs,
 
          off = ((sec->rel_filepos - enclosing->rel_filepos)
                 / bfd_coff_relsz (abfd));
+
          if (! require_internal)
            return coff_section_data (abfd, enclosing)->relocs + off;
          memcpy (internal_relocs,
@@ -1039,6 +577,7 @@ _bfd_xcoff_bfd_link_add_symbols (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
 {
+
   switch (bfd_get_format (abfd))
     {
     case bfd_object:
@@ -1095,6 +634,7 @@ xcoff_link_add_object_symbols (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
 {
+
   if (! _bfd_coff_get_external_symbols (abfd))
     return false;
   if (! xcoff_link_add_symbols (abfd, info))
@@ -1118,6 +658,7 @@ xcoff_link_check_archive_element (abfd, info, pneeded)
      struct bfd_link_info *info;
      boolean *pneeded;
 {
+
   if (! _bfd_coff_get_external_symbols (abfd))
     return false;
 
@@ -1178,6 +719,7 @@ xcoff_link_check_ar_symbols (abfd, info, pneeded)
              object file.  */
 
          name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
+
          if (name == NULL)
            return false;
          h = bfd_link_hash_lookup (info->hash, name, false, false, true);
@@ -1189,7 +731,7 @@ xcoff_link_check_ar_symbols (abfd, info, pneeded)
             undefined references in shared objects.  */
          if (h != (struct bfd_link_hash_entry *) NULL
              && h->type == bfd_link_hash_undefined
-             && (info->hash->creator != abfd->xvec
+             && (info->hash->creator != abfd->xvec 
                  || (((struct xcoff_link_hash_entry *) h)->flags
                      & XCOFF_DEF_DYNAMIC) == 0))
            {
@@ -1218,10 +760,10 @@ xcoff_link_check_dynamic_ar_symbols (abfd, info, pneeded)
      boolean *pneeded;
 {
   asection *lsec;
-  bfd_byte *buf;
+  bfd_byte *contents;
   struct internal_ldhdr ldhdr;
   const char *strings;
-  struct external_ldsym *elsym, *elsymend;
+  bfd_byte *elsym, *elsymend;
 
   *pneeded = false;
 
@@ -1234,22 +776,23 @@ xcoff_link_check_dynamic_ar_symbols (abfd, info, pneeded)
 
   if (! xcoff_get_section_contents (abfd, lsec))
     return false;
-  buf = coff_section_data (abfd, lsec)->contents;
+  contents = coff_section_data (abfd, lsec)->contents;
+
+  bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
 
-  xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) buf, &ldhdr);
+  strings = (char *) contents + ldhdr.l_stoff;
 
-  strings = (char *) buf + ldhdr.l_stoff;
+  elsym = contents + bfd_xcoff_loader_symbol_offset(abfd, &ldhdr);
 
-  elsym = (struct external_ldsym *) (buf + LDHDRSZ);
-  elsymend = elsym + ldhdr.l_nsyms;
-  for (; elsym < elsymend; elsym++)
+  elsymend = elsym + ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
+  for (; elsym < elsymend; elsym += bfd_xcoff_ldsymsz(abfd))
     {
       struct internal_ldsym ldsym;
       char nambuf[SYMNMLEN + 1];
       const char *name;
       struct bfd_link_hash_entry *h;
 
-      xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
+      bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
 
       /* We are only interested in exported symbols.  */
       if ((ldsym.l_smtype & L_EXPORT) == 0)
@@ -1283,7 +826,7 @@ xcoff_link_check_dynamic_ar_symbols (abfd, info, pneeded)
 
   /* We do not need this shared object.  */
 
-  if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
+  if (contents != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
     {
       free (coff_section_data (abfd, lsec)->contents);
       coff_section_data (abfd, lsec)->contents = NULL;
@@ -1342,6 +885,100 @@ xcoff_find_reloc (relocs, count, address)
   return min;
 }
 
+
+/* 
+ * xcoff_link_create_extra_sections
+ *
+ * Takes care of creating the .loader, .gl, .ds, .debug and sections
+ */
+static boolean
+xcoff_link_create_extra_sections(bfd * abfd, struct bfd_link_info *info) {
+
+  boolean return_value = false;
+
+   if (info->hash->creator == abfd->xvec) { 
+
+      /* We need to build a .loader section, so we do it here.  This
+        won't work if we're producing an XCOFF output file with no
+        XCOFF input files.  FIXME.  */
+
+      if (xcoff_hash_table (info)->loader_section == NULL) {
+       asection *lsec;
+       
+       lsec = bfd_make_section_anyway (abfd, ".loader");
+       if (lsec == NULL) {
+         goto end_return;
+       }
+       xcoff_hash_table (info)->loader_section = lsec;
+       lsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+      }
+
+      /* Likewise for the linkage section.  */
+      if (xcoff_hash_table (info)->linkage_section == NULL) {
+       asection *lsec;
+
+       lsec = bfd_make_section_anyway (abfd, ".gl");
+       if (lsec == NULL) {
+         goto end_return;
+       }
+
+       xcoff_hash_table (info)->linkage_section = lsec;
+       lsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+                       | SEC_IN_MEMORY);
+       lsec->alignment_power = 2;
+      }
+
+      /* Likewise for the TOC section.  */
+      if (xcoff_hash_table (info)->toc_section == NULL) {
+       asection *tsec;
+       
+       tsec = bfd_make_section_anyway (abfd, ".tc");
+       if (tsec == NULL) {
+         goto end_return;
+       }
+
+       xcoff_hash_table (info)->toc_section = tsec;
+       tsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+                       | SEC_IN_MEMORY);
+       tsec->alignment_power = 2;
+      }
+
+      /* Likewise for the descriptor section.  */
+      if (xcoff_hash_table (info)->descriptor_section == NULL) {
+       asection *dsec;
+       
+       dsec = bfd_make_section_anyway (abfd, ".ds");
+       if (dsec == NULL) {
+         goto end_return;
+       }
+
+       xcoff_hash_table (info)->descriptor_section = dsec;
+       dsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+                       | SEC_IN_MEMORY);
+       dsec->alignment_power = 2;
+      }
+
+      /* Likewise for the .debug section.  */
+      if (xcoff_hash_table (info)->debug_section == NULL
+         && info->strip != strip_all) {
+       asection *dsec;
+
+       dsec = bfd_make_section_anyway (abfd, ".debug");
+       if (dsec == NULL) {
+         goto end_return;
+       }
+       xcoff_hash_table (info)->debug_section = dsec;
+       dsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+      }
+  } 
+  
+  return_value = true;
+
+ end_return:
+
+  return return_value;
+}
+
 /* Add all the symbols from an object file to the hash table.
 
    XCOFF is a weird format.  A normal XCOFF .o files will have three
@@ -1381,89 +1018,26 @@ xcoff_link_add_symbols (abfd, info)
   bfd_size_type symesz;
   bfd_byte *esym;
   bfd_byte *esym_end;
-  struct reloc_info_struct
-    {
-      struct internal_reloc *relocs;
-      asection **csects;
-      bfd_byte *linenos;
-    } *reloc_info = NULL;
+  struct reloc_info_struct 
+  {
+    struct internal_reloc *relocs;
+    asection **csects;
+    bfd_byte *linenos;
+  } *reloc_info = NULL;
 
   keep_syms = obj_coff_keep_syms (abfd);
 
   if ((abfd->flags & DYNAMIC) != 0
-      && ! info->static_link)
-    {
-      if (! xcoff_link_add_dynamic_symbols (abfd, info))
-       return false;
+      && ! info->static_link) {
+    if (! xcoff_link_add_dynamic_symbols (abfd, info)) {
+      return false;
     }
+  }
 
-  if (info->hash->creator == abfd->xvec)
-    {
-      /* We need to build a .loader section, so we do it here.  This
-        won't work if we're producing an XCOFF output file with no
-        XCOFF input files.  FIXME.  */
-      if (xcoff_hash_table (info)->loader_section == NULL)
-       {
-         asection *lsec;
-
-         lsec = bfd_make_section_anyway (abfd, ".loader");
-         if (lsec == NULL)
-           goto error_return;
-         xcoff_hash_table (info)->loader_section = lsec;
-         lsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
-       }
-      /* Likewise for the linkage section.  */
-      if (xcoff_hash_table (info)->linkage_section == NULL)
-       {
-         asection *lsec;
-
-         lsec = bfd_make_section_anyway (abfd, ".gl");
-         if (lsec == NULL)
-           goto error_return;
-         xcoff_hash_table (info)->linkage_section = lsec;
-         lsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
-                         | SEC_IN_MEMORY);
-         lsec->alignment_power = 2;
-       }
-      /* Likewise for the TOC section.  */
-      if (xcoff_hash_table (info)->toc_section == NULL)
-       {
-         asection *tsec;
-
-         tsec = bfd_make_section_anyway (abfd, ".tc");
-         if (tsec == NULL)
-           goto error_return;
-         xcoff_hash_table (info)->toc_section = tsec;
-         tsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
-                         | SEC_IN_MEMORY);
-         tsec->alignment_power = 2;
-       }
-      /* Likewise for the descriptor section.  */
-      if (xcoff_hash_table (info)->descriptor_section == NULL)
-       {
-         asection *dsec;
-
-         dsec = bfd_make_section_anyway (abfd, ".ds");
-         if (dsec == NULL)
-           goto error_return;
-         xcoff_hash_table (info)->descriptor_section = dsec;
-         dsec->flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
-                         | SEC_IN_MEMORY);
-         dsec->alignment_power = 2;
-       }
-      /* Likewise for the .debug section.  */
-      if (xcoff_hash_table (info)->debug_section == NULL
-         && info->strip != strip_all)
-       {
-         asection *dsec;
-
-         dsec = bfd_make_section_anyway (abfd, ".debug");
-         if (dsec == NULL)
-           goto error_return;
-         xcoff_hash_table (info)->debug_section = dsec;
-         dsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
-       }
-    }
+  /* create the loader, toc, gl, ds and debug sections, if needed */
+  if (false == xcoff_link_create_extra_sections(abfd, info)) {
+    goto error_return;
+  }
 
   if ((abfd->flags & DYNAMIC) != 0
       && ! info->static_link)
@@ -1481,7 +1055,7 @@ xcoff_link_add_symbols (abfd, info)
   else
     default_copy = true;
 
-  symcount = obj_raw_syment_count (abfd);
+  symcount = obj_raw_syment_count (abfd); 
 
   /* We keep a list of the linker hash table entries that correspond
      to each external symbol.  */
@@ -1521,37 +1095,40 @@ xcoff_link_add_symbols (abfd, info)
   /* Read in the relocs and line numbers for each section.  */
   linesz = bfd_coff_linesz (abfd);
   last_real = NULL;
-  for (o = abfd->sections; o != NULL; o = o->next)
-    {
-      last_real = o;
-      if ((o->flags & SEC_RELOC) != 0)
-       {
-         reloc_info[o->target_index].relocs =
-           xcoff_read_internal_relocs (abfd, o, true, (bfd_byte *) NULL,
-                                       false, (struct internal_reloc *) NULL);
-         reloc_info[o->target_index].csects =
-           (asection **) bfd_malloc (o->reloc_count * sizeof (asection *));
-         if (reloc_info[o->target_index].csects == NULL)
-           goto error_return;
-         memset (reloc_info[o->target_index].csects, 0,
-                 o->reloc_count * sizeof (asection *));
-       }
+  for (o = abfd->sections; o != NULL; o = o->next) {
 
-      if ((info->strip == strip_none || info->strip == strip_some)
-         && o->lineno_count > 0)
-       {
-         bfd_byte *linenos;
+    last_real = o;
+    if ((o->flags & SEC_RELOC) != 0) {
 
-         linenos = (bfd_byte *) bfd_malloc (o->lineno_count * linesz);
-         if (linenos == NULL)
-           goto error_return;
-         reloc_info[o->target_index].linenos = linenos;
-         if (bfd_seek (abfd, o->line_filepos, SEEK_SET) != 0
-             || (bfd_read (linenos, linesz, o->lineno_count, abfd)
-                 != linesz * o->lineno_count))
-           goto error_return;
-       }
+      reloc_info[o->target_index].relocs =
+       xcoff_read_internal_relocs (abfd, o, true, (bfd_byte *) NULL,
+                                   false, (struct internal_reloc *) NULL);
+      reloc_info[o->target_index].csects =
+       (asection **) bfd_malloc (o->reloc_count * sizeof (asection *));
+      if (reloc_info[o->target_index].csects == NULL)
+       goto error_return;
+      memset (reloc_info[o->target_index].csects, 0,
+             o->reloc_count * sizeof (asection *));
+      
+    }
+
+    if ((info->strip == strip_none || info->strip == strip_some)
+       && o->lineno_count > 0) {
+
+      bfd_byte *linenos;
+
+      linenos = (bfd_byte *) bfd_malloc (o->lineno_count * linesz);
+      if (linenos == NULL)
+       goto error_return;
+      reloc_info[o->target_index].linenos = linenos;
+      if (bfd_seek (abfd, o->line_filepos, SEEK_SET) != 0
+         || (bfd_read (linenos, linesz, o->lineno_count, abfd)
+             != linesz * o->lineno_count))
+       goto error_return;
+      
     }
+  }
+
 
   /* Don't let the linker relocation routines discard the symbols.  */
   obj_coff_keep_syms (abfd) = true;
@@ -1564,48 +1141,57 @@ xcoff_link_add_symbols (abfd, info)
   BFD_ASSERT (symesz == bfd_coff_auxesz (abfd));
   esym = (bfd_byte *) obj_coff_external_syms (abfd);
   esym_end = esym + symcount * symesz;
-  while (esym < esym_end)
-    {
-      struct internal_syment sym;
-      union internal_auxent aux;
-      const char *name;
-      char buf[SYMNMLEN + 1];
-      int smtyp;
-      flagword flags;
-      asection *section;
-      bfd_vma value;
-      struct xcoff_link_hash_entry *set_toc;
 
-      bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
+  while (esym < esym_end) {
+    struct internal_syment sym;
+    union internal_auxent aux;
+    const char *name;
+    char buf[SYMNMLEN + 1];
+    int smtyp;
+    flagword flags;
+    asection *section;
+    bfd_vma value;
+    struct xcoff_link_hash_entry *set_toc;
+
+    bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
+    
+    /* In this pass we are only interested in symbols with csect
+       information.  */
+    if (sym.n_sclass != C_EXT && sym.n_sclass != C_HIDEXT) {
+
+      /*
+       * Set csect_cache, 
+       *   Normally csect is a .pr, .rw  etc. created in the loop
+       *   If C_FILE or first time, handle special
+       * 
+       * Advance esym, sym_hash, csect_hash ptr's
+       * Keep track of the last_symndx for the current file
+       */
+      if (sym.n_sclass == C_FILE && csect != NULL) {
+       xcoff_section_data (abfd, csect)->last_symndx =
+         ((esym
+           - (bfd_byte *) obj_coff_external_syms (abfd))
+          / symesz);
+       csect = NULL;
+      }
 
-      /* In this pass we are only interested in symbols with csect
-         information.  */
-      if (sym.n_sclass != C_EXT && sym.n_sclass != C_HIDEXT)
-       {
-         if (sym.n_sclass == C_FILE && csect != NULL)
-           {
-             xcoff_section_data (abfd, csect)->last_symndx =
-               ((esym
-                 - (bfd_byte *) obj_coff_external_syms (abfd))
-                / symesz);
-             csect = NULL;
-           }
+      if (csect != NULL)
+       *csect_cache = csect;
+      else if (first_csect == NULL || sym.n_sclass == C_FILE)
+       *csect_cache = coff_section_from_bfd_index (abfd, sym.n_scnum);
+      else
+       *csect_cache = NULL;
+      esym += (sym.n_numaux + 1) * symesz;
+      sym_hash += sym.n_numaux + 1;
+      csect_cache += sym.n_numaux + 1;
+      
+      continue;
+    }
 
-         if (csect != NULL)
-           *csect_cache = csect;
-         else if (first_csect == NULL || sym.n_sclass == C_FILE)
-           *csect_cache = coff_section_from_bfd_index (abfd, sym.n_scnum);
-         else
-           *csect_cache = NULL;
-         esym += (sym.n_numaux + 1) * symesz;
-         sym_hash += sym.n_numaux + 1;
-         csect_cache += sym.n_numaux + 1;
-         continue;
-       }
+    name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
 
-      name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
-      if (name == NULL)
-       goto error_return;
+    if (name == NULL)
+      goto error_return;
 
       /* If this symbol has line number information attached to it,
          and we're not stripping it, count the number of entries and
@@ -1613,86 +1199,80 @@ xcoff_link_add_symbols (abfd, info)
          we are going to attach line number information by symbol,
          rather than by section, in order to more easily handle
          garbage collection.  */
-      if ((info->strip == strip_none || info->strip == strip_some)
-         && sym.n_numaux > 1
-         && csect != NULL
-         && ISFCN (sym.n_type))
-       {
-         union internal_auxent auxlin;
-
-         bfd_coff_swap_aux_in (abfd, (PTR) (esym + symesz),
-                               sym.n_type, sym.n_sclass,
-                               0, sym.n_numaux, (PTR) &auxlin);
-         if (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr != 0)
-           {
-             asection *enclosing;
-             bfd_size_type linoff;
-
-             enclosing = xcoff_section_data (abfd, csect)->enclosing;
-             if (enclosing == NULL)
-               {
-                 (*_bfd_error_handler)
-                   (_("%s: `%s' has line numbers but no enclosing section"),
-                    bfd_get_filename (abfd), name);
-                 bfd_set_error (bfd_error_bad_value);
-                 goto error_return;
-               }
-             linoff = (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr
-                       - enclosing->line_filepos);
-             if (linoff < enclosing->lineno_count * linesz)
-               {
-                 struct internal_lineno lin;
-                 bfd_byte *linpstart;
-
-                 linpstart = (reloc_info[enclosing->target_index].linenos
-                              + linoff);
-                 bfd_coff_swap_lineno_in (abfd, (PTR) linpstart, (PTR) &lin);
-                 if (lin.l_lnno == 0
-                     && ((bfd_size_type) lin.l_addr.l_symndx
-                         == ((esym
-                              - (bfd_byte *) obj_coff_external_syms (abfd))
-                             / symesz)))
-                   {
-                     bfd_byte *linpend, *linp;
-
-                     linpend = (reloc_info[enclosing->target_index].linenos
-                                + enclosing->lineno_count * linesz);
-                     for (linp = linpstart + linesz;
-                          linp < linpend;
-                          linp += linesz)
-                       {
-                         bfd_coff_swap_lineno_in (abfd, (PTR) linp,
-                                                  (PTR) &lin);
-                         if (lin.l_lnno == 0)
-                           break;
-                       }
-                     csect->lineno_count += (linp - linpstart) / linesz;
-                     /* The setting of line_filepos will only be
-                         useful if all the line number entries for a
-                         csect are contiguous; this only matters for
-                         error reporting.  */
-                     if (csect->line_filepos == 0)
-                       csect->line_filepos =
-                         auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr;
-                   }
-               }
-           }
-       }
+    if ((info->strip == strip_none || info->strip == strip_some) && 
+       (sym.n_numaux > 1) && 
+       (csect != NULL) && 
+       (ISFCN (sym.n_type))) {
 
-      /* Pick up the csect auxiliary information.  */
+      union internal_auxent auxlin;
 
-      if (sym.n_numaux == 0)
-       {
+      bfd_coff_swap_aux_in (abfd, (PTR) (esym + symesz),
+                           sym.n_type, sym.n_sclass,
+                           0, sym.n_numaux, (PTR) &auxlin);
+
+      if (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr != 0) {
+       asection *enclosing;
+       bfd_signed_vma linoff;
+         
+       enclosing = xcoff_section_data (abfd, csect)->enclosing;
+       if (enclosing == NULL) {
          (*_bfd_error_handler)
-           (_("%s: class %d symbol `%s' has no aux entries"),
-            bfd_get_filename (abfd), sym.n_sclass, name);
+           (_("%s: `%s' has line numbers but no enclosing section"),
+            bfd_get_filename (abfd), name);
          bfd_set_error (bfd_error_bad_value);
          goto error_return;
        }
+       linoff = (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr
+                 - enclosing->line_filepos);
+       /* explict cast to bfd_signed_vma for compiler */
+       if (linoff < (bfd_signed_vma)(enclosing->lineno_count * linesz)) {
+         struct internal_lineno lin;
+         bfd_byte *linpstart;
+
+         linpstart = (reloc_info[enclosing->target_index].linenos
+                      + linoff);
+         bfd_coff_swap_lineno_in (abfd, (PTR) linpstart, (PTR) &lin);
+         if (lin.l_lnno == 0
+             && ((bfd_size_type) lin.l_addr.l_symndx
+                 == ((esym
+                      - (bfd_byte *) obj_coff_external_syms (abfd))
+                     / symesz))) {
+           bfd_byte *linpend, *linp;
+
+           linpend = (reloc_info[enclosing->target_index].linenos
+                      + enclosing->lineno_count * linesz);
+           for (linp = linpstart + linesz; linp < linpend; linp += linesz) {
+             bfd_coff_swap_lineno_in (abfd, (PTR) linp,
+                                      (PTR) &lin);
+             if (lin.l_lnno == 0)
+               break;
+           }
+           csect->lineno_count += (linp - linpstart) / linesz;
+           /* The setting of line_filepos will only be
+              useful if all the line number entries for a
+              csect are contiguous; this only matters for
+              error reporting.  */
+           if (csect->line_filepos == 0)
+             csect->line_filepos =
+               auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr;
+         }
+       }
+      }
+    }
 
-      bfd_coff_swap_aux_in (abfd,
-                           (PTR) (esym + symesz * sym.n_numaux),
-                           sym.n_type, sym.n_sclass,
+    /* Pick up the csect auxiliary information.  */
+
+    if (sym.n_numaux == 0) {
+      (*_bfd_error_handler)
+       (_("%s: class %d symbol `%s' has no aux entries"),
+        bfd_get_filename (abfd), sym.n_sclass, name);
+      bfd_set_error (bfd_error_bad_value);
+      goto error_return;
+    }
+
+    bfd_coff_swap_aux_in (abfd,
+                         (PTR) (esym + symesz * sym.n_numaux),
+                         sym.n_type, sym.n_sclass,
                            sym.n_numaux - 1, sym.n_numaux,
                            (PTR) &aux);
 
@@ -1739,7 +1319,6 @@ xcoff_link_add_symbols (abfd, info)
 
        case XTY_SD:
          /* This is a csect definition.  */
-
          if (csect != NULL)
            {
              xcoff_section_data (abfd, csect)->last_symndx =
@@ -1767,144 +1346,155 @@ xcoff_link_add_symbols (abfd, info)
              xcoff_data (abfd)->toc = sym.n_value;
            }
 
-         /* We must merge TOC entries for the same symbol.  We can
-            merge two TOC entries if they are both C_HIDEXT, they
-            both have the same name, they are both 4 bytes long, and
-            they both have a relocation table entry for an external
-            symbol with the same name.  Unfortunately, this means
-            that we must look through the relocations.  Ick.  */
-         if (aux.x_csect.x_smclas == XMC_TC
-             && sym.n_sclass == C_HIDEXT
-             && aux.x_csect.x_scnlen.l == 4
-             && info->hash->creator == abfd->xvec)
-           {
-             asection *enclosing;
-             struct internal_reloc *relocs;
-             bfd_size_type relindx;
-             struct internal_reloc *rel;
-
-             enclosing = coff_section_from_bfd_index (abfd, sym.n_scnum);
-             if (enclosing == NULL)
-               goto error_return;
-
-             relocs = reloc_info[enclosing->target_index].relocs;
-             relindx = xcoff_find_reloc (relocs, enclosing->reloc_count,
-                                         sym.n_value);
-             rel = relocs + relindx;
-             if (relindx < enclosing->reloc_count
-                 && rel->r_vaddr == (bfd_vma) sym.n_value
-                 && rel->r_size == 31
-                 && rel->r_type == R_POS)
-               {
-                 bfd_byte *erelsym;
-                 struct internal_syment relsym;
-
-                 erelsym = ((bfd_byte *) obj_coff_external_syms (abfd)
-                            + rel->r_symndx * symesz);
-                 bfd_coff_swap_sym_in (abfd, (PTR) erelsym, (PTR) &relsym);
-                 if (relsym.n_sclass == C_EXT)
-                   {
-                     const char *relname;
-                     char relbuf[SYMNMLEN + 1];
-                     boolean copy;
-                     struct xcoff_link_hash_entry *h;
-
-                     /* At this point we know that the TOC entry is
-                        for an externally visible symbol.  */
-                     relname = _bfd_coff_internal_syment_name (abfd, &relsym,
-                                                               relbuf);
-                     if (relname == NULL)
-                       goto error_return;
-
-                     /* We only merge TOC entries if the TC name is
-                         the same as the symbol name.  This handles
-                         the normal case, but not common cases like
-                         SYM.P4 which gcc generates to store SYM + 4
-                         in the TOC.  FIXME.  */
-                     if (strcmp (name, relname) == 0)
-                       {
-                         copy = (! info->keep_memory
-                                 || relsym._n._n_n._n_zeroes != 0
-                                 || relsym._n._n_n._n_offset == 0);
-                         h = xcoff_link_hash_lookup (xcoff_hash_table (info),
-                                                     relname, true, copy,
-                                                     false);
-                         if (h == NULL)
-                           goto error_return;
-
-                         /* At this point h->root.type could be
-                            bfd_link_hash_new.  That should be OK,
-                            since we know for sure that we will come
-                            across this symbol as we step through the
-                            file.  */
+         /* 
+          * We must merge TOC entries for the same symbol.  We can
+          * merge two TOC entries if they are both C_HIDEXT, they
+          * both have the same name, they are both 4 or 8 bytes long, and
+          * they both have a relocation table entry for an external
+          * symbol with the same name.  Unfortunately, this means
+          * that we must look through the relocations.  Ick.  
+          * 
+          * Logic for 32 bit vs 64 bit.
+          * 32 bit has a csect length of 4 for TOC 
+          * 64 bit has a csect length of 8 for TOC
+          * 
+          * The conditions to get past the if-check are not that bad. 
+          * They are what is used to create the TOC csects in the first 
+          * place
+          */
+         if ((aux.x_csect.x_smclas == XMC_TC) && 
+             (sym.n_sclass == C_HIDEXT) &&
+             (info->hash->creator == abfd->xvec) && 
+             (((bfd_xcoff_is_xcoff32(abfd)) && 
+               (aux.x_csect.x_scnlen.l == 4)) || 
+              ((bfd_xcoff_is_xcoff64(abfd)) && 
+               (aux.x_csect.x_scnlen.l == 8)))) {
 
-                         /* We store h in *sym_hash for the
-                            convenience of the relocate_section
-                            function.  */
-                         *sym_hash = h;
+           asection *enclosing;
+           struct internal_reloc *relocs;
+           bfd_size_type relindx;
+           struct internal_reloc *rel;
 
-                         if (h->toc_section != NULL)
-                           {
-                             asection **rel_csects;
-
-                             /* We already have a TOC entry for this
-                                symbol, so we can just ignore this
-                                one.  */
-                             rel_csects =
-                               reloc_info[enclosing->target_index].csects;
-                             rel_csects[relindx] = bfd_und_section_ptr;
-                             break;
-                           }
+           enclosing = coff_section_from_bfd_index (abfd, sym.n_scnum);
+           if (enclosing == NULL)
+             goto error_return;
 
-                         /* We are about to create a TOC entry for
-                            this symbol.  */
-                         set_toc = h;
-                       }
-                   }
-               }
-           }
+           relocs = reloc_info[enclosing->target_index].relocs;
+           relindx = xcoff_find_reloc (relocs, enclosing->reloc_count,
+                                       sym.n_value);
+           rel = relocs + relindx;
+
+             /*
+              * 32 bit R_POS r_size is 31
+              * 64 bit R_POS r_size is 63
+              */
+           if ((relindx < enclosing->reloc_count) &&
+               (rel->r_vaddr == (bfd_vma) sym.n_value) &&
+               (rel->r_type == R_POS) &&
+               (((bfd_xcoff_is_xcoff32(abfd)) && 
+                 (rel->r_size == 31)) ||
+                ((bfd_xcoff_is_xcoff64(abfd)) && 
+                 (rel->r_size == 63)))) {
+
+             bfd_byte *erelsym;
+
+             struct internal_syment relsym;
+
+             erelsym = ((bfd_byte *) obj_coff_external_syms (abfd)
+                        + rel->r_symndx * symesz);
+             bfd_coff_swap_sym_in (abfd, (PTR) erelsym, (PTR) &relsym);
+             if (relsym.n_sclass == C_EXT) {
+               const char *relname;
+               char relbuf[SYMNMLEN + 1];
+               boolean copy;
+               struct xcoff_link_hash_entry *h;
+                   
+               /* At this point we know that the TOC entry is
+                  for an externally visible symbol.  */
+
+               relname = _bfd_coff_internal_syment_name (abfd, &relsym,
+                                                         relbuf);
+               if (relname == NULL)
+                 goto error_return;
+                   
+               /* We only merge TOC entries if the TC name is
+                  the same as the symbol name.  This handles
+                  the normal case, but not common cases like
+                  SYM.P4 which gcc generates to store SYM + 4
+                  in the TOC.  FIXME.  */
+
+               if (strcmp (name, relname) == 0) {
+                 copy = (! info->keep_memory
+                         || relsym._n._n_n._n_zeroes != 0
+                         || relsym._n._n_n._n_offset == 0);
+                 h = xcoff_link_hash_lookup (xcoff_hash_table (info),
+                                             relname, true, copy,
+                                             false);
+                 if (h == NULL)
+                   goto error_return;
+                     
+                 /* At this point h->root.type could be
+                    bfd_link_hash_new.  That should be OK,
+                    since we know for sure that we will come
+                    across this symbol as we step through the
+                    file.  */
+                     
+                 /* We store h in *sym_hash for the
+                    convenience of the relocate_section
+                    function.  */
+                 *sym_hash = h;
+                     
+                 if (h->toc_section != NULL) {
+                   asection **rel_csects;
+                       
+                   /* We already have a TOC entry for this
+                      symbol, so we can just ignore this
+                      one.  */
+                   rel_csects =
+                     reloc_info[enclosing->target_index].csects;
+                   rel_csects[relindx] = bfd_und_section_ptr;
+                   break;
+                 }
+                     
+                 /* We are about to create a TOC entry for
+                    this symbol.  */
+                 set_toc = h;
+               } /* merge toc reloc */
+             } /* c_ext */
+           } /* reloc */
+         } /* merge toc */
 
-         /* We need to create a new section.  We get the name from
-            the csect storage mapping class, so that the linker can
-            accumulate similar csects together.  */
          {
-           static const char *csect_name_by_class[] = {
-             ".pr", ".ro", ".db", ".tc", ".ua", ".rw", ".gl", ".xo",
-             ".sv", ".bs", ".ds", ".uc", ".ti", ".tb", NULL, ".tc0",
-             ".td"
-           };
-           const char *csect_name;
+
            asection *enclosing;
 
-           if ((aux.x_csect.x_smclas >=
-                sizeof csect_name_by_class / sizeof csect_name_by_class[0])
-               || csect_name_by_class[aux.x_csect.x_smclas] == NULL)
-             {
-               (*_bfd_error_handler)
-                 (_("%s: symbol `%s' has unrecognized smclas %d"),
-                  bfd_get_filename (abfd), name, aux.x_csect.x_smclas);
-               bfd_set_error (bfd_error_bad_value);
-               goto error_return;
-             }
+           /* We need to create a new section.  We get the name from
+              the csect storage mapping class, so that the linker can
+              accumulate similar csects together.  */
 
-           csect_name = csect_name_by_class[aux.x_csect.x_smclas];
-           csect = bfd_make_section_anyway (abfd, csect_name);
-           if (csect == NULL)
+           csect = bfd_xcoff_create_csect_from_smclas(abfd, &aux, name);
+           if (NULL == csect) {
              goto error_return;
+           }
+
+           /*
+            * The enclosing section is the main section : .data, .text
+            * or .bss that the csect is coming from
+            */
            enclosing = coff_section_from_bfd_index (abfd, sym.n_scnum);
            if (enclosing == NULL)
              goto error_return;
-           if (! bfd_is_abs_section (enclosing)
-               && ((bfd_vma) sym.n_value < enclosing->vma
-                   || ((bfd_vma) sym.n_value + aux.x_csect.x_scnlen.l
-                       > enclosing->vma + enclosing->_raw_size)))
-             {
-               (*_bfd_error_handler)
-                 (_("%s: csect `%s' not in enclosing section"),
-                  bfd_get_filename (abfd), name);
-               bfd_set_error (bfd_error_bad_value);
-               goto error_return;
-             }
+
+           if (! bfd_is_abs_section (enclosing) && 
+               ((bfd_vma) sym.n_value < enclosing->vma || 
+                ((bfd_vma) sym.n_value + aux.x_csect.x_scnlen.l
+                 > enclosing->vma + enclosing->_raw_size))) {
+             (*_bfd_error_handler)
+               (_("%s: csect `%s' not in enclosing section"),
+                bfd_get_filename (abfd), name);
+             bfd_set_error (bfd_error_bad_value);
+             goto error_return;
+           }
            csect->vma = sym.n_value;
            csect->filepos = (enclosing->filepos
                              + sym.n_value
@@ -1927,33 +1517,34 @@ xcoff_link_add_symbols (abfd, info)
            xcoff_section_data (abfd, csect)->lineno_count =
              enclosing->lineno_count;
 
-           if (enclosing->owner == abfd)
-             {
-               struct internal_reloc *relocs;
-               bfd_size_type relindx;
-               struct internal_reloc *rel;
-               asection **rel_csect;
-
-               relocs = reloc_info[enclosing->target_index].relocs;
-               relindx = xcoff_find_reloc (relocs, enclosing->reloc_count,
-                                           csect->vma);
-               rel = relocs + relindx;
-               rel_csect = (reloc_info[enclosing->target_index].csects
-                            + relindx);
-               csect->rel_filepos = (enclosing->rel_filepos
-                                     + relindx * bfd_coff_relsz (abfd));
-               while (relindx < enclosing->reloc_count
-                      && *rel_csect == NULL
-                      && rel->r_vaddr < csect->vma + csect->_raw_size)
-                 {
-                   *rel_csect = csect;
-                   csect->flags |= SEC_RELOC;
-                   ++csect->reloc_count;
-                   ++relindx;
-                   ++rel;
-                   ++rel_csect;
-                 }
+           if (enclosing->owner == abfd) {
+             struct internal_reloc *relocs;
+             bfd_size_type relindx;
+             struct internal_reloc *rel;
+             asection **rel_csect;
+
+             relocs = reloc_info[enclosing->target_index].relocs;
+             relindx = xcoff_find_reloc (relocs, enclosing->reloc_count,
+                                         csect->vma);
+
+             rel = relocs + relindx;
+             rel_csect = (reloc_info[enclosing->target_index].csects
+                          + relindx);
+
+             csect->rel_filepos = (enclosing->rel_filepos
+                                   + relindx * bfd_coff_relsz (abfd));
+             while (relindx < enclosing->reloc_count && 
+                    *rel_csect == NULL && 
+                    rel->r_vaddr < csect->vma + csect->_raw_size) {
+
+               *rel_csect = csect;
+               csect->flags |= SEC_RELOC;
+               ++csect->reloc_count;
+               ++relindx;
+               ++rel;
+               ++rel_csect;
              }
+           }
 
            /* There are a number of other fields and section flags
               which we do not bother to set.  */
@@ -2030,10 +1621,16 @@ xcoff_link_add_symbols (abfd, info)
                 / symesz);
            }
 
-         if (aux.x_csect.x_smclas == XMC_TD)
-           csect = bfd_make_section_anyway (abfd, ".tocbss");
-         else
+         if (aux.x_csect.x_smclas == XMC_TD) {
+           /*
+            * The linker script puts the .td section in the data 
+            * section after the .tc section 
+            */
+           csect = bfd_make_section_anyway (abfd, ".td");
+
+         } else {
            csect = bfd_make_section_anyway (abfd, ".bss");
+         }
          if (csect == NULL)
            goto error_return;
          csect->vma = sym.n_value;
@@ -2072,32 +1669,31 @@ xcoff_link_add_symbols (abfd, info)
        }
 
       /* Check for magic symbol names.  */
-      if ((smtyp == XTY_SD || smtyp == XTY_CM)
-         && aux.x_csect.x_smclas != XMC_TC
-         && aux.x_csect.x_smclas != XMC_TD)
-       {
-         int i;
-
-         i = -1;
-         if (name[0] == '_')
-           {
-             if (strcmp (name, "_text") == 0)
-               i = 0;
-             else if (strcmp (name, "_etext") == 0)
-               i = 1;
-             else if (strcmp (name, "_data") == 0)
-               i = 2;
-             else if (strcmp (name, "_edata") == 0)
-               i = 3;
-             else if (strcmp (name, "_end") == 0)
-               i = 4;
-           }
-         else if (name[0] == 'e' && strcmp (name, "end") == 0)
-           i = 5;
-
-         if (i != -1)
-           xcoff_hash_table (info)->special_sections[i] = csect;
-       }
+      if ((smtyp == XTY_SD || smtyp == XTY_CM) && 
+         (aux.x_csect.x_smclas != XMC_TC) && 
+         (aux.x_csect.x_smclas != XMC_TD)) {
+
+       int i = -1;
+
+       if (name[0] == '_') {
+         if (strcmp (name, "_text") == 0)
+           i = XCOFF_SPECIAL_SECTION_TEXT;
+         else if (strcmp (name, "_etext") == 0)
+           i = XCOFF_SPECIAL_SECTION_ETEXT;
+         else if (strcmp (name, "_data") == 0)
+           i = XCOFF_SPECIAL_SECTION_DATA;
+         else if (strcmp (name, "_edata") == 0)
+           i = XCOFF_SPECIAL_SECTION_EDATA;
+         else if (strcmp (name, "_end") == 0)
+           i = XCOFF_SPECIAL_SECTION_END;
+       } else if (name[0] == 'e' && strcmp (name, "end") == 0) {
+         i = XCOFF_SPECIAL_SECTION_END2;
+       } 
+       
+       if (i != -1) {
+         xcoff_hash_table (info)->special_sections[i] = csect;
+       } 
+      }
 
       /* Now we have enough information to add the symbol to the
          linker hash table.  */
@@ -2140,7 +1736,7 @@ xcoff_link_add_symbols (abfd, info)
             shared object, which will cause symbol redefinitions,
             although this is an easier case to detect.  */
 
-         if (info->hash->creator == abfd->xvec)
+         if (info->hash->creator == abfd->xvec) 
            {
              if (! bfd_is_und_section (section))
                *sym_hash = xcoff_link_hash_lookup (xcoff_hash_table (info),
@@ -2262,11 +1858,11 @@ xcoff_link_add_symbols (abfd, info)
              else
                {
                  (*sym_hash)->root.u.c.p->alignment_power
-                   = csect->alignment_power;
+                    = csect->alignment_power;
                }
            }
 
-         if (info->hash->creator == abfd->xvec)
+         if (info->hash->creator == abfd->xvec) 
            {
              int flag;
 
@@ -2310,8 +1906,10 @@ xcoff_link_add_symbols (abfd, info)
 
          rel = reloc_info[o->target_index].relocs;
          rel_csect = reloc_info[o->target_index].csects;
+
          for (i = 0; i < o->reloc_count; i++, rel++, rel_csect++)
            {
+
              if (*rel_csect == NULL)
                {
                  (*_bfd_error_handler)
@@ -2324,7 +1922,7 @@ xcoff_link_add_symbols (abfd, info)
              /* We identify all symbols which are called, so that we
                 can create glue code for calls to functions imported
                 from dynamic objects.  */
-             if (info->hash->creator == abfd->xvec
+             if (info->hash->creator == abfd->xvec 
                  && *rel_csect != bfd_und_section_ptr
                  && (rel->r_type == R_BR
                      || rel->r_type == R_RBR)
@@ -2377,7 +1975,7 @@ xcoff_link_add_symbols (abfd, info)
 
          /* Reset SEC_RELOC and the reloc_count, since the reloc
             information is now attached to the csects.  */
-         o->flags &= ~SEC_RELOC;
+         o->flags &=SEC_RELOC;
          o->reloc_count = 0;
 
          /* If we are not keeping memory, free the reloc information.  */
@@ -2434,10 +2032,10 @@ xcoff_link_add_dynamic_symbols (abfd, info)
      struct bfd_link_info *info;
 {
   asection *lsec;
-  bfd_byte *buf;
+  bfd_byte *contents;
   struct internal_ldhdr ldhdr;
   const char *strings;
-  struct external_ldsym *elsym, *elsymend;
+  bfd_byte *elsym, *elsymend;
   struct xcoff_import_file *n;
   const char *bname;
   const char *mname;
@@ -2447,15 +2045,15 @@ xcoff_link_add_dynamic_symbols (abfd, info)
 
   /* We can only handle a dynamic object if we are generating an XCOFF
      output file.  */
-  if (info->hash->creator != abfd->xvec)
+   if (info->hash->creator != abfd->xvec) 
     {
       (*_bfd_error_handler)
        (_("%s: XCOFF shared object when not producing XCOFF output"),
         bfd_get_filename (abfd));
-      bfd_set_error (bfd_error_invalid_operation);
+      bfd_set_error (bfd_error_invalid_operation); 
       return false;
     }
-
+  
   /* The symbols we use from a dynamic object are not the symbols in
      the normal symbol table, but, rather, the symbols in the export
      table.  If there is a global symbol in a dynamic object which is
@@ -2477,29 +2075,31 @@ xcoff_link_add_dynamic_symbols (abfd, info)
       return false;
     }
 
+
   if (! xcoff_get_section_contents (abfd, lsec))
     return false;
-  buf = coff_section_data (abfd, lsec)->contents;
+  contents = coff_section_data (abfd, lsec)->contents;
 
   /* Remove the sections from this object, so that they do not get
      included in the link.  */
   abfd->sections = NULL;
 
-  xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) buf, &ldhdr);
+  bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);
+
+  strings = (char *) contents + ldhdr.l_stoff;
+
+  elsym = contents + bfd_xcoff_loader_symbol_offset(abfd, &ldhdr);
 
-  strings = (char *) buf + ldhdr.l_stoff;
+  elsymend = elsym + ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
 
-  elsym = (struct external_ldsym *) (buf + LDHDRSZ);
-  elsymend = elsym + ldhdr.l_nsyms;
-  BFD_ASSERT (sizeof (struct external_ldsym) == LDSYMSZ);
-  for (; elsym < elsymend; elsym++)
+  for (; elsym < elsymend; elsym += bfd_xcoff_ldsymsz(abfd))
     {
       struct internal_ldsym ldsym;
       char nambuf[SYMNMLEN + 1];
       const char *name;
       struct xcoff_link_hash_entry *h;
 
-      xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
+      bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
 
       /* We are only interested in exported symbols.  */
       if ((ldsym.l_smtype & L_EXPORT) == 0)
@@ -2618,7 +2218,7 @@ xcoff_link_add_dynamic_symbols (abfd, info)
        }
     }
 
-  if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
+  if (contents != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
     {
       free (coff_section_data (abfd, lsec)->contents);
       coff_section_data (abfd, lsec)->contents = NULL;
@@ -2676,6 +2276,7 @@ xcoff_mark_symbol (info, h)
      struct bfd_link_info *info;
      struct xcoff_link_hash_entry *h;
 {
+
   if ((h->flags & XCOFF_MARK) != 0)
     return true;
 
@@ -3150,28 +2751,6 @@ bfd_xcoff_record_link_assignment (output_bfd, info, name)
   return true;
 }
 
-/* This structure is used to pass information through
-   xcoff_link_hash_traverse.  */
-
-struct xcoff_loader_info {
-  /* Set if a problem occurred.  */
-  boolean failed;
-  /* Output BFD.  */
-  bfd *output_bfd;
-  /* Link information structure.  */
-  struct bfd_link_info *info;
-  /* Whether all defined symbols should be exported.  */
-  boolean export_defineds;
-  /* Number of ldsym structures.  */
-  size_t ldsym_count;
-  /* Size of string table.  */
-  size_t string_size;
-  /* String table.  */
-  bfd_byte *strings;
-  /* Allocated size of string table.  */
-  size_t string_alc;
-};
-
 /* Build the .loader section.  This is called by the XCOFF linker
    emulation before_allocation routine.  We must set the size of the
    .loader section before the linker lays out the output file.
@@ -3221,12 +2800,12 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
   struct bfd_strtab_hash *debug_strtab;
   bfd_byte *debug_contents = NULL;
 
-  if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
-    {
-      for (i = 0; i < 6; i++)
-       special_sections[i] = NULL;
-      return true;
-    }
+  if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour) {
+
+    for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++)
+      special_sections[i] = NULL;
+    return true;
+  }
 
   ldinfo.failed = false;
   ldinfo.output_bfd = output_bfd;
@@ -3244,16 +2823,79 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
   xcoff_hash_table (info)->file_align = file_align;
   xcoff_hash_table (info)->textro = textro;
 
-  if (entry == NULL)
+  if (entry == NULL) {
     hentry = NULL;
-  else
-    {
-      hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
-                                      false, false, true);
-      if (hentry != NULL)
-       hentry->flags |= XCOFF_ENTRY;
+  } else {
+    hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
+                                    false, false, true);
+    if (hentry != NULL)
+      hentry->flags |= XCOFF_ENTRY;
+  }
+
+  /* __rtinit */
+  if (info->init_function || info->fini_function) {
+    struct xcoff_link_hash_entry *hrtinit;
+    struct internal_ldsym *ldsym;
+
+    hrtinit = xcoff_link_hash_lookup (xcoff_hash_table (info), 
+                                     "__rtinit",
+                                     false, false, true);
+    if (hrtinit != NULL) {
+      xcoff_mark_symbol (info, hrtinit);
+      hrtinit->flags |= (XCOFF_DEF_REGULAR | XCOFF_RTINIT);
+    } else {
+      (*_bfd_error_handler)
+       (_("error: undefined symbol __rtinit"));
+      
+      return false;
+    }
+
+    /*
+     * 
+     * __rtinit initalized here 
+     * Some information, like the location of the .initfini seciton will
+     * be filled in later
+     *
+     * name or offset taken case of below with bfd_xcoff_put_ldsymbol_name 
+     */
+    ldsym = (struct internal_ldsym *) 
+      bfd_malloc(sizeof (struct internal_ldsym));
+    
+    ldsym->l_value = 0;                  /* will be filled in later */
+    ldsym->l_scnum = 2;                  /* data section */
+    ldsym->l_smtype = XTY_SD;            /* csect section definition */
+    ldsym->l_smclas = 5;                 /* .rw */
+    ldsym->l_ifile = 0;                  /* special system loader symbol */
+    ldsym->l_parm = 0;                   /* NA */
+    
+    /* 
+     * Force __rtinit to be the first symbol in the loader symbol table
+     * See xcoff_build_ldsyms 
+     *
+     * The first 3 symbol table indices are reserved to indicate the data, 
+     * text and bss sections.  
+     */
+    BFD_ASSERT (0 == ldinfo.ldsym_count);
+    
+    hrtinit->ldindx = 3;
+    ldinfo.ldsym_count = 1;
+    hrtinit->ldsym = ldsym;
+    
+    if (false == bfd_xcoff_put_ldsymbol_name (ldinfo.output_bfd, &ldinfo,
+                                             hrtinit->ldsym, 
+                                             hrtinit->root.root.string)) {
+      return false;
     }
 
+    /* 
+     * This symbol is written out by xcoff_write_global_symbol 
+     * Set stuff up so xcoff_write_global_symbol logic works.
+     */
+    hrtinit->flags |= XCOFF_DEF_REGULAR | XCOFF_MARK;
+    hrtinit->root.type = bfd_link_hash_defined;
+    hrtinit->root.u.def.value = 0; 
+  }
+
   /* Garbage collect unused sections.  */
   if (info->relocateable
       || ! gc
@@ -3289,23 +2931,22 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
     }
 
   /* Return special sections to the caller.  */
-  for (i = 0; i < 6; i++)
-    {
-      asection *sec;
-
-      sec = xcoff_hash_table (info)->special_sections[i];
-      if (sec != NULL
-         && gc
-         && (sec->flags & SEC_MARK) == 0)
-       sec = NULL;
-      special_sections[i] = sec;
+  for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++) {
+    asection *sec;
+    
+    sec = xcoff_hash_table (info)->special_sections[i];
+
+    if ((sec != NULL) && 
+       (gc && (sec->flags & SEC_MARK) == 0)) {
+      sec = NULL;
     }
+    special_sections[i] = sec;
+  }
 
-  if (info->input_bfds == NULL)
-    {
-      /* I'm not sure what to do in this bizarre case.  */
-      return true;
-    }
+  if (info->input_bfds == NULL) {
+    /* I'm not sure what to do in this bizarre case.  */
+    return true;
+  }
 
   xcoff_link_hash_traverse (xcoff_hash_table (info), xcoff_build_ldsyms,
                            (PTR) &ldinfo);
@@ -3331,14 +2972,14 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
 
   /* Set up the .loader section header.  */
   ldhdr = &xcoff_hash_table (info)->ldhdr;
-  ldhdr->l_version = 1;
+  ldhdr->l_version = bfd_xcoff_ldhdr_version(output_bfd);
   ldhdr->l_nsyms = ldinfo.ldsym_count;
   ldhdr->l_nreloc = xcoff_hash_table (info)->ldrel_count;
   ldhdr->l_istlen = impsize;
   ldhdr->l_nimpid = impcount;
-  ldhdr->l_impoff = (LDHDRSZ
-                    + ldhdr->l_nsyms * LDSYMSZ
-                    + ldhdr->l_nreloc * LDRELSZ);
+  ldhdr->l_impoff = (bfd_xcoff_ldhdrsz(output_bfd)
+                    + ldhdr->l_nsyms * bfd_xcoff_ldsymsz(output_bfd)
+                    + ldhdr->l_nreloc * bfd_xcoff_ldrelsz(output_bfd));
   ldhdr->l_stlen = ldinfo.string_size;
   stoff = ldhdr->l_impoff + impsize;
   if (ldinfo.string_size == 0)
@@ -3346,6 +2987,15 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
   else
     ldhdr->l_stoff = stoff;
 
+  /* 
+   * 64 bit elements to ldhdr
+   * The swap out routine for 32 bit will ignore them.
+   * Nothing fancy, symbols come after the header and relocs come after symbols
+   */
+  ldhdr->l_symoff = bfd_xcoff_ldhdrsz(output_bfd);
+  ldhdr->l_rldoff = bfd_xcoff_ldhdrsz(output_bfd) + 
+    (ldhdr->l_nsyms * bfd_xcoff_ldsymsz(output_bfd));
+
   /* We now know the final size of the .loader section.  Allocate
      space for it.  */
   lsec = xcoff_hash_table (info)->loader_section;
@@ -3355,8 +3005,7 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
     goto error_return;
 
   /* Set up the header.  */
-  xcoff_swap_ldhdr_out (output_bfd, ldhdr,
-                       (struct external_ldhdr *) lsec->contents);
+  bfd_xcoff_swap_ldhdr_out (output_bfd, ldhdr, lsec->contents);
 
   /* Set up the import file names.  */
   out = (char *) lsec->contents + ldhdr->l_impoff;
@@ -3395,7 +3044,8 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
      symbols are written out in xcoff_link_input_bfd or
      xcoff_write_global_symbol.  The .loader relocs are written out
      when the corresponding normal relocs are handled in
-     xcoff_link_input_bfd.  */
+     xcoff_link_input_bfd.  
+  */
 
   /* Allocate space for the magic sections.  */
   sec = xcoff_hash_table (info)->linkage_section;
@@ -3540,7 +3190,15 @@ xcoff_build_ldsyms (h, p)
      PTR p;
 {
   struct xcoff_loader_info *ldinfo = (struct xcoff_loader_info *) p;
-  size_t len;
+  
+  /*
+   * __rtinit 
+   * Special handling of this symbol to make is the first symbol in the
+   * loader symbol table.  Make sure this pass through does not undo it
+   */
+  if (h->flags & XCOFF_RTINIT) {
+    return true;
+  }
 
   /* If this is a final link, and the symbol was defined as a common
      symbol in a regular object file, and there was no definition in
@@ -3638,7 +3296,7 @@ xcoff_build_ldsyms (h, p)
       h->root.u.def.value = sec->_raw_size;
       h->smclas = XMC_GL;
       h->flags |= XCOFF_DEF_REGULAR;
-      sec->_raw_size += XCOFF_GLINK_SIZE;
+      sec->_raw_size += bfd_xcoff_glink_code_size(ldinfo->output_bfd);
 
       /* The global linkage code requires a TOC entry for the
          descriptor.  */
@@ -3647,20 +3305,36 @@ xcoff_build_ldsyms (h, p)
                   || hds->root.type == bfd_link_hash_undefweak)
                  && (hds->flags & XCOFF_DEF_REGULAR) == 0);
       hds->flags |= XCOFF_MARK;
-      if (hds->toc_section == NULL)
-       {
-         hds->toc_section = xcoff_hash_table (ldinfo->info)->toc_section;
-         hds->u.toc_offset = hds->toc_section->_raw_size;
-         hds->toc_section->_raw_size += 4;
-         ++xcoff_hash_table (ldinfo->info)->ldrel_count;
-         ++hds->toc_section->reloc_count;
-         hds->indx = -2;
-         hds->flags |= XCOFF_SET_TOC | XCOFF_LDREL;
-
-         /* We need to call xcoff_build_ldsyms recursively here,
-             because we may already have passed hds on the traversal.  */
-         xcoff_build_ldsyms (hds, p);
+      if (hds->toc_section == NULL) {
+       int byte_size;
+
+       /*
+        * 32 vs 64
+        * xcoff32 uses 4 bytes in the toc
+        * xcoff64 uses 8 bytes in the toc
+        */
+       if (bfd_xcoff_is_xcoff64(ldinfo->output_bfd)) {
+         byte_size = 8;
+       } else if (bfd_xcoff_is_xcoff32(ldinfo->output_bfd)) {
+         byte_size = 4;
+       } else {
+         return false;
        }
+
+       hds->toc_section = xcoff_hash_table (ldinfo->info)->toc_section;
+       hds->u.toc_offset = hds->toc_section->_raw_size;
+       hds->toc_section->_raw_size += byte_size;
+       ++xcoff_hash_table (ldinfo->info)->ldrel_count;
+       ++hds->toc_section->reloc_count;
+       hds->indx = -2;
+       hds->flags |= XCOFF_SET_TOC | XCOFF_LDREL;
+
+       /* 
+        * We need to call xcoff_build_ldsyms recursively here,
+        * because we may already have passed hds on the traversal.  
+        */
+       xcoff_build_ldsyms (hds, p);
+      }
     }
 
   /* If this symbol is exported, but not defined, we need to try to
@@ -3689,15 +3363,25 @@ xcoff_build_ldsyms (h, p)
          h->root.u.def.value = sec->_raw_size;
          h->smclas = XMC_DS;
          h->flags |= XCOFF_DEF_REGULAR;
-         sec->_raw_size += 12;
 
-         /* A function descriptor uses two relocs: one for the
-             associated code, and one for the TOC address.  */
+         /*
+          * The size of the function descriptor depends if this is an
+          * xcoff32 (12) or xcoff64 (24)
+          */
+         sec->_raw_size += 
+           bfd_xcoff_function_descriptor_size(ldinfo->output_bfd);
+
+         /* 
+          * A function descriptor uses two relocs: one for the
+           * associated code, and one for the TOC address.  
+          */
          xcoff_hash_table (ldinfo->info)->ldrel_count += 2;
          sec->reloc_count += 2;
 
-         /* We handle writing out the contents of the descriptor in
-             xcoff_write_global_symbol.  */
+         /* 
+          * We handle writing out the contents of the descriptor in
+           * xcoff_write_global_symbol.  
+          */
        }
       else
        {
@@ -3766,46 +3450,19 @@ xcoff_build_ldsyms (h, p)
   if ((h->flags & XCOFF_IMPORT) != 0)
     h->ldsym->l_ifile = h->ldindx;
 
-  /* The first 3 symbol table indices are reserved to indicate the
-     sections.  */
+  /* 
+   * The first 3 symbol table indices are reserved to indicate the data, 
+   * text and bss sections.  
+   */
   h->ldindx = ldinfo->ldsym_count + 3;
 
   ++ldinfo->ldsym_count;
 
-  len = strlen (h->root.root.string);
-  if (len <= SYMNMLEN)
-    strncpy (h->ldsym->_l._l_name, h->root.root.string, SYMNMLEN);
-  else
-    {
-      if (ldinfo->string_size + len + 3 > ldinfo->string_alc)
-       {
-         size_t newalc;
-         bfd_byte *newstrings;
-
-         newalc = ldinfo->string_alc * 2;
-         if (newalc == 0)
-           newalc = 32;
-         while (ldinfo->string_size + len + 3 > newalc)
-           newalc *= 2;
-
-         newstrings = ((bfd_byte *)
-                       bfd_realloc ((PTR) ldinfo->strings, newalc));
-         if (newstrings == NULL)
-           {
-             ldinfo->failed = true;
-             return false;
-           }
-         ldinfo->string_alc = newalc;
-         ldinfo->strings = newstrings;
-       }
-
-      bfd_put_16 (ldinfo->output_bfd, len + 1,
-                 ldinfo->strings + ldinfo->string_size);
-      strcpy (ldinfo->strings + ldinfo->string_size + 2, h->root.root.string);
-      h->ldsym->_l._l_l._l_zeroes = 0;
-      h->ldsym->_l._l_l._l_offset = ldinfo->string_size + 2;
-      ldinfo->string_size += len + 3;
-    }
+  if (false == bfd_xcoff_put_ldsymbol_name (ldinfo->output_bfd, ldinfo,
+                                           h->ldsym, 
+                                           h->root.root.string)) {
+    return false;
+  }
 
   h->flags |= XCOFF_BUILT_LDSYM;
 
@@ -3854,13 +3511,11 @@ _bfd_xcoff_bfd_final_link (abfd, info)
   finfo.contents = NULL;
   finfo.external_relocs = NULL;
 
-  finfo.ldsym = ((struct external_ldsym *)
-                (xcoff_hash_table (info)->loader_section->contents
-                 + LDHDRSZ));
-  finfo.ldrel = ((struct external_ldrel *)
-                (xcoff_hash_table (info)->loader_section->contents
-                 + LDHDRSZ
-                 + xcoff_hash_table (info)->ldhdr.l_nsyms * LDSYMSZ));
+  finfo.ldsym = xcoff_hash_table (info)->loader_section->contents + 
+    bfd_xcoff_ldhdrsz(abfd);
+  finfo.ldrel = xcoff_hash_table (info)->loader_section->contents + 
+    bfd_xcoff_ldhdrsz(abfd) + 
+    xcoff_hash_table (info)->ldhdr.l_nsyms * bfd_xcoff_ldsymsz(abfd);
 
   xcoff_data (abfd)->coff.link_info = info;
 
@@ -3980,10 +3635,16 @@ _bfd_xcoff_bfd_final_link (abfd, info)
          sofar = bfd_coff_filhsz (abfd);
          sofar += bfd_coff_aoutsz (abfd);
          sofar += abfd->section_count * bfd_coff_scnhsz (abfd);
-         for (o = abfd->sections; o != NULL; o = o->next)
-           if (o->reloc_count >= 0xffff || o->lineno_count >= 0xffff)
-             sofar += bfd_coff_scnhsz (abfd);
+         for (o = abfd->sections; o != NULL; o = o->next) {
+           if ((true == 
+                bfd_xcoff_is_reloc_count_overflow(abfd, o->reloc_count)) ||
+               (true == 
+                bfd_xcoff_is_lineno_count_overflow(abfd, o->lineno_count))) {
 
+             /* 64 does not overflow, need to check if 32 does */
+             sofar += bfd_coff_scnhsz (abfd);
+           }
+         }
          for (o = abfd->sections; o != NULL; o = o->next)
            {
              if (strcmp (o->name, ".pad") == 0)
@@ -4125,6 +3786,7 @@ _bfd_xcoff_bfd_final_link (abfd, info)
   finfo.internal_syms = ((struct internal_syment *)
                         bfd_malloc (max_sym_count
                                     * sizeof (struct internal_syment)));
+
   finfo.sym_indices = (long *) bfd_malloc (max_sym_count * sizeof (long));
   finfo.outsyms = ((bfd_byte *)
                   bfd_malloc ((size_t) ((max_sym_count + 1) * symesz)));
@@ -4177,48 +3839,53 @@ _bfd_xcoff_bfd_final_link (abfd, info)
        }
     }
 
+
   /* Free up the buffers used by xcoff_link_input_bfd.  */
 
-  if (finfo.internal_syms != NULL)
-    {
-      free (finfo.internal_syms);
-      finfo.internal_syms = NULL;
-    }
-  if (finfo.sym_indices != NULL)
-    {
-      free (finfo.sym_indices);
-      finfo.sym_indices = NULL;
-    }
-  if (finfo.linenos != NULL)
-    {
-      free (finfo.linenos);
-      finfo.linenos = NULL;
-    }
-  if (finfo.contents != NULL)
-    {
-      free (finfo.contents);
-      finfo.contents = NULL;
-    }
-  if (finfo.external_relocs != NULL)
-    {
-      free (finfo.external_relocs);
-      finfo.external_relocs = NULL;
-    }
+  if (finfo.internal_syms != NULL) {
+    free (finfo.internal_syms);
+    finfo.internal_syms = NULL;
+  }
+  if (finfo.sym_indices != NULL) {
+    free (finfo.sym_indices);
+    finfo.sym_indices = NULL;
+  }
+  if (finfo.linenos != NULL) {
+    free (finfo.linenos);
+    finfo.linenos = NULL;
+  }
+  if (finfo.contents != NULL) {
+    free (finfo.contents);
+    finfo.contents = NULL;
+  }
+  if (finfo.external_relocs != NULL) {
+    free (finfo.external_relocs);
+    finfo.external_relocs = NULL;
+  }
 
   /* The value of the last C_FILE symbol is supposed to be -1.  Write
      it out again.  */
-  if (finfo.last_file_index != -1)
-    {
-      finfo.last_file.n_value = -1;
-      bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,
-                            (PTR) finfo.outsyms);
-      if (bfd_seek (abfd,
-                   (obj_sym_filepos (abfd)
-                    + finfo.last_file_index * symesz),
-                   SEEK_SET) != 0
-         || bfd_write (finfo.outsyms, symesz, 1, abfd) != symesz)
-       goto error_return;
-    }
+  if (finfo.last_file_index != -1) {
+    finfo.last_file.n_value = -1;
+    bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,
+                          (PTR) finfo.outsyms);
+    if (bfd_seek (abfd,
+                 (obj_sym_filepos (abfd)
+                  + finfo.last_file_index * symesz),
+                 SEEK_SET) != 0
+       || bfd_write (finfo.outsyms, symesz, 1, abfd) != symesz)
+      goto error_return;
+  }
+
+  /* init-fini */
+  if (info->init_function || info->fini_function) {
+    struct xcoff_link_hash_entry *hrtinit;
+
+    hrtinit = xcoff_link_hash_lookup (xcoff_hash_table (info), 
+                                     "__rtinit",
+                                     false, false, true);
+  }
+
 
   /* Write out all the global symbols which do not come from XCOFF
      input files.  */
@@ -4239,100 +3906,90 @@ _bfd_xcoff_bfd_final_link (abfd, info)
   if (external_relocs == NULL && max_output_reloc_count != 0)
     goto error_return;
 
-  for (o = abfd->sections; o != NULL; o = o->next)
-    {
-      struct internal_reloc *irel;
-      struct internal_reloc *irelend;
-      struct xcoff_link_hash_entry **rel_hash;
-      struct xcoff_toc_rel_hash *toc_rel_hash;
-      bfd_byte *erel;
-
-      /* A stripped file has no relocs.  */
-      if (info->strip == strip_all)
-       {
-         o->reloc_count = 0;
-         continue;
-       }
-
-      if (o->reloc_count == 0)
-       continue;
-
-      irel = finfo.section_info[o->target_index].relocs;
-      irelend = irel + o->reloc_count;
-      rel_hash = finfo.section_info[o->target_index].rel_hashes;
-      for (; irel < irelend; irel++, rel_hash++, erel += relsz)
-       {
-         if (*rel_hash != NULL)
-           {
-             if ((*rel_hash)->indx < 0)
-               {
-                 if (! ((*info->callbacks->unattached_reloc)
-                        (info, (*rel_hash)->root.root.string,
-                         (bfd *) NULL, o, irel->r_vaddr)))
-                   goto error_return;
-                 (*rel_hash)->indx = 0;
-               }
-             irel->r_symndx = (*rel_hash)->indx;
-           }
-       }
-
-      for (toc_rel_hash = finfo.section_info[o->target_index].toc_rel_hashes;
-          toc_rel_hash != NULL;
-          toc_rel_hash = toc_rel_hash->next)
-       {
-         if (toc_rel_hash->h->u.toc_indx < 0)
-           {
-             if (! ((*info->callbacks->unattached_reloc)
-                    (info, toc_rel_hash->h->root.root.string,
-                     (bfd *) NULL, o, toc_rel_hash->rel->r_vaddr)))
-               goto error_return;
-             toc_rel_hash->h->u.toc_indx = 0;
-           }
-         toc_rel_hash->rel->r_symndx = toc_rel_hash->h->u.toc_indx;
+  for (o = abfd->sections; o != NULL; o = o->next) {
+    struct internal_reloc *irel;
+    struct internal_reloc *irelend;
+    struct xcoff_link_hash_entry **rel_hash;
+    struct xcoff_toc_rel_hash *toc_rel_hash;
+    bfd_byte *erel;
+    
+    /* A stripped file has no relocs.  */
+    if (info->strip == strip_all) {
+      o->reloc_count = 0;
+      continue;
+    }
+    
+    if (o->reloc_count == 0)
+      continue;
+
+    irel = finfo.section_info[o->target_index].relocs;
+    irelend = irel + o->reloc_count;
+    rel_hash = finfo.section_info[o->target_index].rel_hashes;
+    for (; irel < irelend; irel++, rel_hash++, erel += relsz) {
+      if (*rel_hash != NULL) {
+       if ((*rel_hash)->indx < 0) {
+         if (! ((*info->callbacks->unattached_reloc)
+                (info, (*rel_hash)->root.root.string,
+                 (bfd *) NULL, o, irel->r_vaddr)))
+           goto error_return;
+         (*rel_hash)->indx = 0;
        }
-
-      /* XCOFF requires that the relocs be sorted by address.  We tend
-         to produce them in the order in which their containing csects
-         appear in the symbol table, which is not necessarily by
-         address.  So we sort them here.  There may be a better way to
-         do this.  */
-      qsort ((PTR) finfo.section_info[o->target_index].relocs,
-            o->reloc_count, sizeof (struct internal_reloc),
-            xcoff_sort_relocs);
-
-      irel = finfo.section_info[o->target_index].relocs;
-      irelend = irel + o->reloc_count;
-      erel = external_relocs;
-      for (; irel < irelend; irel++, rel_hash++, erel += relsz)
-       bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);
-
-      if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
-         || bfd_write ((PTR) external_relocs, relsz, o->reloc_count,
-                       abfd) != relsz * o->reloc_count)
-       goto error_return;
+       irel->r_symndx = (*rel_hash)->indx;
+      }
     }
 
-  if (external_relocs != NULL)
-    {
-      free (external_relocs);
-      external_relocs = NULL;
+    for (toc_rel_hash = finfo.section_info[o->target_index].toc_rel_hashes;
+        toc_rel_hash != NULL;
+        toc_rel_hash = toc_rel_hash->next) {
+      if (toc_rel_hash->h->u.toc_indx < 0) {
+       if (! ((*info->callbacks->unattached_reloc)
+              (info, toc_rel_hash->h->root.root.string,
+               (bfd *) NULL, o, toc_rel_hash->rel->r_vaddr)))
+         goto error_return;
+       toc_rel_hash->h->u.toc_indx = 0;
+      }
+      toc_rel_hash->rel->r_symndx = toc_rel_hash->h->u.toc_indx;
     }
 
+    /* XCOFF requires that the relocs be sorted by address.  We tend
+       to produce them in the order in which their containing csects
+       appear in the symbol table, which is not necessarily by
+       address.  So we sort them here.  There may be a better way to
+       do this.  */
+    qsort ((PTR) finfo.section_info[o->target_index].relocs,
+          o->reloc_count, sizeof (struct internal_reloc),
+          xcoff_sort_relocs);
+    
+    irel = finfo.section_info[o->target_index].relocs;
+    irelend = irel + o->reloc_count;
+    erel = external_relocs;
+    for (; irel < irelend; irel++, rel_hash++, erel += relsz)
+      bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);
+
+    if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
+       || bfd_write ((PTR) external_relocs, relsz, o->reloc_count,
+                     abfd) != relsz * o->reloc_count)
+      goto error_return;
+  }
+
+  if (external_relocs != NULL) {
+    free (external_relocs);
+    external_relocs = NULL;
+  }
+
   /* Free up the section information.  */
-  if (finfo.section_info != NULL)
-    {
-      unsigned int i;
+  if (finfo.section_info != NULL) {
+    unsigned int i;
 
-      for (i = 0; i < abfd->section_count; i++)
-       {
-         if (finfo.section_info[i].relocs != NULL)
-           free (finfo.section_info[i].relocs);
-         if (finfo.section_info[i].rel_hashes != NULL)
-           free (finfo.section_info[i].rel_hashes);
-       }
-      free (finfo.section_info);
-      finfo.section_info = NULL;
+    for (i = 0; i < abfd->section_count; i++) {
+      if (finfo.section_info[i].relocs != NULL)
+       free (finfo.section_info[i].relocs);
+      if (finfo.section_info[i].rel_hashes != NULL)
+       free (finfo.section_info[i].rel_hashes);
     }
+    free (finfo.section_info);
+    finfo.section_info = NULL;
+  }
 
   /* Write out the loader section contents.  */
   BFD_ASSERT ((bfd_byte *) finfo.ldrel
@@ -4379,43 +4036,42 @@ _bfd_xcoff_bfd_final_link (abfd, info)
 
   /* Write out the debugging string table.  */
   o = xcoff_hash_table (info)->debug_section;
-  if (o != NULL)
-    {
-      struct bfd_strtab_hash *debug_strtab;
-
-      debug_strtab = xcoff_hash_table (info)->debug_strtab;
-      BFD_ASSERT (o->output_section->_raw_size - o->output_offset
-                 >= _bfd_stringtab_size (debug_strtab));
-      if (bfd_seek (abfd,
-                   o->output_section->filepos + o->output_offset,
-                   SEEK_SET) != 0)
-       goto error_return;
-      if (! _bfd_stringtab_emit (abfd, debug_strtab))
-       goto error_return;
-    }
-
+  if (o != NULL) {
+    struct bfd_strtab_hash *debug_strtab;
+    
+    debug_strtab = xcoff_hash_table (info)->debug_strtab;
+    BFD_ASSERT (o->output_section->_raw_size - o->output_offset
+               >= _bfd_stringtab_size (debug_strtab));
+    if (bfd_seek (abfd,
+                 o->output_section->filepos + o->output_offset,
+                 SEEK_SET) != 0)
+      goto error_return;
+    if (! _bfd_stringtab_emit (abfd, debug_strtab))
+      goto error_return;
+  }
+  
   /* Setting bfd_get_symcount to 0 will cause write_object_contents to
      not try to write out the symbols.  */
   bfd_get_symcount (abfd) = 0;
-
+  
   return true;
 
  error_return:
   if (finfo.strtab != NULL)
     _bfd_stringtab_free (finfo.strtab);
-  if (finfo.section_info != NULL)
-    {
-      unsigned int i;
-
-      for (i = 0; i < abfd->section_count; i++)
-       {
-         if (finfo.section_info[i].relocs != NULL)
-           free (finfo.section_info[i].relocs);
-         if (finfo.section_info[i].rel_hashes != NULL)
-           free (finfo.section_info[i].rel_hashes);
-       }
-      free (finfo.section_info);
+  
+  if (finfo.section_info != NULL) {
+    unsigned int i;
+    
+    for (i = 0; i < abfd->section_count; i++) {
+      if (finfo.section_info[i].relocs != NULL)
+       free (finfo.section_info[i].relocs);
+      if (finfo.section_info[i].rel_hashes != NULL)
+       free (finfo.section_info[i].rel_hashes);
     }
+    free (finfo.section_info);
+  }
+  
   if (finfo.internal_syms != NULL)
     free (finfo.internal_syms);
   if (finfo.sym_indices != NULL)
@@ -4510,6 +4166,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
 
   while (esym < esym_end)
     {
+
       struct internal_syment isym;
       union internal_auxent aux;
       int smtyp = 0;
@@ -4529,6 +4186,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
                                isymp->n_type, isymp->n_sclass,
                                isymp->n_numaux - 1, isymp->n_numaux,
                                (PTR) &aux);
+
          smtyp = SMTYP_SMTYP (aux.x_csect.x_smtyp);
        }
 
@@ -4613,17 +4271,18 @@ xcoff_link_input_bfd (finfo, input_bfd)
          ldsym->l_parm = 0;
 
          BFD_ASSERT (h->ldindx >= 0);
-         BFD_ASSERT (LDSYMSZ == sizeof (struct external_ldsym));
-         xcoff_swap_ldsym_out (finfo->output_bfd, ldsym,
-                               finfo->ldsym + h->ldindx - 3);
+         bfd_xcoff_swap_ldsym_out (finfo->output_bfd, ldsym,
+                                   finfo->ldsym + (h->ldindx - 3) * 
+                                   bfd_xcoff_ldsymsz(finfo->output_bfd));
          h->ldsym = NULL;
 
          /* Fill in snentry now that we know the target_index.  */
-         if ((h->flags & XCOFF_ENTRY) != 0
-             && (h->root.type == bfd_link_hash_defined
-                 || h->root.type == bfd_link_hash_defweak))
+         if ((h->flags & XCOFF_ENTRY) != 0 && 
+             (h->root.type == bfd_link_hash_defined
+              || h->root.type == bfd_link_hash_defweak)) {
            xcoff_data (output_bfd)->snentry =
              h->root.u.def.section->output_section->target_index;
+         }
        }
 
       *indexp = -1;
@@ -4716,6 +4375,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
              xcoff_data (finfo->output_bfd)->sntoc =
                (*csectpp)->output_section->target_index;
              require = true;
+             
            }
        }
 
@@ -4771,6 +4431,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
          char buf[SYMNMLEN + 1];
 
          name = _bfd_coff_internal_syment_name (input_bfd, &isym, buf);
+
          if (name == NULL)
            return false;
 
@@ -4811,6 +4472,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
 
                  name = _bfd_coff_internal_syment_name (input_bfd, &isym,
                                                         (char *) NULL);
+
                  if (name == NULL)
                    return false;
                  indx = _bfd_stringtab_add (finfo->strtab, name, hash, copy);
@@ -4839,7 +4501,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
          if (isym.n_sclass == C_FILE)
            {
              if (finfo->last_file_index != -1
-                 && finfo->last_file.n_value != (long) output_index)
+                 && finfo->last_file.n_value != (bfd_vma) output_index)
                {
                  /* We must correct the value of the last C_FILE entry.  */
                  finfo->last_file.n_value = output_index;
@@ -4956,7 +4618,8 @@ xcoff_link_input_bfd (finfo, input_bfd)
          if (isymp->n_sclass == C_BSTAT)
            {
              struct internal_syment isym;
-             unsigned long indx;
+
+             bfd_vma indx;
 
              /* The value of a C_BSTAT symbol is the symbol table
                  index of the containing csect.  */
@@ -5018,6 +4681,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
                        || isymp->n_sclass == C_HIDEXT)
                       && i + 1 == isymp->n_numaux)
                {
+
                  /* We don't support type checking.  I don't know if
                      anybody does.  */
                  aux.x_csect.x_parmhash = 0;
@@ -5025,20 +4689,23 @@ xcoff_link_input_bfd (finfo, input_bfd)
                      better clobber them just in case.  */
                  aux.x_csect.x_stab = 0;
                  aux.x_csect.x_snstab = 0;
+
                  if (SMTYP_SMTYP (aux.x_csect.x_smtyp) == XTY_LD)
                    {
-                     unsigned long indx;
+                     bfd_signed_vma indx;
 
-                     indx = aux.x_csect.x_scnlen.l;
+
+                     indx =  aux.x_csect.x_scnlen.l;
                      if (indx < obj_raw_syment_count (input_bfd))
                        {
                          long symindx;
 
                          symindx = finfo->sym_indices[indx];
-                         if (symindx < 0)
-                           aux.x_sym.x_tagndx.l = 0;
-                         else
-                           aux.x_sym.x_tagndx.l = symindx;
+                         if (symindx < 0) {
+                           aux.x_csect.x_scnlen.l = 0;
+                         } else {
+                           aux.x_csect.x_scnlen.l = symindx;
+                         }
                        }
                    }
                }
@@ -5067,6 +4734,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
                          else
                            indx = finfo->sym_indices[indx];
                          aux.x_sym.x_fcnary.x_fcn.x_endndx.l = indx;
+
                        }
                    }
 
@@ -5081,6 +4749,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
                      else
                        aux.x_sym.x_tagndx.l = symindx;
                    }
+
                }
 
              /* Copy over the line numbers, unless we are stripping
@@ -5100,7 +4769,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
                    {
                      asection *enclosing;
                      unsigned int enc_count;
-                     bfd_size_type linoff;
+                     bfd_signed_vma linoff;
                      struct internal_lineno lin;
 
                      o = *csectpp;
@@ -5199,7 +4868,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
                                      && (iisp->n_sclass == C_BINCL
                                          || iisp->n_sclass == C_EINCL)
                                      && ((bfd_size_type) iisp->n_value
-                                         >= enclosing->line_filepos + linoff)
+                                         >= (bfd_size_type)(enclosing->line_filepos + linoff))
                                      && ((bfd_size_type) iisp->n_value
                                          < (enclosing->line_filepos
                                             + enc_count * linesz)))
@@ -5281,319 +4950,318 @@ xcoff_link_input_bfd (finfo, input_bfd)
   obj_coff_keep_syms (input_bfd) = true;
 
   /* Relocate the contents of each section.  */
-  for (o = input_bfd->sections; o != NULL; o = o->next)
-    {
-      bfd_byte *contents;
+  for (o = input_bfd->sections; o != NULL; o = o->next) {
+    
+    bfd_byte *contents;
 
-      if (! o->linker_mark)
-       {
-         /* This section was omitted from the link.  */
-         continue;
-       }
+    if (! o->linker_mark){
+      /* This section was omitted from the link.  */
+      continue;
+    }
 
-      if ((o->flags & SEC_HAS_CONTENTS) == 0
-         || o->_raw_size == 0
-         || (o->flags & SEC_IN_MEMORY) != 0)
-       continue;
+    if ((o->flags & SEC_HAS_CONTENTS) == 0
+       || o->_raw_size == 0
+       || (o->flags & SEC_IN_MEMORY) != 0)
+      continue;
+    
+    /* We have set filepos correctly for the sections we created to
+       represent csects, so bfd_get_section_contents should work.  */
+    if (coff_section_data (input_bfd, o) != NULL
+       && coff_section_data (input_bfd, o)->contents != NULL)
+      contents = coff_section_data (input_bfd, o)->contents;
+    else {
+      if (! bfd_get_section_contents (input_bfd, o, finfo->contents,
+                                     (file_ptr) 0, o->_raw_size))
+       return false;
+      contents = finfo->contents;
+    }
 
-      /* We have set filepos correctly for the sections we created to
-         represent csects, so bfd_get_section_contents should work.  */
-      if (coff_section_data (input_bfd, o) != NULL
-         && coff_section_data (input_bfd, o)->contents != NULL)
-       contents = coff_section_data (input_bfd, o)->contents;
-      else
-       {
-         if (! bfd_get_section_contents (input_bfd, o, finfo->contents,
-                                         (file_ptr) 0, o->_raw_size))
-           return false;
-         contents = finfo->contents;
-       }
+    if ((o->flags & SEC_RELOC) != 0) {
+      int target_index;
+      struct internal_reloc *internal_relocs;
+      struct internal_reloc *irel;
+      bfd_vma offset;
+      struct internal_reloc *irelend;
+      struct xcoff_link_hash_entry **rel_hash;
+      long r_symndx;
+      
+      /* Read in the relocs.  */
+      target_index = o->output_section->target_index;
+      internal_relocs = (xcoff_read_internal_relocs
+                        (input_bfd, o, false, finfo->external_relocs,
+                         true,
+                         (finfo->section_info[target_index].relocs
+                          + o->output_section->reloc_count)));
+      if (internal_relocs == NULL)
+       return false;
 
-      if ((o->flags & SEC_RELOC) != 0)
-       {
-         int target_index;
-         struct internal_reloc *internal_relocs;
-         struct internal_reloc *irel;
-         bfd_vma offset;
-         struct internal_reloc *irelend;
-         struct xcoff_link_hash_entry **rel_hash;
-         long r_symndx;
-
-         /* Read in the relocs.  */
-         target_index = o->output_section->target_index;
-         internal_relocs = (xcoff_read_internal_relocs
-                            (input_bfd, o, false, finfo->external_relocs,
-                             true,
-                             (finfo->section_info[target_index].relocs
-                              + o->output_section->reloc_count)));
-         if (internal_relocs == NULL)
-           return false;
+      /* Call processor specific code to relocate the section
+        contents.  */
+      if (! bfd_coff_relocate_section (output_bfd, finfo->info,
+                                      input_bfd, o,
+                                      contents,
+                                      internal_relocs,
+                                      finfo->internal_syms,
+                                      xcoff_data (input_bfd)->csects))
+       return false;
 
-         /* Call processor specific code to relocate the section
-             contents.  */
-         if (! bfd_coff_relocate_section (output_bfd, finfo->info,
-                                          input_bfd, o,
-                                          contents,
-                                          internal_relocs,
-                                          finfo->internal_syms,
-                                          xcoff_data (input_bfd)->csects))
-           return false;
+      offset = o->output_section->vma + o->output_offset - o->vma;
+      irel = internal_relocs;
+      irelend = irel + o->reloc_count;
+      rel_hash = (finfo->section_info[target_index].rel_hashes
+                 + o->output_section->reloc_count);
+      for (; irel < irelend; irel++, rel_hash++) {
+       struct xcoff_link_hash_entry *h = NULL;
+       struct internal_ldrel ldrel;
+       boolean quiet;
 
-         offset = o->output_section->vma + o->output_offset - o->vma;
-         irel = internal_relocs;
-         irelend = irel + o->reloc_count;
-         rel_hash = (finfo->section_info[target_index].rel_hashes
-                     + o->output_section->reloc_count);
-         for (; irel < irelend; irel++, rel_hash++)
-           {
-             struct xcoff_link_hash_entry *h = NULL;
-             struct internal_ldrel ldrel;
-             boolean quiet;
+       *rel_hash = NULL;
 
-             *rel_hash = NULL;
+       /* Adjust the reloc address and symbol index.  */
 
-             /* Adjust the reloc address and symbol index.  */
+       irel->r_vaddr += offset;
 
-             irel->r_vaddr += offset;
+       r_symndx = irel->r_symndx;
 
-             r_symndx = irel->r_symndx;
+       if (r_symndx == -1)
+         h = NULL;
+       else
+         h = obj_xcoff_sym_hashes (input_bfd)[r_symndx];
 
-             if (r_symndx == -1)
-               h = NULL;
-             else
-               h = obj_xcoff_sym_hashes (input_bfd)[r_symndx];
+       if (r_symndx != -1 && finfo->info->strip != strip_all)
+         {
+           if (h != NULL
+               && h->smclas != XMC_TD
+               && (irel->r_type == R_TOC
+                   || irel->r_type == R_GL
+                   || irel->r_type == R_TCL
+                   || irel->r_type == R_TRL
+                   || irel->r_type == R_TRLA))
+             {
+               /* This is a TOC relative reloc with a symbol
+                  attached.  The symbol should be the one which
+                  this reloc is for.  We want to make this
+                  reloc against the TOC address of the symbol,
+                  not the symbol itself.  */
+               BFD_ASSERT (h->toc_section != NULL);
+               BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
+               if (h->u.toc_indx != -1)
+                 irel->r_symndx = h->u.toc_indx;
+               else
+                 {
+                   struct xcoff_toc_rel_hash *n;
+                   struct xcoff_link_section_info *si;
 
-             if (r_symndx != -1 && finfo->info->strip != strip_all)
-               {
-                 if (h != NULL
-                     && h->smclas != XMC_TD
-                     && (irel->r_type == R_TOC
-                         || irel->r_type == R_GL
-                         || irel->r_type == R_TCL
-                         || irel->r_type == R_TRL
-                         || irel->r_type == R_TRLA))
-                   {
-                     /* This is a TOC relative reloc with a symbol
-                         attached.  The symbol should be the one which
-                         this reloc is for.  We want to make this
-                         reloc against the TOC address of the symbol,
-                         not the symbol itself.  */
-                     BFD_ASSERT (h->toc_section != NULL);
-                     BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
-                     if (h->u.toc_indx != -1)
-                       irel->r_symndx = h->u.toc_indx;
-                     else
-                       {
-                         struct xcoff_toc_rel_hash *n;
-                         struct xcoff_link_section_info *si;
+                   n = ((struct xcoff_toc_rel_hash *)
+                        bfd_alloc (finfo->output_bfd,
+                                   sizeof (struct xcoff_toc_rel_hash)));
+                   if (n == NULL)
+                     return false;
+                   si = finfo->section_info + target_index;
+                   n->next = si->toc_rel_hashes;
+                   n->h = h;
+                   n->rel = irel;
+                   si->toc_rel_hashes = n;
+                 }
+             }
+           else if (h != NULL)
+             {
+               /* This is a global symbol.  */
+               if (h->indx >= 0)
+                 irel->r_symndx = h->indx;
+               else
+                 {
+                   /* This symbol is being written at the end
+                      of the file, and we do not yet know the
+                      symbol index.  We save the pointer to the
+                      hash table entry in the rel_hash list.
+                      We set the indx field to -2 to indicate
+                      that this symbol must not be stripped.  */
+                   *rel_hash = h;
+                   h->indx = -2;
+                 }
+             }
+           else
+             {
+               long indx;
 
-                         n = ((struct xcoff_toc_rel_hash *)
-                              bfd_alloc (finfo->output_bfd,
-                                         sizeof (struct xcoff_toc_rel_hash)));
-                         if (n == NULL)
-                           return false;
-                         si = finfo->section_info + target_index;
-                         n->next = si->toc_rel_hashes;
-                         n->h = h;
-                         n->rel = irel;
-                         si->toc_rel_hashes = n;
-                       }
-                   }
-                 else if (h != NULL)
-                   {
-                     /* This is a global symbol.  */
-                     if (h->indx >= 0)
-                       irel->r_symndx = h->indx;
-                     else
-                       {
-                         /* This symbol is being written at the end
-                            of the file, and we do not yet know the
-                            symbol index.  We save the pointer to the
-                            hash table entry in the rel_hash list.
-                            We set the indx field to -2 to indicate
-                            that this symbol must not be stripped.  */
-                         *rel_hash = h;
-                         h->indx = -2;
-                       }
-                   }
-                 else
-                   {
-                     long indx;
+               indx = finfo->sym_indices[r_symndx];
 
-                     indx = finfo->sym_indices[r_symndx];
+               if (indx == -1)
+                 {
+                   struct internal_syment *is;
+
+                   /* Relocations against a TC0 TOC anchor are
+                      automatically transformed to be against
+                      the TOC anchor in the output file.  */
+                   is = finfo->internal_syms + r_symndx;
+                   if (is->n_sclass == C_HIDEXT
+                       && is->n_numaux > 0)
+                     {
+                       PTR auxptr;
+                       union internal_auxent aux;
+
+                       auxptr = ((PTR)
+                                 (((bfd_byte *)
+                                   obj_coff_external_syms (input_bfd))
+                                  + ((r_symndx + is->n_numaux)
+                                     * isymesz)));
+                       bfd_coff_swap_aux_in (input_bfd, auxptr,
+                                             is->n_type, is->n_sclass,
+                                             is->n_numaux - 1,
+                                             is->n_numaux,
+                                             (PTR) &aux);
+                       if (SMTYP_SMTYP (aux.x_csect.x_smtyp) == XTY_SD
+                           && aux.x_csect.x_smclas == XMC_TC0)
+                         indx = finfo->toc_symindx;
+                     }
+                 }
 
-                     if (indx == -1)
-                       {
-                         struct internal_syment *is;
-
-                         /* Relocations against a TC0 TOC anchor are
-                            automatically transformed to be against
-                            the TOC anchor in the output file.  */
-                         is = finfo->internal_syms + r_symndx;
-                         if (is->n_sclass == C_HIDEXT
-                             && is->n_numaux > 0)
-                           {
-                             PTR auxptr;
-                             union internal_auxent aux;
-
-                             auxptr = ((PTR)
-                                       (((bfd_byte *)
-                                         obj_coff_external_syms (input_bfd))
-                                        + ((r_symndx + is->n_numaux)
-                                           * isymesz)));
-                             bfd_coff_swap_aux_in (input_bfd, auxptr,
-                                                   is->n_type, is->n_sclass,
-                                                   is->n_numaux - 1,
-                                                   is->n_numaux,
-                                                   (PTR) &aux);
-                             if (SMTYP_SMTYP (aux.x_csect.x_smtyp) == XTY_SD
-                                 && aux.x_csect.x_smclas == XMC_TC0)
-                               indx = finfo->toc_symindx;
-                           }
-                       }
+               if (indx != -1)
+                 irel->r_symndx = indx;
+               else
+                 {
 
-                     if (indx != -1)
-                       irel->r_symndx = indx;
-                     else
-                       {
-                         struct internal_syment *is;
-                         const char *name;
-                         char buf[SYMNMLEN + 1];
-
-                         /* This reloc is against a symbol we are
-                            stripping.  It would be possible to handle
-                            this case, but I don't think it's worth it.  */
-                         is = finfo->internal_syms + r_symndx;
-
-                         name = (_bfd_coff_internal_syment_name
-                                 (input_bfd, is, buf));
-                         if (name == NULL)
-                           return false;
+                   struct internal_syment *is;
 
-                         if (! ((*finfo->info->callbacks->unattached_reloc)
-                                (finfo->info, name, input_bfd, o,
-                                 irel->r_vaddr)))
-                           return false;
-                       }
-                   }
-               }
+                   const char *name;
+                   char buf[SYMNMLEN + 1];
 
-             quiet = false;
-             switch (irel->r_type)
-               {
-               default:
-                 if (h == NULL
-                     || h->root.type == bfd_link_hash_defined
-                     || h->root.type == bfd_link_hash_defweak
-                     || h->root.type == bfd_link_hash_common)
-                   break;
-                 /* Fall through.  */
-               case R_POS:
-               case R_NEG:
-               case R_RL:
-               case R_RLA:
-                 /* This reloc needs to be copied into the .loader
-                    section.  */
-                 ldrel.l_vaddr = irel->r_vaddr;
-                 if (r_symndx == -1)
-                   ldrel.l_symndx = -1;
-                 else if (h == NULL
-                          || (h->root.type == bfd_link_hash_defined
-                              || h->root.type == bfd_link_hash_defweak
-                              || h->root.type == bfd_link_hash_common))
-                   {
-                     asection *sec;
+                   /* This reloc is against a symbol we are
+                      stripping.  It would be possible to handle
+                      this case, but I don't think it's worth it.  */
+                   is = finfo->internal_syms + r_symndx;
 
-                     if (h == NULL)
-                       sec = xcoff_data (input_bfd)->csects[r_symndx];
-                     else if (h->root.type == bfd_link_hash_common)
-                       sec = h->root.u.c.p->section;
-                     else
-                       sec = h->root.u.def.section;
-                     sec = sec->output_section;
-
-                     if (strcmp (sec->name, ".text") == 0)
-                       ldrel.l_symndx = 0;
-                     else if (strcmp (sec->name, ".data") == 0)
-                       ldrel.l_symndx = 1;
-                     else if (strcmp (sec->name, ".bss") == 0)
-                       ldrel.l_symndx = 2;
-                     else
-                       {
-                         (*_bfd_error_handler)
-                           (_("%s: loader reloc in unrecognized section `%s'"),
-                            bfd_get_filename (input_bfd),
-                            sec->name);
-                         bfd_set_error (bfd_error_nonrepresentable_section);
-                         return false;
-                       }
-                   }
-                 else
-                   {
-                     if (! finfo->info->relocateable
-                         && (h->flags & XCOFF_DEF_DYNAMIC) == 0
-                         && (h->flags & XCOFF_IMPORT) == 0)
-                       {
-                         /* We already called the undefined_symbol
-                            callback for this relocation, in
-                            _bfd_ppc_xcoff_relocate_section.  Don't
-                            issue any more warnings.  */
-                         quiet = true;
-                       }
-                     if (h->ldindx < 0 && ! quiet)
-                       {
-                         (*_bfd_error_handler)
-                           (_("%s: `%s' in loader reloc but not loader sym"),
-                            bfd_get_filename (input_bfd),
-                            h->root.root.string);
-                         bfd_set_error (bfd_error_bad_value);
-                         return false;
-                       }
-                     ldrel.l_symndx = h->ldindx;
-                   }
-                 ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
-                 ldrel.l_rsecnm = o->output_section->target_index;
-                 if (xcoff_hash_table (finfo->info)->textro
-                     && strcmp (o->output_section->name, ".text") == 0
-                     && ! quiet)
-                   {
-                     (*_bfd_error_handler)
-                       (_("%s: loader reloc in read-only section %s"),
-                        bfd_get_filename (input_bfd),
-                        bfd_get_section_name (finfo->output_bfd,
-                                              o->output_section));
-                     bfd_set_error (bfd_error_invalid_operation);
+                   name = (_bfd_coff_internal_syment_name
+                           (input_bfd, is, buf));
+
+                   if (name == NULL)
                      return false;
-                   }
-                 xcoff_swap_ldrel_out (output_bfd, &ldrel,
-                                       finfo->ldrel);
-                 BFD_ASSERT (sizeof (struct external_ldrel) == LDRELSZ);
-                 ++finfo->ldrel;
-                 break;
 
-               case R_TOC:
-               case R_GL:
-               case R_TCL:
-               case R_TRL:
-               case R_TRLA:
-                 /* We should never need a .loader reloc for a TOC
-                    relative reloc.  */
-                 break;
-               }
-           }
+                   if (! ((*finfo->info->callbacks->unattached_reloc)
+                          (finfo->info, name, input_bfd, o,
+                           irel->r_vaddr)))
+                     return false;
+                 }
+             }
+         }
 
-         o->output_section->reloc_count += o->reloc_count;
-       }
+       quiet = false;
+       switch (irel->r_type)
+         {
+         default:
+           if (h == NULL
+               || h->root.type == bfd_link_hash_defined
+               || h->root.type == bfd_link_hash_defweak
+               || h->root.type == bfd_link_hash_common)
+             break;
+           /* Fall through.  */
+         case R_POS:
+         case R_NEG:
+         case R_RL:
+         case R_RLA:
+           /* This reloc needs to be copied into the .loader
+              section.  */
+           ldrel.l_vaddr = irel->r_vaddr;
+           if (r_symndx == -1)
+             ldrel.l_symndx = -1;
+           else if (h == NULL
+                    || (h->root.type == bfd_link_hash_defined
+                        || h->root.type == bfd_link_hash_defweak
+                        || h->root.type == bfd_link_hash_common))
+             {
+               asection *sec;
+
+               if (h == NULL)
+                 sec = xcoff_data (input_bfd)->csects[r_symndx];
+               else if (h->root.type == bfd_link_hash_common)
+                 sec = h->root.u.c.p->section;
+               else
+                 sec = h->root.u.def.section;
+               sec = sec->output_section;
+
+               if (strcmp (sec->name, ".text") == 0)
+                 ldrel.l_symndx = 0;
+               else if (strcmp (sec->name, ".data") == 0)
+                 ldrel.l_symndx = 1;
+               else if (strcmp (sec->name, ".bss") == 0)
+                 ldrel.l_symndx = 2;
+               else
+                 {
+                   (*_bfd_error_handler)
+                     (_("%s: loader reloc in unrecognized section `%s'"),
+                      bfd_get_filename (input_bfd),
+                      sec->name);
+                   bfd_set_error (bfd_error_nonrepresentable_section);
+                   return false;
+                 }
+             }
+           else
+             {
+               if (! finfo->info->relocateable
+                   && (h->flags & XCOFF_DEF_DYNAMIC) == 0
+                   && (h->flags & XCOFF_IMPORT) == 0)
+                 {
+                   /* We already called the undefined_symbol
+                      callback for this relocation, in
+                      _bfd_ppc_xcoff_relocate_section.  Don't
+                      issue any more warnings.  */
+                   quiet = true;
+                 }
+               if (h->ldindx < 0 && ! quiet)
+                 {
+                   (*_bfd_error_handler)
+                     (_("%s: `%s' in loader reloc but not loader sym"),
+                      bfd_get_filename (input_bfd),
+                      h->root.root.string);
+                   bfd_set_error (bfd_error_bad_value);
+                   return false;
+                 }
+               ldrel.l_symndx = h->ldindx;
+             }
+           ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
+           ldrel.l_rsecnm = o->output_section->target_index;
+           if (xcoff_hash_table (finfo->info)->textro
+               && strcmp (o->output_section->name, ".text") == 0
+               && ! quiet)
+             {
+               (*_bfd_error_handler)
+                 (_("%s: loader reloc in read-only section %s"),
+                  bfd_get_filename (input_bfd),
+                  bfd_get_section_name (finfo->output_bfd,
+                                        o->output_section));
+               bfd_set_error (bfd_error_invalid_operation);
+               return false;
+             }
+           bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel,
+                                     finfo->ldrel);
 
-      /* Write out the modified section contents.  */
-      if (! bfd_set_section_contents (output_bfd, o->output_section,
-                                     contents, o->output_offset,
-                                     (o->_cooked_size != 0
-                                      ? o->_cooked_size
-                                      : o->_raw_size)))
-       return false;
+           finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
+           break;
+
+         case R_TOC:
+         case R_GL:
+         case R_TCL:
+         case R_TRL:
+         case R_TRLA:
+           /* We should never need a .loader reloc for a TOC
+              relative reloc.  */
+           break;
+         }
+      }
+
+      o->output_section->reloc_count += o->reloc_count;
     }
 
+    /* Write out the modified section contents.  */
+    if (! bfd_set_section_contents (output_bfd, o->output_section,
+                                   contents, o->output_offset,
+                                   (o->_cooked_size != 0
+                                    ? o->_cooked_size
+                                    : o->_raw_size)))
+      return false;
+  }
+
   obj_coff_keep_syms (input_bfd) = keep_syms;
 
   if (! finfo->info->keep_memory)
@@ -5610,6 +5278,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
 
 /* Write out a non-XCOFF global symbol.  */
 
+
 static boolean
 xcoff_write_global_symbol (h, p)
      struct xcoff_link_hash_entry *h;
@@ -5620,6 +5289,7 @@ xcoff_write_global_symbol (h, p)
   bfd_byte *outsym;
   struct internal_syment isym;
   union internal_auxent aux;
+  boolean result;
 
   output_bfd = finfo->output_bfd;
   outsym = finfo->outsyms;
@@ -5630,97 +5300,123 @@ xcoff_write_global_symbol (h, p)
     return true;
 
   /* If we need a .loader section entry, write it out.  */
-  if (h->ldsym != NULL)
-    {
-      struct internal_ldsym *ldsym;
-      bfd *impbfd;
+  if (h->ldsym != NULL) {
+    struct internal_ldsym *ldsym;
+    bfd *impbfd;
+    
+    ldsym = h->ldsym;
 
-      ldsym = h->ldsym;
+    if (h->root.type == bfd_link_hash_undefined || 
+       h->root.type == bfd_link_hash_undefweak) {
 
-      if (h->root.type == bfd_link_hash_undefined
-         || h->root.type == bfd_link_hash_undefweak)
-       {
-         ldsym->l_value = 0;
-         ldsym->l_scnum = N_UNDEF;
-         ldsym->l_smtype = XTY_ER;
-         impbfd = h->root.u.undef.abfd;
-       }
-      else if (h->root.type == bfd_link_hash_defined
-              || h->root.type == bfd_link_hash_defweak)
-       {
-         asection *sec;
+      ldsym->l_value = 0;
+      ldsym->l_scnum = N_UNDEF;
+      ldsym->l_smtype = XTY_ER;
+      impbfd = h->root.u.undef.abfd;
 
-         sec = h->root.u.def.section;
-         ldsym->l_value = (sec->output_section->vma
-                           + sec->output_offset
-                           + h->root.u.def.value);
-         ldsym->l_scnum = sec->output_section->target_index;
-         ldsym->l_smtype = XTY_SD;
-         impbfd = sec->owner;
-       }
-      else
-       abort ();
+    } else if (h->root.type == bfd_link_hash_defined || 
+              h->root.type == bfd_link_hash_defweak) {
 
-      if (((h->flags & XCOFF_DEF_REGULAR) == 0
-          && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
-         || (h->flags & XCOFF_IMPORT) != 0)
-       ldsym->l_smtype |= L_IMPORT;
-      if (((h->flags & XCOFF_DEF_REGULAR) != 0
-          && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
-         || (h->flags & XCOFF_EXPORT) != 0)
-       ldsym->l_smtype |= L_EXPORT;
-      if ((h->flags & XCOFF_ENTRY) != 0)
-       ldsym->l_smtype |= L_ENTRY;
+      asection *sec;
+      
+      sec = h->root.u.def.section;
+      ldsym->l_value = (sec->output_section->vma
+                       + sec->output_offset
+                       + h->root.u.def.value);
+      ldsym->l_scnum = sec->output_section->target_index;
+      ldsym->l_smtype = XTY_SD;
+      impbfd = sec->owner;
+
+    } else {
+      abort ();
+    }
 
-      ldsym->l_smclas = h->smclas;
+    if (((h->flags & XCOFF_DEF_REGULAR) == 0 && 
+        (h->flags & XCOFF_DEF_DYNAMIC) != 0) || 
+       (h->flags & XCOFF_IMPORT) != 0) {
+      ldsym->l_smtype |= L_IMPORT;
+    }
 
-      if (ldsym->l_ifile == (bfd_size_type) -1)
-       ldsym->l_ifile = 0;
-      else if (ldsym->l_ifile == 0)
-       {
-         if ((ldsym->l_smtype & L_IMPORT) == 0)
-           ldsym->l_ifile = 0;
-         else if (impbfd == NULL)
-           ldsym->l_ifile = 0;
-         else
-           {
-             BFD_ASSERT (impbfd->xvec == output_bfd->xvec);
-             ldsym->l_ifile = xcoff_data (impbfd)->import_file_id;
-           }
-       }
+    if (((h->flags & XCOFF_DEF_REGULAR) != 0 && 
+        (h->flags & XCOFF_DEF_DYNAMIC) != 0) || 
+       (h->flags & XCOFF_EXPORT) != 0) {
+      ldsym->l_smtype |= L_EXPORT;
+    }
 
-      ldsym->l_parm = 0;
+    if ((h->flags & XCOFF_ENTRY) != 0) {
+      ldsym->l_smtype |= L_ENTRY;
+    }
 
-      BFD_ASSERT (h->ldindx >= 0);
-      BFD_ASSERT (LDSYMSZ == sizeof (struct external_ldsym));
-      xcoff_swap_ldsym_out (output_bfd, ldsym, finfo->ldsym + h->ldindx - 3);
-      h->ldsym = NULL;
+    if ((h->flags & XCOFF_RTINIT) != 0) {
+      ldsym->l_smtype = XTY_SD;
     }
 
+    ldsym->l_smclas = h->smclas;
+
+    if (ldsym->l_ifile == (bfd_size_type) -1) {
+      ldsym->l_ifile = 0;
+
+    } else if (ldsym->l_ifile == 0) {
+      if ((ldsym->l_smtype & L_IMPORT) == 0) {
+       ldsym->l_ifile = 0;
+      } else if (impbfd == NULL) {
+       ldsym->l_ifile = 0;
+      } else {
+       BFD_ASSERT (impbfd->xvec == output_bfd->xvec);
+       ldsym->l_ifile = xcoff_data (impbfd)->import_file_id;
+      }
+    }
+    
+    ldsym->l_parm = 0;
+    
+    BFD_ASSERT (h->ldindx >= 0);
+    
+    bfd_xcoff_swap_ldsym_out (output_bfd, ldsym, finfo->ldsym + 
+                             (h->ldindx - 3) * 
+                             bfd_xcoff_ldsymsz(finfo->output_bfd));
+    h->ldsym = NULL;
+  }
+  
   /* If this symbol needs global linkage code, write it out.  */
-  if (h->root.type == bfd_link_hash_defined
-      && (h->root.u.def.section
-         == xcoff_hash_table (finfo->info)->linkage_section))
-    {
-      bfd_byte *p;
-      bfd_vma tocoff;
-      unsigned int i;
-
-      p = h->root.u.def.section->contents + h->root.u.def.value;
-
-      /* The first instruction in the global linkage code loads a
-         specific TOC element.  */
-      tocoff = (h->descriptor->toc_section->output_section->vma
-               + h->descriptor->toc_section->output_offset
-               - xcoff_data (output_bfd)->toc);
-      if ((h->descriptor->flags & XCOFF_SET_TOC) != 0)
-       tocoff += h->descriptor->u.toc_offset;
-      bfd_put_32 (output_bfd, XCOFF_GLINK_FIRST | (tocoff & 0xffff), p);
-      for (i = 0, p += 4;
-          i < sizeof xcoff_glink_code / sizeof xcoff_glink_code[0];
-          i++, p += 4)
-       bfd_put_32 (output_bfd, xcoff_glink_code[i], p);
+  if (h->root.type == bfd_link_hash_defined && 
+      (h->root.u.def.section == 
+       xcoff_hash_table (finfo->info)->linkage_section)) {
+
+    bfd_byte *p;
+    bfd_vma tocoff;
+    unsigned int i;
+    
+    p = h->root.u.def.section->contents + h->root.u.def.value;
+
+    /* The first instruction in the global linkage code loads a
+       specific TOC element.  */
+    tocoff = (h->descriptor->toc_section->output_section->vma
+             + h->descriptor->toc_section->output_offset
+             - xcoff_data (output_bfd)->toc);
+
+    if ((h->descriptor->flags & XCOFF_SET_TOC) != 0) {
+      tocoff += h->descriptor->u.toc_offset;
     }
+    
+
+    /*
+     * The first instruction in the glink code needs to be cooked to 
+     * to hold the correct offset in the toc.  The rest are just outputted
+     * raw.
+     */
+    bfd_put_32 (output_bfd, 
+               bfd_xcoff_glink_code(output_bfd, 0) | (tocoff & 0xffff), p);
+
+    /* 
+     * Start with i == 1 to get past the first instruction done above 
+     * The /4 is because the glink code is in bytes and we are going 4
+     * at a pop
+     */
+    for (i = 1; i < bfd_xcoff_glink_code_size(output_bfd) / 4; i++) {
+      bfd_put_32 (output_bfd, bfd_xcoff_glink_code(output_bfd, i), 
+                 &p[4 * i]);
+    }
+  }
 
   /* If we created a TOC entry for this symbol, write out the required
      relocs.  */
@@ -5741,69 +5437,82 @@ xcoff_write_global_symbol (h, p)
       irel->r_vaddr = (osec->vma
                       + tocsec->output_offset
                       + h->u.toc_offset);
-      if (h->indx >= 0)
+
+
+      if (h->indx >= 0) {
        irel->r_symndx = h->indx;
-      else
-       {
-         h->indx = -2;
-         irel->r_symndx = obj_raw_syment_count (output_bfd);
-       }
+      } else {
+       h->indx = -2;
+       irel->r_symndx = obj_raw_syment_count (output_bfd);
+      }
+      
+      BFD_ASSERT (h->ldindx >= 0);
+
+      /*
+       * Initialize the aux union here instead of closer to when it is
+       * written out below because the length of the csect depends on 
+       * whether the output is 32 or 64 bit
+       */
+      memset (&iraux, 0, sizeof iraux);
+      iraux.x_csect.x_smtyp = XTY_SD;
+      /* iraux.x_csect.x_scnlen.l = 4 or 8, see below */
+      iraux.x_csect.x_smclas = XMC_TC;
+
+
+      /* 
+       * 32 bit uses a 32 bit R_POS to do the relocations
+       * 64 bit uses a 64 bit R_POS to do the relocations
+       * 
+       * Also needs to change the csect size : 4 for 32 bit, 8 for 64 bit
+       * 
+       * Which one is determined by the backend
+       */
+      if (bfd_xcoff_is_xcoff64(output_bfd)) {
+       irel->r_size = 63;
+       iraux.x_csect.x_scnlen.l = 8;
+      } else if (bfd_xcoff_is_xcoff32(output_bfd)) {
+       irel->r_size = 31;
+       iraux.x_csect.x_scnlen.l = 4;
+      } else {
+       return false;
+      }
       irel->r_type = R_POS;
-      irel->r_size = 31;
       finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
       ++osec->reloc_count;
 
-      BFD_ASSERT (h->ldindx >= 0);
       ldrel.l_vaddr = irel->r_vaddr;
       ldrel.l_symndx = h->ldindx;
-      ldrel.l_rtype = (31 << 8) | R_POS;
+      ldrel.l_rtype = (irel->r_size << 8) | R_POS;
       ldrel.l_rsecnm = oindx;
-      xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
-      ++finfo->ldrel;
+      bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
+      finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
 
-      /* We need to emit a symbol to define a csect which holds the
-         reloc.  */
-      if (finfo->info->strip != strip_all)
-       {
-         if (strlen (h->root.root.string) <= SYMNMLEN)
-           strncpy (irsym._n._n_name, h->root.root.string, SYMNMLEN);
-         else
-           {
-             boolean hash;
-             bfd_size_type indx;
+      /* We need to emit a symbol to define a csect which holds the reloc.  */
+      if (finfo->info->strip != strip_all) {
 
-             hash = true;
-             if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
-               hash = false;
-             indx = _bfd_stringtab_add (finfo->strtab, h->root.root.string,
-                                        hash, false);
-             if (indx == (bfd_size_type) -1)
-               return false;
-             irsym._n._n_n._n_zeroes = 0;
-             irsym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
-           }
-
-         irsym.n_value = irel->r_vaddr;
-         irsym.n_scnum = osec->target_index;
-         irsym.n_sclass = C_HIDEXT;
-         irsym.n_type = T_NULL;
-         irsym.n_numaux = 1;
+       result = bfd_xcoff_put_symbol_name (output_bfd, finfo->strtab, &irsym, 
+                                           h->root.root.string);
+       if (false == result) {
+         return false;
+       }
 
-         bfd_coff_swap_sym_out (output_bfd, (PTR) &irsym, (PTR) outsym);
-         outsym += bfd_coff_symesz (output_bfd);
+       irsym.n_value = irel->r_vaddr;
+       irsym.n_scnum = osec->target_index;
+       irsym.n_sclass = C_HIDEXT;
+       irsym.n_type = T_NULL;
+       irsym.n_numaux = 1;
 
-         memset (&iraux, 0, sizeof iraux);
-         iraux.x_csect.x_smtyp = XTY_SD;
-         iraux.x_csect.x_scnlen.l = 4;
-         iraux.x_csect.x_smclas = XMC_TC;
+       bfd_coff_swap_sym_out (output_bfd, (PTR) &irsym, (PTR) outsym);
+       outsym += bfd_coff_symesz (output_bfd);
 
-         bfd_coff_swap_aux_out (output_bfd, (PTR) &iraux, T_NULL, C_HIDEXT,
-                                0, 1, (PTR) outsym);
-         outsym += bfd_coff_auxesz (output_bfd);
+       /* note : iraux is initialized above */
+       bfd_coff_swap_aux_out (output_bfd, (PTR) &iraux, T_NULL, C_HIDEXT,
+                              0, 1, (PTR) outsym);
+       outsym += bfd_coff_auxesz (output_bfd);
 
-         if (h->indx >= 0)
-           {
-             /* We aren't going to write out the symbols below, so we
+       if (h->indx >= 0)
+         {
+           /* We aren't going to write out the symbols below, so we
                 need to write them out now.  */
              if (bfd_seek (output_bfd,
                            (obj_sym_filepos (output_bfd)
@@ -5822,10 +5531,18 @@ xcoff_write_global_symbol (h, p)
        }
     }
 
-  /* If this symbol is a specially defined function descriptor, write
-     it out.  The first word is the address of the function code
-     itself, the second word is the address of the TOC, and the third
-     word is zero.  */
+  /* 
+   * If this symbol is a specially defined function descriptor, write
+   * it out.  The first word is the address of the function code
+   * itself, the second word is the address of the TOC, and the third
+   * word is zero.  
+   *
+   * 32 bit vs 64 bit
+   * The addresses for the 32 bit will take 4 bytes and the addresses 
+   * for 64 bit will take 8 bytes.  Similar for the relocs.  This type 
+   * of logic was also done above to create a TOC entry in 
+   * xcoff_write_global_symbol
+   */
   if ((h->flags & XCOFF_DESCRIPTOR) != 0
       && h->root.type == bfd_link_hash_defined
       && (h->root.u.def.section
@@ -5840,6 +5557,17 @@ xcoff_write_global_symbol (h, p)
       struct internal_reloc *irel;
       struct internal_ldrel ldrel;
       asection *tsec;
+      unsigned int reloc_size, byte_size;
+
+      if (bfd_xcoff_is_xcoff64(output_bfd)) {
+       reloc_size = 63;
+       byte_size = 8;
+      } else if (bfd_xcoff_is_xcoff32(output_bfd)) {
+       reloc_size = 31;
+       byte_size = 4;
+      } else {
+       return false;
+      }
 
       sec = h->root.u.def.section;
       osec = sec->output_section;
@@ -5851,11 +5579,6 @@ xcoff_write_global_symbol (h, p)
                  && (hentry->root.type == bfd_link_hash_defined
                      || hentry->root.type == bfd_link_hash_defweak));
       esec = hentry->root.u.def.section;
-      bfd_put_32 (output_bfd,
-                 (esec->output_section->vma
-                  + esec->output_offset
-                  + hentry->root.u.def.value),
-                 p);
 
       irel = finfo->section_info[oindx].relocs + osec->reloc_count;
       irel->r_vaddr = (osec->vma
@@ -5863,7 +5586,7 @@ xcoff_write_global_symbol (h, p)
                       + h->root.u.def.value);
       irel->r_symndx = esec->output_section->target_index;
       irel->r_type = R_POS;
-      irel->r_size = 31;
+      irel->r_size = reloc_size;
       finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
       ++osec->reloc_count;
 
@@ -5883,13 +5606,38 @@ xcoff_write_global_symbol (h, p)
          bfd_set_error (bfd_error_nonrepresentable_section);
          return false;
        }
-      ldrel.l_rtype = (31 << 8) | R_POS;
+      ldrel.l_rtype = (reloc_size << 8) | R_POS;
       ldrel.l_rsecnm = oindx;
-      xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
-      ++finfo->ldrel;
-
-      bfd_put_32 (output_bfd, xcoff_data (output_bfd)->toc, p + 4);
-
+      bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
+      finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
+
+      /*
+       * There are three items to write out, 
+       * the address of the code
+       * the address of the toc anchor
+       * the environment pointer.  
+       * We are ignoring the environment pointer.  So set it to zero
+       */
+      if (bfd_xcoff_is_xcoff64(output_bfd)) {
+       bfd_put_64 (output_bfd, (esec->output_section->vma + 
+                                esec->output_offset + 
+                                hentry->root.u.def.value), p);
+       bfd_put_64 (output_bfd, xcoff_data (output_bfd)->toc, p + 8);
+       bfd_put_64 (output_bfd, 0, p + 16);
+      } else {
+       /* 
+        * 32 bit backend 
+        *
+        * This logic was already called above so the error case where 
+        * the backend is neither has already been checked 
+        */
+       bfd_put_32 (output_bfd, (esec->output_section->vma + 
+                                esec->output_offset + 
+                                hentry->root.u.def.value), p);
+       bfd_put_32 (output_bfd, xcoff_data (output_bfd)->toc, p + 4);
+       bfd_put_32 (output_bfd, 0, p + 8);
+      } 
+      
       tsec = coff_section_from_bfd_index (output_bfd,
                                          xcoff_data (output_bfd)->sntoc);
 
@@ -5897,10 +5645,10 @@ xcoff_write_global_symbol (h, p)
       irel->r_vaddr = (osec->vma
                       + sec->output_offset
                       + h->root.u.def.value
-                      + 4);
+                      + byte_size);
       irel->r_symndx = tsec->output_section->target_index;
       irel->r_type = R_POS;
-      irel->r_size = 31;
+      irel->r_size = reloc_size;
       finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
       ++osec->reloc_count;
 
@@ -5920,10 +5668,10 @@ xcoff_write_global_symbol (h, p)
          bfd_set_error (bfd_error_nonrepresentable_section);
          return false;
        }
-      ldrel.l_rtype = (31 << 8) | R_POS;
+      ldrel.l_rtype = (reloc_size << 8) | R_POS;
       ldrel.l_rsecnm = oindx;
-      xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
-      ++finfo->ldrel;
+      bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
+      finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
     }
 
   if (h->indx >= 0 || finfo->info->strip == strip_all)
@@ -5954,23 +5702,11 @@ xcoff_write_global_symbol (h, p)
 
   h->indx = obj_raw_syment_count (output_bfd);
 
-  if (strlen (h->root.root.string) <= SYMNMLEN)
-    strncpy (isym._n._n_name, h->root.root.string, SYMNMLEN);
-  else
-    {
-      boolean hash;
-      bfd_size_type indx;
-
-      hash = true;
-      if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
-       hash = false;
-      indx = _bfd_stringtab_add (finfo->strtab, h->root.root.string, hash,
-                                false);
-      if (indx == (bfd_size_type) -1)
-       return false;
-      isym._n._n_n._n_zeroes = 0;
-      isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
-    }
+  result = bfd_xcoff_put_symbol_name (output_bfd, finfo->strtab, &isym, 
+                                     h->root.root.string);
+  if (false == result) {
+    return false;
+  }
 
   if (h->root.type == bfd_link_hash_undefined
       || h->root.type == bfd_link_hash_undefweak)
@@ -6035,7 +5771,6 @@ xcoff_write_global_symbol (h, p)
   outsym += bfd_coff_symesz (output_bfd);
 
   aux.x_csect.x_smclas = h->smclas;
-
   bfd_coff_swap_aux_out (output_bfd, (PTR) &aux, T_NULL, isym.n_sclass, 0, 1,
                         (PTR) outsym);
   outsym += bfd_coff_auxesz (output_bfd);
@@ -6054,7 +5789,6 @@ xcoff_write_global_symbol (h, p)
 
       aux.x_csect.x_smtyp = XTY_LD;
       aux.x_csect.x_scnlen.l = obj_raw_syment_count (output_bfd);
-
       bfd_coff_swap_aux_out (output_bfd, (PTR) &aux, T_NULL, C_EXT, 0, 1,
                             (PTR) outsym);
       outsym += bfd_coff_auxesz (output_bfd);
@@ -6253,8 +5987,8 @@ xcoff_reloc_link_order (output_bfd, finfo, output_section, link_order)
 
   ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
   ldrel.l_rsecnm = output_section->target_index;
-  xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
-  ++finfo->ldrel;
+  bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
+  finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);
 
   return true;
 }
@@ -6277,355 +6011,6 @@ xcoff_sort_relocs (p1, p2)
     return 0;
 }
 
-/* This is the relocation function for the RS/6000/POWER/PowerPC.
-   This is currently the only processor which uses XCOFF; I hope that
-   will never change.  */
 
-boolean
-_bfd_ppc_xcoff_relocate_section (output_bfd, info, input_bfd,
-                                input_section, contents, relocs, syms,
-                                sections)
-     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_reloc_status_type rstat;
-
-      /* 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;
-
-      symndx = rel->r_symndx;
-
-      if (symndx == -1)
-       {
-         h = NULL;
-         sym = NULL;
-         addend = 0;
-       }
-      else
-       {
-         h = obj_xcoff_sym_hashes (input_bfd)[symndx];
-         sym = syms + symndx;
-         addend = - sym->n_value;
-       }
-
-      /* We build the howto information on the fly.  */
-
-      howto.type = rel->r_type;
-      howto.rightshift = 0;
-      howto.size = 2;
-      howto.bitsize = (rel->r_size & 0x1f) + 1;
-      howto.pc_relative = false;
-      howto.bitpos = 0;
-      if ((rel->r_size & 0x80) != 0)
-       howto.complain_on_overflow = complain_overflow_signed;
-      else
-       howto.complain_on_overflow = complain_overflow_bitfield;
-      howto.special_function = NULL;
-      howto.name = "internal";
-      howto.partial_inplace = true;
-      if (howto.bitsize == 32)
-       howto.src_mask = howto.dst_mask = 0xffffffff;
-      else
-       {
-         howto.src_mask = howto.dst_mask = (1 << howto.bitsize) - 1;
-         if (howto.bitsize == 16)
-           howto.size = 1;
-       }
-      howto.pcrel_offset = false;
-
-      val = 0;
-
-      if (h == NULL)
-       {
-         asection *sec;
 
-         if (symndx == -1)
-           {
-             sec = bfd_abs_section_ptr;
-             val = 0;
-           }
-         else
-           {
-             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 (h->root.type == bfd_link_hash_defined
-             || h->root.type == bfd_link_hash_defweak)
-           {
-             asection *sec;
-
-             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)
-           {
-             asection *sec;
-
-             sec = h->root.u.c.p->section;
-             val = (sec->output_section->vma
-                    + sec->output_offset);
-           }
-         else if ((h->flags & XCOFF_DEF_DYNAMIC) != 0
-                  || (h->flags & XCOFF_IMPORT) != 0)
-           {
-             /* Every symbol in a shared object is defined somewhere.  */
-             val = 0;
-           }
-         else if (! info->relocateable)
-           {
-             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;
-           }
-       }
-
-      /* I took the relocation type definitions from two documents:
-        the PowerPC AIX Version 4 Application Binary Interface, First
-        Edition (April 1992), and the PowerOpen ABI, Big-Endian
-        32-Bit Hardware Implementation (June 30, 1994).  Differences
-        between the documents are noted below.  */
-
-      switch (rel->r_type)
-       {
-       case R_RTB:
-       case R_RRTBI:
-       case R_RRTBA:
-         /* These relocs are defined by the PowerPC ABI to be
-             relative branches which use half of the difference
-             between the symbol and the program counter.  I can't
-             quite figure out when this is useful.  These relocs are
-             not defined by the PowerOpen ABI.  */
-       default:
-         (*_bfd_error_handler)
-           (_("%s: unsupported relocation type 0x%02x"),
-            bfd_get_filename (input_bfd), (unsigned int) rel->r_type);
-         bfd_set_error (bfd_error_bad_value);
-         return false;
-       case R_POS:
-         /* Simple positive relocation.  */
-         break;
-       case R_NEG:
-         /* Simple negative relocation.  */
-         val = - val;
-         break;
-       case R_REL:
-         /* Simple PC relative relocation.  */
-         howto.pc_relative = true;
-         break;
-       case R_TOC:
-         /* TOC relative relocation.  The value in the instruction in
-             the input file is the offset from the input file TOC to
-             the desired location.  We want the offset from the final
-             TOC to the desired location.  We have:
-                isym = iTOC + in
-                iinsn = in + o
-                osym = oTOC + on
-                oinsn = on + o
-            so we must change insn by on - in.
-            */
-       case R_GL:
-         /* Global linkage relocation.  The value of this relocation
-             is the address of the entry in the TOC section.  */
-       case R_TCL:
-         /* Local object TOC address.  I can't figure out the
-             difference between this and case R_GL.  */
-       case R_TRL:
-         /* TOC relative relocation.  A TOC relative load instruction
-             which may be changed to a load address instruction.
-             FIXME: We don't currently implement this optimization.  */
-       case R_TRLA:
-         /* TOC relative relocation.  This is a TOC relative load
-             address instruction which may be changed to a load
-             instruction.  FIXME: I don't know if this is the correct
-             implementation.  */
-         if (h != NULL && h->smclas != XMC_TD)
-           {
-             if (h->toc_section == NULL)
-               {
-                 (*_bfd_error_handler)
-                   (_("%s: TOC reloc at 0x%x to symbol `%s' with no TOC entry"),
-                    bfd_get_filename (input_bfd), rel->r_vaddr,
-                    h->root.root.string);
-                 bfd_set_error (bfd_error_bad_value);
-                 return false;
-               }
-
-             BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
-             val = (h->toc_section->output_section->vma
-                    + h->toc_section->output_offset);
-           }
-
-         val = ((val - xcoff_data (output_bfd)->toc)
-                - (sym->n_value - xcoff_data (input_bfd)->toc));
-         addend = 0;
-         break;
-       case R_BA:
-         /* Absolute branch.  We don't want to mess with the lower
-             two bits of the instruction.  */
-       case R_CAI:
-         /* The PowerPC ABI defines this as an absolute call which
-             may be modified to become a relative call.  The PowerOpen
-             ABI does not define this relocation type.  */
-       case R_RBA:
-         /* Absolute branch which may be modified to become a
-             relative branch.  */
-       case R_RBAC:
-         /* The PowerPC ABI defines this as an absolute branch to a
-             fixed address which may be modified to an absolute branch
-             to a symbol.  The PowerOpen ABI does not define this
-             relocation type.  */
-       case R_RBRC:
-         /* The PowerPC ABI defines this as an absolute branch to a
-             fixed address which may be modified to a relative branch.
-             The PowerOpen ABI does not define this relocation type.  */
-         howto.src_mask &= ~3;
-         howto.dst_mask = howto.src_mask;
-         break;
-       case R_BR:
-         /* Relative branch.  We don't want to mess with the lower
-             two bits of the instruction.  */
-       case R_CREL:
-         /* The PowerPC ABI defines this as a relative call which may
-             be modified to become an absolute call.  The PowerOpen
-             ABI does not define this relocation type.  */
-       case 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.  */
-         howto.pc_relative = true;
-         howto.src_mask &= ~3;
-         howto.dst_mask = howto.src_mask;
-         break;
-       case R_RL:
-         /* The PowerPC AIX ABI describes this as a load which may be
-             changed to a load address.  The PowerOpen ABI says this
-             is the same as case R_POS.  */
-         break;
-       case R_RLA:
-         /* The PowerPC AIX ABI describes this as a load address
-             which may be changed to a load.  The PowerOpen ABI says
-             this is the same as R_POS.  */
-         break;
-       }
-
-      /* 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
-         instruction, we replace the cror with lwz r2,20(r1).  This
-         restores the TOC after the glink code.  Contrariwise, if the
-         call is followed by a lwz r2,20(r1), but the call is not
-         going to global linkage code, we can replace the load with a
-         cror.  */
-      if ((rel->r_type == R_BR || rel->r_type == R_RBR)
-         && h != NULL
-         && h->root.type == bfd_link_hash_defined
-         && (rel->r_vaddr - input_section->vma + 8
-             <= input_section->_cooked_size))
-       {
-         bfd_byte *pnext;
-         unsigned long next;
-
-         pnext = contents + (rel->r_vaddr - input_section->vma) + 4;
-         next = bfd_get_32 (input_bfd, pnext);
-
-         /* The _ptrgl function is magic.  It is used by the AIX
-             compiler to call a function through a pointer.  */
-         if (h->smclas == XMC_GL
-             || strcmp (h->root.root.string, "._ptrgl") == 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) */
-           }
-         else
-           {
-             if (next == 0x80410014)           /* lwz r1,20(r1) */
-               bfd_put_32 (input_bfd, 0x60000000, pnext); /* ori r0,r0,0 */
-           }
-       }
-
-      /* A PC relative reloc includes the section address.  */
-      if (howto.pc_relative)
-       addend += input_section->vma;
-
-      rstat = _bfd_final_link_relocate (&howto, input_bfd, input_section,
-                                       contents,
-                                       rel->r_vaddr - input_section->vma,
-                                       val, addend);
-
-      switch (rstat)
-       {
-       default:
-         abort ();
-       case bfd_reloc_ok:
-         break;
-       case bfd_reloc_overflow:
-         {
-           const char *name;
-           char buf[SYMNMLEN + 1];
-           char howto_name[10];
-
-           if (symndx == -1)
-             name = "*ABS*";
-           else if (h != NULL)
-             name = h->root.root.string;
-           else
-             {
-               name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
-               if (name == NULL)
-                 return false;
-             }
-           sprintf (howto_name, "0x%02x", rel->r_type);
-
-           if (! ((*info->callbacks->reloc_overflow)
-                  (info, name, howto_name, (bfd_vma) 0, input_bfd,
-                   input_section, rel->r_vaddr - input_section->vma)))
-             return false;
-         }
-       }
-    }
-
-  return true;
-}
This page took 0.120768 seconds and 4 git commands to generate.