ld/testsuite/ld-elf/flags1.d: Update the xfail list
[deliverable/binutils-gdb.git] / bfd / elf64-ppc.c
index 17b7a134a0cc3eecdd9bc6ea5830090871c2c4fd..d15f50b679d59944010ec799fee8b75088840d33 100644 (file)
@@ -1,5 +1,5 @@
 /* PowerPC64-specific support for 64-bit ELF.
-   Copyright (C) 1999-2015 Free Software Foundation, Inc.
+   Copyright (C) 1999-2016 Free Software Foundation, Inc.
    Written by Linus Nordberg, Swox AB <info@swox.com>,
    based on elf32-ppc.c by Ian Lance Taylor.
    Largely rewritten by Alan Modra.
@@ -4344,14 +4344,20 @@ create_linkage_sections (bfd *dynobj, struct bfd_link_info *info)
 
   htab = ppc_hash_table (info);
 
-  /* Create .sfpr for code to save and restore fp regs.  */
   flags = (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY
           | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-  htab->sfpr = bfd_make_section_anyway_with_flags (dynobj, ".sfpr",
-                                                  flags);
-  if (htab->sfpr == NULL
-      || ! bfd_set_section_alignment (dynobj, htab->sfpr, 2))
-    return FALSE;
+  if (htab->params->save_restore_funcs)
+    {
+      /* Create .sfpr for code to save and restore fp regs.  */
+      htab->sfpr = bfd_make_section_anyway_with_flags (dynobj, ".sfpr",
+                                                      flags);
+      if (htab->sfpr == NULL
+         || ! bfd_set_section_alignment (dynobj, htab->sfpr, 2))
+       return FALSE;
+    }
+
+  if (bfd_link_relocatable (info))
+    return TRUE;
 
   /* Create .glink for lazy dynamic linking support.  */
   htab->glink = bfd_make_section_anyway_with_flags (dynobj, ".glink",
@@ -4424,14 +4430,9 @@ ppc64_elf_init_stub_bfd (struct bfd_link_info *info,
    linker created stub bfd.  This ensures that the GOT header is at
    the start of the output TOC section.  */
   htab = ppc_hash_table (info);
-  if (htab == NULL)
-    return FALSE;
   htab->elf.dynobj = params->stub_bfd;
   htab->params = params;
 
-  if (bfd_link_relocatable (info))
-    return TRUE;
-
   return create_linkage_sections (htab->elf.dynobj, info);
 }
 
@@ -5340,7 +5341,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       enum elf_ppc64_reloc_type r_type;
       int tls_type;
       struct _ppc64_elf_section_data *ppc64_sec;
-      struct plt_entry **ifunc;
+      struct plt_entry **ifunc, **plt_list;
 
       r_symndx = ELF64_R_SYM (rel->r_info);
       if (r_symndx < symtab_hdr->sh_info)
@@ -5383,28 +5384,8 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
                return FALSE;
            }
        }
-      r_type = ELF64_R_TYPE (rel->r_info);
-      if (is_branch_reloc (r_type))
-       {
-         if (h != NULL && (h == tga || h == dottga))
-           {
-             if (rel != relocs
-                 && (ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_TLSGD
-                     || ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_TLSLD))
-               /* We have a new-style __tls_get_addr call with a marker
-                  reloc.  */
-               ;
-             else
-               /* Mark this section as having an old-style call.  */
-               sec->has_tls_get_addr_call = 1;
-           }
-
-         /* STT_GNU_IFUNC symbols must have a PLT entry.  */
-         if (ifunc != NULL
-             && !update_plt_info (abfd, ifunc, rel->r_addend))
-           return FALSE;
-       }
 
