* Makefile.am: Use a temporary file to build chew.
[deliverable/binutils-gdb.git] / bfd / elf32-ppc.c
index bc269d0559d5fb7fe7e5fae7fedb55feec4527ef..ecee78ac067fdf2cf571f1ea7c1f94bc24ae630d 100644 (file)
@@ -17,8 +17,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the
-   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 /* This file is based on a preliminary PowerPC ELF ABI.  The
    information may not match the final PowerPC ELF ABI.  It includes
@@ -1506,14 +1506,16 @@ ppc_elf_unhandled_reloc (bfd *abfd,
 
 typedef struct elf_linker_section
 {
-  /* pointer to the section */
+  /* Pointer to the bfd section.  */
   asection *section;
-  /* pointer to the relocations needed for this section */
-  asection *rel_section;
-  /* pointer to the created symbol hash value */
-  struct elf_link_hash_entry *sym_hash;
-  /* offset of symbol from beginning of section */
-  bfd_vma sym_offset;
+  /* Section name.  */
+  const char *name;
+  /* Associated bss section name.  */
+  const char *bss_name;
+  /* Associated symbol name.  */
+  const char *sym_name;
+  /* Value of symbol.  */
+  bfd_vma sym_val;
 } elf_linker_section_t;
 
 /* Linked list of allocated pointer entries.  This hangs off of the
@@ -1530,8 +1532,6 @@ typedef struct elf_linker_section_pointers
   bfd_vma addend;
   /* which linker section this is */
   elf_linker_section_t *lsect;
-  /* whether address was written yet */
-  bfd_boolean written_address_p;
 } elf_linker_section_pointers_t;
 
 struct ppc_elf_obj_tdata
@@ -1594,109 +1594,6 @@ ppc_elf_set_private_flags (bfd *abfd, flagword flags)
   return TRUE;
 }
 
-/* Return 1 if target is one of ours.  */
-
-static bfd_boolean
-is_ppc_elf_target (const struct bfd_target *targ)
-{
-  extern const bfd_target bfd_elf32_powerpc_vec;
-  extern const bfd_target bfd_elf32_powerpcle_vec;
-
-  return targ == &bfd_elf32_powerpc_vec || targ == &bfd_elf32_powerpcle_vec;
-}
-
-/* Merge backend specific data from an object file to the output
-   object file when linking.  */
-
-static bfd_boolean
-ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
-{
-  flagword old_flags;
-  flagword new_flags;
-  bfd_boolean error;
-
-  if (!is_ppc_elf_target (ibfd->xvec)
-      || !is_ppc_elf_target (obfd->xvec))
-    return TRUE;
-
-  /* Check if we have the same endianess.  */
-  if (! _bfd_generic_verify_endian_match (ibfd, obfd))
-    return FALSE;
-
-  new_flags = elf_elfheader (ibfd)->e_flags;
-  old_flags = elf_elfheader (obfd)->e_flags;
-  if (!elf_flags_init (obfd))
-    {
-      /* First call, no flags set.  */
-      elf_flags_init (obfd) = TRUE;
-      elf_elfheader (obfd)->e_flags = new_flags;
-    }
-
-  /* Compatible flags are ok.  */
-  else if (new_flags == old_flags)
-    ;
-
-  /* Incompatible flags.  */
-  else
-    {
-      /* Warn about -mrelocatable mismatch.  Allow -mrelocatable-lib
-        to be linked with either.  */
-      error = FALSE;
-      if ((new_flags & EF_PPC_RELOCATABLE) != 0
-         && (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0)
-       {
-         error = TRUE;
-         (*_bfd_error_handler)
-           (_("%B: compiled with -mrelocatable and linked with "
-              "modules compiled normally"), ibfd);
-       }
-      else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0
-              && (old_flags & EF_PPC_RELOCATABLE) != 0)
-       {
-         error = TRUE;
-         (*_bfd_error_handler)
-           (_("%B: compiled normally and linked with "
-              "modules compiled with -mrelocatable"), ibfd);
-       }
-
-      /* The output is -mrelocatable-lib iff both the input files are.  */
-      if (! (new_flags & EF_PPC_RELOCATABLE_LIB))
-       elf_elfheader (obfd)->e_flags &= ~EF_PPC_RELOCATABLE_LIB;
-
-      /* The output is -mrelocatable iff it can't be -mrelocatable-lib,
-        but each input file is either -mrelocatable or -mrelocatable-lib.  */
-      if (! (elf_elfheader (obfd)->e_flags & EF_PPC_RELOCATABLE_LIB)
-         && (new_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE))
-         && (old_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE)))
-       elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE;
-
-      /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if
-        any module uses it.  */
-      elf_elfheader (obfd)->e_flags |= (new_flags & EF_PPC_EMB);
-
-      new_flags &= ~(EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB);
-      old_flags &= ~(EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB);
-
-      /* Warn about any other mismatches.  */
-      if (new_flags != old_flags)
-       {
-         error = TRUE;
-         (*_bfd_error_handler)
-           (_("%B: uses different e_flags (0x%lx) fields "
-              "than previous modules (0x%lx)"),
-            ibfd, (long) new_flags, (long) old_flags);
-       }
-
-      if (error)
-       {
-         bfd_set_error (bfd_error_bad_value);
-         return FALSE;
-       }
-    }
-
-  return TRUE;
-}
-
 /* Support for core dump NOTE sections.  */
 
 static bfd_boolean
@@ -1839,18 +1736,69 @@ ppc_elf_additional_program_headers (bfd *abfd)
    that the linker doesn't crater when trying to make more than
    2 sections.  */
 
