aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog24
-rw-r--r--bfd/elf-bfd.h2
-rw-r--r--bfd/elf-eh-frame.c47
-rw-r--r--bfd/elf32-i386.c45
-rw-r--r--bfd/elf32-ppc.c3
-rw-r--r--bfd/elf64-ppc.c2
-rw-r--r--bfd/elf64-x86-64.c38
-rw-r--r--bfd/elflink.c24
8 files changed, 114 insertions, 71 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 35bbb31..2165cd8 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index b07d8c4..5426c93 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -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 *);
diff --git a/bfd/elf-eh-frame.c b/bfd/elf-eh-frame.c
index 685540c..a75d806 100644
--- a/bfd/elf-eh-frame.c
+++ b/bfd/elf-eh-frame.c
@@ -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;
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index 84299ce..7b33d77 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -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
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 9665d39..98f1aa8 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -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;
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index df1db6d..79f551d 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -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;
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 1f490d4..abd8d60 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -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
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 7722fb5..7f35e7f 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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);