This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

xcoff64 bfd-xcofflink.c.patch




xcofflink.c :
	Many changes for xcoff64 support
	Move common structures to include/coff/xcoff.h
	Move specific structure to backends coff-rs6000.c and coff64-rs6000.c
	Use new backend functions, defined in libxcoff.h, to isolate 32/64
	dependencies.
	(bfd_xcoff_size_dynamic_sections) : special __rtinit symbol for
	aix4.2+ -binitfini.
	(xcoff_build_ldsyms) : handle special __rtinit symbol.


----------------------------------------------------------------------------
-

diff -rcp sources-original/src/bfd/xcofflink.c sources/src/bfd/xcofflink.c
*** sources-original/src/bfd/xcofflink.c	Sat Jan 20 00:28:28 2001
--- sources/src/bfd/xcofflink.c	Mon Jan 29 11:48:33 2001
*************** Foundation, Inc., 59 Temple Place - Suit
*** 23,208 ****
  #include "bfdlink.h"
  #include "libbfd.h"
  #include "coff/internal.h"
  #include "libcoff.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 {
--- 23,41 ----
  #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)

  /* 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 list of import files.  */

  struct xcoff_import_file {
*************** struct xcoff_import_file {
*** 216,349 ****
    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.  */

--- 49,54 ----
*************** struct xcoff_final_link_info {
*** 383,391 ****
    /* Symbol index of TOC symbol.  */
    long toc_symindx;
    /* Start of .loader symbols.  */
!   struct external_ldsym *ldsym;
    /* Next .loader reloc to swap out.  */
!   struct external_ldrel *ldrel;
    /* File position of start of line numbers.  */
    file_ptr line_filepos;
    /* Buffer large enough to hold swapped symbols of any input file.  */
--- 88,96 ----
    /* Symbol index of TOC symbol.  */
    long toc_symindx;
    /* Start of .loader symbols.  */
!   bfd_byte *ldsym;
    /* Next .loader reloc to swap out.  */
!   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.  */
*************** struct xcoff_final_link_info {
*** 404,421 ****
    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 *));
--- 109,114 ----
*************** static boolean xcoff_reloc_link_order
*** 450,570 ****
  	   struct bfd_link_order *));
  static int xcoff_sort_relocs PARAMS ((const PTR, const PTR));
  
- /* 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);
- }
- 
  /* Routines to read XCOFF dynamic information.  This don't really
     belong here, but we already have the ldsym manipulation routines
     here.  */
--- 143,149 ----
*************** _bfd_xcoff_get_dynamic_symtab_upper_boun
*** 627,633 ****
      return -1;
    contents = coff_section_data (abfd, lsec)->contents;

!   xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);

    return (ldhdr.l_nsyms + 1) * sizeof (asymbol *);
  }
--- 206,212 ----
      return -1;
    contents = coff_section_data (abfd, lsec)->contents;

!   bfd_xcoff_swap_ldhdr_in (abfd, (PTR) contents, &ldhdr);

    return (ldhdr.l_nsyms + 1) * sizeof (asymbol *);
  }
*************** _bfd_xcoff_canonicalize_dynamic_symtab (
*** 643,649 ****
    bfd_byte *contents;
    struct internal_ldhdr ldhdr;
    const char *strings;
!   struct external_ldsym *elsym, *elsymend;
    coff_symbol_type *symbuf;

    if ((abfd->flags & DYNAMIC) == 0)
--- 222,228 ----
    bfd_byte *contents;
    struct internal_ldhdr ldhdr;
    const char *strings;
!   bfd_byte *elsym, *elsymend;
    coff_symbol_type *symbuf;

    if ((abfd->flags & DYNAMIC) == 0)
*************** _bfd_xcoff_canonicalize_dynamic_symtab (
*** 665,671 ****

    coff_section_data (abfd, lsec)->keep_contents = true;

!   xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents, &ldhdr);

    strings = (char *) contents + ldhdr.l_stoff;

--- 244,250 ----

    coff_section_data (abfd, lsec)->keep_contents = true;

!   bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);

    strings = (char *) contents + ldhdr.l_stoff;

*************** _bfd_xcoff_canonicalize_dynamic_symtab (
*** 674,686 ****
    if (symbuf == NULL)
      return -1;

!   elsym = (struct external_ldsym *) (contents + LDHDRSZ);
!   elsymend = elsym + ldhdr.l_nsyms;
!   for (; elsym < elsymend; elsym++, symbuf++, psyms++)
      {
        struct internal_ldsym ldsym;

!       xcoff_swap_ldsym_in (abfd, elsym, &ldsym);

        symbuf->symbol.the_bfd = abfd;

--- 253,266 ----
    if (symbuf == NULL)
      return -1;

!   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;

!       bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);

        symbuf->symbol.the_bfd = abfd;

*************** _bfd_xcoff_canonicalize_dynamic_symtab (
*** 688,711 ****
  	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;
! 	    }
  	}

        if (ldsym.l_smclas == XMC_XO)
--- 268,281 ----
  	symbuf->symbol.name = strings + ldsym._l._l_l._l_offset;
        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;
  	}

        if (ldsym.l_smclas == XMC_XO)