-static struct bfd_elf_special_section const ppc_elf_special_sections[]=
+static struct bfd_elf_special_section const
+  ppc_special_sections_p[] =
+{
+  { ".plt",              4,  0, SHT_NOBITS,   SHF_ALLOC + SHF_EXECINSTR },
+  { NULL,                0,  0, 0,            0 }
+};
+
+static struct bfd_elf_special_section const
+  ppc_special_sections_s[] =
 {
-  { ".tags",             5,  0, SHT_ORDERED,  SHF_ALLOC },
   { ".sdata",            6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
   { ".sbss",             5, -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
   { ".sdata2",           7, -2, SHT_PROGBITS, SHF_ALLOC },
   { ".sbss2",            6, -2, SHT_PROGBITS, SHF_ALLOC },
+  { NULL,        0, 0, 0,            0 }
+};
+
+static struct bfd_elf_special_section const
+  ppc_special_sections_t[] =
+{
+  { ".tags",             5,  0, SHT_ORDERED,  SHF_ALLOC },
+  { NULL,        0, 0, 0,            0 }
+};
+
+static struct bfd_elf_special_section const
+  ppc_special_sections_other[]=
+{
   { ".PPC.EMB.apuinfo", 16,  0, SHT_NOTE,     0 },
   { ".PPC.EMB.sdata0",  15,  0, SHT_PROGBITS, SHF_ALLOC },
   { ".PPC.EMB.sbss0",   14,  0, SHT_PROGBITS, SHF_ALLOC },
-  { ".plt",              4,  0, SHT_NOBITS,   SHF_ALLOC + SHF_EXECINSTR },
-  { NULL,                0,  0, 0,            0 }
+  { NULL,        0, 0, 0,            0 }
+};
+
+static struct bfd_elf_special_section const *
+  ppc_elf_special_sections[27]=
+{
+  NULL,                                /* 'a' */
+  NULL,                                /* 'b' */
+  NULL,                                /* 'c' */
+  NULL,                                /* 'd' */
+  NULL,                                /* 'e' */
+  NULL,                                /* 'f' */
+  NULL,                                /* 'g' */
+  NULL,                                /* 'h' */
+  NULL,                                /* 'i' */
+  NULL,                                /* 'j' */
+  NULL,                                /* 'k' */
+  NULL,                                /* 'l' */
+  NULL,                                /* 'm' */
+  NULL,                                /* 'n' */
+  NULL,                                /* 'o' */
+  ppc_special_sections_p,      /* 'p' */
+  NULL,                                /* 'q' */
+  NULL,                                /* 'r' */
+  ppc_special_sections_s,      /* 's' */
+  ppc_special_sections_t,      /* 's' */
+  NULL,                                /* 'u' */
+  NULL,                                /* 'v' */
+  NULL,                                /* 'w' */
+  NULL,                                /* 'x' */
+  NULL,                                /* 'y' */
+  NULL,                                /* 'z' */
+  ppc_special_sections_other,  /* other */
 };
 \f
 /* Very simple linked list structure for recording apuinfo values.  */
@@ -2222,8 +2170,7 @@ struct ppc_elf_link_hash_table
   asection *relbss;
   asection *dynsbss;
   asection *relsbss;
-  elf_linker_section_t *sdata;
-  elf_linker_section_t *sdata2;
+  elf_linker_section_t sdata[2];
   asection *sbss;
 
   /* Shortcut to .__tls_get_addr.  */
@@ -2235,6 +2182,11 @@ struct ppc_elf_link_hash_table
     bfd_vma offset;
   } tlsld_got;
 
+  /* Size of reserved GOT entries.  */
+  unsigned int got_header_size;
+  /* Non-zero if allocating the header left a gap.  */
+  unsigned int got_gap;
+
   /* Small local sym to section mapping cache.  */
   struct sym_sec_cache sym_sec;
 };
@@ -2291,6 +2243,14 @@ ppc_elf_link_hash_table_create (bfd *abfd)
       return NULL;
     }
 
+  ret->sdata[0].name = ".sdata";
+  ret->sdata[0].sym_name = "_SDA_BASE_";
+  ret->sdata[0].bss_name = ".sbss";
+
+  ret->sdata[1].name = ".sdata2";
+  ret->sdata[1].sym_name = "_SDA2_BASE_";
+  ret->sdata[1].bss_name = ".sbss2";
+
   return &ret->elf.root;
 }
 
@@ -2316,12 +2276,10 @@ ppc_elf_create_got (bfd *abfd, struct bfd_link_info *info)
   if (!bfd_set_section_flags (abfd, s, flags))
     return FALSE;
 
-  htab->relgot = bfd_make_section (abfd, ".rela.got");
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+          | SEC_LINKER_CREATED | SEC_READONLY);
+  htab->relgot = bfd_make_section_with_flags (abfd, ".rela.got", flags);
   if (!htab->relgot
-      || ! bfd_set_section_flags (abfd, htab->relgot,
-                                 (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
-                                  | SEC_IN_MEMORY | SEC_LINKER_CREATED
-                                  | SEC_READONLY))
       || ! bfd_set_section_alignment (abfd, htab->relgot, 2))
     return FALSE;
 
@@ -2352,17 +2310,19 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
           | SEC_LINKER_CREATED);
 
   htab->dynbss = bfd_get_section_by_name (abfd, ".dynbss");
-  htab->dynsbss = s = bfd_make_section (abfd, ".dynsbss");
-  if (s == NULL
-      || ! bfd_set_section_flags (abfd, s, SEC_ALLOC | SEC_LINKER_CREATED))
+  s = bfd_make_section_with_flags (abfd, ".dynsbss",
+                                  SEC_ALLOC | SEC_LINKER_CREATED);
+  htab->dynsbss = s;
+  if (s == NULL)
     return FALSE;
 
   if (! info->shared)
     {
       htab->relbss = bfd_get_section_by_name (abfd, ".rela.bss");
-      htab->relsbss = s = bfd_make_section (abfd, ".rela.sbss");
+      s = bfd_make_section_with_flags (abfd, ".rela.sbss",
+                                      flags | SEC_READONLY);
+      htab->relsbss = s;
       if (s == NULL
-         || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
          || ! bfd_set_section_alignment (abfd, s, 2))
        return FALSE;
     }
@@ -2372,7 +2332,7 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   if (s == NULL)
     abort ();
 
-  flags = SEC_ALLOC | SEC_CODE | SEC_IN_MEMORY | SEC_LINKER_CREATED;
+  flags = SEC_ALLOC | SEC_CODE | SEC_LINKER_CREATED;
   return bfd_set_section_flags (abfd, s, flags);
 }
 
@@ -2440,6 +2400,17 @@ ppc_elf_copy_indirect_symbol (const struct elf_backend_data *bed,
     _bfd_elf_link_hash_copy_indirect (bed, dir, ind);
 }
 
+/* Return 1 if target is one of ours.  */
+
+static bfd_boolean
+is_ppc_elf_target (const struct bfd_target *targ)
+{
+  extern const bfd_target bfd_elf32_powerpc_vec;
+  extern const bfd_target bfd_elf32_powerpcle_vec;
+
+  return targ == &bfd_elf32_powerpc_vec || targ == &bfd_elf32_powerpcle_vec;
+}
+
 /* Hook called by the linker routine which adds symbols from an object
    file.  We use it to put .comm items in .sbss, and not .bss.  */
 