+      r_type = ELF64_R_TYPE (rel->r_info);
       switch (r_type)
        {
        case R_PPC64_TLSGD:
@@ -5516,27 +5497,29 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_PLT16_LO:
        case R_PPC64_PLT32:
        case R_PPC64_PLT64:
-         /* This symbol requires a procedure linkage table entry.  We
-            actually build the entry in adjust_dynamic_symbol,
-            because this might be a case of linking PIC code without
-            linking in any dynamic objects, in which case we don't
-            need to generate a procedure linkage table after all.  */
-         if (h == NULL)
-           {
-             /* It does not make sense to have a procedure linkage
-                table entry for a local symbol.  */
-             bfd_set_error (bfd_error_bad_value);
-             return FALSE;
-           }
-         else
+         /* This symbol requires a procedure linkage table entry.  */
+         plt_list = ifunc;
+         if (h != NULL)
            {
-             if (!update_plt_info (abfd, &h->plt.plist, rel->r_addend))
-               return FALSE;
              h->needs_plt = 1;
              if (h->root.root.string[0] == '.'
                  && h->root.root.string[1] != '\0')
                ((struct ppc_link_hash_entry *) h)->is_func = 1;
+             plt_list = &h->plt.plist;
+           }
+         if (plt_list == NULL)
+           {
+             /* It does not make sense to have a procedure linkage
+                table entry for a non-ifunc local symbol.  */
+             info->callbacks->einfo
+               (_("%P: %H: %s reloc against local symbol\n"),
+                abfd, sec, rel->r_offset,
+                ppc64_elf_howto_table[r_type]->name);
+             bfd_set_error (bfd_error_bad_value);
+             return FALSE;
            }
+         if (!update_plt_info (abfd, plt_list, rel->r_addend))
+           return FALSE;
          break;
 
          /* The following relocations don't need to propagate the
@@ -5649,21 +5632,43 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
          /* Fall through.  */
 
        case R_PPC64_REL24:
-         if (h != NULL && ifunc == NULL)
+         plt_list = ifunc;
+         if (h != NULL)
            {
-             /* We may need a .plt entry if the function this reloc
-                refers to is in a shared lib.  */
-             if (!update_plt_info (abfd, &h->plt.plist, rel->r_addend))
-               return FALSE;
              h->needs_plt = 1;
              if (h->root.root.string[0] == '.'
                  && h->root.root.string[1] != '\0')
                ((struct ppc_link_hash_entry *) h)->is_func = 1;
+
              if (h == tga || h == dottga)
-               sec->has_tls_reloc = 1;
+               {
+                 sec->has_tls_reloc = 1;
+                 if (rel != relocs
+                     && (ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_TLSGD
+                         || ELF64_R_TYPE (rel[-1].r_info) == R_PPC64_TLSLD))
+                   /* We have a new-style __tls_get_addr call with
+                      a marker reloc.  */
+                   ;
+                 else
+                   /* Mark this section as having an old-style call.  */
+                   sec->has_tls_get_addr_call = 1;
+               }
+             plt_list = &h->plt.plist;
            }
+
+         /* We may need a .plt entry if the function this reloc
+            refers to is in a shared lib.  */
+         if (plt_list
+             && !update_plt_info (abfd, plt_list, rel->r_addend))
+           return FALSE;
          break;
 
+       case R_PPC64_ADDR14:
+       case R_PPC64_ADDR14_BRNTAKEN:
+       case R_PPC64_ADDR14_BRTAKEN:
+       case R_PPC64_ADDR24:
+         goto dodyn;
+
        case R_PPC64_TPREL64:
          tls_type = TLS_EXPLICIT | TLS_TLS | TLS_TPREL;
          if (bfd_link_pic (info))
@@ -5806,10 +5811,6 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_REL30:
        case R_PPC64_REL32:
        case R_PPC64_REL64:
-       case R_PPC64_ADDR14:
-       case R_PPC64_ADDR14_BRNTAKEN:
-       case R_PPC64_ADDR14_BRTAKEN:
-       case R_PPC64_ADDR24:
        case R_PPC64_ADDR32:
        case R_PPC64_UADDR16:
        case R_PPC64_UADDR32:
@@ -6505,6 +6506,7 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
       unsigned long r_symndx;
       enum elf_ppc64_reloc_type r_type;
       struct elf_link_hash_entry *h = NULL;
+      struct plt_entry **plt_list;
       unsigned char tls_type = 0;
 
       r_symndx = ELF64_R_SYM (rel->r_info);
@@ -6528,38 +6530,6 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
              }
        }
 