*************** _bfd_xcoff_get_dynamic_reloc_upper_bound
*** 757,784 ****
      return -1;
    contents = coff_section_data (abfd, lsec)->contents;

!   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
--- 327,337 ----
      return -1;
    contents = coff_section_data (abfd, lsec)->contents;

!   bfd_xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) contents,
&ldhdr);

    return (ldhdr.l_nreloc + 1) * sizeof (arelent *);
  }

  /* Get the dynamic relocs.  */

  long
*************** _bfd_xcoff_canonicalize_dynamic_reloc (a
*** 791,797 ****
    bfd_byte *contents;
    struct internal_ldhdr ldhdr;
    arelent *relbuf;
!   struct external_ldrel *elrel, *elrelend;

    if ((abfd->flags & DYNAMIC) == 0)
      {
--- 344,350 ----
    bfd_byte *contents;
    struct internal_ldhdr ldhdr;
    arelent *relbuf;
!   bfd_byte *elrel, *elrelend;

    if ((abfd->flags & DYNAMIC) == 0)
      {
*************** _bfd_xcoff_canonicalize_dynamic_reloc (a
*** 810,829 ****
      return -1;
    contents = coff_section_data (abfd, lsec)->contents;

!   xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) 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++)
      {
        struct internal_ldrel ldrel;

!       xcoff_swap_ldrel_in (abfd, elrel, &ldrel);

        if (ldrel.l_symndx >= 3)
  	relbuf->sym_ptr_ptr = syms + (ldrel.l_symndx - 3);
--- 363,383 ----
      return -1;
    contents = coff_section_data (abfd, lsec)->contents;

!   bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);

    relbuf = (arelent *) bfd_alloc (abfd, ldhdr.l_nreloc * sizeof
(arelent));
    if (relbuf == NULL)
      return -1;

!   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;

!       bfd_xcoff_swap_ldrel_in (abfd, elrel, &ldrel);

        if (ldrel.l_symndx >= 3)
  	relbuf->sym_ptr_ptr = syms + (ldrel.l_symndx - 3);
*************** _bfd_xcoff_canonicalize_dynamic_reloc (a
*** 864,870 ****
        /* 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;

        /* FIXME: We have no way to record the l_rsecnm field.  */

--- 418,424 ----
        /* 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 = bfd_xcoff_dynamic_reloc_howto(abfd);

        /* FIXME: We have no way to record the l_rsecnm field.  */

*************** _bfd_xcoff_bfd_link_hash_table_create (a
*** 954,978 ****
    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))
  
  /* Read internal relocs for an XCOFF csect.  This is a wrapper around
     _bfd_coff_read_internal_relocs which tries to take advantage of any
--- 508,513 ----
*************** xcoff_link_check_ar_symbols (abfd, info,
*** 1177,1182 ****
--- 712,718 ----
               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);
*************** xcoff_link_check_ar_symbols (abfd, info,
*** 1188,1194 ****
  	     undefined references in shared objects.  */
  	  if (h != (struct bfd_link_hash_entry *) NULL
  	      && h->type == bfd_link_hash_undefined
! 	      && (info->hash->creator != abfd->xvec
  		  || (((struct xcoff_link_hash_entry *) h)->flags
  		      & XCOFF_DEF_DYNAMIC) == 0))
  	    {
--- 724,730 ----
  	     undefined references in shared objects.  */
  	  if (h != (struct bfd_link_hash_entry *) NULL
  	      && h->type == bfd_link_hash_undefined
!  	      && (info->hash->creator != abfd->xvec
  		  || (((struct xcoff_link_hash_entry *) h)->flags
  		      & XCOFF_DEF_DYNAMIC) == 0))
  	    {
*************** xcoff_link_check_dynamic_ar_symbols (abf
*** 1217,1226 ****
       boolean *pneeded;
  {
    asection *lsec;
!   bfd_byte *buf;
    struct internal_ldhdr ldhdr;
    const char *strings;
!   struct external_ldsym *elsym, *elsymend;

    *pneeded = false;

--- 753,762 ----
       boolean *pneeded;
  {
    asection *lsec;
!   bfd_byte *contents;
    struct internal_ldhdr ldhdr;
    const char *strings;
!   bfd_byte *elsym, *elsymend;

    *pneeded = false;

*************** xcoff_link_check_dynamic_ar_symbols (abf
*** 1233,1254 ****

    if (! xcoff_get_section_contents (abfd, lsec))
      return false;
!   buf = coff_section_data (abfd, lsec)->contents;

!   xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) buf, &ldhdr);

!   strings = (char *) buf + ldhdr.l_stoff;

!   elsym = (struct external_ldsym *) (buf + LDHDRSZ);
!   elsymend = elsym + ldhdr.l_nsyms;
!   for (; elsym < elsymend; elsym++)
      {
        struct internal_ldsym ldsym;
        char nambuf[SYMNMLEN + 1];
        const char *name;
        struct bfd_link_hash_entry *h;

!       xcoff_swap_ldsym_in (abfd, elsym, &ldsym);

        /* We are only interested in exported symbols.  */
        if ((ldsym.l_smtype & L_EXPORT) == 0)
--- 769,791 ----

    if (! xcoff_get_section_contents (abfd, lsec))
      return false;
!   contents = coff_section_data (abfd, lsec)->contents;
!
!   bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);

!   strings = (char *) contents + ldhdr.l_stoff;

!   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))
      {
        struct internal_ldsym ldsym;
        char nambuf[SYMNMLEN + 1];
        const char *name;
        struct bfd_link_hash_entry *h;

!       bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);

        /* We are only interested in exported symbols.  */
        if ((ldsym.l_smtype & L_EXPORT) == 0)
*************** xcoff_link_check_dynamic_ar_symbols (abf
*** 1282,1288 ****

    /* We do not need this shared object.  */

!   if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
      {
        free (coff_section_data (abfd, lsec)->contents);
        coff_section_data (abfd, lsec)->contents = NULL;
--- 819,825 ----

    /* We do not need this shared object.  */

!   if (contents != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
      {
        free (coff_section_data (abfd, lsec)->contents);
        coff_section_data (abfd, lsec)->contents = NULL;
*************** xcoff_find_reloc (relocs, count, address
*** 1341,1346 ****
--- 878,977 ----
    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
*************** xcoff_link_add_symbols (abfd, info)
*** 1380,1468 ****
    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;
!
    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;
      }

!   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;
! 	}
!     }

    if ((abfd->flags & DYNAMIC) != 0
        && ! info->static_link)
--- 1011,1036 ----
    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;
!
    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;
      }
+   }

!   /* 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)
*************** xcoff_link_add_symbols (abfd, info)
*** 1480,1486 ****
    else
      default_copy = true;

!   symcount = obj_raw_syment_count (abfd);

    /* We keep a list of the linker hash table entries that correspond
       to each external symbol.  */
--- 1048,1054 ----
    else
      default_copy = true;

!   symcount = obj_raw_syment_count (abfd);

    /* We keep a list of the linker hash table entries that correspond
       to each external symbol.  */
*************** xcoff_link_add_symbols (abfd, info)
*** 1520,1556 ****
    /* 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 *));
! 	}

!       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;
--- 1088,1127 ----
    /* 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 *));
!
!     }
!
!     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;
*************** xcoff_link_add_symbols (abfd, info)
*** 1563,1610 ****
    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);

!       /* 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;
! 	}

!       name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
!       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
--- 1134,1190 ----
    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);
!
!     /* 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;
!       }

!       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);

!     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
*************** xcoff_link_add_symbols (abfd, info)
*** 1612,1697 ****
           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;
! 		    }
! 		}
! 	    }
! 	}

!       /* 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);

--- 1192,1270 ----
           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_signed_vma 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;
+ 	  }
+ 	}
+       }
+     }

!     /* 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);

*************** xcoff_link_add_symbols (abfd, info)
*** 1738,1744 ****

  	case XTY_SD:
  	  /* This is a csect definition.  */
-
  	  if (csect != NULL)
  	    {
  	      xcoff_section_data (abfd, csect)->last_symndx =
--- 1311,1316 ----
*************** xcoff_link_add_symbols (abfd, info)
*** 1766,1909 ****
  	      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 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;
! 			}
! 		    }
! 		}
! 	    }

- 	  /* 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;
! 	      }

! 	    csect_name = csect_name_by_class[aux.x_csect.x_smclas];
! 	    csect = bfd_make_section_anyway (abfd, csect_name);
! 	    if (csect == NULL)
  	      goto error_return;
  	    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;
! 	      }
  	    csect->vma = sym.n_value;
  	    csect->filepos = (enclosing->filepos
  			      + sym.n_value
--- 1338,1492 ----
  	      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 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)))) {

! 	    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;
!
! 	      /*
! 	       * 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 */

  	  {
!
  	    asection *enclosing;

! 	    /* 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 = 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;
! 	    }
  	    csect->vma = sym.n_value;
  	    csect->filepos = (enclosing->filepos
  			      + sym.n_value
*************** xcoff_link_add_symbols (abfd, info)
*** 1926,1958 ****
  	    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;
! 		  }
  	      }

  	    /* There are a number of other fields and section flags
  	       which we do not bother to set.  */
--- 1509,1542 ----
  	    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;
  	      }
+ 	    }

  	    /* There are a number of other fields and section flags
  	       which we do not bother to set.  */