@@ -2464,11 +2435,15 @@ ppc_elf_add_symbol_hook (bfd *abfd,
       htab = ppc_elf_hash_table (info);
       if (htab->sbss == NULL)
        {
-         flagword flags = SEC_IS_COMMON;
+         flagword flags = SEC_IS_COMMON | SEC_LINKER_CREATED;
+
+         if (!htab->elf.dynobj)
+           htab->elf.dynobj = abfd;
 
-         htab->sbss = bfd_make_section_anyway (abfd, ".sbss");
-         if (htab->sbss == NULL
-             || ! bfd_set_section_flags (abfd, htab->sbss, flags))
+         htab->sbss = bfd_make_section_anyway_with_flags (htab->elf.dynobj,
+                                                          ".sbss",
+                                                          flags);
+         if (htab->sbss == NULL)
            return FALSE;
        }
 
@@ -2479,133 +2454,33 @@ ppc_elf_add_symbol_hook (bfd *abfd,
   return TRUE;
 }
 \f
-/* Enumeration to specify the special section.  */
-enum elf_linker_section_enum
-{
-  LINKER_SECTION_SDATA,
-  LINKER_SECTION_SDATA2
-};
+/* Create a special linker section.  */
 
-/* Create a special linker section */
-static elf_linker_section_t *
+static bfd_boolean
 ppc_elf_create_linker_section (bfd *abfd,
                               struct bfd_link_info *info,
-                              enum elf_linker_section_enum which)
+                              flagword flags,
+                              elf_linker_section_t *lsect)
 {
-  elf_linker_section_t *lsect;
   struct ppc_elf_link_hash_table *htab = ppc_elf_hash_table (info);
-  asection *s, *sym_sec;
-  bfd_size_type amt;
-  flagword flags;
-  const char *name;
-  const char *rel_name;
-  const char *sym_name;
-  bfd_vma sym_offset;
-
-  /* The linker creates these sections so it has somewhere to attach
-     their respective symbols.  Startup code (crt1.o) uses these symbols
-     to initialize a register pointing to the section.  If the output
-     sections corresponding to these input sections were empty it would
-     be OK to set the symbol to 0 (or any random number), because the
-     associated register should never be used.
-     FIXME: Setting a symbol this way is silly.  The symbols ought to 
-     be set the same way other backends set gp.  */
-  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
-          | SEC_LINKER_CREATED);
-  sym_offset = 32768;
-
-  switch (which)
-    {
-    default:
-      abort ();
-      return NULL;
-
-    case LINKER_SECTION_SDATA: /* .sdata/.sbss section */
-      name     = ".sdata";
-      rel_name = ".rela.sdata";
-      sym_name = "_SDA_BASE_";
-      break;
+  asection *s;
 
-    case LINKER_SECTION_SDATA2:        /* .sdata2/.sbss2 section */
-      name     = ".sdata2";
-      rel_name = ".rela.sdata2";
-      sym_name = "_SDA2_BASE_";
-      flags    |= SEC_READONLY;
-      break;
-    }
+  flags |= (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+           | SEC_LINKER_CREATED);
 
   /* Record the first bfd that needs the special sections.  */
   if (!htab->elf.dynobj)
     htab->elf.dynobj = abfd;
 
-  amt = sizeof (elf_linker_section_t);
-  lsect = bfd_zalloc (htab->elf.dynobj, amt);
-
-  lsect->sym_offset = sym_offset;
-
-  /* See if the sections already exist.  */
-  sym_sec = s = bfd_get_section_by_name (htab->elf.dynobj, name);
-  if (s == NULL || (s->flags & flags) != flags)
-    {
-      s = bfd_make_section_anyway (htab->elf.dynobj, name);
-      if (s == NULL
-         || !bfd_set_section_flags (htab->elf.dynobj, s, flags))
-       return NULL;
-      if (sym_sec == NULL)
-       sym_sec = s;
-    }
+  s = bfd_make_section_anyway_with_flags (htab->elf.dynobj,
+                                         lsect->name,
+                                         flags);
+  if (s == NULL
+      || !bfd_set_section_alignment (htab->elf.dynobj, s, 2))
+    return FALSE;
   lsect->section = s;
 
-  if (bfd_get_section_alignment (htab->elf.dynobj, s) < 2
-      && !bfd_set_section_alignment (htab->elf.dynobj, s, 2))
-    return NULL;
-
-  s->size = align_power (s->size, 2);
-
-#ifdef DEBUG
-  fprintf (stderr, "Creating section %s, current size = %ld\n",
-          name, (long) s->size);
-#endif
-
-  if (sym_name)
-    {
-      struct elf_link_hash_entry *h;
-      struct bfd_link_hash_entry *bh;
-
-#ifdef DEBUG
-      fprintf (stderr, "Adding %s to section %s\n", sym_name, name);
-#endif
-      bh = bfd_link_hash_lookup (info->hash, sym_name,
-                                FALSE, FALSE, FALSE);
-
-      if ((bh == NULL || bh->type == bfd_link_hash_undefined)
-         && !(_bfd_generic_link_add_one_symbol
-              (info, abfd, sym_name, BSF_GLOBAL, sym_sec, sym_offset, NULL,
-               FALSE, get_elf_backend_data (abfd)->collect, &bh)))
-       return NULL;
-      h = (struct elf_link_hash_entry *) bh;
-
-      h->type = STT_OBJECT;
-      lsect->sym_hash = h;
-
-      if (info->shared
-         && ! bfd_elf_link_record_dynamic_symbol (info, h))
-       return NULL;
-    }
-
-  if (info->shared)
-    {
-      s = bfd_make_section_anyway (htab->elf.dynobj, rel_name);
-      lsect->rel_section = s;
-      flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
-              | SEC_LINKER_CREATED | SEC_READONLY);
-      if (s == NULL
-         || ! bfd_set_section_flags (htab->elf.dynobj, s, flags)
-         || ! bfd_set_section_alignment (htab->elf.dynobj, s, 2))
-       return NULL;
-    }
-
-  return lsect;
+  return TRUE;
 }
 
 /* Find a linker generated pointer with a given addend and type.  */
@@ -2627,7 +2502,6 @@ elf_find_pointer_linker_section
 
 static bfd_boolean
 elf_create_pointer_linker_section (bfd *abfd,
-                                  struct bfd_link_info *info,
                                   elf_linker_section_t *lsect,
                                   struct elf_link_hash_entry *h,
                                   const Elf_Internal_Rela *rel)
