* emultempl/xtensaelf.em (elf_xtensa_before_allocation): Call new

function to strip inconsistent linkonce sections.
	(input_section_linked_worker, input_section_linked): New.
	(is_inconsistent_linkonce_section): New.
	(xtensa_strip_inconsistent_linkonce_sections): New.
This commit is contained in:
Bob Wilson 2006-04-14 21:31:16 +00:00
parent cd852561d0
commit a255b6c7b0
2 changed files with 153 additions and 1 deletions

View File

@ -1,3 +1,12 @@
2006-04-14 David Heine <dlheine@tensilica.com>
Bob Wilson <bob.wilson@acm.org>
* emultempl/xtensaelf.em (elf_xtensa_before_allocation): Call new
function to strip inconsistent linkonce sections.
(input_section_linked_worker, input_section_linked): New.
(is_inconsistent_linkonce_section): New.
(xtensa_strip_inconsistent_linkonce_sections): New.
2006-04-11 Diego Pettenò <flameeyes@gentoo.org>
* emultempl/elf32.em: Add support for elf-hints.h on FreeBSD

View File

@ -1,5 +1,5 @@
# This shell script emits a C file. -*- C -*-
# Copyright 2003, 2004, 2005
# Copyright 2003, 2004, 2005, 2006
# Free Software Foundation, Inc.
#
# This file is part of GLD, the Gnu Linker.
@ -32,6 +32,8 @@ cat >>e${EMULATION_NAME}.c <<EOF
static void xtensa_wild_group_interleave (lang_statement_union_type *);
static void xtensa_colocate_output_literals (lang_statement_union_type *);
static void xtensa_strip_inconsistent_linkonce_sections
(lang_statement_list_type *);
/* Flag for the emulation-specific "--no-relax" option. */
@ -370,6 +372,8 @@ elf_xtensa_before_allocation (void)
if (!disable_relaxation)
command_line.relax = TRUE;
xtensa_strip_inconsistent_linkonce_sections (stat_ptr);
gld${EMULATION_NAME}_before_allocation ();
xtensa_wild_group_interleave (stat_ptr->head);
@ -1157,6 +1161,145 @@ ld_count_children (lang_statement_union_type *s)
#endif /* EXTRA_VALIDATION */
/* Check if a particular section is included in the link. This will only
be true for one instance of a particular linkonce section. */
static bfd_boolean input_section_found = FALSE;
static asection *input_section_target = NULL;
static void
input_section_linked_worker (lang_statement_union_type *statement)
{
if ((statement->header.type == lang_input_section_enum
&& (statement->input_section.section == input_section_target)))
input_section_found = TRUE;
}
static bfd_boolean
input_section_linked (asection *sec)
{
input_section_found = FALSE;
input_section_target = sec;
lang_for_each_statement_worker (input_section_linked_worker, stat_ptr->head);
return input_section_found;
}
/* Strip out any linkonce literal sections or property tables where the
associated linkonce text is from a different object file. Normally,
a matching set of linkonce sections is taken from the same object file,
but sometimes the files are compiled differently so that some of the
linkonce sections are not present in all files. Stripping the
inconsistent sections like this is not completely robust -- a much
better solution is to use comdat groups. */
static int linkonce_len = sizeof (".gnu.linkonce.") - 1;
static bfd_boolean
is_inconsistent_linkonce_section (asection *sec)
{
bfd *abfd = sec->owner;
const char *sec_name = bfd_get_section_name (abfd, sec);
char *prop_tag = 0;
if ((bfd_get_section_flags (abfd, sec) & SEC_LINK_ONCE) == 0
|| strncmp (sec_name, ".gnu.linkonce.", linkonce_len) != 0)
return FALSE;
/* Check if this is an Xtensa property section. */
if (strncmp (sec_name + linkonce_len, "p.", 2) == 0)
prop_tag = "p.";
else if (strncmp (sec_name + linkonce_len, "prop.", 5) == 0)
prop_tag = "prop.";
if (prop_tag)
{
int tag_len = strlen (prop_tag);
char *dep_sec_name = xmalloc (strlen (sec_name));
asection *dep_sec;
/* Get the associated linkonce text section and check if it is
included in the link. If not, this section is inconsistent
and should be stripped. */
strcpy (dep_sec_name, ".gnu.linkonce.");
strcat (dep_sec_name, sec_name + linkonce_len + tag_len);
dep_sec = bfd_get_section_by_name (abfd, dep_sec_name);
if (dep_sec == NULL || ! input_section_linked (dep_sec))
{
free (dep_sec_name);
return TRUE;
}
free (dep_sec_name);
}
return FALSE;
}
static void
xtensa_strip_inconsistent_linkonce_sections (lang_statement_list_type *slist)
{
lang_statement_union_type **s_p = &slist->head;
while (*s_p)
{
lang_statement_union_type *s = *s_p;
lang_statement_union_type *s_next = (*s_p)->header.next;
switch (s->header.type)
{
case lang_input_section_enum:
if (is_inconsistent_linkonce_section (s->input_section.section))
{
*s_p = s_next;
continue;
}
break;
case lang_constructors_statement_enum:
xtensa_strip_inconsistent_linkonce_sections (&constructor_list);
break;
case lang_output_section_statement_enum:
if (s->output_section_statement.children.head)
xtensa_strip_inconsistent_linkonce_sections
(&s->output_section_statement.children);
break;
case lang_wild_statement_enum:
xtensa_strip_inconsistent_linkonce_sections
(&s->wild_statement.children);
break;
case lang_group_statement_enum:
xtensa_strip_inconsistent_linkonce_sections
(&s->group_statement.children);
break;
case lang_data_statement_enum:
case lang_reloc_statement_enum:
case lang_object_symbols_statement_enum:
case lang_output_statement_enum:
case lang_target_statement_enum:
case lang_input_statement_enum:
case lang_assignment_statement_enum:
case lang_padding_statement_enum:
case lang_address_statement_enum:
case lang_fill_statement_enum:
break;
default:
FAIL ();
break;
}
s_p = &(*s_p)->header.next;
}
/* Reset the tail of the list, in case the last entry was removed. */
if (s_p != slist->tail)
slist->tail = s_p;
}
static void
xtensa_wild_group_interleave_callback (lang_statement_union_type *statement)
{