*************** xcoff_link_add_symbols (abfd, info)
*** 2029,2038 ****
  		 / symesz);
  	    }

! 	  if (aux.x_csect.x_smclas == XMC_TD)
! 	    csect = bfd_make_section_anyway (abfd, ".tocbss");
! 	  else
  	    csect = bfd_make_section_anyway (abfd, ".bss");
  	  if (csect == NULL)
  	    goto error_return;
  	  csect->vma = sym.n_value;
--- 1613,1628 ----
  		 / symesz);
  	    }

! 	  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;
*************** xcoff_link_add_symbols (abfd, info)
*** 2071,2102 ****
  	}

        /* 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;
! 	}

        /* Now we have enough information to add the symbol to the
           linker hash table.  */
--- 1661,1691 ----
  	}

        /* 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 = -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.  */
*************** xcoff_link_add_symbols (abfd, info)
*** 2139,2145 ****
  	     shared object, which will cause symbol redefinitions,
  	     although this is an easier case to detect.  */

! 	  if (info->hash->creator == abfd->xvec)
  	    {
  	      if (! bfd_is_und_section (section))
  		*sym_hash = xcoff_link_hash_lookup (xcoff_hash_table (info),
--- 1728,1734 ----
  	     shared object, which will cause symbol redefinitions,
  	     although this is an easier case to detect.  */

!  	  if (info->hash->creator == abfd->xvec)
  	    {
  	      if (! bfd_is_und_section (section))
  		*sym_hash = xcoff_link_hash_lookup (xcoff_hash_table (info),
*************** xcoff_link_add_symbols (abfd, info)
*** 2261,2271 ****
  	      else
  		{
  		  (*sym_hash)->root.u.c.p->alignment_power
! 		    = csect->alignment_power;
  		}
  	    }

! 	  if (info->hash->creator == abfd->xvec)
  	    {
  	      int flag;

--- 1850,1860 ----
  	      else
  		{
  		  (*sym_hash)->root.u.c.p->alignment_power
! 		     = csect->alignment_power;
  		}
  	    }

!  	  if (info->hash->creator == abfd->xvec)
  	    {
  	      int flag;

*************** xcoff_link_add_symbols (abfd, info)
*** 2309,2316 ****
--- 1898,1907 ----

  	  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)
*************** xcoff_link_add_symbols (abfd, info)
*** 2323,2329 ****
  	      /* 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
  		  && *rel_csect != bfd_und_section_ptr
  		  && (rel->r_type == R_BR
  		      || rel->r_type == R_RBR)
--- 1914,1920 ----
  	      /* 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
  		  && *rel_csect != bfd_und_section_ptr
  		  && (rel->r_type == R_BR
  		      || rel->r_type == R_RBR)
*************** xcoff_link_add_symbols (abfd, info)
*** 2376,2382 ****

  	  /* Reset SEC_RELOC and the reloc_count, since the reloc
  	     information is now attached to the csects.  */
! 	  o->flags &= ~SEC_RELOC;
  	  o->reloc_count = 0;

  	  /* If we are not keeping memory, free the reloc information.  */
--- 1967,1973 ----

  	  /* Reset SEC_RELOC and the reloc_count, since the reloc
  	     information is now attached to the csects.  */
! 	  o->flags &=~ SEC_RELOC;
  	  o->reloc_count = 0;

  	  /* If we are not keeping memory, free the reloc information.  */
*************** xcoff_link_add_dynamic_symbols (abfd, in
*** 2433,2442 ****
       struct bfd_link_info *info;
  {
    asection *lsec;
!   bfd_byte *buf;
    struct internal_ldhdr ldhdr;
    const char *strings;
!   struct external_ldsym *elsym, *elsymend;
    struct xcoff_import_file *n;
    const char *bname;
    const char *mname;
--- 2024,2033 ----
       struct bfd_link_info *info;
  {
    asection *lsec;
!   bfd_byte *contents;
    struct internal_ldhdr ldhdr;
    const char *strings;
!   bfd_byte *elsym, *elsymend;
    struct xcoff_import_file *n;
    const char *bname;
    const char *mname;
*************** xcoff_link_add_dynamic_symbols (abfd, in
*** 2446,2460 ****

    /* We can only handle a dynamic object if we are generating an XCOFF
       output file.  */
!   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);
        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
--- 2037,2051 ----

    /* We can only handle a dynamic object if we are generating an XCOFF
       output file.  */
!    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);
        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
*************** xcoff_link_add_dynamic_symbols (abfd, in
*** 2476,2504 ****
        return false;
      }

    if (! xcoff_get_section_contents (abfd, lsec))
      return false;
!   buf = 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);

!   strings = (char *) buf + ldhdr.l_stoff;

!   elsym = (struct external_ldsym *) (buf + LDHDRSZ);
!   elsymend = elsym + ldhdr.l_nsyms;
!   BFD_ASSERT (sizeof (struct external_ldsym) == LDSYMSZ);
!   for (; elsym < elsymend; elsym++)
      {
        struct internal_ldsym ldsym;
        char nambuf[SYMNMLEN + 1];
        const char *name;
        struct xcoff_link_hash_entry *h;

!       xcoff_swap_ldsym_in (abfd, elsym, &ldsym);

        /* We are only interested in exported symbols.  */
        if ((ldsym.l_smtype & L_EXPORT) == 0)
--- 2067,2097 ----
        return false;
      }

+
    if (! xcoff_get_section_contents (abfd, lsec))
      return false;
!   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;

!   bfd_xcoff_swap_ldhdr_in (abfd, contents, &ldhdr);

!   strings = (char *) contents + ldhdr.l_stoff;
!
!   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))
      {
        struct internal_ldsym ldsym;
        char nambuf[SYMNMLEN + 1];
        const char *name;
        struct xcoff_link_hash_entry *h;

!       bfd_xcoff_swap_ldsym_in (abfd, elsym, &ldsym);

        /* We are only interested in exported symbols.  */
        if ((ldsym.l_smtype & L_EXPORT) == 0)
*************** xcoff_link_add_dynamic_symbols (abfd, in
*** 2617,2623 ****
  	}
      }

!   if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
      {
        free (coff_section_data (abfd, lsec)->contents);
        coff_section_data (abfd, lsec)->contents = NULL;
--- 2210,2216 ----
  	}
      }

!   if (contents != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
      {
        free (coff_section_data (abfd, lsec)->contents);
        coff_section_data (abfd, lsec)->contents = NULL;
*************** xcoff_mark_symbol (info, h)
*** 2675,2680 ****
--- 2268,2274 ----
       struct bfd_link_info *info;
       struct xcoff_link_hash_entry *h;
  {
+
    if ((h->flags & XCOFF_MARK) != 0)
      return true;

*************** xcoff_mark (info, sec)
*** 2714,2719 ****
--- 2308,2314 ----
       struct bfd_link_info *info;
       asection *sec;
  {
+
    if (bfd_is_abs_section (sec)
        || (sec->flags & SEC_MARK) != 0)
      return true;
*************** bfd_xcoff_record_link_assignment (output
*** 3149,3176 ****
    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.
--- 2744,2749 ----
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3220,3231 ****
    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;
!     }

    ldinfo.failed = false;
    ldinfo.output_bfd = output_bfd;
--- 2793,2805 ----
    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 < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++)
!       special_sections[i] = NULL;
!     return true;
!   }

    ldinfo.failed = false;
    ldinfo.output_bfd = output_bfd;
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3243,3258 ****
    xcoff_hash_table (info)->file_align = file_align;
    xcoff_hash_table (info)->textro = textro;

!   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;
      }

    /* Garbage collect unused sections.  */
    if (info->relocateable
        || ! gc
--- 2817,2895 ----
    xcoff_hash_table (info)->file_align = file_align;
    xcoff_hash_table (info)->textro = textro;

!   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;
!   }
!
!   /* __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
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3288,3310 ****
      }

    /* 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;
      }

!   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);
--- 2925,2946 ----
      }

    /* Return special sections to the caller.  */
!   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;
!   }

    xcoff_link_hash_traverse (xcoff_hash_table (info), xcoff_build_ldsyms,
  			    (PTR) &ldinfo);
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3330,3343 ****

    /* Set up the .loader section header.  */
    ldhdr = &xcoff_hash_table (info)->ldhdr;
!   ldhdr->l_version = 1;
    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_stlen = ldinfo.string_size;
    stoff = ldhdr->l_impoff + impsize;
    if (ldinfo.string_size == 0)
--- 2966,2979 ----

    /* Set up the .loader section header.  */
    ldhdr = &xcoff_hash_table (info)->ldhdr;
!   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 = (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)
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3345,3350 ****
--- 2981,2995 ----
    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;
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3354,3361 ****
      goto error_return;

    /* Set up the header.  */
!   xcoff_swap_ldhdr_out (output_bfd, ldhdr,
! 			(struct external_ldhdr *) lsec->contents);

    /* Set up the import file names.  */
    out = (char *) lsec->contents + ldhdr->l_impoff;
--- 2999,3005 ----
      goto error_return;

    /* Set up the header.  */
!   bfd_xcoff_swap_ldhdr_out (output_bfd, ldhdr, lsec->contents);

    /* Set up the import file names.  */
    out = (char *) lsec->contents + ldhdr->l_impoff;
*************** bfd_xcoff_size_dynamic_sections (output_
*** 3394,3400 ****
       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.  */

    /* Allocate space for the magic sections.  */
    sec = xcoff_hash_table (info)->linkage_section;
--- 3038,3045 ----
       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.
!   */

    /* Allocate space for the magic sections.  */
    sec = xcoff_hash_table (info)->linkage_section;
*************** xcoff_build_ldsyms (h, p)
*** 3539,3545 ****
       PTR p;
  {
    struct xcoff_loader_info *ldinfo = (struct xcoff_loader_info *) p;
!   size_t len;

    /* 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
--- 3184,3198 ----
       PTR p;
  {
    struct xcoff_loader_info *ldinfo = (struct xcoff_loader_info *) p;
!
!   /*
!    * __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
*************** xcoff_build_ldsyms (h, p)
*** 3637,3643 ****
        h->root.u.def.value = sec->_raw_size;
        h->smclas = XMC_GL;
        h->flags |= XCOFF_DEF_REGULAR;
!       sec->_raw_size += XCOFF_GLINK_SIZE;

        /* The global linkage code requires a TOC entry for the
           descriptor.  */
--- 3290,3296 ----
        h->root.u.def.value = sec->_raw_size;
        h->smclas = XMC_GL;
        h->flags |= XCOFF_DEF_REGULAR;
!       sec->_raw_size += bfd_xcoff_glink_code_size(ldinfo->output_bfd);

        /* The global linkage code requires a TOC entry for the
           descriptor.  */
*************** xcoff_build_ldsyms (h, p)
*** 3646,3665 ****
  		   || 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 this symbol is exported, but not defined, we need to try to
--- 3299,3334 ----
  		   || hds->root.type == bfd_link_hash_undefweak)
  		  && (hds->flags & XCOFF_DEF_REGULAR) == 0);
        hds->flags |= XCOFF_MARK;
!       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
*************** xcoff_build_ldsyms (h, p)
*** 3688,3702 ****
  	  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.  */
  	  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.  */
  	}
        else
  	{
--- 3357,3381 ----
  	  h->root.u.def.value = sec->_raw_size;
  	  h->smclas = XMC_DS;
  	  h->flags |= XCOFF_DEF_REGULAR;

! 	  /*
! 	   * 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.
! 	   */
  	}
        else
  	{
*************** xcoff_build_ldsyms (h, p)
*** 3765,3810 ****
    if ((h->flags & XCOFF_IMPORT) != 0)
      h->ldsym->l_ifile = h->ldindx;

!   /* The first 3 symbol table indices are reserved to indicate the
!      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;
!     }

    h->flags |= XCOFF_BUILT_LDSYM;

--- 3444,3462 ----
    if ((h->flags & XCOFF_IMPORT) != 0)
      h->ldsym->l_ifile = h->ldindx;

!   /*
!    * 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;

!   if (false == bfd_xcoff_put_ldsymbol_name (ldinfo->output_bfd, ldinfo,
! 					    h->ldsym,
! 					    h->root.root.string)) {
!     return false;
!   }

    h->flags |= XCOFF_BUILT_LDSYM;

*************** _bfd_xcoff_bfd_final_link (abfd, info)
*** 3853,3865 ****
    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));

    xcoff_data (abfd)->coff.link_info = info;

--- 3505,3515 ----
    finfo.contents = NULL;
    finfo.external_relocs = NULL;

!   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;

*************** _bfd_xcoff_bfd_final_link (abfd, info)
*** 3979,3988 ****
  	  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 (strcmp (o->name, ".pad") == 0)
--- 3629,3644 ----
  	  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 ((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)
*************** _bfd_xcoff_bfd_final_link (abfd, info)
*** 4124,4129 ****
--- 3780,3786 ----
    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)));
*************** _bfd_xcoff_bfd_final_link (abfd, info)
*** 4176,4223 ****
  	}
      }

    /* 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;
!     }

    /* 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;
!     }

    /* Write out all the global symbols which do not come from XCOFF
       input files.  */
--- 3833,3875 ----
  	}
      }

