* elf-hppa.h (elf_hppa_fake_sections): Compute section indices
[deliverable/binutils-gdb.git] / bfd / xcofflink.c
index 3892f171516d52c7e213a1ff7542fba7481574d9..9ec75bd01d8f4edabd7300b9bad2dbeacfc51bab 100644 (file)
@@ -1,5 +1,5 @@
 /* POWER/PowerPC XCOFF linker support.
 /* POWER/PowerPC XCOFF linker support.
-   Copyright 1995, 1996 Free Software Foundation, Inc.
+   Copyright 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian@cygnus.com>, Cygnus Support.
 
 This file is part of BFD, the Binary File Descriptor library.
    Written by Ian Lance Taylor <ian@cygnus.com>, Cygnus Support.
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -269,7 +269,9 @@ struct xcoff_link_hash_entry
   /* The .loader symbol table entry, if there is one.  */
   struct internal_ldsym *ldsym;
 
   /* The .loader symbol table entry, if there is one.  */
   struct internal_ldsym *ldsym;
 
-  /* The .loader symbol table index.  */
+  /* 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.  */
   long ldindx;
 
   /* Some linker flags.  */
@@ -443,6 +445,7 @@ 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 *));
   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 *));
 static struct internal_reloc *xcoff_read_internal_relocs
   PARAMS ((bfd *, asection *, boolean, bfd_byte *, boolean,
           struct internal_reloc *));
 static struct internal_reloc *xcoff_read_internal_relocs
   PARAMS ((bfd *, asection *, boolean, bfd_byte *, boolean,
           struct internal_reloc *));
@@ -459,6 +462,8 @@ static bfd_size_type xcoff_find_reloc
 static boolean xcoff_link_add_symbols PARAMS ((bfd *, struct bfd_link_info *));
 static boolean xcoff_link_add_dynamic_symbols
   PARAMS ((bfd *, struct bfd_link_info *));
 static boolean xcoff_link_add_symbols PARAMS ((bfd *, struct bfd_link_info *));
 static boolean xcoff_link_add_dynamic_symbols
   PARAMS ((bfd *, struct bfd_link_info *));
+static boolean xcoff_mark_symbol
+  PARAMS ((struct bfd_link_info *, struct xcoff_link_hash_entry *));
 static boolean xcoff_mark PARAMS ((struct bfd_link_info *, asection *));
 static void xcoff_sweep PARAMS ((struct bfd_link_info *));
 static boolean xcoff_build_ldsyms
 static boolean xcoff_mark PARAMS ((struct bfd_link_info *, asection *));
 static void xcoff_sweep PARAMS ((struct bfd_link_info *));
 static boolean xcoff_build_ldsyms
