* elf64-ppc.c (bfd_elf64_mkobject): Define.
authorAlan Modra <amodra@gmail.com>
Thu, 10 Jul 2003 00:37:27 +0000 (00:37 +0000)
committerAlan Modra <amodra@gmail.com>
Thu, 10 Jul 2003 00:37:27 +0000 (00:37 +0000)
(struct ppc64_elf_obj_tdata): New.
(ppc64_elf_tdata, ppc64_tlsld_got): Define.
(ppc64_elf_mkobject): New function.
(struct got_entry): Add "owner".  Move "tls_type".
(struct ppc_link_hash_table): Delete "relgot", "tlsld_got".
(ppc64_elf_init_stub_bfd): New function.
(create_got_section): Create header .got in dynobj.  Create .got
and .rela.got in each bfd.  Stash pointers in ppc64_elf_obj_tdata.
(ppc64_elf_create_dynamic_sections): Don't call create_got_section.
Look for dynobj .got, and test it.
(ppc64_elf_copy_indirect_symbol): Adjust for changed got.
(update_local_sym_info): Likewise.
(ppc64_elf_check_relocs): Likewise.
(ppc64_elf_gc_sweep_hook): Likewise.
(ppc64_elf_tls_optimize): Likewise.
(allocate_dynrelocs): Likewise.
(ppc64_elf_size_dynamic_sections): Likewise.
(ppc64_elf_relocate_section): Likewise.
(ppc64_elf_next_toc_section): Update comment.
(toc_adjusting_stub_needed): Remove unneeded cast.
(ppc64_elf_build_stubs): Check for stub sections in stub bfd by
testing section flags.
(ppc64_elf_build_stubs): Likewise.
(ppc64_elf_size_stubs): Likewise.  Remove stub_bfd param.
(ppc64_elf_finish_dynamic_sections): Write out got sections.
(func_desc_adjust): Copy over dynamic info for undef weaks.
* elf64-ppc.h (ppc64_elf_init_stub_bfd): Declare.
(ppc64_elf_size_stubs): Update prototype.
* elflink.h (elf_link_sort_relocs): Use link_orders to find reldyn
input sections rather than scanning dynobj.

bfd/ChangeLog
bfd/elf64-ppc.c
bfd/elf64-ppc.h
bfd/elflink.h

index 55d40ef7d1fbf838048e83a55baa06fb920acb0f..86cc6d298bb50c3c255b9d9c99267ab5c97298c2 100644 (file)
@@ -1,3 +1,37 @@
+2003-07-10  Alan Modra  <amodra@bigpond.net.au>
+
+       * elf64-ppc.c (bfd_elf64_mkobject): Define.
+       (struct ppc64_elf_obj_tdata): New.
+       (ppc64_elf_tdata, ppc64_tlsld_got): Define.
+       (ppc64_elf_mkobject): New function.
+       (struct got_entry): Add "owner".  Move "tls_type".
+       (struct ppc_link_hash_table): Delete "relgot", "tlsld_got".
+       (ppc64_elf_init_stub_bfd): New function.
+       (create_got_section): Create header .got in dynobj.  Create .got
+       and .rela.got in each bfd.  Stash pointers in ppc64_elf_obj_tdata.
+       (ppc64_elf_create_dynamic_sections): Don't call create_got_section.
+       Look for dynobj .got, and test it.
+       (ppc64_elf_copy_indirect_symbol): Adjust for changed got.
+       (update_local_sym_info): Likewise.
+       (ppc64_elf_check_relocs): Likewise.
+       (ppc64_elf_gc_sweep_hook): Likewise.
+       (ppc64_elf_tls_optimize): Likewise.
+       (allocate_dynrelocs): Likewise.
+       (ppc64_elf_size_dynamic_sections): Likewise.
+       (ppc64_elf_relocate_section): Likewise.
+       (ppc64_elf_next_toc_section): Update comment.
+       (toc_adjusting_stub_needed): Remove unneeded cast.
+       (ppc64_elf_build_stubs): Check for stub sections in stub bfd by
+       testing section flags.
+       (ppc64_elf_build_stubs): Likewise.
+       (ppc64_elf_size_stubs): Likewise.  Remove stub_bfd param.
+       (ppc64_elf_finish_dynamic_sections): Write out got sections.
+       (func_desc_adjust): Copy over dynamic info for undef weaks.
+       * elf64-ppc.h (ppc64_elf_init_stub_bfd): Declare.
+       (ppc64_elf_size_stubs): Update prototype.
+       * elflink.h (elf_link_sort_relocs): Use link_orders to find reldyn
+       input sections rather than scanning dynobj.
+
 2003-07-09  Richard Sandiford  <rsandifo@redhat.com>
 
        * elfxx-mips.c (mips_elf_link_hash_entry): Remove min_dyn_reloc_index.