+
    /* 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;
!   }

    /* 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;
!   }

    /* Write out all the global symbols which do not come from XCOFF
       input files.  */
*************** _bfd_xcoff_bfd_final_link (abfd, info)
*** 4238,4337 ****
    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;
  	}
!
!       /* 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;

!       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
--- 3890,3979 ----
    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;
      }

+     /* 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;

!     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
*************** _bfd_xcoff_bfd_final_link (abfd, info)
*** 4378,4420 ****

    /* 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;
!     }
!
    /* 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.internal_syms != NULL)
      free (finfo.internal_syms);
    if (finfo.sym_indices != NULL)
--- 4020,4061 ----

    /* 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;
!   }
!
    /* 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.internal_syms != NULL)
      free (finfo.internal_syms);
    if (finfo.sym_indices != NULL)
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 4509,4514 ****
--- 4150,4156 ----

    while (esym < esym_end)
      {
+
        struct internal_syment isym;
        union internal_auxent aux;
        int smtyp = 0;
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 4528,4533 ****
--- 4170,4176 ----
  				isymp->n_type, isymp->n_sclass,
  				isymp->n_numaux - 1, isymp->n_numaux,
  				(PTR) &aux);
+
  	  smtyp = SMTYP_SMTYP (aux.x_csect.x_smtyp);
  	}

*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 4612,4628 ****
  	  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);
  	  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))
  	    xcoff_data (output_bfd)->snentry =
  	      h->root.u.def.section->output_section->target_index;
  	}

        *indexp = -1;
--- 4255,4272 ----
  	  ldsym->l_parm = 0;

  	  BFD_ASSERT (h->ldindx >= 0);
! 	  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)) {
  	    xcoff_data (output_bfd)->snentry =
  	      h->root.u.def.section->output_section->target_index;
+ 	  }
  	}

        *indexp = -1;
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 4715,4720 ****
--- 4359,4365 ----
  	      xcoff_data (finfo->output_bfd)->sntoc =
  		(*csectpp)->output_section->target_index;
  	      require = true;
+
  	    }
  	}

*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 4770,4775 ****
--- 4415,4421 ----
  	  char buf[SYMNMLEN + 1];

  	  name = _bfd_coff_internal_syment_name (input_bfd, &isym, buf);
+
  	  if (name == NULL)
  	    return false;

*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 4810,4815 ****
--- 4456,4462 ----

  		  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);
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 4955,4961 ****
  	  if (isymp->n_sclass == C_BSTAT)
  	    {
  	      struct internal_syment isym;
! 	      unsigned long indx;

  	      /* The value of a C_BSTAT symbol is the symbol table
                   index of the containing csect.  */
