public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
From: Alan Modra <amodra@gmail.com>
To: binutils@sourceware.org
Subject: Reload --as-needed libraries inside groups
Date: Thu, 03 Jul 2014 08:07:00 -0000	[thread overview]
Message-ID: <20140703080645.GL4471@bubble.grove.modra.org> (raw)

When a shared library appears within --start-group/--end-group ld may
only discover a need for loading the library on the second or
subsequent pass over archive libraries, as more objects are extracted.
If --as-needed is in force, the first pass might determine the shared
library is not needed, so we'd better load it again on subsequent
passes.

One way to avoid this problem is simply to not put shared libraries
inside --start-group/--end-group, but instead put them after archive
libraries have been handled.  However, that only works if you know
you're dealing with shared libraries (-lfoo might be libfoo.so on
some systems and libfoo.a on others).

ld/
	PR 17068
	* ldlang.c (load_symbols): Always check flags.reload.
	(open_input_bfds): Always reload --as-needed shared libraries,
	not just when rescanning.
	* ldlang.h (struct lang_input_statement_flags): Update reload comment.
	* plugin.c (plugin_should_reload): Assume shared library arg.
	* plugin.h (plugin_should_reload): Update comment.
ld/testsuite
	* ld-elf/pr17068.s: New.
	* ld-elf/pr17068a.s: New.
	* ld-elf/pr17068b.s: New.
	* ld-elf/pr17068c.s: New.
	* ld-elf/pr17068d.s: New.
	* ld-elf/pr17068e.s: New.
	* ld-elf/pr17068ez.s: New.
	* ld-elf/elf.exp: Run new test.

diff --git a/ld/ldlang.c b/ld/ldlang.c
index 60877b8..5e10c4a 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -2790,9 +2790,7 @@ load_symbols (lang_input_statement_type *entry,
       break;
 
     case bfd_object:
-#ifdef ENABLE_PLUGINS
       if (!entry->flags.reload)
-#endif
 	ldlang_add_file (entry);
       if (trace_files || verbose)
 	info_msg ("%I\n", entry);
@@ -3268,38 +3266,32 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
 	    {
 	      lang_statement_union_type **os_tail;
 	      lang_statement_list_type add;
+	      bfd *abfd;
 
 	      s->input_statement.target = current_target;
 
 	      /* If we are being called from within a group, and this
 		 is an archive which has already been searched, then
 		 force it to be researched unless the whole archive
-		 has been loaded already.  Do the same for a rescan.  */
+		 has been loaded already.  Do the same for a rescan.
+		 Likewise reload --as-needed shared libs.  */
 	      if (mode != OPEN_BFD_NORMAL
 #ifdef ENABLE_PLUGINS
 		  && ((mode & OPEN_BFD_RESCAN) == 0
 		      || plugin_insert == NULL)
 #endif
-		  && !s->input_statement.flags.whole_archive
 		  && s->input_statement.flags.loaded
-		  && s->input_statement.the_bfd != NULL
-		  && bfd_check_format (s->input_statement.the_bfd,
-				       bfd_archive))
-		s->input_statement.flags.loaded = FALSE;
-#ifdef ENABLE_PLUGINS
-	      /* When rescanning, reload --as-needed shared libs.  */
-	      else if ((mode & OPEN_BFD_RESCAN) != 0
-		       && plugin_insert == NULL
-		       && s->input_statement.flags.loaded
-		       && s->input_statement.flags.add_DT_NEEDED_for_regular
-		       && s->input_statement.the_bfd != NULL
-		       && ((s->input_statement.the_bfd->flags) & DYNAMIC) != 0
-		       && plugin_should_reload (s->input_statement.the_bfd))
+		  && (abfd = s->input_statement.the_bfd) != NULL
+		  && ((bfd_get_format (abfd) == bfd_archive
+		       && !s->input_statement.flags.whole_archive)
+		      || (bfd_get_format (abfd) == bfd_object
+			  && ((abfd->flags) & DYNAMIC) != 0
+			  && s->input_statement.flags.add_DT_NEEDED_for_regular
+			  && plugin_should_reload (abfd))))
 		{
 		  s->input_statement.flags.loaded = FALSE;
 		  s->input_statement.flags.reload = TRUE;
 		}
-#endif
 
 	      os_tail = lang_output_section_statement.tail;
 	      lang_list_init (&add);
diff --git a/ld/ldlang.h b/ld/ldlang.h
index 7d69c56..0f7fdd4 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -279,7 +279,7 @@ struct lang_input_statement_flags
   /* Set if the file was claimed from an archive.  */
   unsigned int claim_archive : 1;
 
-  /* Set if reloading an --as-needed lib.  */
+  /* Set if reloading an archive or --as-needed lib.  */
   unsigned int reload : 1;
 #endif /* ENABLE_PLUGINS */
 };
diff --git a/ld/plugin.c b/ld/plugin.c
index 2a6d7c5..cd6ae60 100644
--- a/ld/plugin.c
+++ b/ld/plugin.c
@@ -1029,13 +1029,11 @@ plugin_notice (struct bfd_link_info *info,
   return TRUE;
 }
 