index ab2f45a3ad6e3daf3d1b3dac011871990078ed8d..0334d84c9b55d35469e565e94ddefe3f9e5b8fc9 100644 (file)
@@ -69,6 +69,7 @@ static bfd_reloc_status_type ppc64_elf_unhandled_reloc
 #define elf_backend_can_refcount 1
 #define elf_backend_rela_normal 1
 
+#define bfd_elf64_mkobject                   ppc64_elf_mkobject
 #define bfd_elf64_bfd_reloc_type_lookup              ppc64_elf_reloc_type_lookup
 #define bfd_elf64_bfd_merge_private_bfd_data  ppc64_elf_merge_private_bfd_data
 #define bfd_elf64_new_section_hook           ppc64_elf_new_section_hook
@@ -2316,6 +2317,40 @@ ppc64_elf_unhandled_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
   return bfd_reloc_dangerous;
 }
 
+struct ppc64_elf_obj_tdata
+{
+  struct elf_obj_tdata elf;
+
+  /* Shortcuts to dynamic linker sections.  */
+  asection *got;
+  asection *relgot;
+
+  /* TLS local dynamic got entry handling.  Suppose for multiple GOT
+     sections means we potentially need one of these for each input bfd.  */
+  union {
+    bfd_signed_vma refcount;
+    bfd_vma offset;
+  } tlsld_got;
+};
+
+#define ppc64_elf_tdata(bfd) \
+  ((struct ppc64_elf_obj_tdata *) (bfd)->tdata.any)
+
+#define ppc64_tlsld_got(bfd) \
+  (&ppc64_elf_tdata (bfd)->tlsld_got)
+
+/* Override the generic function because we store some extras.  */
+
+static bfd_boolean
+ppc64_elf_mkobject (bfd *abfd)
+{
+  bfd_size_type amt = sizeof (struct ppc64_elf_obj_tdata);
+  abfd->tdata.any = bfd_zalloc (abfd, amt);
+  if (abfd->tdata.any == NULL)
+    return FALSE;
+  return TRUE;
+}
+
 /* Fix bad default arch selected for a 64 bit input bfd when the
    default is 32 bit.  */
 
@@ -2497,16 +2532,24 @@ struct got_entry
   /* The symbol addend that we'll be placing in the GOT.  */
   bfd_vma addend;
 
+  /* Unlike other ELF targets, we use separate GOT entries for the same
+     symbol referenced from different input files.  This is to support
+     automatic multiple TOC/GOT sections, where the TOC base can vary
+     from one input file to another.
+
+     Point to the BFD owning this GOT entry.  */
+  bfd *owner;
+
+  /* Zero for non-tls entries, or TLS_TLS and one of TLS_GD, TLS_LD,
+     TLS_TPREL or TLS_DTPREL for tls entries.  */
+  char tls_type;
+
   /* Reference count until size_dynamic_sections, GOT offset thereafter.  */
   union
     {
       bfd_signed_vma refcount;
       bfd_vma offset;
     } got;
-
-  /* Zero for non-tls entries, or TLS_TLS and one of TLS_GD, TLS_LD,
-     TLS_TPREL or TLS_DTPREL for tls entries.  */
-  char tls_type;
 };
 
 /* The same for PLT.  */
@@ -2719,7 +2762,6 @@ struct ppc_link_hash_table
 
   /* Short-cuts to get to dynamic linker sections.  */
   asection *got;
-  asection *relgot;
   asection *plt;
   asection *relplt;
   asection *dynbss;
@@ -2735,12 +2777,6 @@ struct ppc_link_hash_table
   /* Shortcut to .__tls_get_addr.  */
   struct elf_link_hash_entry *tls_get_addr;
 
-  /* TLS local dynamic got entry handling.  */
-  union {
-    bfd_signed_vma refcount;
-    bfd_vma offset;
-  } tlsld_got;
-
   /* Statistics.  */
   unsigned long stub_count[ppc_stub_plt_call];
 
@@ -2928,6 +2964,23 @@ ppc64_elf_link_hash_table_free (struct bfd_link_hash_table *hash)
   _bfd_generic_link_hash_table_free (hash);
 }
 
+/* Satisfy the ELF linker by filling in some fields in our fake bfd.  */
+
+void
+ppc64_elf_init_stub_bfd (bfd *abfd, struct bfd_link_info *info)
+{
+  struct ppc_link_hash_table *htab;
+
+  elf_elfheader (abfd)->e_ident[EI_CLASS] = ELFCLASS64;
+
+/* Always hook our dynamic sections into the first bfd, which is the
+   linker created stub bfd.  This ensures that the GOT header is at
+   the start of the output TOC section.  */
+  htab = ppc_hash_table (info);
+  htab->stub_bfd = abfd;
+  htab->elf.dynobj = abfd;
+}
+
 /* Build a name for an entry in the stub hash table.  */
 
 static char *