--- 4602,4609 ----
  	  if (isymp->n_sclass == C_BSTAT)
  	    {
  	      struct internal_syment isym;
!
! 	      bfd_vma indx;

  	      /* The value of a C_BSTAT symbol is the symbol table
                   index of the containing csect.  */
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 5017,5022 ****
--- 4665,4671 ----
  			|| 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;
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 5024,5043 ****
                       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;

! 		      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;
  			}
  		    }
  		}
--- 4673,4695 ----
                       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)
  		    {
! 		      bfd_signed_vma indx;
!

! 		      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_csect.x_scnlen.l = 0;
! 			  } else {
! 			    aux.x_csect.x_scnlen.l = symindx;
! 			  }
  			}
  		    }
  		}
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 5066,5071 ****
--- 4718,4724 ----
  			  else
  			    indx = finfo->sym_indices[indx];
  			  aux.x_sym.x_fcnary.x_fcn.x_endndx.l = indx;
+
  			}
  		    }

*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 5080,5085 ****
--- 4733,4739 ----
  		      else
  			aux.x_sym.x_tagndx.l = symindx;
  		    }
+
  		}

  	      /* Copy over the line numbers, unless we are stripping
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 5099,5105 ****
  		    {
  		      asection *enclosing;
  		      unsigned int enc_count;
! 		      bfd_size_type linoff;
  		      struct internal_lineno lin;

  		      o = *csectpp;
--- 4753,4759 ----
  		    {
  		      asection *enclosing;
  		      unsigned int enc_count;
! 		      bfd_signed_vma linoff;
  		      struct internal_lineno lin;

  		      o = *csectpp;
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 5280,5598 ****
    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;
!
!       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;

!       /* 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;

! 	  /* 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;

! 	      *rel_hash = NULL;

! 	      /* Adjust the reloc address and symbol index.  */