@@ -2652,15 +2526,6 @@ elf_create_pointer_linker_section (bfd *abfd,
        return TRUE;
 
       ptr_linker_section_ptr = &eh->linker_section_pointer;
-      /* Make sure this symbol is output as a dynamic symbol.  */
-      if (h->dynindx == -1)
-       {
-         if (! bfd_elf_link_record_dynamic_symbol (info, h))
-           return FALSE;
-       }
-
-      if (lsect->rel_section)
-       lsect->rel_section->size += sizeof (Elf32_External_Rela);
     }
   else
     {
@@ -2689,15 +2554,6 @@ elf_create_pointer_linker_section (bfd *abfd,
        return TRUE;
 
       ptr_linker_section_ptr = &ptr[r_symndx];
-
-      if (info->shared)
-       {
-         /* If we are generating a shared object, we need to
-            output a R_<xxx>_RELATIVE reloc so that the
-            dynamic linker can adjust this GOT entry.  */
-         BFD_ASSERT (lsect->rel_section != NULL);
-         lsect->rel_section->size += sizeof (Elf32_External_Rela);
-       }
     }
 
   /* Allocate space for a pointer in the linker section, and allocate
@@ -2712,7 +2568,6 @@ elf_create_pointer_linker_section (bfd *abfd,
   linker_section_ptr->next = *ptr_linker_section_ptr;
   linker_section_ptr->addend = rel->r_addend;
   linker_section_ptr->lsect = lsect;
-  linker_section_ptr->written_address_p = FALSE;
   *ptr_linker_section_ptr = linker_section_ptr;
 
   linker_section_ptr->offset = lsect->section->size;
@@ -2784,6 +2639,15 @@ ppc_elf_check_relocs (bfd *abfd,
   if (info->relocatable)
     return TRUE;
 
+  /* Don't do anything special with non-loaded, non-alloced sections.
+     In particular, any relocs in such sections should not affect GOT
+     and PLT reference counting (ie. we don't allow them to create GOT
+     or PLT entries), there's no possibility or desire to optimize TLS
+     relocs, and there's not much point in propagating relocs to shared
+     libs that the dynamic linker won't relocate.  */
+  if ((sec->flags & SEC_ALLOC) == 0)
+    return TRUE;
+
 #ifdef DEBUG
   _bfd_error_handler ("ppc_elf_check_relocs called for section %A in %B",
                      sec, abfd);
@@ -2793,25 +2657,7 @@ ppc_elf_check_relocs (bfd *abfd,
   if (!ppc_elf_howto_table[R_PPC_ADDR32])
     ppc_elf_howto_init ();
 
-  /* Create the linker generated sections all the time so that the
-     special symbols are created.  */
   htab = ppc_elf_hash_table (info);
-  if (htab->sdata == NULL)
-    {
-      htab->sdata = ppc_elf_create_linker_section (abfd, info,
-                                                  LINKER_SECTION_SDATA);
-      if (htab->sdata == NULL)
-       return FALSE;
-    }
-
-  if (htab->sdata2 == NULL)
-    {
-      htab->sdata2 = ppc_elf_create_linker_section (abfd, info,
-                                                   LINKER_SECTION_SDATA2);
-      if (htab->sdata2 == NULL)
-       return FALSE;
-    }
-
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
   sym_hashes = elf_sym_hashes (abfd);
   sreloc = NULL;
@@ -2833,15 +2679,15 @@ ppc_elf_check_relocs (bfd *abfd,
       /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got.
         This shows up in particular in an R_PPC_ADDR32 in the eabi
         startup code.  */
-      if (h && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+      if (h != NULL
+         && htab->got == NULL
+         && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
        {
-         if (htab->got == NULL)
-           {
-             if (htab->elf.dynobj == NULL)
-               htab->elf.dynobj = abfd;
-             if (!ppc_elf_create_got (htab->elf.dynobj, info))
-               return FALSE;
-           }
+         if (htab->elf.dynobj == NULL)
+           htab->elf.dynobj = abfd;
+         if (!ppc_elf_create_got (htab->elf.dynobj, info))
+           return FALSE;
+         BFD_ASSERT (h == htab->elf.hgot);
        }
 
       r_type = ELF32_R_TYPE (rel->r_info);
@@ -2911,8 +2757,12 @@ ppc_elf_check_relocs (bfd *abfd,
              bad_shared_reloc (abfd, r_type);
              return FALSE;
            }
-         if (!elf_create_pointer_linker_section (abfd, info,
-                                                 htab->sdata, h, rel))
+         if (htab->sdata[0].section == NULL
+             && !ppc_elf_create_linker_section (abfd, info, 0,
+                                                &htab->sdata[0]))
+           return FALSE;
+         if (!elf_create_pointer_linker_section (abfd, &htab->sdata[0],
+                                                 h, rel))
            return FALSE;
          break;
 
@@ -2923,8 +2773,12 @@ ppc_elf_check_relocs (bfd *abfd,
              bad_shared_reloc (abfd, r_type);
              return FALSE;
            }
-         if (!elf_create_pointer_linker_section (abfd, info,
-                                                 htab->sdata2, h, rel))
+         if (htab->sdata[1].section == NULL
+             && !ppc_elf_create_linker_section (abfd, info, SEC_READONLY,
+                                                &htab->sdata[1]))
+           return FALSE;
+         if (!elf_create_pointer_linker_section (abfd, &htab->sdata[1],
+                                                 h, rel))
            return FALSE;
          break;
 
@@ -3059,8 +2913,7 @@ ppc_elf_check_relocs (bfd *abfd,
        case R_PPC_REL14_BRTAKEN:
        case R_PPC_REL14_BRNTAKEN:
        case R_PPC_REL32:
-         if (h == NULL
-             || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+         if (h == NULL || h == htab->elf.hgot)
            break;
          /* fall through */
 
@@ -3115,7 +2968,6 @@ ppc_elf_check_relocs (bfd *abfd,
                           || !h->def_regular))))
              || (ELIMINATE_COPY_RELOCS
                  && !info->shared
-                 && (sec->flags & SEC_ALLOC) != 0
                  && h != NULL
                  && (h->root.type == bfd_link_hash_defweak
                      || !h->def_regular)))
@@ -3145,19 +2997,20 @@ ppc_elf_check_relocs (bfd *abfd,
                              && strcmp (bfd_get_section_name (abfd, sec),
                                         name + 5) == 0);
 
+                 if (htab->elf.dynobj == NULL)
+                   htab->elf.dynobj = abfd;
                  sreloc = bfd_get_section_by_name (htab->elf.dynobj, name);
                  if (sreloc == NULL)
                    {
                      flagword flags;
 
-                     sreloc = bfd_make_section (htab->elf.dynobj, name);
                      flags = (SEC_HAS_CONTENTS | SEC_READONLY
-                              | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-                     if ((sec->flags & SEC_ALLOC) != 0)
-                       flags |= SEC_ALLOC | SEC_LOAD;
+                              | SEC_IN_MEMORY | SEC_LINKER_CREATED
+                              | SEC_ALLOC | SEC_LOAD);
+                     sreloc = bfd_make_section_with_flags (htab->elf.dynobj,
+                                                           name,
+                                                           flags);
                      if (sreloc == NULL
-                         || ! bfd_set_section_flags (htab->elf.dynobj,
-                                                     sreloc, flags)
                          || ! bfd_set_section_alignment (htab->elf.dynobj,
                                                          sreloc, 2))
                        return FALSE;
@@ -3212,6 +3065,98 @@ ppc_elf_check_relocs (bfd *abfd,
   return TRUE;
 }
 \f
+/* Merge backend specific data from an object file to the output
+   object file when linking.  */
+
+static bfd_boolean
+ppc_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
+{
+  flagword old_flags;
+  flagword new_flags;
+  bfd_boolean error;
+
+  if (!is_ppc_elf_target (ibfd->xvec)
+      || !is_ppc_elf_target (obfd->xvec))
+    return TRUE;
+
+  /* Check if we have the same endianess.  */
+  if (! _bfd_generic_verify_endian_match (ibfd, obfd))
+    return FALSE;
+
+  new_flags = elf_elfheader (ibfd)->e_flags;
+  old_flags = elf_elfheader (obfd)->e_flags;
+  if (!elf_flags_init (obfd))
+    {
+      /* First call, no flags set.  */
+      elf_flags_init (obfd) = TRUE;
+      elf_elfheader (obfd)->e_flags = new_flags;
+    }
+
+  /* Compatible flags are ok.  */
+  else if (new_flags == old_flags)
+    ;
+
+  /* Incompatible flags.  */
+  else
+    {
+      /* Warn about -mrelocatable mismatch.  Allow -mrelocatable-lib
+        to be linked with either.  */
+      error = FALSE;
+      if ((new_flags & EF_PPC_RELOCATABLE) != 0
+         && (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0)
+       {
+         error = TRUE;
+         (*_bfd_error_handler)
+           (_("%B: compiled with -mrelocatable and linked with "
+              "modules compiled normally"), ibfd);
+       }
+      else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0
+              && (old_flags & EF_PPC_RELOCATABLE) != 0)
+       {
+         error = TRUE;
+         (*_bfd_error_handler)
+           (_("%B: compiled normally and linked with "
+              "modules compiled with -mrelocatable"), ibfd);
+       }
+
+      /* The output is -mrelocatable-lib iff both the input files are.  */
+      if (! (new_flags & EF_PPC_RELOCATABLE_LIB))
+       elf_elfheader (obfd)->e_flags &= ~EF_PPC_RELOCATABLE_LIB;
+
+      /* The output is -mrelocatable iff it can't be -mrelocatable-lib,
+        but each input file is either -mrelocatable or -mrelocatable-lib.  */
+      if (! (elf_elfheader (obfd)->e_flags & EF_PPC_RELOCATABLE_LIB)
+         && (new_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE))
+         && (old_flags & (EF_PPC_RELOCATABLE_LIB | EF_PPC_RELOCATABLE)))
+       elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE;
+
+      /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if
+        any module uses it.  */
+      elf_elfheader (obfd)->e_flags |= (new_flags & EF_PPC_EMB);
+
+      new_flags &= ~(EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB);
+      old_flags &= ~(EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB);
+
+      /* Warn about any other mismatches.  */
+      if (new_flags != old_flags)
+       {
+         error = TRUE;
+         (*_bfd_error_handler)
+           (_("%B: uses different e_flags (0x%lx) fields "
+              "than previous modules (0x%lx)"),
+            ibfd, (long) new_flags, (long) old_flags);
+       }
+
+      if (error)
+       {
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
+    }
+
+  return TRUE;
+}
+\f
 /* Return the section that should be marked against GC for a given
    relocation.  */
 
@@ -3266,6 +3211,9 @@ ppc_elf_gc_sweep_hook (bfd *abfd,
   bfd_signed_vma *local_got_refcounts;
   const Elf_Internal_Rela *rel, *relend;
 
+  if ((sec->flags & SEC_ALLOC) == 0)
+    return TRUE;
+
   elf_section_data (sec)->local_dynrel = NULL;
 
   htab = ppc_elf_hash_table (info);
@@ -3344,8 +3292,7 @@ ppc_elf_gc_sweep_hook (bfd *abfd,
        case R_PPC_REL14_BRTAKEN:
        case R_PPC_REL14_BRNTAKEN:
        case R_PPC_REL32:
-         if (h == NULL
-             || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+         if (h == NULL || h == htab->elf.hgot)
            break;
          /* Fall thru */
 
@@ -3752,6 +3699,34 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
   return TRUE;
 }
 \f
+/* Allocate NEED contiguous space in .got, and return the offset.
+   Handles allocation of the got header when crossing 32k.  */
+
+static bfd_vma
+allocate_got (struct ppc_elf_link_hash_table *htab, unsigned int need)
+{
+  bfd_vma where;
+  unsigned int max_before_header = 32764;
+
+  if (need <= htab->got_gap)
+    {
+      where = max_before_header - htab->got_gap;
+      htab->got_gap -= need;
+    }
+  else
+    {
+      if (htab->got->size + need > max_before_header
+         && htab->got->size <= max_before_header)
+       {
+         htab->got_gap = max_before_header - htab->got->size;
+         htab->got->size = max_before_header + htab->got_header_size;
+       }
+      where = htab->got->size;
+      htab->got->size += need;
+    }
+  return where;
+}
+
 /* Allocate space in associated reloc sections for dynamic relocs.  */
 
 static bfd_boolean
@@ -3853,33 +3828,32 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       else
        {
          bfd_boolean dyn;
-         eh->elf.got.offset = htab->got->size;
+         unsigned int need = 0;
          if ((eh->tls_mask & TLS_TLS) != 0)
            {
              if ((eh->tls_mask & TLS_LD) != 0)
-               htab->got->size += 8;
+               need += 8;
              if ((eh->tls_mask & TLS_GD) != 0)
-               htab->got->size += 8;
+               need += 8;
              if ((eh->tls_mask & (TLS_TPREL | TLS_TPRELGD)) != 0)
-               htab->got->size += 4;
+               need += 4;
              if ((eh->tls_mask & TLS_DTPREL) != 0)
-               htab->got->size += 4;
+               need += 4;
            }
          else
-           htab->got->size += 4;
+           need += 4;
+         eh->elf.got.offset = allocate_got (htab, need);
          dyn = htab->elf.dynamic_sections_created;
          if ((info->shared
               || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf))
              && (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT
                  || eh->elf.root.type != bfd_link_hash_undefweak))
            {
-             /* All the entries we allocated need relocs.  */
-             htab->relgot->size
-               += ((htab->got->size - eh->elf.got.offset) / 4
-                   * sizeof (Elf32_External_Rela));
-             /* Except LD only needs one.  */
+             /* All the entries we allocated need relocs.
+                Except LD only needs one.  */
              if ((eh->tls_mask & TLS_LD) != 0)
-               htab->relgot->size -= sizeof (Elf32_External_Rela);
+               need -= 4;
+             htab->relgot->size += need * (sizeof (Elf32_External_Rela) / 4);
            }
        }
     }
@@ -4036,15 +4010,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        }
     }
 
-  if (htab->tlsld_got.refcount > 0)
-    {
-      htab->tlsld_got.offset = htab->got->size;
-      htab->got->size += 8;
-      if (info->shared)
-       htab->relgot->size += sizeof (Elf32_External_Rela);
-    }
-  else
-    htab->tlsld_got.offset = (bfd_vma) -1;
+  htab->got_header_size = 16;
 
   /* Set up .got offsets for local syms, and space for local dynamic
      relocs.  */
@@ -4055,7 +4021,6 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       char *lgot_masks;
       bfd_size_type locsymcount;
       Elf_Internal_Shdr *symtab_hdr;
-      asection *srel;
 
       if (!is_ppc_elf_target (ibfd->xvec))
        continue;
@@ -4097,8 +4062,6 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       locsymcount = symtab_hdr->sh_info;
       end_local_got = local_got + locsymcount;
       lgot_masks = (char *) end_local_got;
-      s = htab->got;
-      srel = htab->relgot;
       for (; local_got < end_local_got; ++local_got, ++lgot_masks)
        if (*local_got > 0)
          {
@@ -4106,41 +4069,60 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
              {
                /* If just an LD reloc, we'll just use
                   htab->tlsld_got.offset.  */
-               if (htab->tlsld_got.offset == (bfd_vma) -1)
-                 {
-                   htab->tlsld_got.offset = s->size;
-                   s->size += 8;
-                   if (info->shared)
-                     srel->size += sizeof (Elf32_External_Rela);
-                 }
+               htab->tlsld_got.refcount += 1;
                *local_got = (bfd_vma) -1;
              }
            else
              {
-               *local_got = s->size;
+               unsigned int need = 0;
                if ((*lgot_masks & TLS_TLS) != 0)
                  {
                    if ((*lgot_masks & TLS_GD) != 0)
-                     s->size += 8;
+                     need += 8;
                    if ((*lgot_masks & (TLS_TPREL | TLS_TPRELGD)) != 0)
-                     s->size += 4;
+                     need += 4;
                    if ((*lgot_masks & TLS_DTPREL) != 0)
-                     s->size += 4;
+                     need += 4;
                  }
                else
-                 s->size += 4;
+                 need += 4;
+               *local_got = allocate_got (htab, need);
                if (info->shared)
-                 srel->size += ((s->size - *local_got) / 4
-                                * sizeof (Elf32_External_Rela));
+                 htab->relgot->size += (need
+                                        * (sizeof (Elf32_External_Rela) / 4));
              }
          }
        else
          *local_got = (bfd_vma) -1;
     }
 
+  if (htab->tlsld_got.refcount > 0)
+    {
+      htab->tlsld_got.offset = allocate_got (htab, 8);
+      if (info->shared)
+       htab->relgot->size += sizeof (Elf32_External_Rela);
+    }
+  else
+    htab->tlsld_got.offset = (bfd_vma) -1;
+
   /* Allocate space for global sym dynamic relocs.  */
   elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
 
+  if (htab->got != NULL)
+    {
+      unsigned int g_o_t = 32768;
+
+      /* If we haven't allocated the header, do so now.  */
+      if (htab->got->size <= 32768)
+       {
+         g_o_t = htab->got->size;
+         htab->got->size += htab->got_header_size;
+       }
+      g_o_t += 4;
+
+      htab->elf.hgot->root.u.def.value = g_o_t;
+    }
+
   /* We've now determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -4150,19 +4132,16 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        continue;
 
       if (s == htab->plt
-         || s == htab->got)
+         || s == htab->got
+         || s == htab->sbss)
        {
          /* Strip this section if we don't need it; see the
             comment below.  */
        }
