On 01/02/2011 02:33, Joel Sherrill wrote:
> Hi,
> 
> There are ~100 failures on each *-rtems* target
> in the latest test runs when various lto related
> flags are on.  The symbols in questions are in the
> RTEMS libraries which are picked up via the
> -B... argument.  Other symbols from the same
> library are resolved.

  These have all cropped up since -fuse-linker-plugin became the default.

> Should LTO work with a target not using gold?

  Yes, it should, but some work is needed at the binutils end.  I am testing
the attached two patches at the moment; the idea is to have fully-debugged
support for LTO+plugin in the 2.20.1 release, to support 4.6.0 when it comes 
out.

    cheers,
      DaveK
-- 
Apologies if dup - ENOPATCH first time I hit send.


>From 6cad541c1902edf5ceb483a20666a90be954e3d4 Mon Sep 17 00:00:00 2001
From: Dave Korn <dave.korn.cyg...@gmail.com>
Date: Mon, 31 Jan 2011 03:26:05 +0000
Subject: [PATCH] ld/ChangeLog:

2011-01-29  Dave Korn  <...

	* ldlang.h (lang_input_statement_type): Add new 'claim_archive' flag.
	* ldmain.c (add_archive_element): Set it if the member is claimed.
	* ldlang.c (new_afile): Initialise claim_archive and claimed members.
	(find_replacements_insert_point): New helper function.
	(lang_process): After adding and opening replacement files passed
	from plugin, splice them into correct place in statement list and
	file chains to preserve critical link order.
	(lang_list_insert_after): New helper function.
	(lang_list_remove_tail): Likewise.
---
 ld/ldlang.c |  134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 ld/ldlang.h |    3 +
 ld/ldmain.c |    1 +
 3 files changed, 129 insertions(+), 9 deletions(-)