! 	      irel->r_vaddr += offset;

! 	      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 && 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;

! 		      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)
! 			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;

! 			  if (! ((*finfo->info->callbacks->unattached_reloc)
! 				 (finfo->info, name, input_bfd, o,
! 				  irel->r_vaddr)))
! 			    return false;
! 			}
! 		    }
! 		}

! 	      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;
! 		    }
! 		  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;
! 		}
! 	    }

! 	  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)
--- 4934,5251 ----
    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;
!
!     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;
!
!     /* 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;

!       /* 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;

! 	*rel_hash = NULL;

! 	/* Adjust the reloc address and symbol index.  */

! 	irel->r_vaddr += offset;

! 	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 && 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;

! 		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)
! 		  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;

! 		    if (! ((*finfo->info->callbacks->unattached_reloc)
! 			   (finfo->info, name, input_bfd, o,
! 			    irel->r_vaddr)))
  		      return false;
! 		  }
! 	      }
! 	  }

! 	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);

! 	    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)
*************** xcoff_link_input_bfd (finfo, input_bfd)
*** 5609,5614 ****
--- 5262,5268 ----

  /* Write out a non-XCOFF global symbol.  */

+
  static boolean
  xcoff_write_global_symbol (h, p)
       struct xcoff_link_hash_entry *h;