@@ -608,7 +613,8 @@ xcoff_get_section_contents (abfd, sec)
 
   if (coff_section_data (abfd, sec)->contents == NULL)
     {
 
   if (coff_section_data (abfd, sec)->contents == NULL)
     {
-      coff_section_data (abfd, sec)->contents = bfd_malloc (sec->_raw_size);
+      coff_section_data (abfd, sec)->contents =
+       (bfd_byte *) bfd_malloc (sec->_raw_size);
       if (coff_section_data (abfd, sec)->contents == NULL)
        return false;
 
       if (coff_section_data (abfd, sec)->contents == NULL)
        return false;
 
@@ -715,7 +721,7 @@ _bfd_xcoff_canonicalize_dynamic_symtab (abfd, psyms)
            if (ldsym._l._l_name[i] == '\0')
              break;
          if (i < SYMNMLEN)
            if (ldsym._l._l_name[i] == '\0')
              break;
          if (i < SYMNMLEN)
-           symbuf->symbol.name = elsym->_l._l_name;
+           symbuf->symbol.name = (char *) elsym->_l._l_name;
          else
            {
              char *c;
          else
            {
              char *c;
@@ -1408,6 +1414,8 @@ xcoff_link_add_symbols (abfd, info)
       bfd_byte *linenos;
     } *reloc_info = NULL;
 
       bfd_byte *linenos;
     } *reloc_info = NULL;
 
+  keep_syms = obj_coff_keep_syms (abfd);
+
   if ((abfd->flags & DYNAMIC) != 0
       && ! info->static_link)
     {
   if ((abfd->flags & DYNAMIC) != 0
       && ! info->static_link)
     {
@@ -1470,7 +1478,8 @@ xcoff_link_add_symbols (abfd, info)
          dsec->alignment_power = 2;
        }
       /* Likewise for the .debug section.  */
          dsec->alignment_power = 2;
        }
       /* Likewise for the .debug section.  */
-      if (xcoff_hash_table (info)->debug_section == NULL)
+      if (xcoff_hash_table (info)->debug_section == NULL
+         && info->strip != strip_all)
        {
          asection *dsec;
 
        {
          asection *dsec;
 
@@ -1571,7 +1580,6 @@ xcoff_link_add_symbols (abfd, info)
     }
 
   /* Don't let the linker relocation routines discard the symbols.  */
     }
 
   /* Don't let the linker relocation routines discard the symbols.  */
-  keep_syms = obj_coff_keep_syms (abfd);
   obj_coff_keep_syms (abfd) = true;
 
   csect = NULL;
   obj_coff_keep_syms (abfd) = true;
 
   csect = NULL;
@@ -1650,7 +1658,7 @@ xcoff_link_add_symbols (abfd, info)
              if (enclosing == NULL)
                {
                  (*_bfd_error_handler)
              if (enclosing == NULL)
                {
                  (*_bfd_error_handler)
-                   ("%s: `%s' has line numbers but no enclosing section",
+                   (_("%s: `%s' has line numbers but no enclosing section"),
                     bfd_get_filename (abfd), name);
                  bfd_set_error (bfd_error_bad_value);
                  goto error_return;
                     bfd_get_filename (abfd), name);
                  bfd_set_error (bfd_error_bad_value);
                  goto error_return;
@@ -1702,7 +1710,7 @@ xcoff_link_add_symbols (abfd, info)
       if (sym.n_numaux == 0)
        {
          (*_bfd_error_handler)
       if (sym.n_numaux == 0)
        {
          (*_bfd_error_handler)
-           ("%s: class %d symbol `%s' has no aux entries",
+           (_("%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_get_filename (abfd), sym.n_sclass, name);
          bfd_set_error (bfd_error_bad_value);
          goto error_return;
@@ -1725,7 +1733,7 @@ xcoff_link_add_symbols (abfd, info)
        {
        default:
          (*_bfd_error_handler)
        {
        default:
          (*_bfd_error_handler)
-           ("%s: symbol `%s' has unrecognized csect type %d",
+           (_("%s: symbol `%s' has unrecognized csect type %d"),
             bfd_get_filename (abfd), name, smtyp);
          bfd_set_error (bfd_error_bad_value);
          goto error_return;
             bfd_get_filename (abfd), name, smtyp);
          bfd_set_error (bfd_error_bad_value);
          goto error_return;
@@ -1737,7 +1745,7 @@ xcoff_link_add_symbols (abfd, info)
              || aux.x_csect.x_scnlen.l != 0)
            {
              (*_bfd_error_handler)
              || aux.x_csect.x_scnlen.l != 0)
            {
              (*_bfd_error_handler)
-               ("%s: bad XTY_ER symbol `%s': class %d scnum %d scnlen %d",
+               (_("%s: bad XTY_ER symbol `%s': class %d scnum %d scnlen %d"),
                 bfd_get_filename (abfd), name, sym.n_sclass, sym.n_scnum,
                 aux.x_csect.x_scnlen.l);
              bfd_set_error (bfd_error_bad_value);
                 bfd_get_filename (abfd), name, sym.n_sclass, sym.n_scnum,
                 aux.x_csect.x_scnlen.l);
              bfd_set_error (bfd_error_bad_value);
@@ -1776,7 +1784,7 @@ xcoff_link_add_symbols (abfd, info)
                  || aux.x_csect.x_scnlen.l != 0)
                {
                  (*_bfd_error_handler)
                  || aux.x_csect.x_scnlen.l != 0)
                {
                  (*_bfd_error_handler)
-                   ("%s: XMC_TC0 symbol `%s' is class %d scnlen %d",
+                   (_("%s: XMC_TC0 symbol `%s' is class %d scnlen %d"),
                     bfd_get_filename (abfd), name, sym.n_sclass,
                     aux.x_csect.x_scnlen.l);
                  bfd_set_error (bfd_error_bad_value);
                     bfd_get_filename (abfd), name, sym.n_sclass,
                     aux.x_csect.x_scnlen.l);
                  bfd_set_error (bfd_error_bad_value);
@@ -1900,7 +1908,7 @@ xcoff_link_add_symbols (abfd, info)
                || csect_name_by_class[aux.x_csect.x_smclas] == NULL)
              {
                (*_bfd_error_handler)
                || csect_name_by_class[aux.x_csect.x_smclas] == NULL)
              {
                (*_bfd_error_handler)
-                 ("%s: symbol `%s' has unrecognized smclas %d",
+                 (_("%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;
                   bfd_get_filename (abfd), name, aux.x_csect.x_smclas);
                bfd_set_error (bfd_error_bad_value);
                goto error_return;
@@ -1919,7 +1927,7 @@ xcoff_link_add_symbols (abfd, info)
                        > enclosing->vma + enclosing->_raw_size)))
              {
                (*_bfd_error_handler)
                        > enclosing->vma + enclosing->_raw_size)))
              {
                (*_bfd_error_handler)
-                 ("%s: csect `%s' not in enclosing section",
+                 (_("%s: csect `%s' not in enclosing section"),
                   bfd_get_filename (abfd), name);
                bfd_set_error (bfd_error_bad_value);
                goto error_return;
                   bfd_get_filename (abfd), name);
                bfd_set_error (bfd_error_bad_value);
                goto error_return;
@@ -1935,8 +1943,7 @@ xcoff_link_add_symbols (abfd, info)
            /* Record the enclosing section in the tdata for this new
               section.  */
            csect->used_by_bfd =
            /* Record the enclosing section in the tdata for this new
               section.  */
            csect->used_by_bfd =
-             ((struct coff_section_tdata *)
-              bfd_zalloc (abfd, sizeof (struct coff_section_tdata)));
+             (PTR) bfd_zalloc (abfd, sizeof (struct coff_section_tdata));
            if (csect->used_by_bfd == NULL)
              goto error_return;
            coff_section_data (abfd, csect)->tdata =
            if (csect->used_by_bfd == NULL)
              goto error_return;
            coff_section_data (abfd, csect)->tdata =
@@ -2024,7 +2031,7 @@ xcoff_link_add_symbols (abfd, info)
            if (bad)
              {
                (*_bfd_error_handler)
            if (bad)
              {
                (*_bfd_error_handler)
-                 ("%s: misplaced XTY_LD `%s'",
+                 (_("%s: misplaced XTY_LD `%s'"),
                   bfd_get_filename (abfd), name);
                bfd_set_error (bfd_error_bad_value);
                goto error_return;
                   bfd_get_filename (abfd), name);
                bfd_set_error (bfd_error_bad_value);
                goto error_return;
@@ -2036,8 +2043,11 @@ xcoff_link_add_symbols (abfd, info)
 
        case XTY_CM:
          /* This is an unitialized csect.  We could base the name on
 
        case XTY_CM:
          /* This is an unitialized csect.  We could base the name on
-             the storage mapping class, but we don't bother.  If this
-             csect is externally visible, it is a common symbol.  */
+             the storage mapping class, but we don't bother except for
+             an XMC_TD symbol.  If this csect is externally visible,
+             it is a common symbol.  We put XMC_TD symbols in sections
+             named .tocbss, and rely on the linker script to put that
+             in the TOC area.  */
 
          if (csect != NULL)
            {
 
          if (csect != NULL)
            {
@@ -2047,7 +2057,10 @@ xcoff_link_add_symbols (abfd, info)
                 / symesz);
            }
 
                 / symesz);
            }
 
-         csect = bfd_make_section_anyway (abfd, ".bss");
+         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;
          if (csect == NULL)
            goto error_return;
          csect->vma = sym.n_value;
@@ -2062,8 +2075,7 @@ xcoff_link_add_symbols (abfd, info)
                         / symesz);
 
          csect->used_by_bfd =
                         / symesz);
 
          csect->used_by_bfd =
-           ((struct coff_section_tdata *)
-            bfd_zalloc (abfd, sizeof (struct coff_section_tdata)));
+           (PTR) bfd_zalloc (abfd, sizeof (struct coff_section_tdata));
          if (csect->used_by_bfd == NULL)
            goto error_return;
          coff_section_data (abfd, csect)->tdata =
          if (csect->used_by_bfd == NULL)
            goto error_return;
          coff_section_data (abfd, csect)->tdata =
@@ -2143,6 +2155,14 @@ xcoff_link_add_symbols (abfd, info)
             file actually defines an initialized array, so we have to
             actually permit that to work.
 
             file actually defines an initialized array, so we have to
             actually permit that to work.
 
+            Just to make matters even more confusing, the AIX linker
+            appears to permit multiple symbol definitions whenever
+            the second definition is in an archive rather than an
+            object file.  This may be a consequence of the manner in
+            which it handles archives: I think it may load the entire
+            archive in as separate csects, and then let garbage
+            collection discard symbols.
+
             We also have to handle the case of statically linking a
             shared object, which will cause symbol redefinitions,
             although this is an easier case to detect.  */
             We also have to handle the case of statically linking a
             shared object, which will cause symbol redefinitions,
             although this is an easier case to detect.  */
@@ -2188,6 +2208,14 @@ xcoff_link_add_symbols (abfd, info)
                      (*sym_hash)->root.u.undef.abfd =
                        (*sym_hash)->root.u.def.section->owner;
                    }
                      (*sym_hash)->root.u.undef.abfd =
                        (*sym_hash)->root.u.def.section->owner;
                    }
+                 else if (abfd->my_archive != NULL)
+                   {
+                     /* This is a redefinition in an object contained
+                         in an archive.  Just ignore it.  See the
+                         comment above.  */
+                     section = bfd_und_section_ptr;
+                     value = 0;
+                   }
                  else if ((*sym_hash)->root.next != NULL
                           || info->hash->undefs_tail == &(*sym_hash)->root)
                    {
                  else if ((*sym_hash)->root.next != NULL
                           || info->hash->undefs_tail == &(*sym_hash)->root)
                    {
@@ -2314,7 +2342,7 @@ xcoff_link_add_symbols (abfd, info)
              if (*rel_csect == NULL)
                {
                  (*_bfd_error_handler)
              if (*rel_csect == NULL)
                {
                  (*_bfd_error_handler)
-                   ("%s: reloc %s:%d not in csect",
+                   (_("%s: reloc %s:%d not in csect"),
                     bfd_get_filename (abfd), o->name, i);
                  bfd_set_error (bfd_error_bad_value);
                  goto error_return;
                     bfd_get_filename (abfd), o->name, i);
                  bfd_set_error (bfd_error_bad_value);
                  goto error_return;
@@ -2449,7 +2477,7 @@ xcoff_link_add_dynamic_symbols (abfd, info)
   if (info->hash->creator != abfd->xvec)
     {
       (*_bfd_error_handler)
   if (info->hash->creator != abfd->xvec)
     {
       (*_bfd_error_handler)
-       ("%s: XCOFF shared object when not producing XCOFF output",
+       (_("%s: XCOFF shared object when not producing XCOFF output"),
         bfd_get_filename (abfd));
       bfd_set_error (bfd_error_invalid_operation);
       return false;
         bfd_get_filename (abfd));
       bfd_set_error (bfd_error_invalid_operation);
       return false;
@@ -2470,7 +2498,7 @@ xcoff_link_add_dynamic_symbols (abfd, info)
   if (lsec == NULL)
     {
       (*_bfd_error_handler)
   if (lsec == NULL)
     {
       (*_bfd_error_handler)
-       ("%s: dynamic object with no .loader section",
+       (_("%s: dynamic object with no .loader section"),
         bfd_get_filename (abfd));
       bfd_set_error (bfd_error_no_symbols);
       return false;
         bfd_get_filename (abfd));
       bfd_set_error (bfd_error_no_symbols);
       return false;
@@ -2560,6 +2588,61 @@ xcoff_link_add_dynamic_symbols (abfd, info)
          h->root.u.def.section = bfd_abs_section_ptr;
          h->root.u.def.value = ldsym.l_value;
        }
          h->root.u.def.section = bfd_abs_section_ptr;
          h->root.u.def.value = ldsym.l_value;
        }
+
+      /* If this symbol defines a function descriptor, then it
+        implicitly defines the function code as well.  */
+      if (h->smclas == XMC_DS
+         || (h->smclas == XMC_XO && name[0] != '.'))
+       h->flags |= XCOFF_DESCRIPTOR;
+      if ((h->flags & XCOFF_DESCRIPTOR) != 0)
+       {
+         struct xcoff_link_hash_entry *hds;
+
+         hds = h->descriptor;
+         if (hds == NULL)
+           {
+             char *dsnm;
+
+             dsnm = bfd_malloc (strlen (name) + 2);
+             if (dsnm == NULL)
+               return false;
+             dsnm[0] = '.';
+             strcpy (dsnm + 1, name);
+             hds = xcoff_link_hash_lookup (xcoff_hash_table (info), dsnm,
+                                           true, true, true);
+             free (dsnm);
+             if (hds == NULL)
+               return false;
+
+             if (hds->root.type == bfd_link_hash_new)
+               {
+                 hds->root.type = bfd_link_hash_undefined;
+                 hds->root.u.undef.abfd = abfd;
+                 /* We do not want to add this to the undefined
+                     symbol list.  */
+               }
+
+             hds->descriptor = h;
+             h->descriptor = hds;
+           }
+
+         hds->flags |= XCOFF_DEF_DYNAMIC;
+         if (hds->smclas == XMC_UA)
+           hds->smclas = XMC_PR;
+
+         /* An absolute symbol appears to actually define code, not a
+            function descriptor.  This is how some math functions are
+            implemented on AIX 4.1.  */
+         if (h->smclas == XMC_XO
+             && (hds->root.type == bfd_link_hash_undefined
+                 || hds->root.type == bfd_link_hash_undefweak))
+           {
+             hds->smclas = XMC_XO;
+             hds->root.type = bfd_link_hash_defined;
+             hds->root.u.def.section = bfd_abs_section_ptr;
+             hds->root.u.def.value = ldsym.l_value;
+           }
+       }
     }
 
   if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
     }
 
   if (buf != NULL && ! coff_section_data (abfd, lsec)->keep_contents)
@@ -2630,7 +2713,8 @@ xcoff_mark_symbol (info, h)
       asection *hsec;
 
       hsec = h->root.u.def.section;
       asection *hsec;
 
       hsec = h->root.u.def.section;
-      if ((hsec->flags & SEC_MARK) == 0)
+      if (! bfd_is_abs_section (hsec)
+         && (hsec->flags & SEC_MARK) == 0)
        {
          if (! xcoff_mark (info, hsec))
            return false;
        {
          if (! xcoff_mark (info, hsec))
            return false;
@@ -2658,7 +2742,8 @@ xcoff_mark (info, sec)
      struct bfd_link_info *info;
      asection *sec;
 {
      struct bfd_link_info *info;
      asection *sec;
 {
-  if ((sec->flags & SEC_MARK) != 0)
+  if (bfd_is_abs_section (sec)
+      || (sec->flags & SEC_MARK) != 0)
     return true;
 
   sec->flags |= SEC_MARK;
     return true;
 
   sec->flags |= SEC_MARK;
@@ -2740,7 +2825,6 @@ xcoff_mark (info, sec)
                          && h->root.root.string[0] == '.'
                          && h->descriptor != NULL
                          && ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
                          && h->root.root.string[0] == '.'
                          && h->descriptor != NULL
                          && ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
-                             || info->shared
                              || ((h->descriptor->flags & XCOFF_IMPORT) != 0
                                  && (h->descriptor->flags
                                      & XCOFF_DEF_REGULAR) == 0))))
                              || ((h->descriptor->flags & XCOFF_IMPORT) != 0
                                  && (h->descriptor->flags
                                      & XCOFF_DEF_REGULAR) == 0))))
@@ -2870,6 +2954,42 @@ bfd_xcoff_import_symbol (output_bfd, info, harg, val, imppath, impfile,
   if (! XCOFF_XVECP (output_bfd->xvec))
     return true;
 
   if (! XCOFF_XVECP (output_bfd->xvec))
     return true;
 
+  /* A symbol name which starts with a period is the code for a
+     function.  If the symbol is undefined, then add an undefined
+     symbol for the function descriptor, and import that instead.  */
+  if (h->root.root.string[0] == '.'
+      && h->root.type == bfd_link_hash_undefined
+      && val == (bfd_vma) -1)
+    {
+      struct xcoff_link_hash_entry *hds;
+
+      hds = h->descriptor;
+      if (hds == NULL)
+       {
+         hds = xcoff_link_hash_lookup (xcoff_hash_table (info),
+                                       h->root.root.string + 1,
+                                       true, false, true);
+         if (hds == NULL)
+           return false;
+         if (hds->root.type == bfd_link_hash_new)
+           {
+             hds->root.type = bfd_link_hash_undefined;
+             hds->root.u.undef.abfd = h->root.u.undef.abfd;
+           }
+         hds->flags |= XCOFF_DESCRIPTOR;
+         BFD_ASSERT ((hds->flags & XCOFF_CALLED) == 0
+                     && (h->flags & XCOFF_DESCRIPTOR) == 0);
+         hds->descriptor = h;
+         h->descriptor = hds;
+       }
+
+      /* Now, if the descriptor is undefined, import the descriptor
+         rather than the symbol we were told to import.  FIXME: Is
+         this correct in all cases?  */
+      if (hds->root.type == bfd_link_hash_undefined)
+       h = hds;
+    }
+
   h->flags |= XCOFF_IMPORT;
 
   if (val != (bfd_vma) -1)
   h->flags |= XCOFF_IMPORT;
 
   if (val != (bfd_vma) -1)
@@ -2890,16 +3010,12 @@ bfd_xcoff_import_symbol (output_bfd, info, harg, val, imppath, impfile,
       h->root.u.def.value = val;
     }
 
       h->root.u.def.value = val;
     }
 
-  if (h->ldsym == NULL)
-    {
-      h->ldsym = ((struct internal_ldsym *)
-                 bfd_zalloc (output_bfd, sizeof (struct internal_ldsym)));
-      if (h->ldsym == NULL)
-       return false;
-    }
-
+  /* We overload the ldindx field to hold the l_ifile value for this
+     symbol.  */
+  BFD_ASSERT (h->ldsym == NULL);
+  BFD_ASSERT ((h->flags & XCOFF_BUILT_LDSYM) == 0);
   if (imppath == NULL)
   if (imppath == NULL)
-    h->ldsym->l_ifile = (bfd_size_type) -1;
+    h->ldindx = -1;
   else
     {
       unsigned int c;
   else
     {
       unsigned int c;
@@ -2932,7 +3048,7 @@ bfd_xcoff_import_symbol (output_bfd, info, harg, val, imppath, impfile,
          *pp = n;
        }
 
          *pp = n;
        }
 
-      h->ldsym->l_ifile = c;
+      h->ldindx = c;
     }
 
   return true;
     }
 
   return true;
@@ -2945,7 +3061,7 @@ bfd_xcoff_export_symbol (output_bfd, info, harg, syscall)
      bfd *output_bfd;
      struct bfd_link_info *info;
      struct bfd_link_hash_entry *harg;
      bfd *output_bfd;
      struct bfd_link_info *info;
      struct bfd_link_hash_entry *harg;
-     boolean syscall;
+     boolean syscall ATTRIBUTE_UNUSED;
 {
   struct xcoff_link_hash_entry *h = (struct xcoff_link_hash_entry *) harg;
 
 {
   struct xcoff_link_hash_entry *h = (struct xcoff_link_hash_entry *) harg;
 
@@ -3022,7 +3138,7 @@ bfd_xcoff_link_count_reloc (output_bfd, info, name)
                                     false));
   if (h == NULL)
     {
                                     false));
   if (h == NULL)
     {
-      (*_bfd_error_handler) ("%s: no such symbol", name);
+      (*_bfd_error_handler) (_("%s: no such symbol"), name);
       bfd_set_error (bfd_error_no_symbols);
       return false;
     }
       bfd_set_error (bfd_error_no_symbols);
       return false;
     }
@@ -3156,10 +3272,15 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
   xcoff_hash_table (info)->file_align = file_align;
   xcoff_hash_table (info)->textro = textro;
 
   xcoff_hash_table (info)->file_align = file_align;
   xcoff_hash_table (info)->textro = textro;
 
-  hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
-                                  false, false, true);
-  if (hentry != NULL)
-    hentry->flags |= XCOFF_ENTRY;
+  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
 
   /* Garbage collect unused sections.  */
   if (info->relocateable
@@ -3365,7 +3486,7 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
       xcoff_data (sub)->debug_indices = debug_index;
 
       /* Grab the contents of the .debug section.  We use malloc and
       xcoff_data (sub)->debug_indices = debug_index;
 
       /* Grab the contents of the .debug section.  We use malloc and
-        copy the neams into the debug stringtab, rather than
+        copy the names into the debug stringtab, rather than
         bfd_alloc, because I expect that, when linking many files
         together, many of the strings will be the same.  Storing the
         strings in the hash table should save space in this case.  */
         bfd_alloc, because I expect that, when linking many files
         together, many of the strings will be the same.  Storing the
         strings in the hash table should save space in this case.  */
@@ -3425,8 +3546,9 @@ bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
        }
     }
 
        }
     }
 