@@ -3122,30 +3175,43 @@ create_linkage_sections (bfd *dynobj, struct bfd_link_info *info)
   return TRUE;
 }
 
-/* Create .got and .rela.got sections in DYNOBJ, and set up
-   shortcuts to them in our hash table.  */
+/* Create .got and .rela.got sections in ABFD, and .got in dynobj if
+   not already done.  */
 
 static bfd_boolean
-create_got_section (bfd *dynobj, struct bfd_link_info *info)
+create_got_section (bfd *abfd, struct bfd_link_info *info)
 {
-  struct ppc_link_hash_table *htab;
-
-  if (! _bfd_elf_create_got_section (dynobj, info))
-    return FALSE;
+  asection *got, *relgot;
+  flagword flags;
+  struct ppc_link_hash_table *htab = ppc_hash_table (info);
 
-  htab = ppc_hash_table (info);
-  htab->got = bfd_get_section_by_name (dynobj, ".got");
   if (!htab->got)
-    abort ();
+    {
+      if (! _bfd_elf_create_got_section (htab->elf.dynobj, info))
+       return FALSE;
+
+      htab->got = bfd_get_section_by_name (htab->elf.dynobj, ".got");
+      if (!htab->got)
+       abort ();
+    }
+
+  flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+          | SEC_LINKER_CREATED);
+
+  got = bfd_make_section (abfd, ".got");
+  if (!got
+      || !bfd_set_section_flags (abfd, got, flags)
+      || !bfd_set_section_alignment (abfd, got, 3))
+    return FALSE;
 
-  htab->relgot = bfd_make_section (dynobj, ".rela.got");
-  if (!htab->relgot
-      || ! bfd_set_section_flags (dynobj, htab->relgot,
-                                 (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
-                                  | SEC_IN_MEMORY | SEC_LINKER_CREATED
-                                  | SEC_READONLY))
-      || ! bfd_set_section_alignment (dynobj, htab->relgot, 3))
+  relgot = bfd_make_section (abfd, ".rela.got");
+  if (!relgot
+      || ! bfd_set_section_flags (abfd, relgot, flags | SEC_READONLY)
+      || ! bfd_set_section_alignment (abfd, relgot, 3))
     return FALSE;
+
+  ppc64_elf_tdata (abfd)->got = got;
+  ppc64_elf_tdata (abfd)->relgot = relgot;
   return TRUE;
 }
 
