* 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:
parent
cd852561d0
commit
a255b6c7b0
2 changed files with 153 additions and 1 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue