Run --gc-sections tests only if supported.
[deliverable/binutils-gdb.git] / bfd / elf32-ppc.c
index d8be8c65260c2fb7f349a53a9a5038e3cafcd00b..cfb473479f9dc84f0d61fe71d0d9ebc1b3335d59 100644 (file)
@@ -36,6 +36,7 @@
 #include "elf/ppc.h"
 #include "elf32-ppc.h"
 #include "elf-vxworks.h"
+#include "dwarf2.h"
 
 /* RELA relocations are used here.  */
 
@@ -2679,6 +2680,7 @@ struct ppc_elf_link_hash_table
   asection *relsbss;
   elf_linker_section_t sdata[2];
   asection *sbss;
+  asection *glink_eh_frame;
 
   /* The (unloaded but important) .rela.plt.unloaded on VxWorks.  */
   asection *srelplt2;
@@ -2869,6 +2871,17 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info)
       || !bfd_set_section_alignment (abfd, s, 4))
     return FALSE;
 
+  if (!info->no_ld_generated_unwind_info)
+    {
+      flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_HAS_CONTENTS
+              | SEC_IN_MEMORY | SEC_LINKER_CREATED);
+      s = bfd_make_section_anyway_with_flags (abfd, ".eh_frame", flags);
+      htab->glink_eh_frame = s;
+      if (s == NULL
+         || !bfd_set_section_alignment (abfd, s, 2))
+       return FALSE;
+    }
+
   flags = SEC_ALLOC | SEC_LINKER_CREATED;
   s = bfd_make_section_anyway_with_flags (abfd, ".iplt", flags);
   htab->iplt = s;