-      else if ((htab->sdata != NULL && s == htab->sdata->section)
-              || (htab->sdata2 != NULL && s == htab->sdata2->section))
+      else if (s == htab->sdata[0].section
+              || s == htab->sdata[1].section)
        {
-         if (s->size == 0)
-           /* Don't strip these sections.  We need them because they
-              define _SDA_BASE_ and _SDA2_BASE_.  crt1.o makes a
-              reference to _SDA_BASE_ to set up r13.  */
-           continue;
+         /* Strip these too.  */
        }
       else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0)
        {
@@ -4196,10 +4175,13 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
       if (s->size == 0)
        {
-         _bfd_strip_section_from_output (info, s);
+         s->flags |= SEC_EXCLUDE;
          continue;
        }
 
+      if (s == htab->sbss)
+       continue;
+
       /* Allocate memory for the section contents.  */
       s->contents = bfd_zalloc (htab->elf.dynobj, s->size);
       if (s->contents == NULL)
@@ -4304,8 +4286,11 @@ ppc_elf_relax_section (bfd *abfd,
 
   *again = FALSE;
 
-  /* Nothing to do if there are no relocations.  */
-  if ((isec->flags & SEC_RELOC) == 0 || isec->reloc_count == 0)
+  /* Nothing to do if there are no relocations, and no need to do
+     anything with non-alloc sections.  */
+  if ((isec->flags & SEC_ALLOC) == 0
+      || (isec->flags & SEC_RELOC) == 0
+      || isec->reloc_count == 0)
     return TRUE;
 
   trampoff = (isec->size + 3) & (bfd_vma) -4;
@@ -4664,19 +4649,64 @@ ppc_elf_relax_section (bfd *abfd,
   return FALSE;
 }
 \f
-#define bfd_put_ptr(BFD, VAL, ADDR) bfd_put_32 (BFD, VAL, ADDR)
+/* Set _SDA_BASE_, _SDA2_BASE, and sbss start and end syms.  They are
+   set here rather than via PROVIDE in the default linker script,
+   because using PROVIDE inside an output section statement results in
+   unnecessary output sections.  Using PROVIDE outside an output section
+   statement runs the risk of section alignment affecting where the
+   section starts.  */
 
+bfd_boolean
+ppc_elf_set_sdata_syms (bfd *obfd, struct bfd_link_info *info)
+{
+  struct ppc_elf_link_hash_table *htab;
+  unsigned i;
+  asection *s;
+  bfd_vma val;
+
+  htab = ppc_elf_hash_table (info);
+
+  for (i = 0; i < 2; i++)
+    {
+      elf_linker_section_t *lsect = &htab->sdata[i];
+
+      s = lsect->section;
+      if (s != NULL)
+       s = s->output_section;
+      if (s == NULL)
+       s = bfd_get_section_by_name (obfd, lsect->name);
+      if (s == NULL)
+       s = bfd_get_section_by_name (obfd, lsect->bss_name);
+
+      val = 0;
+      if (s != NULL)
+       val = s->vma + 32768;
+      lsect->sym_val = val;
+
+      _bfd_elf_provide_symbol (info, lsect->sym_name, val);
+    }
+
+  s = bfd_get_section_by_name (obfd, ".sbss");
+  val = 0;
+  if (s != NULL)
+    val = s->vma;
+  _bfd_elf_provide_symbol (info, "__sbss_start", val);
+  _bfd_elf_provide_symbol (info, "___sbss_start", val);
+  if (s != NULL)
+    val += s->size;
+  _bfd_elf_provide_symbol (info, "__sbss_end", val);
+  _bfd_elf_provide_symbol (info, "___sbss_end", val);
+  return TRUE;
+}
+\f
 /* Fill in the address for a pointer generated in a linker section.  */
 
 static bfd_vma
-elf_finish_pointer_linker_section (bfd *output_bfd,
-                                  bfd *input_bfd,
-                                  struct bfd_link_info *info,
+elf_finish_pointer_linker_section (bfd *input_bfd,
                                   elf_linker_section_t *lsect,
                                   struct elf_link_hash_entry *h,
                                   bfd_vma relocation,
-                                  const Elf_Internal_Rela *rel,
-                                  int relative_reloc)
+                                  const Elf_Internal_Rela *rel)
 {
   elf_linker_section_pointers_t *linker_section_ptr;
 
@@ -4688,90 +4718,36 @@ elf_finish_pointer_linker_section (bfd *output_bfd,
       struct ppc_elf_link_hash_entry *eh;
 
       eh = (struct ppc_elf_link_hash_entry *) h;
-      linker_section_ptr
-       = elf_find_pointer_linker_section (eh->linker_section_pointer,
-                                          rel->r_addend,
-                                          lsect);
-
-      BFD_ASSERT (linker_section_ptr != NULL);
-
-      if (! elf_hash_table (info)->dynamic_sections_created
-         || (info->shared
-             && info->symbolic
-             && h->def_regular))
-       {
-         /* This is actually a static link, or it is a
-            -Bsymbolic link and the symbol is defined
-            locally.  We must initialize this entry in the
-            global section.
-
-            When doing a dynamic link, we create a .rela.<xxx>
-            relocation entry to initialize the value.  This
-            is done in the finish_dynamic_symbol routine.  */
-         if (!linker_section_ptr->written_address_p)
-           {
-             linker_section_ptr->written_address_p = TRUE;
-             bfd_put_ptr (output_bfd,
-                          relocation + linker_section_ptr->addend,
-                          (lsect->section->contents
-                           + linker_section_ptr->offset));
-           }
-       }
+      BFD_ASSERT (eh->elf.def_regular);
+      linker_section_ptr = eh->linker_section_pointer;
     }
   else
     {
       /* Handle local symbol.  */
       unsigned long r_symndx = ELF32_R_SYM (rel->r_info);
-      BFD_ASSERT (elf_local_ptr_offsets (input_bfd) != NULL);
-      BFD_ASSERT (elf_local_ptr_offsets (input_bfd)[r_symndx] != NULL);
-      linker_section_ptr = (elf_find_pointer_linker_section
-                           (elf_local_ptr_offsets (input_bfd)[r_symndx],
-                            rel->r_addend,
-                            lsect));
-
-      BFD_ASSERT (linker_section_ptr != NULL);
-
-      /* Write out pointer if it hasn't been rewritten out before.  */
-      if (!linker_section_ptr->written_address_p)
-       {
-         linker_section_ptr->written_address_p = TRUE;
-         bfd_put_ptr (output_bfd, relocation + linker_section_ptr->addend,
-                      lsect->section->contents + linker_section_ptr->offset);
-
-         if (info->shared)
-           {
-             /* We need to generate a relative reloc for the dynamic
-                linker.  */
 
-             asection *srel = lsect->rel_section;
-             Elf_Internal_Rela outrel[MAX_INT_RELS_PER_EXT_REL];
-             bfd_byte *erel;
-             const struct elf_backend_data *bed;
-             unsigned int i;
+      BFD_ASSERT (elf_local_ptr_offsets (input_bfd) != NULL);
+      linker_section_ptr = elf_local_ptr_offsets (input_bfd)[r_symndx];
+    }
 
-             BFD_ASSERT (srel != NULL);
+  linker_section_ptr = elf_find_pointer_linker_section (linker_section_ptr,
+                                                       rel->r_addend,
+                                                       lsect);
+  BFD_ASSERT (linker_section_ptr != NULL);
 
-             bed = get_elf_backend_data (output_bfd);
-             for (i = 0; i < bed->s->int_rels_per_ext_rel; i++)
-               {
-                 outrel[i].r_offset = (lsect->section->output_section->vma
-                                       + lsect->section->output_offset
-                                       + linker_section_ptr->offset);
-                 outrel[i].r_info = 0;
-                 outrel[i].r_addend = 0;
-               }
-             outrel[0].r_info = ELF32_R_INFO (0, relative_reloc);
-             erel = lsect->section->contents;
-             erel += (elf_section_data (lsect->section)->rel_count++
-                      * sizeof (Elf32_External_Rela));
-             bfd_elf32_swap_reloca_out (output_bfd, outrel, erel);
-           }
-       }
+  /* Offset will always be a multiple of four, so use the bottom bit
+     as a "written" flag.  */
+  if ((linker_section_ptr->offset & 1) == 0)
+    {
+      bfd_put_32 (lsect->section->owner,
+                 relocation + linker_section_ptr->addend,
+                 lsect->section->contents + linker_section_ptr->offset);
+      linker_section_ptr->offset += 1;
     }
 
   relocation = (lsect->section->output_offset
-               + linker_section_ptr->offset
-               - lsect->sym_offset);
+               + linker_section_ptr->offset - 1
+               - 0x8000);
 
 #ifdef DEBUG
   fprintf (stderr,
@@ -4884,7 +4860,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
        {
          sym = local_syms + r_symndx;
          sec = local_sections[r_symndx];
-         sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym);
+         sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec);
 
          relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
        }
@@ -5383,7 +5359,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
                  }
              }
 