*************** xcoff_write_global_symbol (h, p)
*** 5619,5624 ****
--- 5273,5279 ----
    bfd_byte *outsym;
    struct internal_syment isym;
    union internal_auxent aux;
+   boolean result;

    output_bfd = finfo->output_bfd;
    outsym = finfo->outsyms;
*************** xcoff_write_global_symbol (h, p)
*** 5629,5725 ****
      return true;

    /* If we need a .loader section entry, write it out.  */
!   if (h->ldsym != NULL)
!     {
!       struct internal_ldsym *ldsym;
!       bfd *impbfd;
!
!       ldsym = h->ldsym;

!       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;

! 	  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 ();

!       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;

!       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_ASSERT (LDSYMSZ == sizeof (struct external_ldsym));
!       xcoff_swap_ldsym_out (output_bfd, ldsym, finfo->ldsym + h->ldindx -
3);
!       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 we created a TOC entry for this symbol, write out the required
       relocs.  */
--- 5284,5406 ----
      return true;

    /* If we need a .loader section entry, write it out.  */
!   if (h->ldsym != NULL) {
!     struct internal_ldsym *ldsym;
!     bfd *impbfd;
!
!     ldsym = h->ldsym;
!
!     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;
!
!       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 ();
!     }

!     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;
!     }

!     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;
!     }
!
!
!     /*
!      * 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.  */
*************** xcoff_write_global_symbol (h, p)
*** 5740,5808 ****
        irel->r_vaddr = (osec->vma
  		       + tocsec->output_offset
  		       + h->u.toc_offset);
!       if (h->indx >= 0)
  	irel->r_symndx = h->indx;
!       else
! 	{
! 	  h->indx = -2;
! 	  irel->r_symndx = obj_raw_syment_count (output_bfd);
! 	}
        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_rsecnm = oindx;