@@ -3156,20 +3222,19 @@ ppc64_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
 {
   struct ppc_link_hash_table *htab;
 
-  htab = ppc_hash_table (info);
-  if (!htab->got && !create_got_section (dynobj, info))
-    return FALSE;
-
   if (!_bfd_elf_create_dynamic_sections (dynobj, info))
     return FALSE;
 
+  htab = ppc_hash_table (info);
+  if (!htab->got)
+    htab->got = bfd_get_section_by_name (dynobj, ".got");
   htab->plt = bfd_get_section_by_name (dynobj, ".plt");
   htab->relplt = bfd_get_section_by_name (dynobj, ".rela.plt");
   htab->dynbss = bfd_get_section_by_name (dynobj, ".dynbss");
   if (!info->shared)
     htab->relbss = bfd_get_section_by_name (dynobj, ".rela.bss");
 
-  if (!htab->plt || !htab->relplt || !htab->dynbss
+  if (!htab->got || !htab->plt || !htab->relplt || !htab->dynbss
       || (!info->shared && !htab->relbss))
     abort ();
 
@@ -3260,6 +3325,7 @@ ppc64_elf_copy_indirect_symbol (struct elf_backend_data *bed ATTRIBUTE_UNUSED,
 
              for (dent = edir->elf.got.glist; dent != NULL; dent = dent->next)
                if (dent->addend == ent->addend
+                   && dent->owner == ent->owner
                    && dent->tls_type == ent->tls_type)
                  {
                    dent->got.refcount += ent->got.refcount;
@@ -3360,7 +3426,9 @@ update_local_sym_info (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
       struct got_entry *ent;
 
       for (ent = local_got_ents[r_symndx]; ent != NULL; ent = ent->next)
-       if (ent->addend == r_addend && ent->tls_type == tls_type)
+       if (ent->addend == r_addend
+           && ent->owner == abfd
+           && ent->tls_type == tls_type)
          break;
       if (ent == NULL)
        {
@@ -3370,6 +3438,7 @@ update_local_sym_info (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
            return FALSE;
          ent->next = local_got_ents[r_symndx];
          ent->addend = r_addend;
+         ent->owner = abfd;
          ent->tls_type = tls_type;
          ent->got.refcount = 0;
          local_got_ents[r_symndx] = ent;
@@ -3460,8 +3529,6 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       ppc64_elf_section_data (sec)->opd.func_sec = opd_sym_map;
     }
 
-  if (htab->elf.dynobj == NULL)
-    htab->elf.dynobj = abfd;
   if (htab->sfpr == NULL
       && !create_linkage_sections (htab->elf.dynobj, info))
     return FALSE;
@@ -3487,7 +3554,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_GOT_TLSLD16_LO:
        case R_PPC64_GOT_TLSLD16_HI:
        case R_PPC64_GOT_TLSLD16_HA:
-         htab->tlsld_got.refcount += 1;
+         ppc64_tlsld_got (abfd)->refcount += 1;
          tls_type = TLS_TLS | TLS_LD;
          goto dogottls;
 
@@ -3524,8 +3591,8 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_GOT16_LO_DS:
          /* This symbol requires a global offset table entry.  */
          sec->has_gp_reloc = 1;
-         if (htab->got == NULL
-             && !create_got_section (htab->elf.dynobj, info))
+         if (ppc64_elf_tdata (abfd)->got == NULL
+             && !create_got_section (abfd, info))
            return FALSE;
 
          if (h != NULL)
@@ -3536,6 +3603,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
              eh = (struct ppc_link_hash_entry *) h;
              for (ent = eh->elf.got.glist; ent != NULL; ent = ent->next)
                if (ent->addend == rel->r_addend
+                   && ent->owner == abfd
                    && ent->tls_type == tls_type)
                  break;
              if (ent == NULL)
@@ -3546,6 +3614,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                    return FALSE;
                  ent->next = eh->elf.got.glist;
                  ent->addend = rel->r_addend;
+                 ent->owner = abfd;
                  ent->tls_type = tls_type;
                  ent->got.refcount = 0;
                  eh->elf.got.glist = ent;
@@ -4054,7 +4123,7 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_GOT_TLSLD16_LO:
        case R_PPC64_GOT_TLSLD16_HI:
        case R_PPC64_GOT_TLSLD16_HA:
-         htab->tlsld_got.refcount -= 1;
+         ppc64_tlsld_got (abfd)->refcount -= 1;
          tls_type = TLS_TLS | TLS_LD;
          goto dogot;
 
@@ -4096,6 +4165,7 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
 
            for (; ent != NULL; ent = ent->next)
              if (ent->addend == rel->r_addend
+                 && ent->owner == abfd
                  && ent->tls_type == tls_type)
                break;
            if (ent == NULL)
@@ -4213,7 +4283,9 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf)
          && (fdh->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0
          && (info->shared
              || (fdh->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
-             || (fdh->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0))
+             || (fdh->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0
+             || (fdh->root.type == bfd_link_hash_undefweak
+                 && ELF_ST_VISIBILITY (fdh->other) == STV_DEFAULT)))
        {
          if (fdh->dynindx == -1)
            if (! bfd_elf64_link_record_dynamic_symbol (info, fdh))
@@ -5138,7 +5210,7 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
                    /* These relocs should never be against a symbol
                       defined in a shared lib.  Leave them alone if
                       that turns out to be the case.  */
-                   htab->tlsld_got.refcount -= 1;
+                   ppc64_tlsld_got (ibfd)->refcount -= 1;
                    if (!is_local)
                      continue;
 
@@ -5276,6 +5348,7 @@ ppc64_elf_tls_optimize (bfd *obfd ATTRIBUTE_UNUSED, struct bfd_link_info *info)
 
                    for (; ent != NULL; ent = ent->next)
                      if (ent->addend == rel->r_addend
+                         && ent->owner == ibfd
                          && ent->tls_type == tls_type)
                        break;
                    if (ent == NULL)
@@ -5431,7 +5504,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
          for (ent = h->got.glist; ent != NULL; ent = ent->next)
            if (ent->got.refcount > 0
                && (ent->tls_type & TLS_TPREL) != 0
-               && ent->addend == gent->addend)
+               && ent->addend == gent->addend
+               && ent->owner == gent->owner)
              {
                gent->got.refcount = 0;
                break;
@@ -5460,11 +5534,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
        if ((gent->tls_type & TLS_LD) != 0
            && !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC))
          {
-           gent->got.offset = htab->tlsld_got.offset;
+           gent->got.offset = ppc64_tlsld_got (gent->owner)->offset;
            continue;
          }
 
-       s = htab->got;
+       s = ppc64_elf_tdata (gent->owner)->got;
        gent->got.offset = s->_raw_size;
        s->_raw_size
          += (gent->tls_type & eh->tls_mask & (TLS_GD | TLS_LD)) ? 16 : 8;
@@ -5473,7 +5547,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
             || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
            && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                || h->root.type != bfd_link_hash_undefweak))
-         htab->relgot->_raw_size
+         ppc64_elf_tdata (gent->owner)->relgot->_raw_size
            += (gent->tls_type & eh->tls_mask & TLS_GD
                ? 2 * sizeof (Elf64_External_Rela)
                : sizeof (Elf64_External_Rela));
@@ -5618,16 +5692,6 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        }
     }
 
-  if (htab->tlsld_got.refcount > 0)
-    {
-      htab->tlsld_got.offset = htab->got->_raw_size;
-      htab->got->_raw_size += 16;
-      if (info->shared)
-       htab->relgot->_raw_size += sizeof (Elf64_External_Rela);
-    }
-  else
-    htab->tlsld_got.offset = (bfd_vma) -1;
-
   /* Set up .got offsets for local syms, and space for local dynamic
      relocs.  */
   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
@@ -5642,6 +5706,20 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
        continue;
 
+      if (ppc64_tlsld_got (ibfd)->refcount > 0)
+       {
+         s = ppc64_elf_tdata (ibfd)->got;
+         ppc64_tlsld_got (ibfd)->offset = s->_raw_size;
+         s->_raw_size += 16;
+         if (info->shared)
+           {
+             srel = ppc64_elf_tdata (ibfd)->relgot;
+             srel->_raw_size += sizeof (Elf64_External_Rela);
+           }
+       }
+      else
+       ppc64_tlsld_got (ibfd)->offset = (bfd_vma) -1;
+
       for (s = ibfd->sections; s != NULL; s = s->next)
        {
          struct ppc_dyn_relocs *p;
@@ -5677,8 +5755,8 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       locsymcount = symtab_hdr->sh_info;
       end_lgot_ents = lgot_ents + locsymcount;
       lgot_masks = (char *) end_lgot_ents;
-      s = htab->got;
-      srel = htab->relgot;
+      s = ppc64_elf_tdata (ibfd)->got;
+      srel = ppc64_elf_tdata (ibfd)->relgot;
       for (; lgot_ents < end_lgot_ents; ++lgot_ents, ++lgot_masks)
        {
          struct got_entry *ent;
@@ -5688,14 +5766,14 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
              {
                if ((ent->tls_type & *lgot_masks & TLS_LD) != 0)
                  {
-                   if (htab->tlsld_got.offset == (bfd_vma) -1)
+                   if (ppc64_tlsld_got (ibfd)->offset == (bfd_vma) -1)
                      {
-                       htab->tlsld_got.offset = s->_raw_size;
+                       ppc64_tlsld_got (ibfd)->offset = s->_raw_size;
                        s->_raw_size += 16;
                        if (info->shared)
                          srel->_raw_size += sizeof (Elf64_External_Rela);
                      }
-                   ent->got.offset = htab->tlsld_got.offset;
+                   ent->got.offset = ppc64_tlsld_got (ibfd)->offset;
                  }
                else
                  {
@@ -5738,16 +5816,8 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       if (s == htab->brlt || s == htab->relbrlt)
        /* These haven't been allocated yet;  don't strip.  */
        continue;
-      else if (s == htab->got)
-       {
-         /* Automatic multiple tocs aren't possible if we are using the
-            GOT.  The GOT is accessed via r2, so we can't adjust r2.
-            FIXME: There's no reason why we couldn't lay out multiple
-            GOTs too.  */
-         if (s->_raw_size > elf_backend_got_header_size)
-           htab->no_multi_toc = 1;
-       }
-      else if (s == htab->plt
+      else if (s == htab->got
+              || s == htab->plt
               || s == htab->glink)
        {
          /* Strip this section if we don't need it; see the
@@ -5805,6 +5875,38 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        return FALSE;
     }
 
+  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+    {
+      s = ppc64_elf_tdata (ibfd)->got;
+      if (s != NULL && s != htab->got)
+       {
+         s->_cooked_size = 0;
+         if (s->_raw_size == 0)
+           _bfd_strip_section_from_output (info, s);
+         else
+           {
+             s->contents = bfd_zalloc (ibfd, s->_raw_size);
+             if (s->contents == NULL)
+               return FALSE;
+           }
+       }
+      s = ppc64_elf_tdata (ibfd)->relgot;
+      if (s != NULL)
+       {
+         s->_cooked_size = 0;
+         if (s->_raw_size == 0)
+           _bfd_strip_section_from_output (info, s);
+         else
+           {
+             s->contents = bfd_zalloc (ibfd, s->_raw_size);
+             if (s->contents == NULL)
+               return FALSE;
+             relocs = TRUE;
+             s->reloc_count = 0;
+           }
+       }
+    }
+
   if (htab->elf.dynamic_sections_created)
     {
       /* Add some entries to the .dynamic section.  We fill in the
@@ -6323,10 +6425,10 @@ ppc64_elf_setup_section_lists (bfd *output_bfd, struct bfd_link_info *info)
   return 1;
 }
 
-/* The linker repeatedly calls this function for each toc input
-   section.  Group input bfds such that the toc within a group
-   is less than 64k in size.  Will break with cute linker scripts
-   that play games with dot in the output toc section.  */
+/* The linker repeatedly calls this function for each TOC input section
+   and linker generated GOT section.  Group input bfds such that the toc
+   within a group is less than 64k in size.  Will break with cute linker
+   scripts that play games with dot in the output toc section.  */
 
 void
 ppc64_elf_next_toc_section (struct bfd_link_info *info, asection *isec)
@@ -6389,7 +6491,7 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
       if (contents == NULL)
        return -1;
       if (! bfd_get_section_contents (isec->owner, isec, contents,
-                                     (file_ptr) 0, isec->_raw_size))
+                                     0, isec->_raw_size))
        {
          free (contents);
          return -1;
@@ -6555,7 +6657,6 @@ group_sections (struct ppc_link_hash_table *htab,
 
 bfd_boolean
 ppc64_elf_size_stubs (bfd *output_bfd,
-                     bfd *stub_bfd,
                      struct bfd_link_info *info,
                      bfd_signed_vma group_size,
                      asection *(*add_stub_section) (const char *, asection *),
@@ -6566,7 +6667,6 @@ ppc64_elf_size_stubs (bfd *output_bfd,
   struct ppc_link_hash_table *htab = ppc_hash_table (info);
 
   /* Stash our params away.  */
-  htab->stub_bfd = stub_bfd;
   htab->add_stub_section = add_stub_section;
   htab->layout_sections_again = layout_sections_again;
   stubs_always_before_branch = group_size < 0;
@@ -6820,10 +6920,11 @@ ppc64_elf_size_stubs (bfd *output_bfd,
       for (stub_sec = htab->stub_bfd->sections;
           stub_sec != NULL;
           stub_sec = stub_sec->next)
-       {
-         stub_sec->_raw_size = 0;
-         stub_sec->_cooked_size = 0;
-       }
+       if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+         {
+           stub_sec->_raw_size = 0;
+           stub_sec->_cooked_size = 0;
+         }
       htab->brlt->_raw_size = 0;
       htab->brlt->_cooked_size = 0;
 
@@ -6909,24 +7010,26 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
   struct ppc_link_hash_table *htab = ppc_hash_table (info);
   asection *stub_sec;
   bfd_byte *p;
+  int stub_sec_count = 0;
 
   htab->emit_stub_syms = emit_stub_syms;
   for (stub_sec = htab->stub_bfd->sections;
        stub_sec != NULL;
        stub_sec = stub_sec->next)
-    {
-      bfd_size_type size;
+    if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+      {
+       bfd_size_type size;
 
-      /* Allocate memory to hold the linker stubs.  */
-      size = stub_sec->_raw_size;
-      if (size != 0)
-       {
-         stub_sec->contents = bfd_zalloc (htab->stub_bfd, size);
-         if (stub_sec->contents == NULL)
-           return FALSE;
-       }
-      stub_sec->_cooked_size = 0;
-    }
+       /* Allocate memory to hold the linker stubs.  */
+       size = stub_sec->_raw_size;
+       if (size != 0)
+         {
+           stub_sec->contents = bfd_zalloc (htab->stub_bfd, size);
+           if (stub_sec->contents == NULL)
+             return FALSE;
+         }
+       stub_sec->_cooked_size = 0;
+      }
 
   if (htab->plt != NULL)
     {
@@ -7018,10 +7121,12 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
   for (stub_sec = htab->stub_bfd->sections;
        stub_sec != NULL;
        stub_sec = stub_sec->next)
-    {
-      if (stub_sec->_raw_size != stub_sec->_cooked_size)
-       break;
-    }
+    if ((stub_sec->flags & SEC_LINKER_CREATED) == 0)
+      {
+       stub_sec_count += 1;
+       if (stub_sec->_raw_size != stub_sec->_cooked_size)
+         break;
+      }
 
   if (stub_sec != NULL
       || htab->glink->_raw_size != htab->glink->_cooked_size)
@@ -7045,7 +7150,7 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
                         "  long branch  %lu\n"
                         "  long toc adj %lu\n"
                         "  plt call     %lu"),
-              htab->stub_bfd->section_count,
+              stub_sec_count,
               htab->stub_count[ppc_stub_long_branch - 1],
               htab->stub_count[ppc_stub_long_branch_r2off - 1],
               htab->stub_count[ppc_stub_plt_branch - 1],
@@ -7736,17 +7841,15 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          {
            /* Relocation is to the entry for this symbol in the global
               offset table.  */
+           asection *got;
            bfd_vma *offp;
            bfd_vma off;
            unsigned long indx = 0;
 
-           if (htab->got == NULL)
-             abort ();
-
            if (tls_type == (TLS_TLS | TLS_LD)
                && (h == NULL
                    || !(h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC)))
-             offp = &htab->tlsld_got.offset;
+             offp = &ppc64_tlsld_got (input_bfd)->offset;
            else
              {
                struct got_entry *ent;
@@ -7778,6 +7881,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
                for (; ent != NULL; ent = ent->next)
                  if (ent->addend == rel->r_addend
+                     && ent->owner == input_bfd
                      && ent->tls_type == tls_type)
                    break;
                if (ent == NULL)
@@ -7785,6 +7889,10 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                offp = &ent->got.offset;
              }
 
+           got = ppc64_elf_tdata (input_bfd)->got;
+           if (got == NULL)
+             abort ();
+
            /* The offset must always be a multiple of 8.  We use the
               least significant bit to record whether we have already
               processed this entry.  */
@@ -7796,14 +7904,16 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                /* Generate relocs for the dynamic linker, except in
                   the case of TLSLD where we'll use one entry per
                   module.  */
+               asection *relgot = ppc64_elf_tdata (input_bfd)->relgot;
+
                *offp = off | 1;
                if ((info->shared || indx != 0)
                    && (h == NULL
                        || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
                        || h->root.type != bfd_link_hash_undefweak))
                  {
-                   outrel.r_offset = (htab->got->output_section->vma
-                                      + htab->got->output_offset
+                   outrel.r_offset = (got->output_section->vma
+                                      + got->output_offset
                                       + off);
                    outrel.r_addend = rel->r_addend;
                    if (tls_type & (TLS_LD | TLS_GD))
@@ -7812,8 +7922,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                        outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPMOD64);
                        if (tls_type == (TLS_TLS | TLS_GD))
                          {
-                           loc = htab->relgot->contents;
-                           loc += (htab->relgot->reloc_count++
+                           loc = relgot->contents;
+                           loc += (relgot->reloc_count++
                                    * sizeof (Elf64_External_Rela));
                            bfd_elf64_swap_reloca_out (output_bfd,
                                                       &outrel, loc);
@@ -7833,7 +7943,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
 
                        /* Write the .got section contents for the sake
                           of prelink.  */
-                       loc = htab->got->contents + off;
+                       loc = got->contents + off;
                        bfd_put_64 (output_bfd, outrel.r_addend + relocation,
                                    loc);
                      }
@@ -7846,8 +7956,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                        if (tls_type & (TLS_GD | TLS_DTPREL | TLS_TPREL))
                          outrel.r_addend -= htab->tls_sec->vma;
                      }
-                   loc = htab->relgot->contents;
-                   loc += (htab->relgot->reloc_count++
+                   loc = relgot->contents;
+                   loc += (relgot->reloc_count++
                            * sizeof (Elf64_External_Rela));
                    bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
                  }
@@ -7868,23 +7978,23 @@ ppc64_elf_relocate_section (bfd *output_bfd,
                        if (tls_type == (TLS_TLS | TLS_GD))
                          {
                            bfd_put_64 (output_bfd, relocation,
-                                       htab->got->contents + off + 8);
+                                       got->contents + off + 8);
                            relocation = 1;
                          }
                      }
 
                    bfd_put_64 (output_bfd, relocation,
-                               htab->got->contents + off);
+                               got->contents + off);
                  }
              }
 
            if (off >= (bfd_vma) -2)
              abort ();
 
-           relocation = htab->got->output_offset + off;
+           relocation = got->output_offset + off;
 
            /* TOC base (r2) is TOC start plus 0x8000.  */
-           addend = - TOC_BASE_OFF;
+           addend = -TOC_BASE_OFF;
          }
          break;
 
@@ -8626,6 +8736,29 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
        = PLT_ENTRY_SIZE;
     }
 
+  /* We need to handle writing out multiple GOT sections ourselves,
+     since we didn't add them to DYNOBJ.  */
+  while ((dynobj = dynobj->link_next) != NULL)
+    {
+      asection *s;
+      s = ppc64_elf_tdata (dynobj)->got;
+      if (s != NULL
+         && s->_raw_size != 0
+         && s->output_section != bfd_abs_section_ptr
+         && !bfd_set_section_contents (output_bfd, s->output_section,
+                                       s->contents, s->output_offset,
+                                       s->_raw_size))
+       return FALSE;
+      s = ppc64_elf_tdata (dynobj)->relgot;
+      if (s != NULL
+         && s->_raw_size != 0
+         && s->output_section != bfd_abs_section_ptr
+         && !bfd_set_section_contents (output_bfd, s->output_section,
+                                       s->contents, s->output_offset,
+                                       s->_raw_size))
+       return FALSE;
+    }
+  
   return TRUE;
 }
 
index 0572d52801609e66c00e18d5387ed814a2db13d3..c26df82da8e71489d0d2a4bfd55c849154c7ab26 100644 (file)
@@ -17,6 +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.  */
 
+void ppc64_elf_init_stub_bfd
+  (bfd *, struct bfd_link_info *);
 bfd_boolean ppc64_elf_mark_entry_syms
   (struct bfd_link_info *);
 bfd_boolean ppc64_elf_edit_opd
@@ -36,7 +38,7 @@ void ppc64_elf_reinit_toc
 bfd_boolean ppc64_elf_next_input_section
   (struct bfd_link_info *, asection *);
 bfd_boolean ppc64_elf_size_stubs
-  (bfd *, bfd *, struct bfd_link_info *, bfd_signed_vma,
+  (bfd *, struct bfd_link_info *, bfd_signed_vma,
    asection *(*) (const char *, asection *), void (*) (void));
 bfd_boolean ppc64_elf_build_stubs
   (bfd_boolean, struct bfd_link_info *, char **);
index f679ab76a6b51d2308aeaf02dd90d83f5c9da5b1..661b0236189b6a39d8c7ad2324be429e8c7102a4 100644 (file)
@@ -3029,8 +3029,7 @@ elf_link_sort_relocs (abfd, info, psec)
      struct bfd_link_info *info;
      asection **psec;
 {
-  bfd *dynobj = elf_hash_table (info)->dynobj;
-  asection *reldyn, *o;
+  asection *reldyn;
   bfd_size_type count, size;
   size_t i, ret, sort_elt, ext_size;
   bfd_byte *sort, *s_non_relative, *p;
@@ -3039,6 +3038,7 @@ elf_link_sort_relocs (abfd, info, psec)
   int i2e = bed->s->int_rels_per_ext_rel;
   void (*swap_in) PARAMS ((bfd *, const bfd_byte *, Elf_Internal_Rela *));
   void (*swap_out) PARAMS ((bfd *, const Elf_Internal_Rela *, bfd_byte *));
+  struct bfd_link_order *lo;
 
   reldyn = bfd_get_section_by_name (abfd, ".rela.dyn");
   if (reldyn == NULL || reldyn->_raw_size == 0)
@@ -3059,11 +3059,12 @@ elf_link_sort_relocs (abfd, info, psec)
   count = reldyn->_raw_size / ext_size;
 
   size = 0;
-  for (o = dynobj->sections; o != NULL; o = o->next)
-    if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
-       == (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)
-       && o->output_section == reldyn)
-      size += o->_raw_size;
+  for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
+    if (lo->type == bfd_indirect_link_order)
+      {
+       asection *o = lo->u.indirect.section;
+       size += o->_raw_size;
+      }
 
   if (size != reldyn->_raw_size)
     return 0;
@@ -3079,12 +3080,11 @@ elf_link_sort_relocs (abfd, info, psec)
       return 0;
     }
 
-  for (o = dynobj->sections; o != NULL; o = o->next)
-    if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
-       == (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)
-       && o->output_section == reldyn)
+  for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
+    if (lo->type == bfd_indirect_link_order)
       {
        bfd_byte *erel, *erelend;
+       asection *o = lo->u.indirect.section;
 
        erel = o->contents;
        erelend = o->contents + o->_raw_size;
@@ -3121,12 +3121,11 @@ elf_link_sort_relocs (abfd, info, psec)
 
   qsort (s_non_relative, (size_t) count - ret, sort_elt, elf_link_sort_cmp2);
 
-  for (o = dynobj->sections; o != NULL; o = o->next)
-    if ((o->flags & (SEC_HAS_CONTENTS|SEC_LINKER_CREATED))
-       == (SEC_HAS_CONTENTS|SEC_LINKER_CREATED)
-       && o->output_section == reldyn)
+  for (lo = reldyn->link_order_head; lo != NULL; lo = lo->next)
+    if (lo->type == bfd_indirect_link_order)
       {
        bfd_byte *erel, *erelend;
+       asection *o = lo->u.indirect.section;
 
        erel = o->contents;
        erelend = o->contents + o->_raw_size;