diff --git a/ld/ldlang.c b/ld/ldlang.c
index 7ffe760..53d2901 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -85,6 +85,11 @@ static void print_statement_list (lang_statement_union_type *,
 static void print_statements (void);
 static void print_input_section (asection *, bfd_boolean);
 static bfd_boolean lang_one_common (struct bfd_link_hash_entry *, void *);
+static void lang_list_insert_after (lang_statement_list_type *destlist,
+				    lang_statement_list_type *srclist,
+				    lang_statement_union_type **field);
+static void lang_list_remove_tail (lang_statement_list_type *destlist,
+				   lang_statement_list_type *origlist);
 static void lang_record_phdrs (void);
 static void lang_do_version_exports_section (void);
 static void lang_finalize_version_expr_head
@@ -1126,6 +1131,8 @@ new_afile (const char *name,
   p->whole_archive = whole_archive;
   p->loaded = FALSE;
   p->missing_file = FALSE;
+  p->claimed = FALSE;
+  p->claim_archive = FALSE;
 
   lang_statement_append (&input_file_chain,
 			 (lang_statement_union_type *) p,
@@ -6394,6 +6401,38 @@ lang_relax_sections (bfd_boolean need_layout)
     }
 }
 
+/* Find the insert point for the plugin's replacement files.  We
+   place them after the first claimed real object file, or if the
+   first claimed object is an archive member, after the last real
+   object file immediately preceding the archive.  In the event
+   no objects have been claimed at all, we return the first dummy
+   object file on the list as the insert point; that works, but
+   the callee must be careful when relinking the file_chain as it
+   is not actually on that chain, only the statement_list and the
+   input_file list; in that case, the replacement files must be
+   inserted at the head of the file_chain.  */
+
+static lang_input_statement_type *
+find_replacements_insert_point (void)
+{
+  lang_input_statement_type *claim1, *lastobject;
+  lastobject = &input_file_chain.head->input_statement;
+  for (claim1 = &file_chain.head->input_statement;
+       claim1 != NULL;
+       claim1 = &claim1->next->input_statement)
+    {
+      if (claim1->claimed)
+	return claim1->claim_archive ? lastobject : claim1;
+      /* Update lastobject if this is a real object file.  */
+      if (claim1->the_bfd && (claim1->the_bfd->my_archive == NULL))
+	lastobject = claim1;
+    }
+  /* No files were claimed by the plugin.  Choose the last object
+     file found on the list (maybe the first, dummy entry) as the
+     insert point.  */
+  return lastobject;
+}
+
 void
 lang_process (void)
 {
@@ -6420,21 +6459,54 @@ lang_process (void)
   open_input_bfds (statement_list.head, FALSE);
 
 #ifdef ENABLE_PLUGINS
+  if (plugin_active_plugins_p ())
     {
-      union lang_statement_union **listend;
+      lang_statement_list_type added;
+      lang_statement_list_type files, inputfiles;
       /* Now all files are read, let the plugin(s) decide if there
 	 are any more to be added to the link before we call the
-	 emulation's after_open hook.  */
-      listend = statement_list.tail;
-      ASSERT (!*listend);
+	 emulation's after_open hook.  We create a private list of
+	 input statements for this purpose, which we will eventually
+	 insert into the global statment list after the first claimed
+	 file.  */
+      added = *stat_ptr;
+      /* We need to manipulate all three chains in synchrony.  */
+      files = file_chain;
+      inputfiles = input_file_chain;
       if (plugin_call_all_symbols_read ())
 	einfo (_("%P%F: %s: plugin reported error after all symbols read\n"),
 	       plugin_error_plugin ());
-      /* If any new files were added, they will be on the end of the
-	 statement list, and we can open them now by getting open_input_bfds
-	 to carry on from where it ended last time.  */
-      if (*listend)
-	open_input_bfds (*listend, FALSE);
+      /* Open any newly added files, updating the file chains.  */
+      open_input_bfds (added.head, FALSE);
+      /* Restore the global list pointer now they have all been added.  */
+      lang_list_remove_tail (stat_ptr, &added);
+      /* And detach the fresh ends of the file lists.  */
+      lang_list_remove_tail (&file_chain, &files);
+      lang_list_remove_tail (&input_file_chain, &inputfiles);
+      /* Were any new files added?  */
+      if (added.head != NULL)
+	{
+	  /* If so, we will insert them into the statement list immediately
+	     after the first input file that was claimed by the plugin.  */
+	  lang_input_statement_type *claim1 = find_replacements_insert_point ();
+	  /* If a plugin adds input files without having claimed any, we
+	     don't really have a good idea where to place them.  Just putting
+	     them at the start or end of the list is liable to leave them
+	     outside the crtbegin...crtend range.  */
+	  ASSERT (claim1 != NULL);
+	  /* Splice the new statement list into the old one after claim1.  */
+	  lang_list_insert_after (stat_ptr, &added, &claim1->header.next);
+	  /* Likewise for the file chains.  */
+	  lang_list_insert_after (&input_file_chain, &inputfiles,
+				  &claim1->next_real_file);
+	  /* We must be careful when relinking file_chain; we may need to
+	     insert the new files at the head of the list if the insert
+	     point chosen is the dummy first input file.  */
+	  if (claim1->filename)
+	    lang_list_insert_after (&file_chain, &files, &claim1->next);
+	  else
+	    lang_list_insert_after (&file_chain, &files, &file_chain.head);
+	}
     }
 #endif /* ENABLE_PLUGINS */
 
@@ -6857,6 +6929,50 @@ lang_statement_append (lang_statement_list_type *list,
   list->tail = field;
 }
 
+/* Insert SRCLIST into DESTLIST after given element by chaining
+   on FIELD as the next-pointer.  (Counterintuitively does not need
+   a pointer to the actual after-node itself, just its chain field.)  */
+
+static void
+lang_list_insert_after (lang_statement_list_type *destlist,
+			lang_statement_list_type *srclist,
+			lang_statement_union_type **field)
+{
+  /* Are we adding at the very end of the list?  */
+  if (*field == NULL)
+    {
+      /* (*field == NULL) should imply (destlist->tail == field),
+	  if not then the element isn't really in the DESTLIST.  */
+      ASSERT (destlist->tail == field);
+      /* Yes, append to and update tail pointer.  */
+      *(destlist->tail) = srclist->head;
+      destlist->tail = srclist->tail;
+    }
+  else
+    {
+      /* We're inserting in the middle somewhere.  */
+      *(srclist->tail) = *field;
+      *field = srclist->head;
+    }
+}
+
+/* Detach new nodes added to DESTLIST since the time ORIGLIST
+   was taken as a copy of it and leave them in ORIGLIST.  */
+
+static void
+lang_list_remove_tail (lang_statement_list_type *destlist,
+		       lang_statement_list_type *origlist)
+{
+  union lang_statement_union **savetail;
+  /* Check that ORIGLIST really is an earlier state of DESTLIST.  */
+  ASSERT (origlist->head == destlist->head);
+  savetail = origlist->tail;
+  origlist->head = *(savetail);
+  origlist->tail = destlist->tail;
+  destlist->tail = savetail;
+  *savetail = NULL;
+}
+
 /* Set the output format type.  -oformat overrides scripts.  */
 
 void
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 8aff0b3..105253a 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -290,6 +290,9 @@ typedef struct lang_input_statement_struct
   /* Set if the file was claimed by a plugin.  */
   unsigned int claimed : 1;
 
+  /* Set if the file was claimed from an archive.  */
+  unsigned int claim_archive : 1;
+
 } lang_input_statement_type;
 
 typedef struct
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 19c42d9..1c6d4be 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -834,6 +834,7 @@ add_archive_element (struct bfd_link_info *info,
 	      /* Substitute the dummy BFD.  */
 	      input->the_bfd = file.handle;
 	      input->claimed = TRUE;
+	      input->claim_archive = TRUE;
 	      bfd_make_readable (input->the_bfd);
 	      *subsbfd = input->the_bfd;
 	    }
>From fd18b9d502186db79ec84bfd5f43b0eb285281c6 Mon Sep 17 00:00:00 2001
From: Dave Korn <dave.korn.cyg...@gmail.com>
Date: Tue, 1 Feb 2011 10:18:04 +0000
Subject: [PATCH] ld/ChangeLog:

2011-01-29  Dave Korn  <...

	* ldlang.c (rescan_input_libs): New function.
	(lang_process): Call it if replacement files have added any new
	undefined symbols.
	* plugin.c (plugin_opt_plugin_arg): Discard any instances of the
	(now-obsolete) "-pass-through=" option if found.
---
 ld/ldlang.c |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ld/plugin.c |    3 +++
 2 files changed, 62 insertions(+), 0 deletions(-)

diff --git a/ld/ldlang.c b/ld/ldlang.c
index 53d2901..4e528d1 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -3273,6 +3273,60 @@ open_input_bfds (lang_statement_union_type *s, bfd_boolean force)
     einfo ("%F");
 }
 