!       xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
!       ++finfo->ldrel;
!
!       /* 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;
!
! 	      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;

! 	  bfd_coff_swap_sym_out (output_bfd, (PTR) &irsym, (PTR) outsym);
! 	  outsym += bfd_coff_symesz (output_bfd);
!
! 	  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_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
  		 need to write them out now.  */
  	      if (bfd_seek (output_bfd,
  			    (obj_sym_filepos (output_bfd)
--- 5421,5502 ----
        irel->r_vaddr = (osec->vma
  		       + tocsec->output_offset
  		       + h->u.toc_offset);
!
!
!       if (h->indx >= 0) {
  	irel->r_symndx = h->indx;
!       } 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;
        finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
        ++osec->reloc_count;

        ldrel.l_vaddr = irel->r_vaddr;
        ldrel.l_symndx = h->ldindx;
!       ldrel.l_rtype = (irel->r_size << 8) | R_POS;
        ldrel.l_rsecnm = oindx;
!       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) {

! 	result = bfd_xcoff_put_symbol_name (output_bfd, finfo->strtab, &irsym,
! 					    h->root.root.string);
! 	if (false == result) {
! 	  return false;
! 	}

! 	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;
!
! 	bfd_coff_swap_sym_out (output_bfd, (PTR) &irsym, (PTR) outsym);
! 	outsym += bfd_coff_symesz (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
  		 need to write them out now.  */
  	      if (bfd_seek (output_bfd,
  			    (obj_sym_filepos (output_bfd)
*************** xcoff_write_global_symbol (h, p)
*** 5821,5830 ****
  	}
      }

!   /* 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 ((h->flags & XCOFF_DESCRIPTOR) != 0
        && h->root.type == bfd_link_hash_defined
        && (h->root.u.def.section
--- 5515,5532 ----
  	}
      }

!   /*
!    * 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
*************** xcoff_write_global_symbol (h, p)
*** 5839,5844 ****
--- 5541,5557 ----
        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;
*************** xcoff_write_global_symbol (h, p)
*** 5850,5860 ****
  		  && (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
--- 5563,5568 ----
*************** xcoff_write_global_symbol (h, p)
*** 5862,5868 ****
  		       + h->root.u.def.value);
        irel->r_symndx = esec->output_section->target_index;
        irel->r_type = R_POS;
!       irel->r_size = 31;
        finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
        ++osec->reloc_count;

--- 5570,5576 ----
  		       + h->root.u.def.value);
        irel->r_symndx = esec->output_section->target_index;
        irel->r_type = R_POS;
!       irel->r_size = reloc_size;
        finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
        ++osec->reloc_count;

*************** xcoff_write_global_symbol (h, p)
*** 5882,5894 ****
  	  bfd_set_error (bfd_error_nonrepresentable_section);
  	  return false;
  	}
!       ldrel.l_rtype = (31 << 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);

        tsec = coff_section_from_bfd_index (output_bfd,
  					  xcoff_data (output_bfd)->sntoc);

--- 5590,5627 ----
  	  bfd_set_error (bfd_error_nonrepresentable_section);
  	  return false;
  	}
!       ldrel.l_rtype = (reloc_size << 8) | R_POS;
        ldrel.l_rsecnm = oindx;
!       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);

*************** xcoff_write_global_symbol (h, p)
*** 5896,5905 ****
        irel->r_vaddr = (osec->vma
  		       + sec->output_offset
  		       + h->root.u.def.value
! 		       + 4);
        irel->r_symndx = tsec->output_section->target_index;
        irel->r_type = R_POS;
!       irel->r_size = 31;
        finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
        ++osec->reloc_count;

--- 5629,5638 ----
        irel->r_vaddr = (osec->vma
  		       + sec->output_offset
  		       + h->root.u.def.value
! 		       + byte_size);
        irel->r_symndx = tsec->output_section->target_index;
        irel->r_type = R_POS;
!       irel->r_size = reloc_size;
        finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
        ++osec->reloc_count;

*************** xcoff_write_global_symbol (h, p)
*** 5919,5928 ****
  	  bfd_set_error (bfd_error_nonrepresentable_section);
  	  return false;
  	}
!       ldrel.l_rtype = (31 << 8) | R_POS;
        ldrel.l_rsecnm = oindx;
!       xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
!       ++finfo->ldrel;
      }

    if (h->indx >= 0 || finfo->info->strip == strip_all)
--- 5652,5661 ----
  	  bfd_set_error (bfd_error_nonrepresentable_section);
  	  return false;
  	}
!       ldrel.l_rtype = (reloc_size << 8) | R_POS;
        ldrel.l_rsecnm = oindx;
!       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)
*************** xcoff_write_global_symbol (h, p)
*** 5953,5975 ****

    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;
!     }

    if (h->root.type == bfd_link_hash_undefined
        || h->root.type == bfd_link_hash_undefweak)
--- 5686,5696 ----

    h->indx = obj_raw_syment_count (output_bfd);

!   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)
*************** xcoff_write_global_symbol (h, p)
*** 6034,6040 ****
    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);
--- 5755,5760 ----
*************** xcoff_write_global_symbol (h, p)
*** 6053,6059 ****

        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);
--- 5773,5778 ----
*************** xcoff_reloc_link_order (output_bfd, finf
*** 6252,6259 ****

    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;

    return true;
  }
--- 5971,5978 ----

    ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
    ldrel.l_rsecnm = output_section->target_index;
!   bfd_xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
!   finfo->ldrel += bfd_xcoff_ldrelsz(output_bfd);

    return true;
  }
*************** xcoff_sort_relocs (p1, p2)
*** 6276,6630 ****
      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;
- }
--- 5995,6000 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]