PR ld/13909
authorAlan Modra <amodra@gmail.com>
Fri, 25 May 2012 01:12:20 +0000 (01:12 +0000)
committerAlan Modra <amodra@gmail.com>
Fri, 25 May 2012 01:12:20 +0000 (01:12 +0000)
* elf-eh-frame.c (_bfd_elf_eh_frame_present): New function.
(_bfd_elf_maybe_strip_eh_frame_hdr): Use it here.
* elf-bfd.h (_bfd_elf_eh_frame_present): Declare.
* elflink.c (bfd_elf_size_dynamic_sections): Let the backend
size dynamic sections before stripping eh_frame_hdr.
(bfd_elf_gc_sections): Handle multiple .eh_frame sections.
* elf32-ppc.c (ppc_elf_size_dynamic_sections): Drop glink_eh_frame
if no other .eh_frame sections exist.
* elf64-ppc.c (ppc64_elf_size_stubs): Likewise.
* elf32-i386.c (elf_i386_create_dynamic_sections): Don't size
or alloc plt_eh_frame here..
(elf_i386_size_dynamic_sections): ..do it here instead.  Don't
specially keep sgotplt, iplt, tgotplt, sdynbss for symbols.
(elf_i386_finish_dynamic_sections): Check plt_eh_frame->contents
before writing plt offset.
* elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Don't size
or alloc plt_eh_frame here..
(elf_x86_64_size_dynamic_sections): ..do it here instead.
(elf_x86_64_finish_dynamic_sections): Check plt_eh_frame->contents
before writing plt offset.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf-eh-frame.c
bfd/elf32-i386.c
bfd/elf32-ppc.c
bfd/elf64-ppc.c
bfd/elf64-x86-64.c
bfd/elflink.c

index 35bbb31..2165cd8 100644 (file)
@@ -1,3 +1,27 @@
+2012-05-25  Alan Modra  <amodra@gmail.com>
+
+       PR ld/13909
+       * elf-eh-frame.c (_bfd_elf_eh_frame_present): New function.
+       (_bfd_elf_maybe_strip_eh_frame_hdr): Use it here.
+       * elf-bfd.h (_bfd_elf_eh_frame_present): Declare.
+       * elflink.c (bfd_elf_size_dynamic_sections): Let the backend
+       size dynamic sections before stripping eh_frame_hdr.
+       (bfd_elf_gc_sections): Handle multiple .eh_frame sections.
+       * elf32-ppc.c (ppc_elf_size_dynamic_sections): Drop glink_eh_frame
+       if no other .eh_frame sections exist.
+       * elf64-ppc.c (ppc64_elf_size_stubs): Likewise.
+       * elf32-i386.c (elf_i386_create_dynamic_sections): Don't size
+       or alloc plt_eh_frame here..
+       (elf_i386_size_dynamic_sections): ..do it here instead.  Don't
+       specially keep sgotplt, iplt, tgotplt, sdynbss for symbols.
+       (elf_i386_finish_dynamic_sections): Check plt_eh_frame->contents
+       before writing plt offset.
+       * elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Don't size
+       or alloc plt_eh_frame here..
+       (elf_x86_64_size_dynamic_sections): ..do it here instead.
+       (elf_x86_64_finish_dynamic_sections): Check plt_eh_frame->contents
+       before writing plt offset.
+
 2012-05-24  Alan Modra  <amodra@gmail.com>
 
        PR ld/14158
index b07d8c4..5426c93 100644 (file)
@@ -1950,6 +1950,8 @@ extern bfd_boolean _bfd_elf_write_section_eh_frame
   (bfd *, struct bfd_link_info *, asection *, bfd_byte *);
 extern bfd_boolean _bfd_elf_write_section_eh_frame_hdr
   (bfd *, struct bfd_link_info *);
+extern bfd_boolean _bfd_elf_eh_frame_present
+  (struct bfd_link_info *);
 extern bfd_boolean _bfd_elf_maybe_strip_eh_frame_hdr
   (struct bfd_link_info *);
 