-/* Return true if bfd is a dynamic library that should be reloaded.  */
+/* Return true if ABFD, a dynamic library, should be reloaded.  */
 
 bfd_boolean
 plugin_should_reload (bfd *abfd)
 {
-  return ((abfd->flags & DYNAMIC) != 0
-	  && bfd_get_flavour (abfd) == bfd_target_elf_flavour
-	  && bfd_get_format (abfd) == bfd_object
+  return (bfd_get_flavour (abfd) == bfd_target_elf_flavour
 	  && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0);
 }
diff --git a/ld/plugin.h b/ld/plugin.h
index beae7ab..1e239ca 100644
--- a/ld/plugin.h
+++ b/ld/plugin.h
@@ -66,7 +66,7 @@ extern void plugin_call_cleanup (void);
    add_symbols hook has been called so that it can be read when linking.  */
 extern bfd *plugin_get_ir_dummy_bfd (const char *name, bfd *template);
 
-/* Return true if bfd is a dynamic library that should be reloaded.  */
+/* Return true if ABFD, a dynamic library, should be reloaded.  */
 extern bfd_boolean plugin_should_reload (bfd *);
 
 #endif /* !def GLD_PLUGIN_H */
diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp
index 4c8ca3a..839c931 100644
--- a/ld/testsuite/ld-elf/elf.exp
+++ b/ld/testsuite/ld-elf/elf.exp
@@ -77,13 +77,12 @@ if { ![istarget hppa64*-hpux*] } {
     }
 }
 
-# Run a test to check linking a shared library with a broken linker
-# script that accidentally marks dynamic sections as notes.  The
-# resulting executable is not expected to work, but the linker
-# should not seg-fault whilst creating the binary.
-#
-# Only run the test on targets thats support creating shared libraries.
+# Only run these tests on targets thats support creating shared libraries.
 if { [check_shared_lib_support] } then {
+    # Run a test to check linking a shared library with a broken linker
+    # script that accidentally marks dynamic sections as notes.  The
+    # resulting executable is not expected to work, but the linker
+    # should not seg-fault whilst creating the binary.
     setup_xfail "tic6x-*-*"
     run_ld_link_tests {
 	{"Build shared library for next test"
@@ -93,6 +92,21 @@ if { [check_shared_lib_support] } then {
 	    { { ld "note-3.l" } }
 	    "a.out" }
     }
+    setup_xfail "tic6x-*-*"
+    run_ld_link_tests {
+	{"Build pr17068.so"
+	    "-shared" "" ""
+	    {pr17068d.s} {} "pr17068.so"}
+	{"Build pr17068a.a"
+	    "" "" ""
+	    {pr17068a.s pr17068c.s pr17068ez.s} {} "pr17068a.a"}
+	{"Build pr17068b.a"
+	    "" "" ""
+	    {pr17068b.s pr17068e.s} {} "pr17068b.a"}
+	{"pr17068 link --as-needed lib in group"
+	    "--as-needed" "--start-group tmpdir/pr17068a.a tmpdir/pr17068.so tmpdir/pr17068b.a --end-group" ""
+	    {start.s pr17068.s} {} "pr17068"}
+    }
 }
 
 set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
diff --git a/ld/testsuite/ld-elf/pr17068.s b/ld/testsuite/ld-elf/pr17068.s
new file mode 100644
index 0000000..9675ab4
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr17068.s
@@ -0,0 +1,2 @@
+ .data
+ .dc.a a
diff --git a/ld/testsuite/ld-elf/pr17068a.s b/ld/testsuite/ld-elf/pr17068a.s
new file mode 100644
index 0000000..552697c
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr17068a.s
@@ -0,0 +1,4 @@
+ .data
+ .globl a
+a:
+ .dc.a b
diff --git a/ld/testsuite/ld-elf/pr17068b.s b/ld/testsuite/ld-elf/pr17068b.s
new file mode 100644
index 0000000..aa536f2
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr17068b.s
@@ -0,0 +1,4 @@
+ .data
+ .globl b
+b:
+ .dc.a c
diff --git a/ld/testsuite/ld-elf/pr17068c.s b/ld/testsuite/ld-elf/pr17068c.s
new file mode 100644
index 0000000..1d78f6d
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr17068c.s
@@ -0,0 +1,4 @@
+ .data
+ .globl c
+c:
+ .dc.a d
diff --git a/ld/testsuite/ld-elf/pr17068d.s b/ld/testsuite/ld-elf/pr17068d.s
new file mode 100644
index 0000000..6165128
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr17068d.s
@@ -0,0 +1,6 @@
+ .data
+ .globl d
+ .type d,%object
+d:
+ .dc.a e
+ .size d,.-d
diff --git a/ld/testsuite/ld-elf/pr17068e.s b/ld/testsuite/ld-elf/pr17068e.s
new file mode 100644
index 0000000..095eb89
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr17068e.s
@@ -0,0 +1,3 @@
+ .data
+ .globl e
+e:
diff --git a/ld/testsuite/ld-elf/pr17068ez.s b/ld/testsuite/ld-elf/pr17068ez.s
new file mode 100644
index 0000000..70e040d
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr17068ez.s
@@ -0,0 +1,4 @@
+ .data
+ .globl e
+e:
+ .dc.a z

-- 
Alan Modra
Australia Development Lab, IBM

             reply	other threads:[~2014-07-03  8:07 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-03  8:07 Alan Modra [this message]
2014-07-03 11:59 ` Aarch64 linker issue Renjith G
2014-07-03 12:14   ` Andreas Schwab

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=20140703080645.GL4471@bubble.grove.modra.org \
    --to=amodra@gmail.com \
    --cc=binutils@sourceware.org \
    /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).