-  xcoff_hash_table (info)->debug_section->_raw_size =
-    _bfd_stringtab_size (debug_strtab);
+  if (info->strip != strip_all)
+    xcoff_hash_table (info)->debug_section->_raw_size =
+      _bfd_stringtab_size (debug_strtab);
 
   return true;
 
 
   return true;
 
@@ -3457,7 +3579,8 @@ xcoff_build_ldsyms (h, p)
       && (h->flags & XCOFF_DEF_REGULAR) == 0
       && (h->flags & XCOFF_REF_REGULAR) != 0
       && (h->flags & XCOFF_DEF_DYNAMIC) == 0
       && (h->flags & XCOFF_DEF_REGULAR) == 0
       && (h->flags & XCOFF_REF_REGULAR) != 0
       && (h->flags & XCOFF_DEF_DYNAMIC) == 0
-      && (h->root.u.def.section->owner->flags & DYNAMIC) == 0)
+      && (bfd_is_abs_section (h->root.u.def.section)
+         || (h->root.u.def.section->owner->flags & DYNAMIC) == 0))
     h->flags |= XCOFF_DEF_REGULAR;
 
   /* If all defined symbols should be exported, mark them now.  We
     h->flags |= XCOFF_DEF_REGULAR;
 
   /* If all defined symbols should be exported, mark them now.  We
@@ -3466,7 +3589,47 @@ xcoff_build_ldsyms (h, p)
   if (ldinfo->export_defineds
       && (h->flags & XCOFF_DEF_REGULAR) != 0
       && h->root.root.string[0] != '.')
   if (ldinfo->export_defineds
       && (h->flags & XCOFF_DEF_REGULAR) != 0
       && h->root.root.string[0] != '.')
-    h->flags |= XCOFF_EXPORT;
+    {
+      boolean export;
+
+      /* We don't export a symbol which is being defined by an object
+        included from an archive which contains a shared object.  The
+        rationale is that if an archive contains both an unshared and
+        a shared object, then there must be some reason that the
+        unshared object is unshared, and we don't want to start
+        providing a shared version of it.  In particular, this solves
+        a bug involving the _savefNN set of functions.  gcc will call
+        those functions without providing a slot to restore the TOC,
+        so it is essential that these functions be linked in directly
+        and not from a shared object, which means that a shared
+        object which also happens to link them in must not export
+        them.  This is confusing, but I haven't been able to think of
+        a different approach.  Note that the symbols can, of course,
+        be exported explicitly.  */
+      export = true;
+      if ((h->root.type == bfd_link_hash_defined
+          || h->root.type == bfd_link_hash_defweak)
+         && h->root.u.def.section->owner != NULL
+         && h->root.u.def.section->owner->my_archive != NULL)
+       {
+         bfd *arbfd, *member;
+
+         arbfd = h->root.u.def.section->owner->my_archive;
+         member = bfd_openr_next_archived_file (arbfd, (bfd *) NULL);
+         while (member != NULL)
+           {
+             if ((member->flags & DYNAMIC) != 0)
+               {
+                 export = false;
+                 break;
+               }
+             member = bfd_openr_next_archived_file (arbfd, member);
+           }
+       }
+
+      if (export)
+       h->flags |= XCOFF_EXPORT;
+    }
 
   /* We don't want to garbage collect symbols which are not defined in
      XCOFF files.  This is a convenient place to mark them.  */
 
   /* We don't want to garbage collect symbols which are not defined in
      XCOFF files.  This is a convenient place to mark them.  */
