Reload --as-needed libraries inside groups
authorAlan Modra <amodra@gmail.com>
Thu, 3 Jul 2014 07:02:45 +0000 (16:32 +0930)
committerAlan Modra <amodra@gmail.com>
Thu, 3 Jul 2014 07:35:42 +0000 (17:05 +0930)
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.

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.

14 files changed:
ld/ChangeLog
ld/ldlang.c
ld/ldlang.h
ld/plugin.c
ld/plugin.h
ld/testsuite/ChangeLog
ld/testsuite/ld-elf/elf.exp
ld/testsuite/ld-elf/pr17068.s [new file with mode: 0644]
ld/testsuite/ld-elf/pr17068a.s [new file with mode: 0644]
ld/testsuite/ld-elf/pr17068b.s [new file with mode: 0644]
ld/testsuite/ld-elf/pr17068c.s [new file with mode: 0644]
ld/testsuite/ld-elf/pr17068d.s [new file with mode: 0644]
ld/testsuite/ld-elf/pr17068e.s [new file with mode: 0644]
ld/testsuite/ld-elf/pr17068ez.s [new file with mode: 0644]

index bfddd80..f7dd212 100644 (file)
@@ -1,3 +1,13 @@
+2014-07-03  Alan Modra  <amodra@gmail.com>
+
+       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.
+
 2014-07-01  Alan Modra  <amodra@gmail.com>
 
        * emultempl/ppc64elf.em (stub_added): Delete.
index 60877b8..5e10c4a 100644 (file)
@@ -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);
index 7d69c56..0f7fdd4 100644 (file)
@@ -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 */
 };
index 2a6d7c5..cd6ae60 100644 (file)
@@ -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);
 }
index beae7ab..1e239ca 100644 (file)
@@ -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 */
index b59f584..7d3a6e4 100644 (file)
@@ -1,3 +1,14 @@
+2014-07-03  Alan Modra  <amodra@gmail.com>
+
+       * 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.
+
 2014-07-02  Alan Modra  <amodra@gmail.com>
 
        * ld-powerpc/ambiguousv1.d: Match symbol table too.
index 4c8ca3a..839c931 100644 (file)
@@ -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 (file)
index 0000000..9675ab4
--- /dev/null
@@ -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 (file)
index 0000000..552697c
--- /dev/null
@@ -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 (file)
index 0000000..aa536f2
--- /dev/null
@@ -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 (file)
index 0000000..1d78f6d
--- /dev/null
@@ -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 (file)
index 0000000..6165128
--- /dev/null
@@ -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 (file)
index 0000000..095eb89
--- /dev/null
@@ -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 (file)
index 0000000..70e040d
--- /dev/null
@@ -0,0 +1,4 @@
+ .data
+ .globl e
+e:
+ .dc.a z