From: Bob Wilson <bwilson@tensilica.com>
To: binutils@sources.redhat.com
Subject: [Xtensa] add LD workaround for inconsistent linkonce sections
Date: Fri, 14 Apr 2006 22:00:00 -0000 [thread overview]
Message-ID: <44401755.3000001@tensilica.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 1345 bytes --]
This is patch is a workaround for a problem with .gnu.linkonce sections that is
better solved by using COMDAT groups. Xtensa "property tables" describing
linkonce sections must be kept together with those sections in a link. If a
linkonce section is taken from one input file, and the corresponding property
table is taken from a different input file, bad things happen. This doesn't
normally happen, but it can occur when a particular property table is missing
from one input file. (I think an alternate solution would be to require
property tables to exist even when they are empty.) When property tables are
kept in COMDAT groups with the sections they describe, the whole problem will be
nicely avoided. In the meantime, this patch iterates over all the sections
included in the link and throws out any property tables that are inconsistent,
i.e., that refer to sections from different input files.
Tested with an xtensa-elf build and committed on the mainline.
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.
[-- Attachment #2: inconsistent-linkonce.diff --]
[-- Type: text/x-patch, Size: 5533 bytes --]
Index: emultempl/xtensaelf.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/xtensaelf.em,v
retrieving revision 1.11
diff -u -p -r1.11 xtensaelf.em
--- emultempl/xtensaelf.em 27 Dec 2005 22:56:02 -0000 1.11
+++ emultempl/xtensaelf.em 14 Apr 2006 21:19:35 -0000
@@ -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_
#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)
{
next reply other threads:[~2006-04-14 21:42 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-04-14 22:00 Bob Wilson [this message]
2006-04-14 22:50 ` H. J. Lu
2006-04-14 22:54 ` Bob Wilson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=44401755.3000001@tensilica.com \
--to=bwilson@tensilica.com \
--cc=binutils@sources.redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).