public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
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)
 {

             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).