@@ -3479,17 +3642,16 @@ xcoff_build_ldsyms (h, p)
              != ldinfo->info->hash->creator)))
     h->flags |= XCOFF_MARK;
 
              != ldinfo->info->hash->creator)))
     h->flags |= XCOFF_MARK;
 
-  /* If this symbol is called and defined in a dynamic object, or not
-     defined at all when building a shared object, or imported, then
-     we need to set up global linkage code for it.  (Unless we did
-     garbage collection and we didn't need this symbol.)  */
+  /* If this symbol is called and defined in a dynamic object, or it
+     is imported, then we need to set up global linkage code for it.
+     (Unless we did garbage collection and we didn't need this
+     symbol.)  */
   if ((h->flags & XCOFF_CALLED) != 0
       && (h->root.type == bfd_link_hash_undefined
          || h->root.type == bfd_link_hash_undefweak)
       && h->root.root.string[0] == '.'
       && h->descriptor != NULL
       && ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
   if ((h->flags & XCOFF_CALLED) != 0
       && (h->root.type == bfd_link_hash_undefined
          || h->root.type == bfd_link_hash_undefweak)
       && h->root.root.string[0] == '.'
       && h->descriptor != NULL
       && ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
-         || ldinfo->info->shared
          || ((h->descriptor->flags & XCOFF_IMPORT) != 0
              && (h->descriptor->flags & XCOFF_DEF_REGULAR) == 0))
       && (! xcoff_hash_table (ldinfo->info)->gc
          || ((h->descriptor->flags & XCOFF_IMPORT) != 0
              && (h->descriptor->flags & XCOFF_DEF_REGULAR) == 0))
       && (! xcoff_hash_table (ldinfo->info)->gc
@@ -3568,7 +3730,7 @@ xcoff_build_ldsyms (h, p)
       else
        {
          (*_bfd_error_handler)
       else
        {
          (*_bfd_error_handler)
-           ("warning: attempt to export undefined symbol `%s'",
+           (_("warning: attempt to export undefined symbol `%s'"),
             h->root.root.string);
          h->ldsym = NULL;
          return true;
             h->root.root.string);
          h->ldsym = NULL;
          return true;
@@ -3619,20 +3781,19 @@ xcoff_build_ldsyms (h, p)
 
   /* We need to add this symbol to the .loader symbols.  */
 
 
   /* We need to add this symbol to the .loader symbols.  */
 
-  /* h->ldsym will already have been allocated for an explicitly
-     imported symbol.  */
+  BFD_ASSERT (h->ldsym == NULL);
+  h->ldsym = ((struct internal_ldsym *)
+             bfd_zalloc (ldinfo->output_bfd,
+                         sizeof (struct internal_ldsym)));
   if (h->ldsym == NULL)
     {
   if (h->ldsym == NULL)
     {
-      h->ldsym = ((struct internal_ldsym *)
-                 bfd_zalloc (ldinfo->output_bfd,
-                             sizeof (struct internal_ldsym)));
-      if (h->ldsym == NULL)
-       {
-         ldinfo->failed = true;
-         return false;
-       }
+      ldinfo->failed = true;
+      return false;
     }
 
     }
 
+  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;
   /* The first 3 symbol table indices are reserved to indicate the
      sections.  */
   h->ldindx = ldinfo->ldsym_count + 3;
@@ -3807,7 +3968,6 @@ _bfd_xcoff_bfd_final_link (abfd, info)
          saw_contents = true;
          for (op = &abfd->sections; *op != NULL; op = &(*op)->next)
            {
          saw_contents = true;
          for (op = &abfd->sections; *op != NULL; op = &(*op)->next)
            {
-             (*op)->target_index = indx;
              if (strcmp ((*op)->name, ".pad") == 0)
                saw_contents = false;
              else if (((*op)->flags & SEC_HAS_CONTENTS) != 0
              if (strcmp ((*op)->name, ".pad") == 0)
                saw_contents = false;
              else if (((*op)->flags & SEC_HAS_CONTENTS) != 0
@@ -3876,7 +4036,8 @@ _bfd_xcoff_bfd_final_link (abfd, info)
            }
        }
 
            }
        }
 
-      bfd_coff_compute_section_file_positions (abfd);
+      if (! bfd_coff_compute_section_file_positions (abfd))
+       goto error_return;
     }
 
   /* Allocate space for the pointers we need to keep for the relocs.  */
     }
 
   /* Allocate space for the pointers we need to keep for the relocs.  */
@@ -3909,9 +4070,17 @@ _bfd_xcoff_bfd_final_link (abfd, info)
        o->rel_filepos = 0;
       else
        {
        o->rel_filepos = 0;
       else
        {
-         o->flags |= SEC_RELOC;
-         o->rel_filepos = rel_filepos;
-         rel_filepos += o->reloc_count * relsz;
+         /* A stripped file has no relocs.  However, we still
+             allocate the buffers, so that later code doesn't have to
+             worry about whether we are stripping or not.  */
+         if (info->strip == strip_all)
+           o->rel_filepos = 0;
+         else
+           {
+             o->flags |= SEC_RELOC;
+             o->rel_filepos = rel_filepos;
+             rel_filepos += o->reloc_count * relsz;
+           }
 
          /* We don't know the indices of global symbols until we have
              written out all the local symbols.  For each section in
 
          /* We don't know the indices of global symbols until we have
              written out all the local symbols.  For each section in
@@ -3967,9 +4136,9 @@ _bfd_xcoff_bfd_final_link (abfd, info)
 
   /* Figure out the largest number of symbols in an input BFD.  Take
      the opportunity to clear the output_has_begun fields of all the
 
   /* Figure out the largest number of symbols in an input BFD.  Take
      the opportunity to clear the output_has_begun fields of all the
-     input BFD's.  We want at least 4 symbols, since that is the
+     input BFD's.  We want at least 6 symbols, since that is the
      number which xcoff_write_global_symbol may need.  */
      number which xcoff_write_global_symbol may need.  */
-  max_sym_count = 4;
+  max_sym_count = 6;
   for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
     {
       size_t sz;
   for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
     {
       size_t sz;
@@ -4094,12 +4263,9 @@ _bfd_xcoff_bfd_final_link (abfd, info)
   /* Now that we have written out all the global symbols, we know the
      symbol indices to use for relocs against them, and we can finally
      write out the relocs.  */
   /* Now that we have written out all the global symbols, we know the
      symbol indices to use for relocs against them, and we can finally
      write out the relocs.  */
-  external_relocs = (bfd_byte *) malloc (max_output_reloc_count * relsz);
+  external_relocs = (bfd_byte *) bfd_malloc (max_output_reloc_count * relsz);
   if (external_relocs == NULL && max_output_reloc_count != 0)
   if (external_relocs == NULL && max_output_reloc_count != 0)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      goto error_return;
-    }
+    goto error_return;
 
   for (o = abfd->sections; o != NULL; o = o->next)
     {
 
   for (o = abfd->sections; o != NULL; o = o->next)
     {
@@ -4109,6 +4275,13 @@ _bfd_xcoff_bfd_final_link (abfd, info)
       struct xcoff_toc_rel_hash *toc_rel_hash;
       bfd_byte *erel;
 
       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;
 
       if (o->reloc_count == 0)
        continue;
 
@@ -4524,7 +4697,8 @@ xcoff_link_input_bfd (finfo, input_bfd)
                  of the TOC using a 16 bit offset from tocval.  This
                  test assumes that the TOC comes at the end of the
                  output section, as it does in the default linker
                  of the TOC using a 16 bit offset from tocval.  This
                  test assumes that the TOC comes at the end of the
                  output section, as it does in the default linker
-                 script.  */
+                 script.  FIXME: This doesn't handle .tocbss sections
+                 created from XMC_TD common symbols correctly.  */
 
              tocend = ((*csectpp)->output_section->vma
                        + (*csectpp)->output_section->_raw_size);
 
              tocend = ((*csectpp)->output_section->vma
                        + (*csectpp)->output_section->_raw_size);
@@ -4532,7 +4706,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
              if (tocval + 0x10000 < tocend)
                {
                  (*_bfd_error_handler)
              if (tocval + 0x10000 < tocend)
                {
                  (*_bfd_error_handler)
-                   ("TOC overflow: 0x%lx > 0x10000; try -mminimal-toc when compiling",
+                   (_("TOC overflow: 0x%lx > 0x10000; try -mminimal-toc when compiling"),
                     (unsigned long) (tocend - tocval));
                  bfd_set_error (bfd_error_file_too_big);
                  return false;
                     (unsigned long) (tocend - tocval));
                  bfd_set_error (bfd_error_file_too_big);
                  return false;
@@ -4617,8 +4791,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
                  && (isym.n_sclass != C_EXT
                      && (isym.n_sclass != C_HIDEXT
                          || smtyp != XTY_SD))
                  && (isym.n_sclass != C_EXT
                      && (isym.n_sclass != C_HIDEXT
                          || smtyp != XTY_SD))
-                 && strncmp (name, finfo->info->lprefix,
-                             finfo->info->lprefix_len) == 0))
+                 && bfd_is_local_label_name (input_bfd, name)))
            skip = true;
        }
 
            skip = true;
        }
 
@@ -5195,9 +5368,13 @@ xcoff_link_input_bfd (finfo, input_bfd)
 
              r_symndx = irel->r_symndx;
 
 
              r_symndx = irel->r_symndx;
 
-             if (r_symndx != -1)
+             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)
                {
                {
-                 h = obj_xcoff_sym_hashes (input_bfd)[r_symndx];
                  if (h != NULL
                      && h->smclas != XMC_TD
                      && (irel->r_type == R_TOC
                  if (h != NULL
                      && h->smclas != XMC_TD
                      && (irel->r_type == R_TOC
@@ -5354,7 +5531,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
                      else
                        {
                          (*_bfd_error_handler)
                      else
                        {
                          (*_bfd_error_handler)
-                           ("%s: loader reloc in unrecognized section `%s'",
+                           (_("%s: loader reloc in unrecognized section `%s'"),
                             bfd_get_filename (input_bfd),
                             sec->name);
                          bfd_set_error (bfd_error_nonrepresentable_section);
                             bfd_get_filename (input_bfd),
                             sec->name);
                          bfd_set_error (bfd_error_nonrepresentable_section);
@@ -5376,7 +5553,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
                      if (h->ldindx < 0 && ! quiet)
                        {
                          (*_bfd_error_handler)
                      if (h->ldindx < 0 && ! quiet)
                        {
                          (*_bfd_error_handler)
-                           ("%s: `%s' in loader reloc but not loader sym",
+                           (_("%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);
                             bfd_get_filename (input_bfd),
                             h->root.root.string);
                          bfd_set_error (bfd_error_bad_value);
@@ -5391,7 +5568,7 @@ xcoff_link_input_bfd (finfo, input_bfd)
                      && ! quiet)
                    {
                      (*_bfd_error_handler)
                      && ! quiet)
                    {
                      (*_bfd_error_handler)
-                       ("%s: loader reloc in read-only section %s",
+                       (_("%s: loader reloc in read-only section %s"),
                         bfd_get_filename (input_bfd),
                         bfd_get_section_name (finfo->output_bfd,
                                               o->output_section));
                         bfd_get_filename (input_bfd),
                         bfd_get_section_name (finfo->output_bfd,
                                               o->output_section));
@@ -5455,6 +5632,7 @@ xcoff_write_global_symbol (h, p)
   union internal_auxent aux;
 
   output_bfd = finfo->output_bfd;
   union internal_auxent aux;
 
   output_bfd = finfo->output_bfd;
+  outsym = finfo->outsyms;
 
   /* If this symbol was garbage collected, just skip it.  */
   if (xcoff_hash_table (finfo->info)->gc
 
   /* If this symbol was garbage collected, just skip it.  */
   if (xcoff_hash_table (finfo->info)->gc
@@ -5563,6 +5741,8 @@ xcoff_write_global_symbol (h, p)
       int oindx;
       struct internal_reloc *irel;
       struct internal_ldrel ldrel;
       int oindx;
       struct internal_reloc *irel;
       struct internal_ldrel ldrel;
+      struct internal_syment irsym;
+      union internal_auxent iraux;
 
       tocsec = h->toc_section;
       osec = tocsec->output_section;
 
       tocsec = h->toc_section;
       osec = tocsec->output_section;
@@ -5590,6 +5770,66 @@ xcoff_write_global_symbol (h, p)
       ldrel.l_rsecnm = oindx;
       xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
       ++finfo->ldrel;
       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)
+                            + (obj_raw_syment_count (output_bfd)
+                               * bfd_coff_symesz (output_bfd))),
+                           SEEK_SET) != 0
+                 || (bfd_write (finfo->outsyms, outsym - finfo->outsyms, 1,
+                                output_bfd)
+                     != (bfd_size_type) (outsym - finfo->outsyms)))
+               return false;
+             obj_raw_syment_count (output_bfd) +=
+               (outsym - finfo->outsyms) / bfd_coff_symesz (output_bfd);
+
+             outsym = finfo->outsyms;
+           }
+       }
     }
 
   /* If this symbol is a specially defined function descriptor, write
     }
 
   /* If this symbol is a specially defined function descriptor, write
@@ -5647,7 +5887,7 @@ xcoff_write_global_symbol (h, p)
       else
        {
          (*_bfd_error_handler)
       else
        {
          (*_bfd_error_handler)
-           ("%s: loader reloc in unrecognized section `%s'",
+           (_("%s: loader reloc in unrecognized section `%s'"),
             bfd_get_filename (output_bfd),
             esec->output_section->name);
          bfd_set_error (bfd_error_nonrepresentable_section);
             bfd_get_filename (output_bfd),
             esec->output_section->name);
          bfd_set_error (bfd_error_nonrepresentable_section);
@@ -5684,7 +5924,7 @@ xcoff_write_global_symbol (h, p)
       else
        {
          (*_bfd_error_handler)
       else
        {
          (*_bfd_error_handler)
-           ("%s: loader reloc in unrecognized section `%s'",
+           (_("%s: loader reloc in unrecognized section `%s'"),
             bfd_get_filename (output_bfd),
             tsec->output_section->name);
          bfd_set_error (bfd_error_nonrepresentable_section);
             bfd_get_filename (output_bfd),
             tsec->output_section->name);
          bfd_set_error (bfd_error_nonrepresentable_section);
@@ -5696,8 +5936,11 @@ xcoff_write_global_symbol (h, p)
       ++finfo->ldrel;
     }
 
       ++finfo->ldrel;
     }
 
-  if (h->indx >= 0)
-    return true;
+  if (h->indx >= 0 || finfo->info->strip == strip_all)
+    {
+      BFD_ASSERT (outsym == finfo->outsyms);
+      return true;
+    }
 
   if (h->indx != -2
       && (finfo->info->strip == strip_all
 
   if (h->indx != -2
       && (finfo->info->strip == strip_all
@@ -5705,13 +5948,17 @@ xcoff_write_global_symbol (h, p)
              && (bfd_hash_lookup (finfo->info->keep_hash,
                                   h->root.root.string, false, false)
                  == NULL))))
              && (bfd_hash_lookup (finfo->info->keep_hash,
                                   h->root.root.string, false, false)
                  == NULL))))
-    return true;
+    {
+      BFD_ASSERT (outsym == finfo->outsyms);
+      return true;
+    }
 
   if (h->indx != -2
       && (h->flags & (XCOFF_REF_REGULAR | XCOFF_DEF_REGULAR)) == 0)
 
   if (h->indx != -2
       && (h->flags & (XCOFF_REF_REGULAR | XCOFF_DEF_REGULAR)) == 0)
-    return true;
-
-  outsym = finfo->outsyms;
+    {
+      BFD_ASSERT (outsym == finfo->outsyms);
+      return true;
+    }
 
   memset (&aux, 0, sizeof aux);
 
 
   memset (&aux, 0, sizeof aux);
 
@@ -5743,6 +5990,16 @@ xcoff_write_global_symbol (h, p)
       isym.n_sclass = C_EXT;
       aux.x_csect.x_smtyp = XTY_ER;
     }
       isym.n_sclass = C_EXT;
       aux.x_csect.x_smtyp = XTY_ER;
     }
+  else if ((h->root.type == bfd_link_hash_defined
+           || h->root.type == bfd_link_hash_defweak)
+          && h->smclas == XMC_XO)
+    {
+      BFD_ASSERT (bfd_is_abs_section (h->root.u.def.section));
+      isym.n_value = h->root.u.def.value;
+      isym.n_scnum = N_UNDEF;
+      isym.n_sclass = C_EXT;
+      aux.x_csect.x_smtyp = XTY_ER;
+    }
   else if (h->root.type == bfd_link_hash_defined
           || h->root.type == bfd_link_hash_defweak)
     {
   else if (h->root.type == bfd_link_hash_defined
           || h->root.type == bfd_link_hash_defweak)
     {
@@ -5793,8 +6050,9 @@ xcoff_write_global_symbol (h, p)
                         (PTR) outsym);
   outsym += bfd_coff_auxesz (output_bfd);
 
                         (PTR) outsym);
   outsym += bfd_coff_auxesz (output_bfd);
 
-  if (h->root.type == bfd_link_hash_defined
-      || h->root.type == bfd_link_hash_defweak)
+  if ((h->root.type == bfd_link_hash_defined
+       || h->root.type == bfd_link_hash_defweak)
+      && h->smclas != XMC_XO)
     {
       /* We just output an SD symbol.  Now output an LD symbol.  */
 
     {
       /* We just output an SD symbol.  Now output an LD symbol.  */
 
@@ -5983,7 +6241,7 @@ xcoff_reloc_link_order (output_bfd, finfo, output_section, link_order)
       else
        {
          (*_bfd_error_handler)
       else
        {
          (*_bfd_error_handler)
-           ("%s: loader reloc in unrecognized section `%s'",
+           (_("%s: loader reloc in unrecognized section `%s'"),
             bfd_get_filename (output_bfd), secname);
          bfd_set_error (bfd_error_nonrepresentable_section);
          return false;
             bfd_get_filename (output_bfd), secname);
          bfd_set_error (bfd_error_nonrepresentable_section);
          return false;
@@ -5994,7 +6252,7 @@ xcoff_reloc_link_order (output_bfd, finfo, output_section, link_order)
       if (h->ldindx < 0)
        {
          (*_bfd_error_handler)
       if (h->ldindx < 0)
        {
          (*_bfd_error_handler)
-           ("%s: `%s' in loader reloc but not loader sym",
+           (_("%s: `%s' in loader reloc but not loader sym"),
             bfd_get_filename (output_bfd),
             h->root.root.string);
          bfd_set_error (bfd_error_bad_value);
             bfd_get_filename (output_bfd),
             h->root.root.string);
          bfd_set_error (bfd_error_bad_value);
@@ -6190,7 +6448,7 @@ _bfd_ppc_xcoff_relocate_section (output_bfd, info, input_bfd,
              not defined by the PowerOpen ABI.  */
        default:
          (*_bfd_error_handler)
              not defined by the PowerOpen ABI.  */
        default:
          (*_bfd_error_handler)
-           ("%s: unsupported relocation type 0x%02x",
+           (_("%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;
             bfd_get_filename (input_bfd), (unsigned int) rel->r_type);
          bfd_set_error (bfd_error_bad_value);
          return false;
@@ -6236,7 +6494,7 @@ _bfd_ppc_xcoff_relocate_section (output_bfd, info, input_bfd,
              if (h->toc_section == NULL)
                {
                  (*_bfd_error_handler)
              if (h->toc_section == NULL)
                {
                  (*_bfd_error_handler)
-                   ("%s: TOC reloc at 0x%x to symbol `%s' with no TOC entry",
+                   (_("%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);
                     bfd_get_filename (input_bfd), rel->r_vaddr,
                     h->root.root.string);
                  bfd_set_error (bfd_error_bad_value);
This page took 0.048224 seconds and 4 git commands to generate.