index 685540c..a75d806 100644 (file)
@@ -1247,6 +1247,26 @@ _bfd_elf_discard_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
   return TRUE;
 }
 
+/* Return true if there is at least one non-empty .eh_frame section in
+   input files.  Can only be called after ld has mapped input to
+   output sections, and before sections are stripped.  */
+bfd_boolean
+_bfd_elf_eh_frame_present (struct bfd_link_info *info)
+{
+  asection *eh = bfd_get_section_by_name (info->output_bfd, ".eh_frame");
+
+  if (eh == NULL)
+    return FALSE;
+
+  /* Count only sections which have at least a single CIE or FDE.
+     There cannot be any CIE or FDE <= 8 bytes.  */
+  for (eh = eh->map_head.s; eh != NULL; eh = eh->map_head.s)
+    if (eh->size > 8)
+      return TRUE;
+
+  return FALSE;
+}
+
 /* This function is called from size_dynamic_sections.
    It needs to decide whether .eh_frame_hdr should be output or not,
    because when the dynamic symbol table has been sized it is too late
@@ -1255,8 +1275,6 @@ _bfd_elf_discard_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
 bfd_boolean
 _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *info)
 {
-  asection *o;
-  bfd *abfd;
   struct elf_link_hash_table *htab;
   struct eh_frame_hdr_info *hdr_info;
 
@@ -1265,28 +1283,9 @@ _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *info)
   if (hdr_info->hdr_sec == NULL)
     return TRUE;
 
-  if (bfd_is_abs_section (hdr_info->hdr_sec->output_section))
-    {
-      hdr_info->hdr_sec = NULL;
-      return TRUE;
-    }
-
-  abfd = NULL;
-  if (info->eh_frame_hdr)
-    for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
-      {
-       /* Count only sections which have at least a single CIE or FDE.
-          There cannot be any CIE or FDE <= 8 bytes.  */
-       o = bfd_get_section_by_name (abfd, ".eh_frame");
-       while (o != NULL
-              && (o->size <= 8
-                  || bfd_is_abs_section (o->output_section)))
-         o = bfd_get_next_section_by_name (o);
-       if (o != NULL)
-         break;
-      }
-
-  if (abfd == NULL)
+  if (bfd_is_abs_section (hdr_info->hdr_sec->output_section)
+      || !info->eh_frame_hdr
+      || !_bfd_elf_eh_frame_present (info))
     {
       hdr_info->hdr_sec->flags |= SEC_EXCLUDE;
       hdr_info->hdr_sec = NULL;
index 84299ce..7b33d77 100644 (file)
@@ -1027,12 +1027,6 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
       if (htab->plt_eh_frame == NULL
          || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 2))
        return FALSE;
-
-      htab->plt_eh_frame->size = sizeof (elf_i386_eh_frame_plt);
-      htab->plt_eh_frame->contents
-       = bfd_alloc (dynobj, htab->plt_eh_frame->size);
-      memcpy (htab->plt_eh_frame->contents, elf_i386_eh_frame_plt,
-             sizeof (elf_i386_eh_frame_plt));
     }
 
   return TRUE;
@@ -2726,7 +2720,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
                                  FALSE, FALSE, FALSE);
 
       /* Don't allocate .got.plt section if there are no GOT nor PLT
-         entries and there is no refeence to _GLOBAL_OFFSET_TABLE_.  */
+         entries and there is no reference to _GLOBAL_OFFSET_TABLE_.  */
       if ((got == NULL
           || !got->ref_regular_nonweak)
          && (htab->elf.sgotplt->size
@@ -2742,6 +2736,14 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
        htab->elf.sgotplt->size = 0;
     }
 
+
+  if (htab->plt_eh_frame != NULL
+      && htab->elf.splt != NULL
+      && htab->elf.splt->size != 0
+      && !bfd_is_abs_section (htab->elf.splt->output_section)
+      && _bfd_elf_eh_frame_present (info))
+    htab->plt_eh_frame->size = sizeof (elf_i386_eh_frame_plt);
+
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -2753,11 +2755,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
        continue;
 
       if (s == htab->elf.splt
-         || s == htab->elf.sgot
-         || s == htab->elf.sgotplt
-         || s == htab->elf.iplt
-         || s == htab->elf.igotplt
-         || s == htab->sdynbss)
+         || s == htab->elf.sgot)
        {
          /* Strip this section if we don't need it; see the
             comment below.  */
@@ -2768,6 +2766,14 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
          if (htab->elf.hplt != NULL)
            strip_section = FALSE;
        }
