Linker part of PR16563 fix

Presents .eh_frame input sections to the optimisation machinery in
elf-eh-frame.c in the order they are given by the linker script.

	PR 16563
bfd/
	* elflink.c (bfd_elf_discard_info): Process .eh_frame and .stab
	in the order they are mapped to output sections.
ld/
	* ldlang.c (map_head_is_link_order): Rename from
	stripped_excluded_sections.
	(lang_clear_os_map): New function, extracted from..
	(strip_excluded_output_sections): ..here.
	* ldlang.h (lang_clear_os_map): Declare.
	* ldwrite.c (ldwrite): Call lang_clear_os_map.
	* emultempl/sh64elf.em (sh64_elf_${EMULATION_NAME}_after_allocation):
	Likewise.
This commit is contained in:
Alan Modra 2014-08-14 13:49:31 +09:30
parent b879806f2f
commit 18cd5bce47
7 changed files with 128 additions and 61 deletions

View File

@ -1,3 +1,9 @@
2014-08-14 Alan Modra <amodra@gmail.com>
PR 16563
* elflink.c (bfd_elf_discard_info): Process .eh_frame and .stab
in the order they are mapped to output sections.
2014-08-14 Alan Modra <amodra@gmail.com> 2014-08-14 Alan Modra <amodra@gmail.com>
* configure.ac: Delete redundant plugin related checks. * configure.ac: Delete redundant plugin related checks.

View File