+/* Rescan all the input library files starting from S.  */
+
+static void
+rescan_input_libs (lang_statement_union_type *s)
+{
+  for (; s != NULL; s = s->header.next)
+    {
+      switch (s->header.type)
+	{
+	default:
+	  break;
+	case lang_group_statement_enum:
+	  {
+	    struct bfd_link_hash_entry *undefs;
+	    /* We must continually search the entries in the group
+	       until no new symbols are added to the list of undefined
+	       symbols.  */
+	    do
+	      {
+		undefs = link_info.hash->undefs_tail;
+		rescan_input_libs (s->group_statement.children.head);
+	      }
+	    while (undefs != link_info.hash->undefs_tail);
+	  }
+	  break;
+	case lang_input_statement_enum:
+	  if (s->input_statement.real && s->input_statement.the_bfd
+	      && bfd_check_format (s->input_statement.the_bfd, bfd_archive))
+	    {
+	      lang_statement_list_type add;
+
+	      /* If this archive has already been searched, then
+		 force it to be researched unless the whole archive
+		 has been loaded already.  */
+	      if (!s->input_statement.whole_archive
+		  && s->input_statement.loaded)
+		s->input_statement.loaded = FALSE;
+
+	      lang_list_init (&add);
+
+	      if (!load_symbols (&s->input_statement, &add))
+		config.make_executable = FALSE;
+
+	      if (add.head != NULL)
+		{
+		  *add.tail = s->header.next;
+		  s->header.next = add.head;
+		}
+	    }
+	  break;
+	}
+    }
+}
+
 /* Add a symbol to a hash of symbols used in DEFINED (NAME) expressions.  */
 
 void
@@ -6463,6 +6517,7 @@ lang_process (void)
     {
       lang_statement_list_type added;
       lang_statement_list_type files, inputfiles;
+      struct bfd_link_hash_entry *undefs = link_info.hash->undefs_tail;
       /* Now all files are read, let the plugin(s) decide if there
 	 are any more to be added to the link before we call the
 	 emulation's after_open hook.  We create a private list of
@@ -6506,6 +6561,10 @@ lang_process (void)
 	    lang_list_insert_after (&file_chain, &files, &claim1->next);
 	  else
 	    lang_list_insert_after (&file_chain, &files, &file_chain.head);
+	  /* Now, if there are any new undefined symbols, rescan any
+	     libraries after the insertion point.  */
+	  if (undefs != link_info.hash->undefs_tail)
+	    rescan_input_libs (claim1->next_real_file);
 	}
     }
 #endif /* ENABLE_PLUGINS */
diff --git a/ld/plugin.c b/ld/plugin.c
index b285787..cd8aeb9 100644
--- a/ld/plugin.c
+++ b/ld/plugin.c
@@ -214,6 +214,9 @@ plugin_opt_plugin_arg (const char *arg)
   if (!last_plugin)
     return set_plugin_error (_("<no plugin>"));
 
+  if (CONST_STRNEQ (arg, "-pass-through="))
+    return 0;
+
   newarg = xmalloc (sizeof *newarg);
   newarg->arg = arg;
   newarg->next = NULL;

Reply via email to