-           relocation = htab->got->output_offset + off - 4;
+           relocation = htab->got->output_offset + off;
+           relocation -= htab->elf.hgot->root.u.def.value;
 
            /* Addends on got relocations don't make much sense.
               x+off@got is actually x@got+off, and since the got is
@@ -5457,7 +5434,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
          /* If these relocations are not to a named symbol, they can be
             handled right here, no need to bother the dynamic linker.  */
          if (SYMBOL_REFERENCES_LOCAL (info, h)
-             || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+             || h == htab->elf.hgot)
            break;
          /* fall through */
 
@@ -5482,6 +5459,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
            break;
          /* Fall thru.  */
 
+         if ((input_section->flags & SEC_ALLOC) == 0)
+           break;
+         /* Fall thru.  */
+
          if ((info->shared
               && (h == NULL
                   || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
@@ -5490,7 +5471,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
                   || !SYMBOL_CALLS_LOCAL (info, h)))
              || (ELIMINATE_COPY_RELOCS
                  && !info->shared
-                 && (input_section->flags & SEC_ALLOC) != 0
                  && h != NULL
                  && h->dynindx != -1
                  && !h->non_got_ref
@@ -5654,20 +5634,18 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
          /* Indirect .sdata relocation.  */
        case R_PPC_EMB_SDAI16:
-         BFD_ASSERT (htab->sdata != NULL);
+         BFD_ASSERT (htab->sdata[0].section != NULL);
          relocation
-           = elf_finish_pointer_linker_section (output_bfd, input_bfd, info,
-                                                htab->sdata, h, relocation,
-                                                rel, R_PPC_RELATIVE);
+           = elf_finish_pointer_linker_section (input_bfd, &htab->sdata[0],
+                                                h, relocation, rel);
          break;
 
          /* Indirect .sdata2 relocation.  */
        case R_PPC_EMB_SDA2I16:
-         BFD_ASSERT (htab->sdata2 != NULL);
+         BFD_ASSERT (htab->sdata[1].section != NULL);
          relocation
-           = elf_finish_pointer_linker_section (output_bfd, input_bfd, info,
-                                                htab->sdata2, h, relocation,
-                                                rel, R_PPC_RELATIVE);
+           = elf_finish_pointer_linker_section (input_bfd, &htab->sdata[1],
+                                                h, relocation, rel);
          break;
 
          /* Handle the TOC16 reloc.  We want to use the offset within the .got
@@ -5707,7 +5685,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_SDAREL16:
          {
            const char *name;
-           const struct elf_link_hash_entry *sh;
 
            BFD_ASSERT (sec != NULL);
            name = bfd_get_section_name (abfd, sec->output_section);
@@ -5724,10 +5701,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                   howto->name,
                   name);
              }
-           sh = htab->sdata->sym_hash;
-           addend -= (sh->root.u.def.value
-                      + sh->root.u.def.section->output_section->vma
-                      + sh->root.u.def.section->output_offset);
+           addend -= htab->sdata[0].sym_val;
          }
          break;
 
@@ -5735,7 +5709,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_EMB_SDA2REL:
          {
            const char *name;
-           const struct elf_link_hash_entry *sh;
 
            BFD_ASSERT (sec != NULL);
            name = bfd_get_section_name (abfd, sec->output_section);
@@ -5754,10 +5727,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                ret = FALSE;
                continue;
              }
-           sh = htab->sdata2->sym_hash;
-           addend -= (sh->root.u.def.value
-                      + sh->root.u.def.section->output_section->vma
-                      + sh->root.u.def.section->output_offset);
+           addend -= htab->sdata[1].sym_val;
          }
          break;
 
@@ -5766,7 +5736,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_EMB_RELSDA:
          {
            const char *name;
-           const struct elf_link_hash_entry *sh;
            int reg;
 
            BFD_ASSERT (sec != NULL);
@@ -5777,20 +5746,14 @@ ppc_elf_relocate_section (bfd *output_bfd,
                     && (name[5] == 0 || name[5] == '.'))))
              {
                reg = 13;
-               sh = htab->sdata->sym_hash;
-               addend -= (sh->root.u.def.value
-                          + sh->root.u.def.section->output_section->vma
-                          + sh->root.u.def.section->output_offset);
+               addend -= htab->sdata[0].sym_val;
              }
 
            else if (strncmp (name, ".sdata2", 7) == 0
                     || strncmp (name, ".sbss2", 6) == 0)
              {
                reg = 2;
-               sh = htab->sdata2->sym_hash;
-               addend -= (sh->root.u.def.value
-                          + sh->root.u.def.section->output_section->vma
-                          + sh->root.u.def.section->output_offset);
+               addend -= htab->sdata[1].sym_val;
              }
 
            else if (strcmp (name, ".PPC.EMB.sdata0") == 0
@@ -5931,8 +5894,6 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
       if (r != bfd_reloc_ok)
        {
-         if (sym_name == NULL)
-           sym_name = "(null)";
          if (r == bfd_reloc_overflow)
            {
              if (warned)
@@ -6078,8 +6039,8 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
 #endif
 
   /* Mark some specially defined symbols as absolute.  */
-  if (strcmp (h->root.root.string, "_DYNAMIC") == 0
-      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
+  if (h == htab->elf.hgot
+      || strcmp (h->root.root.string, "_DYNAMIC") == 0
       || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
     sym->st_shndx = SHN_ABS;
 
@@ -6161,17 +6122,18 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
 
   /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can
      easily find the address of the _GLOBAL_OFFSET_TABLE_.  */
-  if (htab->got)
+  if (htab->got != NULL)
     {
-      unsigned char *contents = htab->got->contents;
-      bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, contents);
+      unsigned char *p = htab->got->contents;
+      bfd_vma val;
 
-      if (sdyn == NULL)
-       bfd_put_32 (output_bfd, 0, contents + 4);
-      else
-       bfd_put_32 (output_bfd,
-                   sdyn->output_section->vma + sdyn->output_offset,
-                   contents + 4);
+      p += elf_hash_table (info)->hgot->root.u.def.value;
+      bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4);
+
+      val = 0;
+      if (sdyn != NULL)
+       val = sdyn->output_section->vma + sdyn->output_offset;
+      bfd_put_32 (output_bfd, val, p);
 
       elf_section_data (htab->got->output_section)->this_hdr.sh_entsize = 4;
     }
@@ -6202,10 +6164,8 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
 #endif
 
 #define elf_backend_plt_not_loaded     1
-#define elf_backend_got_symbol_offset  4
 #define elf_backend_can_gc_sections    1
 #define elf_backend_can_refcount       1
-#define elf_backend_got_header_size    12
 #define elf_backend_rela_normal                1
 
 #define bfd_elf32_mkobject                     ppc_elf_mkobject
This page took 0.042032 seconds and 4 git commands to generate.