-      if (is_branch_reloc (r_type))
-       {
-         struct plt_entry **ifunc = NULL;
-         if (h != NULL)
-           {
-             if (h->type == STT_GNU_IFUNC)
-               ifunc = &h->plt.plist;
-           }
-         else if (local_got_ents != NULL)
-           {
-             struct plt_entry **local_plt = (struct plt_entry **)
-               (local_got_ents + symtab_hdr->sh_info);
-             unsigned char *local_got_tls_masks = (unsigned char *)
-               (local_plt + symtab_hdr->sh_info);
-             if ((local_got_tls_masks[r_symndx] & PLT_IFUNC) != 0)
-               ifunc = local_plt + r_symndx;
-           }
-         if (ifunc != NULL)
-           {
-             struct plt_entry *ent;
-
-             for (ent = *ifunc; ent != NULL; ent = ent->next)
-               if (ent->addend == rel->r_addend)
-                 break;
-             if (ent == NULL)
-               abort ();
-             if (ent->plt.refcount > 0)
-               ent->plt.refcount -= 1;
-             continue;
-           }
-       }
-
       switch (r_type)
        {
        case R_PPC64_GOT_TLSLD16:
@@ -6626,11 +6596,23 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
        case R_PPC64_REL14_BRNTAKEN:
        case R_PPC64_REL14_BRTAKEN:
        case R_PPC64_REL24:
+         plt_list = NULL;
          if (h != NULL)
+           plt_list = &h->plt.plist;
+         else if (local_got_ents != NULL)
+           {
+             struct plt_entry **local_plt = (struct plt_entry **)
+               (local_got_ents + symtab_hdr->sh_info);
+             unsigned char *local_got_tls_masks = (unsigned char *)
+               (local_plt + symtab_hdr->sh_info);
+             if ((local_got_tls_masks[r_symndx] & PLT_IFUNC) != 0)
+               plt_list = local_plt + r_symndx;
+           }
+         if (plt_list)
            {
              struct plt_entry *ent;
 
-             for (ent = h->plt.plist; ent != NULL; ent = ent->next)
+             for (ent = *plt_list; ent != NULL; ent = ent->next)
                if (ent->addend == rel->r_addend)
                  break;
              if (ent != NULL && ent->plt.refcount > 0)
@@ -6684,7 +6666,7 @@ sfpr_define (struct bfd_link_info *info,
       sym[len + 0] = i / 10 + '0';
       sym[len + 1] = i % 10 + '0';
       h = (struct ppc_link_hash_entry *)
-       elf_link_hash_lookup (&htab->elf, sym, FALSE, FALSE, TRUE);
+       elf_link_hash_lookup (&htab->elf, sym, writing, TRUE, TRUE);
       if (stub_sec != NULL)
        {
          if (h != NULL
@@ -6725,6 +6707,7 @@ sfpr_define (struct bfd_link_info *info,
              h->elf.root.u.def.value = htab->sfpr->size;
              h->elf.type = STT_FUNC;
              h->elf.def_regular = 1;
+             h->elf.non_elf = 0;
              _bfd_elf_link_hash_hide_symbol (info, &h->elf, TRUE);
              writing = TRUE;
              if (htab->sfpr->contents == NULL)
@@ -7069,14 +7052,28 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
                            struct bfd_link_info *info)
 {
   struct ppc_link_hash_table *htab;
-  unsigned int i;
 
   htab = ppc_hash_table (info);
   if (htab == NULL)
     return FALSE;
 
-  if (!bfd_link_relocatable (info)
-      && htab->elf.hgot != NULL)
+  /* Provide any missing _save* and _rest* functions.  */
+  if (htab->sfpr != NULL)
+    {
+      unsigned int i;
+
+      htab->sfpr->size = 0;
+      for (i = 0; i < ARRAY_SIZE (save_res_funcs); i++)
+       if (!sfpr_define (info, &save_res_funcs[i], NULL))
+         return FALSE;
+      if (htab->sfpr->size == 0)
+       htab->sfpr->flags |= SEC_EXCLUDE;
+    }
+
+  if (bfd_link_relocatable (info))
+    return TRUE;
+
+  if (htab->elf.hgot != NULL)
     {
       _bfd_elf_link_hash_hide_symbol (info, htab->elf.hgot, TRUE);
       /* Make .TOC. defined so as to prevent it being made dynamic.
@@ -7095,22 +7092,8 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
                               | STV_HIDDEN);
     }
 
-  if (htab->sfpr == NULL)
-    /* We don't have any relocs.  */
-    return TRUE;
-
-  /* Provide any missing _save* and _rest* functions.  */
-  htab->sfpr->size = 0;
-  if (htab->params->save_restore_funcs)
-    for (i = 0; i < ARRAY_SIZE (save_res_funcs); i++)
-      if (!sfpr_define (info, &save_res_funcs[i], NULL))
-       return FALSE;
-
   elf_link_hash_traverse (&htab->elf, func_desc_adjust, info);
 
-  if (htab->sfpr->size == 0)
-    htab->sfpr->flags |= SEC_EXCLUDE;
-
   return TRUE;
 }
 
@@ -8243,6 +8226,7 @@ ppc64_elf_tls_setup (struct bfd_link_info *info)
                  tga_fd->root.type = bfd_link_hash_indirect;
                  tga_fd->root.u.i.link = &opt_fd->root;
                  ppc64_elf_copy_indirect_symbol (info, opt_fd, tga_fd);
+                 opt_fd->forced_local = 0;
                  if (opt_fd->dynindx != -1)
                    {
                      /* Use __tls_get_addr_opt in dynamic relocations.  */
@@ -8259,6 +8243,7 @@ ppc64_elf_tls_setup (struct bfd_link_info *info)
                      tga->root.type = bfd_link_hash_indirect;
                      tga->root.u.i.link = &opt->root;
                      ppc64_elf_copy_indirect_symbol (info, opt, tga);
+                     opt->forced_local = 0;
                      _bfd_elf_link_hash_hide_symbol (info, opt,
                                                      tga->forced_local);
                      htab->tls_get_addr = (struct ppc_link_hash_entry *) opt;
@@ -13934,6 +13919,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
          if (!bfd_link_pic (info)
              && !info->traditional_format
              && !htab->opd_abi
+             && rel->r_addend == d_offset
              && h != NULL && &h->elf == htab->elf.hgot
              && rel + 1 < relend
              && rel[1].r_info == ELF64_R_INFO (r_symndx, R_PPC64_REL16_LO)
@@ -14485,30 +14471,43 @@ ppc64_elf_relocate_section (bfd *output_bfd,
        case R_PPC64_PLT64:
          /* Relocation is to the entry for this symbol in the
             procedure linkage table.  */
+         {
+           struct plt_entry **plt_list = NULL;
+           if (h != NULL)
+             plt_list = &h->elf.plt.plist;
+           else if (local_got_ents != NULL)
+             {
+               struct plt_entry **local_plt = (struct plt_entry **)
+                 (local_got_ents + symtab_hdr->sh_info);
+               unsigned char *local_got_tls_masks = (unsigned char *)
+                 (local_plt + symtab_hdr->sh_info);
+               if ((local_got_tls_masks[r_symndx] & PLT_IFUNC) != 0)
+                 plt_list = local_plt + r_symndx;
+             }
+           if (plt_list)
+             {
+               struct plt_entry *ent;
 
-         /* Resolve a PLT reloc against a local symbol directly,
-            without using the procedure linkage table.  */
-         if (h == NULL)
-           break;
-
-         /* It's possible that we didn't make a PLT entry for this
-            symbol.  This happens when statically linking PIC code,
-            or when using -Bsymbolic.  Go find a match if there is a
-            PLT entry.  */
-         if (htab->elf.splt != NULL)
-           {
-             struct plt_entry *ent;
-             for (ent = h->elf.plt.plist; ent != NULL; ent = ent->next)
-               if (ent->plt.offset != (bfd_vma) -1
-                   && ent->addend == orig_rel.r_addend)
-                 {
-                   relocation = (htab->elf.splt->output_section->vma
-                                 + htab->elf.splt->output_offset
-                                 + ent->plt.offset);
-                   unresolved_reloc = FALSE;
-                   break;
-                 }
-           }
+               for (ent = *plt_list; ent != NULL; ent = ent->next)
+                 if (ent->plt.offset != (bfd_vma) -1
+                     && ent->addend == orig_rel.r_addend)
+                   {
+                     asection *plt;
+
+                     plt = htab->elf.splt;
+                     if (!htab->elf.dynamic_sections_created
+                         || h == NULL
+                         || h->elf.dynindx == -1)
+                       plt = htab->elf.iplt;
+                     relocation = (plt->output_section->vma
+                                   + plt->output_offset
+                                   + ent->plt.offset);
+                     addend = 0;
+                     unresolved_reloc = FALSE;
+                     break;
+                   }
+             }
+         }
          break;
 
        case R_PPC64_TOC:
This page took 0.030188 seconds and 4 git commands to generate.