@ -12637,8 +12637,7 @@ bfd_boolean
bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
{ {
struct elf_reloc_cookie cookie; struct elf_reloc_cookie cookie;
asection *stab, *eh; asection *o;
const struct elf_backend_data *bed;
bfd *abfd; bfd *abfd;
bfd_boolean ret = FALSE; bfd_boolean ret = FALSE;
@ -12646,70 +12645,86 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
|| !is_elf_hash_table (info->hash)) || !is_elf_hash_table (info->hash))
return FALSE; return FALSE;
o = bfd_get_section_by_name (output_bfd, ".stab");
if (o != NULL)
{
asection *i;
for (i = o->map_head.s; i != NULL; i = i->map_head.s)
{
if (i->size == 0
|| i->reloc_count == 0
|| i->sec_info_type != SEC_INFO_TYPE_STABS)
continue;
abfd = i->owner;
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
continue;
if (!init_reloc_cookie_for_section (&cookie, info, i))
return FALSE;
if (_bfd_discard_section_stabs (abfd, i,
elf_section_data (i)->sec_info,
bfd_elf_reloc_symbol_deleted_p,
&cookie))
ret = TRUE;
fini_reloc_cookie_for_section (&cookie, i);
}
}
o = NULL;
if (!info->relocatable)
o = bfd_get_section_by_name (output_bfd, ".eh_frame");
if (o != NULL)
{
asection *i;
_bfd_elf_begin_eh_frame_parsing (info); _bfd_elf_begin_eh_frame_parsing (info);
for (i = o->map_head.s; i != NULL; i = i->map_head.s)
{
if (i->size == 0)
continue;
abfd = i->owner;
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
continue;
if (!init_reloc_cookie_for_section (&cookie, info, i))
return FALSE;
_bfd_elf_parse_eh_frame (abfd, info, i, &cookie);
if (_bfd_elf_discard_section_eh_frame (abfd, info, i,
bfd_elf_reloc_symbol_deleted_p,
&cookie))
ret = TRUE;
fini_reloc_cookie_for_section (&cookie, i);
}
_bfd_elf_end_eh_frame_parsing (info);
}
for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next) for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next)
{ {
const struct elf_backend_data *bed;
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
continue; continue;
bed = get_elf_backend_data (abfd); bed = get_elf_backend_data (abfd);
eh = NULL; if (bed->elf_backend_discard_info != NULL)
if (!info->relocatable)
{ {
eh = bfd_get_section_by_name (abfd, ".eh_frame");
while (eh != NULL
&& (eh->size == 0
|| bfd_is_abs_section (eh->output_section)))
eh = bfd_get_next_section_by_name (eh);
}
stab = bfd_get_section_by_name (abfd, ".stab");
if (stab != NULL
&& (stab->size == 0
|| bfd_is_abs_section (stab->output_section)
|| stab->sec_info_type != SEC_INFO_TYPE_STABS))
stab = NULL;
if (stab == NULL
&& eh == NULL
&& bed->elf_backend_discard_info == NULL)
continue;
if (!init_reloc_cookie (&cookie, info, abfd)) if (!init_reloc_cookie (&cookie, info, abfd))
return FALSE; return FALSE;
if (stab != NULL if ((*bed->elf_backend_discard_info) (abfd, &cookie, info))
&& stab->reloc_count > 0
&& init_reloc_cookie_rels (&cookie, info, abfd, stab))
{
if (_bfd_discard_section_stabs (abfd, stab,
elf_section_data (stab)->sec_info,
bfd_elf_reloc_symbol_deleted_p,
&cookie))
ret = TRUE;
fini_reloc_cookie_rels (&cookie, stab);
}
while (eh != NULL
&& init_reloc_cookie_rels (&cookie, info, abfd, eh))
{
_bfd_elf_parse_eh_frame (abfd, info, eh, &cookie);
if (_bfd_elf_discard_section_eh_frame (abfd, info, eh,
bfd_elf_reloc_symbol_deleted_p,
&cookie))
ret = TRUE;
fini_reloc_cookie_rels (&cookie, eh);
eh = bfd_get_next_section_by_name (eh);
}
if (bed->elf_backend_discard_info != NULL
&& (*bed->elf_backend_discard_info) (abfd, &cookie, info))
ret = TRUE; ret = TRUE;
fini_reloc_cookie (&cookie, abfd); fini_reloc_cookie (&cookie, abfd);
} }
_bfd_elf_end_eh_frame_parsing (info); }
if (info->eh_frame_hdr if (info->eh_frame_hdr
&& !info->relocatable && !info->relocatable

View File

@ -1,3 +1,15 @@
2014-08-14 Alan Modra <amodra@gmail.com>
PR 16563
* ldlang.c (map_head_is_link_order): Rename from
stripped_excluded_sections.
(lang_clear_os_map): New function, extracted from..
(strip_excluded_output_sections): ..here.
* ldlang.h (lang_clear_os_map): Declare.
* ldwrite.c (ldwrite): Call lang_clear_os_map.
* emultempl/sh64elf.em (sh64_elf_${EMULATION_NAME}_after_allocation):
Likewise.
2014-08-14 Alan Modra <amodra@gmail.com> 2014-08-14 Alan Modra <amodra@gmail.com>
* configure.ac: Move AC_PROG_CC and other macros earlier. Delete * configure.ac: Move AC_PROG_CC and other macros earlier. Delete

View File

@ -248,6 +248,9 @@ sh64_elf_${EMULATION_NAME}_after_allocation (void)
gld${EMULATION_NAME}_after_allocation (); gld${EMULATION_NAME}_after_allocation ();
/* Needed, since we create link_orders here. */
lang_clear_os_map ();
cranges = bfd_get_section_by_name (link_info.output_bfd, cranges = bfd_get_section_by_name (link_info.output_bfd,
SH64_CRANGES_SECTION_NAME); SH64_CRANGES_SECTION_NAME);

View File

@ -57,7 +57,7 @@ static struct obstack map_obstack;
#define obstack_chunk_free free #define obstack_chunk_free free
static const char *entry_symbol_default = "start"; static const char *entry_symbol_default = "start";
static bfd_boolean placed_commons = FALSE; static bfd_boolean placed_commons = FALSE;
static bfd_boolean stripped_excluded_sections = FALSE; static bfd_boolean map_head_is_link_order = FALSE;
static lang_output_section_statement_type *default_common_section; static lang_output_section_statement_type *default_common_section;
static bfd_boolean map_option_f; static bfd_boolean map_option_f;
static bfd_vma print_dot; static bfd_vma print_dot;
@ -2412,7 +2412,7 @@ lang_add_section (lang_statement_list_type *ptr,
section->output_section = output->bfd_section; section->output_section = output->bfd_section;
if (!link_info.relocatable if (!link_info.relocatable
&& !stripped_excluded_sections) && !map_head_is_link_order)
{ {
asection *s = output->bfd_section->map_tail.s; asection *s = output->bfd_section->map_tail.s;
output->bfd_section->map_tail.s = section; output->bfd_section->map_tail.s = section;
@ -3912,10 +3912,6 @@ strip_excluded_output_sections (void)
} }
} }
/* TODO: Don't just junk map_head.s, turn them into link_orders. */
output_section->map_head.link_order = NULL;
output_section->map_tail.link_order = NULL;
if (exclude) if (exclude)
{ {
/* We don't set bfd_section to NULL since bfd_section of the /* We don't set bfd_section to NULL since bfd_section of the
@ -3927,10 +3923,42 @@ strip_excluded_output_sections (void)
link_info.output_bfd->section_count--; link_info.output_bfd->section_count--;
} }
} }
}
/* Called from ldwrite to clear out asection.map_head and
asection.map_tail for use as link_orders in ldwrite.
FIXME: Except for sh64elf.em which starts creating link_orders in
its after_allocation routine so needs to call it early. */
void
lang_clear_os_map (void)
{
lang_output_section_statement_type *os;
if (map_head_is_link_order)
return;
for (os = &lang_output_section_statement.head->output_section_statement;
os != NULL;
os = os->next)
{
asection *output_section;
if (os->constraint < 0)
continue;
output_section = os->bfd_section;
if (output_section == NULL)
continue;
/* TODO: Don't just junk map_head.s, turn them into link_orders. */
output_section->map_head.link_order = NULL;
output_section->map_tail.link_order = NULL;
}
/* Stop future calls to lang_add_section from messing with map_head /* Stop future calls to lang_add_section from messing with map_head
and map_tail link_order fields. */ and map_tail link_order fields. */
stripped_excluded_sections = TRUE; map_head_is_link_order = TRUE;
} }
static void static void

View File

@ -636,6 +636,8 @@ extern void *stat_alloc
(size_t); (size_t);
extern void strip_excluded_output_sections extern void strip_excluded_output_sections
(void); (void);
extern void lang_clear_os_map
(void);
extern void dprint_statement extern void dprint_statement
(lang_statement_union_type *, int); (lang_statement_union_type *, int);
extern void lang_size_sections extern void lang_size_sections

View File

@ -572,6 +572,7 @@ ldwrite (void)
/* Reset error indicator, which can typically something like invalid /* Reset error indicator, which can typically something like invalid
format from opening up the .o files. */ format from opening up the .o files. */
bfd_set_error (bfd_error_no_error); bfd_set_error (bfd_error_no_error);
lang_clear_os_map ();
lang_for_each_statement (build_link_order); lang_for_each_statement (build_link_order);
if (config.split_by_reloc != (unsigned) -1 if (config.split_by_reloc != (unsigned) -1