+      else if (s == htab->elf.sgotplt
+              || s == htab->elf.iplt
+              || s == htab->elf.igotplt
+              || s == htab->plt_eh_frame
+              || s == htab->sdynbss)
+       {
+         /* Strip these too.  */
+       }
       else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rel"))
        {
          if (s->size != 0
@@ -2815,11 +2821,13 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
     }
 
   if (htab->plt_eh_frame != NULL
-      && htab->elf.splt != NULL
-      && htab->elf.splt->size != 0
-      && (htab->elf.splt->flags & SEC_EXCLUDE) == 0)
-    bfd_put_32 (dynobj, htab->elf.splt->size,
-               htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
+      && htab->plt_eh_frame->contents != NULL)
+    {
+      memcpy (htab->plt_eh_frame->contents, elf_i386_eh_frame_plt,
+             sizeof (elf_i386_eh_frame_plt));
+      bfd_put_32 (dynobj, htab->elf.splt->size,
+                 htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
+    }
 
   if (htab->elf.dynamic_sections_created)
     {
@@ -4840,7 +4848,8 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd,
     }
 
   /* Adjust .eh_frame for .plt section.  */
-  if (htab->plt_eh_frame != NULL)
+  if (htab->plt_eh_frame != NULL
+      && htab->plt_eh_frame->contents != NULL)
     {
       if (htab->elf.splt != NULL
          && htab->elf.splt->size != 0
index 9665d39..98f1aa8 100644 (file)
@@ -6244,7 +6244,8 @@ 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))
+      && !bfd_is_abs_section (htab->glink_eh_frame->output_section)
+      && _bfd_elf_eh_frame_present (info))
     {
       s = htab->glink_eh_frame;
       s->size = sizeof (glink_eh_frame_cie) + 20;
index df1db6d..79f551d 100644 (file)
@@ -11662,7 +11662,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
 
       if (htab->glink_eh_frame != NULL
          && !bfd_is_abs_section (htab->glink_eh_frame->output_section)
-         && (htab->glink_eh_frame->flags & SEC_EXCLUDE) == 0)
+         && htab->glink_eh_frame->output_section->size != 0)
        {
          size_t size = 0, align;
 
index 1f490d4..abd8d60 100644 (file)
@@ -982,8 +982,6 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj,
       && htab->plt_eh_frame == NULL
       && htab->elf.splt != NULL)
     {
-      const struct elf_x86_64_backend_data *const abed
-       = get_elf_x86_64_backend_data (dynobj);
       flagword flags = get_elf_backend_data (dynobj)->dynamic_sec_flags;
       htab->plt_eh_frame
        = bfd_make_section_anyway_with_flags (dynobj, ".eh_frame",
@@ -993,12 +991,6 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj,
       if (htab->plt_eh_frame == NULL
          || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 3))
        return FALSE;
-
-      htab->plt_eh_frame->size = abed->eh_frame_plt_size;
-      htab->plt_eh_frame->contents
-       = bfd_alloc (dynobj, htab->plt_eh_frame->size);
-      memcpy (htab->plt_eh_frame->contents,
-             abed->eh_frame_plt, abed->eh_frame_plt_size);
     }
   return TRUE;
 }
@@ -2797,6 +2789,17 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
        htab->elf.sgotplt->size = 0;
     }
 
