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.
This commit is contained in:
Alan Modra 2012-05-25 01:12:20 +00:00
parent 3161ca4f50
commit 9a2a56cc5a
8 changed files with 114 additions and 71 deletions

View 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

View 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 *);

View 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;

View 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

View 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;

View 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;

View 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

View 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);