This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Reload --as-needed libraries inside groups


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]