+  if (htab->plt_eh_frame != NULL
+      && htab->elf.splt != NULL
+      && htab->elf.splt->size != 0
+      && !bfd_is_abs_section (htab->elf.splt->output_section)
+      && _bfd_elf_eh_frame_present (info))
+    {
+      const struct elf_x86_64_backend_data *arch_data
+       = (const struct elf_x86_64_backend_data *) bed->arch_data;
+      htab->plt_eh_frame->size = arch_data->eh_frame_plt_size;
+    }
+
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -2810,6 +2813,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
          || s == htab->elf.sgotplt
          || s == htab->elf.iplt
          || s == htab->elf.igotplt
+         || s == htab->plt_eh_frame
          || s == htab->sdynbss)
        {
          /* Strip this section if we don't need it; see the
@@ -2861,11 +2865,16 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
     }
 
   if (htab->plt_eh_frame != NULL
-      && htab->elf.splt != NULL
-      && htab->elf.splt->size != 0
-      && (htab->elf.splt->flags & SEC_EXCLUDE) == 0)
-    bfd_put_32 (dynobj, htab->elf.splt->size,
-               htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
+      && htab->plt_eh_frame->contents != NULL)
+    {
+      const struct elf_x86_64_backend_data *arch_data
+       = (const struct elf_x86_64_backend_data *) bed->arch_data;
+
+      memcpy (htab->plt_eh_frame->contents,
+             arch_data->eh_frame_plt, htab->plt_eh_frame->size);
+      bfd_put_32 (dynobj, htab->elf.splt->size,
+                 htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
+    }
 
   if (htab->elf.dynamic_sections_created)
     {
@@ -4725,7 +4734,8 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
     }
 
   /* Adjust .eh_frame for .plt section.  */
-  if (htab->plt_eh_frame != NULL)
+  if (htab->plt_eh_frame != NULL
+      && htab->plt_eh_frame->contents != NULL)
     {
       if (htab->elf.splt != NULL
          && htab->elf.splt->size != 0
index 7722fb5..7f35e7f 100644 (file)
@@ -5584,17 +5584,9 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       && ! (*bed->elf_backend_always_size_sections) (output_bfd, info))
     return FALSE;
 
-  if (! _bfd_elf_maybe_strip_eh_frame_hdr (info))
-    return FALSE;
-
   dynobj = elf_hash_table (info)->dynobj;
 
-  /* If there were no dynamic objects in the link, there is nothing to
-     do here.  */
-  if (dynobj == NULL)
-    return TRUE;
-
-  if (elf_hash_table (info)->dynamic_sections_created)
+  if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
     {
       struct elf_info_failed eif;
       struct elf_link_hash_entry *h;
@@ -5897,11 +5889,15 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
   /* The backend must work out the sizes of all the other dynamic
      sections.  */
-  if (bed->elf_backend_size_dynamic_sections
+  if (dynobj != NULL
+      && bed->elf_backend_size_dynamic_sections != NULL
       && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
     return FALSE;
 
-  if (elf_hash_table (info)->dynamic_sections_created)
+  if (! _bfd_elf_maybe_strip_eh_frame_hdr (info))
+    return FALSE;
+
+  if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
     {
       unsigned long section_sym_count;
       struct bfd_elf_version_tree *verdefs;
@@ -12002,12 +11998,14 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
       struct elf_reloc_cookie cookie;
 
       sec = bfd_get_section_by_name (sub, ".eh_frame");
-      if (sec && init_reloc_cookie_for_section (&cookie, info, sec))
+      while (sec && init_reloc_cookie_for_section (&cookie, info, sec))
        {
          _bfd_elf_parse_eh_frame (sub, info, sec, &cookie);
-         if (elf_section_data (sec)->sec_info)
+         if (elf_section_data (sec)->sec_info
+             && (sec->flags & SEC_LINKER_CREATED) == 0)
            elf_eh_frame_section (sub) = sec;
          fini_reloc_cookie_for_section (&cookie, sec);
+         sec = bfd_get_next_section_by_name (sec);
        }
     }
   _bfd_elf_end_eh_frame_parsing (info);