@@ -2957,6 +2970,27 @@ ppc_elf_copy_indirect_symbol (struct bfd_link_info *info,
   edir = (struct ppc_elf_link_hash_entry *) dir;
   eind = (struct ppc_elf_link_hash_entry *) ind;
 
+  edir->tls_mask |= eind->tls_mask;
+  edir->has_sda_refs |= eind->has_sda_refs;
+
+  /* If called to transfer flags for a weakdef during processing
+     of elf_adjust_dynamic_symbol, don't copy non_got_ref.
+     We clear it ourselves for ELIMINATE_COPY_RELOCS.  */
+  if (!(ELIMINATE_COPY_RELOCS
+       && eind->elf.root.type != bfd_link_hash_indirect
+       && edir->elf.dynamic_adjusted))
+    edir->elf.non_got_ref |= eind->elf.non_got_ref;
+
+  edir->elf.ref_dynamic |= eind->elf.ref_dynamic;
+  edir->elf.ref_regular |= eind->elf.ref_regular;
+  edir->elf.ref_regular_nonweak |= eind->elf.ref_regular_nonweak;
+  edir->elf.needs_plt |= eind->elf.needs_plt;
+  edir->elf.pointer_equality_needed |= eind->elf.pointer_equality_needed;
+
+  /* If we were called to copy over info for a weak sym, that's all.  */
+  if (eind->elf.root.type != bfd_link_hash_indirect)
+    return;
+
   if (eind->dyn_relocs != NULL)
     {
       if (edir->dyn_relocs != NULL)
@@ -2988,27 +3022,6 @@ ppc_elf_copy_indirect_symbol (struct bfd_link_info *info,
       eind->dyn_relocs = NULL;
     }
 
-  edir->tls_mask |= eind->tls_mask;
-  edir->has_sda_refs |= eind->has_sda_refs;
-
-  /* If called to transfer flags for a weakdef during processing
-     of elf_adjust_dynamic_symbol, don't copy non_got_ref.
-     We clear it ourselves for ELIMINATE_COPY_RELOCS.  */
-  if (!(ELIMINATE_COPY_RELOCS
-       && eind->elf.root.type != bfd_link_hash_indirect
-       && edir->elf.dynamic_adjusted))
-    edir->elf.non_got_ref |= eind->elf.non_got_ref;
-
-  edir->elf.ref_dynamic |= eind->elf.ref_dynamic;
-  edir->elf.ref_regular |= eind->elf.ref_regular;
-  edir->elf.ref_regular_nonweak |= eind->elf.ref_regular_nonweak;
-  edir->elf.needs_plt |= eind->elf.needs_plt;
-  edir->elf.pointer_equality_needed |= eind->elf.pointer_equality_needed;
-
-  /* If we were called to copy over info for a weak sym, that's all.  */
-  if (eind->elf.root.type != bfd_link_hash_indirect)
-    return;
-
   /* Copy over the GOT refcount entries that we may have already seen to
      the symbol which just became indirect.  */
   edir->elf.got.refcount += eind->elf.got.refcount;
@@ -3684,7 +3697,7 @@ ppc_elf_check_relocs (bfd *abfd,
            {
              /* It does not make sense to have a procedure linkage
                 table entry for a local symbol.  */
-             info->callbacks->einfo (_("%H: %s reloc against local symbol\n"),
+             info->callbacks->einfo (_("%P: %H: %s reloc against local symbol\n"),
                                      abfd, sec, rel->r_offset,
                                      ppc_elf_howto_table[r_type]->name);
              bfd_set_error (bfd_error_bad_value);
@@ -4243,8 +4256,27 @@ ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   if (htab->plt_type == PLT_UNSET)
     {
+      struct elf_link_hash_entry *h;
+
       if (plt_style == PLT_OLD)
        htab->plt_type = PLT_OLD;
+      else if (info->shared
+              && htab->elf.dynamic_sections_created
+              && (h = elf_link_hash_lookup (&htab->elf, "_mcount",
+                                            FALSE, FALSE, TRUE)) != NULL
+              && (h->type == STT_FUNC
+                  || h->needs_plt)
+              && h->ref_regular
+              && !(SYMBOL_CALLS_LOCAL (info, h)
+                   || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+                       && h->root.type == bfd_link_hash_undefweak)))
+       {
+         /* Profiling of shared libs (and pies) is not supported with
+            secure plt, because ppc32 does profiling before a
+            function prologue and a secure plt pic call stubs needs
+            r30 to be set up.  */
+         htab->plt_type = PLT_OLD;
+       }
       else
        {
          bfd *ibfd;
@@ -4272,7 +4304,13 @@ ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
        }
     }
   if (htab->plt_type == PLT_OLD && plt_style == PLT_NEW)
-    info->callbacks->info (_("Using bss-plt due to %B"), htab->old_bfd);
+    {
+      if (htab->old_bfd != NULL)
+       info->callbacks->einfo (_("%P: bss-plt forced due to %B\n"),
+                               htab->old_bfd);
+      else
+       info->callbacks->einfo (_("%P: bss-plt forced by profiling\n"));
+    }
 
   BFD_ASSERT (htab->plt_type != PLT_VXWORKS);
 
@@ -5003,7 +5041,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   if (h->size == 0)
     {
-      info->callbacks->einfo (_("dynamic variable `%s' is zero size\n"),
+      info->callbacks->einfo (_("%P: dynamic variable `%s' is zero size\n"),
                              h->root.root.string);
       return TRUE;
     }
@@ -5149,12 +5187,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (h->root.type == bfd_link_hash_warning)
-    /* When warning symbols are created, they **replace** the "real"
-       entry in the hash table, thus we never get to see the real
-       symbol in a hash traversal.  So look at it now.  */
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   htab = ppc_elf_hash_table (info);
   if (htab->elf.dynamic_sections_created
       || h->type == STT_GNU_IFUNC)
@@ -5504,9 +5536,6 @@ maybe_set_textrel (struct elf_link_hash_entry *h, void *info)
   if (h->root.type == bfd_link_hash_indirect)
     return TRUE;
 
-  if (h->root.type == bfd_link_hash_warning)
-    h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
   if (readonly_dynrelocs (h))
     {
       ((struct bfd_link_info *) info)->flags |= DF_TEXTREL;
@@ -5517,6 +5546,20 @@ maybe_set_textrel (struct elf_link_hash_entry *h, void *info)
   return TRUE;
 }
 
+static const unsigned char glink_eh_frame_cie[] =
+{
+  0, 0, 0, 16,                         /* length.  */
+  0, 0, 0, 0,                          /* id.  */
+  1,                                   /* CIE version.  */
+  'z', 'R', 0,                         /* Augmentation string.  */
+  4,                                   /* Code alignment.  */
+  0x7c,                                        /* Data alignment.  */
+  65,                                  /* RA reg.  */
+  1,                                   /* Augmentation size.  */
+  DW_EH_PE_pcrel | DW_EH_PE_sdata4,    /* FDE encoding.  */
+  DW_CFA_def_cfa, 1, 0                 /* def_cfa: r1 offset 0.  */
+};
+
 /* Set the sizes of the dynamic sections.  */
 
 static bfd_boolean
@@ -5777,6 +5820,21 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        }
     }
 
+  if (htab->glink != NULL
+      && htab->glink->size != 0
+      && htab->glink_eh_frame != NULL
+      && !bfd_is_abs_section (htab->glink_eh_frame->output_section))
+    {
+      s = htab->glink_eh_frame;
+      s->size = sizeof (glink_eh_frame_cie) + 20;
+      if (info->shared)
+       {
+         s->size += 4;
+         if (htab->glink->size - GLINK_PLTRESOLVE + 8 >= 256)
+           s->size += 4;
+       }
+    }
+
   /* We've now determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -5800,6 +5858,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        }
       else if (s == htab->iplt
               || s == htab->glink
+              || s == htab->glink_eh_frame
               || s == htab->sgotplt
               || s == htab->sbss
               || s == htab->dynbss
@@ -7201,7 +7260,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
        {
        default:
          info->callbacks->einfo
-           (_("%B: unknown relocation type %d for symbol %s\n"),
+           (_("%P: %B: unknown relocation type %d for symbol %s\n"),
             input_bfd, (int) r_type, sym_name);
 
          bfd_set_error (bfd_error_bad_value);
@@ -7462,7 +7521,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
               got at entry m+n bears little relation to the entry m.  */
            if (addend != 0)
              info->callbacks->einfo
-               (_("%H: non-zero addend on %s reloc against `%s'\n"),
+               (_("%P: %H: non-zero addend on %s reloc against `%s'\n"),
                 input_bfd, input_section, rel->r_offset,
                 howto->name,
                 sym_name);
@@ -7658,7 +7717,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                             So we'll segfault when trying to run the
                             indirection function to resolve the reloc.  */
                          info->callbacks->einfo
-                           (_("%H: relocation %s for indirect "
+                           (_("%P: %H: relocation %s for indirect "
                               "function %s unsupported\n"),
                             input_bfd, input_section, rel->r_offset,
                             howto->name,
@@ -7886,7 +7945,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                       && (name[5] == 0 || name[5] == '.'))))
              {
                info->callbacks->einfo
-                 (_("%B: the target (%s) of a %s relocation is "
+                 (_("%P: %B: the target (%s) of a %s relocation is "
                     "in the wrong output section (%s)\n"),
                   input_bfd,
                   sym_name,
@@ -7916,7 +7975,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                   || CONST_STRNEQ (name, ".sbss2")))
              {
                info->callbacks->einfo
-                 (_("%B: the target (%s) of a %s relocation is "
+                 (_("%P: %B: the target (%s) of a %s relocation is "
                     "in the wrong output section (%s)\n"),
                   input_bfd,
                   sym_name,
@@ -7963,7 +8022,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
            else
              {
                info->callbacks->einfo
-                 (_("%B: the target (%s) of a %s relocation is "
+                 (_("%P: %B: the target (%s) of a %s relocation is "
                     "in the wrong output section (%s)\n"),
                   input_bfd,
                   sym_name,
@@ -8035,7 +8094,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
        case R_PPC_EMB_RELST_HA:
        case R_PPC_EMB_BIT_FLD:
          info->callbacks->einfo
-           (_("%B: relocation %s is not yet supported for symbol %s\n"),
+           (_("%P: %B: relocation %s is not yet supported for symbol %s\n"),
             input_bfd,
             howto->name,
             sym_name);
@@ -8094,7 +8153,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
               && h->def_dynamic))
        {
          info->callbacks->einfo
-           (_("%H: unresolvable %s relocation against symbol `%s'\n"),
+           (_("%P: %H: unresolvable %s relocation against symbol `%s'\n"),
             input_bfd, input_section, rel->r_offset,
             howto->name,
             sym_name);
@@ -8141,7 +8200,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
          else
            {
              info->callbacks->einfo
-               (_("%H: %s reloc against `%s': error %d\n"),
+               (_("%P: %H: %s reloc against `%s': error %d\n"),
                 input_bfd, input_section, rel->r_offset,
                 howto->name, sym_name, (int) r);
              ret = FALSE;
@@ -8632,7 +8691,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
        }
       else
        {
-         info->callbacks->einfo (_("%s not defined in linker created %s\n"),
+         info->callbacks->einfo (_("%P: %s not defined in linker created %s\n"),
                                  htab->elf.hgot->root.root.string,
                                  (htab->sgotplt != NULL
                                   ? htab->sgotplt->name : htab->got->name));
@@ -8924,6 +8983,78 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
        }
     }
 
+  if (htab->glink_eh_frame != NULL
+      && htab->glink_eh_frame->contents != NULL)
+    {
+      unsigned char *p = htab->glink_eh_frame->contents;
+      bfd_vma val;
+
+      memcpy (p, glink_eh_frame_cie, sizeof (glink_eh_frame_cie));
+      /* CIE length (rewrite in case little-endian).  */
+      bfd_put_32 (htab->elf.dynobj, sizeof (glink_eh_frame_cie) - 4, p);
+      p += sizeof (glink_eh_frame_cie);
+      /* FDE length.  */
+      val = htab->glink_eh_frame->size - 4 - sizeof (glink_eh_frame_cie);
+      bfd_put_32 (htab->elf.dynobj, val, p);
+      p += 4;
+      /* CIE pointer.  */
+      val = p - htab->glink_eh_frame->contents;
+      bfd_put_32 (htab->elf.dynobj, val, p);
+      p += 4;
+      /* Offset to .glink.  */
+      val = (htab->glink->output_section->vma
+            + htab->glink->output_offset);
+      val -= (htab->glink_eh_frame->output_section->vma
+             + htab->glink_eh_frame->output_offset);
+      val -= p - htab->glink_eh_frame->contents;
+      bfd_put_32 (htab->elf.dynobj, val, p);
+      p += 4;
+      /* .glink size.  */
+      bfd_put_32 (htab->elf.dynobj, htab->glink->size, p);
+      p += 4;
+      /* Augmentation.  */
+      p += 1;
+
+      if (info->shared
+         && htab->elf.dynamic_sections_created)
+       {
+         bfd_vma adv = (htab->glink->size - GLINK_PLTRESOLVE + 8) >> 2;
+         if (adv < 64)
+           *p++ = DW_CFA_advance_loc + adv;
+         else if (adv < 256)
+           {
+             *p++ = DW_CFA_advance_loc1;
+             *p++ = adv;
+           }
+         else if (adv < 65536)
+           {
+             *p++ = DW_CFA_advance_loc2;
+             bfd_put_16 (htab->elf.dynobj, adv, p);
+             p += 2;
+           }
+         else
+           {
+             *p++ = DW_CFA_advance_loc4;
+             bfd_put_32 (htab->elf.dynobj, adv, p);
+             p += 4;
+           }
+         *p++ = DW_CFA_register;
+         *p++ = 65;
+         p++;
+         *p++ = DW_CFA_advance_loc + 4;
+         *p++ = DW_CFA_restore_extended;
+         *p++ = 65;
+       }
+      BFD_ASSERT ((bfd_vma) ((p + 3 - htab->glink_eh_frame->contents) & -4)
+                 == htab->glink_eh_frame->size);
+
+      if (htab->glink_eh_frame->sec_info_type == ELF_INFO_TYPE_EH_FRAME
+         && !_bfd_elf_write_section_eh_frame (output_bfd, info,
+                                              htab->glink_eh_frame,
+                                              htab->glink_eh_frame->contents))
+       return FALSE;
+    }
+
   return ret;
 }
 \f
This page took 0.028291 seconds and 4 git commands to generate.