PR ld/14265
authorNick Clifton <nickc@redhat.com>
Tue, 14 Aug 2012 08:31:57 +0000 (08:31 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 14 Aug 2012 08:31:57 +0000 (08:31 +0000)
* script-sections.cc (Sections_element::output_section_name): Add
keep return parameter.
(Output_section_element::match_name): Add keep return parameter.
Return the value of the keep_ member.
* script-sections.h (class Output_section): Update
output_section_name prototype.
* layout.cc (Layout::keep_input_section): New public member
function.
(Layout::choose_output_section): Pass keep parameter to
output_section_name.
* layout.h (class Layout): Add keep_input_section.
* object.cc (Sized_relobj_file::do_layout): Check for kept input
sections.
* testsuite/Makefile.am: Add a test.
* testsuite/Makefile.in: Regenerate.
* testsuite/pr14265.c: Source file for the test.
* testsuite/pr14265.t: Linker script for the test.
* testsuite/pr14265.sh: Shell script for the test.

* ld-gc/gc.exp: Add a new test.
* ld-gc/pr14265.c: Source file for the new test.
* ld-gc/pr14265.t: Linker script for the new test.
* ld-gc/pr14265.d: Expected symbol dump.

16 files changed:
gold/ChangeLog
gold/layout.cc
gold/layout.h
gold/object.cc
gold/script-sections.cc
gold/script-sections.h
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/pr14265.c [new file with mode: 0644]
gold/testsuite/pr14265.sh [new file with mode: 0755]
gold/testsuite/pr14265.t [new file with mode: 0644]
ld/testsuite/ChangeLog
ld/testsuite/ld-gc/gc.exp
ld/testsuite/ld-gc/pr14265.c [new file with mode: 0644]
ld/testsuite/ld-gc/pr14265.d [new file with mode: 0644]
ld/testsuite/ld-gc/pr14265.t [new file with mode: 0644]

index 70c15b79f8d7ddfa7683d4ca83217aa18874fa51..fd1952927e77e2f63e26a7390e375d6776871677 100644 (file)
@@ -1,3 +1,25 @@
+2012-08-14  Nick Clifton  <nickc@redhat.com>
+
+       PR ld/14265
+       * script-sections.cc (Sections_element::output_section_name): Add
+       keep return parameter.
+       (Output_section_element::match_name): Add keep return parameter.
+       Return the value of the keep_ member.
+       * script-sections.h (class Output_section): Update
+       output_section_name prototype.
+       * layout.cc (Layout::keep_input_section): New public member
+       function.
+       (Layout::choose_output_section): Pass keep parameter to
+       output_section_name.
+       * layout.h (class Layout): Add keep_input_section.
+       * object.cc (Sized_relobj_file::do_layout): Check for kept input
+       sections.
+       * testsuite/Makefile.am: Add a test.
+       * testsuite/Makefile.in: Regenerate.
+       * testsuite/pr14265.c: Source file for the test.
+       * testsuite/pr14265.t: Linker script for the test.
+       * testsuite/pr14265.sh: Shell script for the test.
+
 2012-08-14  Alan Modra  <amodra@gmail.com>
 
        * target.h (Target::output_section_name): New function.
index 006afefc305abf353c3d78d7e7f0a5bcce1ee753..1e31ccef9128642262fec474606ccd96df65f44c 100644 (file)
@@ -805,6 +805,26 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key,
     }
 }
 
+// Returns TRUE iff NAME (an input section from RELOBJ) will
+// be mapped to an output section that should be KEPT.
+
+bool
+Layout::keep_input_section(const Relobj* relobj, const char* name)
+{
+  if (! this->script_options_->saw_sections_clause())
+    return false;
+
+  Script_sections* ss = this->script_options_->script_sections();
+  const char* file_name = relobj == NULL ? NULL : relobj->name().c_str();
+  Output_section** output_section_slot;
+  Script_sections::Section_type script_section_type;
+  bool keep;
+
+  name = ss->output_section_name(file_name, name, &output_section_slot,
+                                &script_section_type, &keep);
+  return name != NULL && keep;
+}
+
 // Pick the output section to use for section NAME, in input file
 // RELOBJ, with type TYPE and flags FLAGS.  RELOBJ may be NULL for a
 // linker created section.  IS_INPUT_SECTION is true if we are
@@ -845,8 +865,10 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
       Output_section** output_section_slot;
       Script_sections::Section_type script_section_type;
       const char* orig_name = name;
+      bool keep;
       name = ss->output_section_name(file_name, name, &output_section_slot,
-                                    &script_section_type);
+                                    &script_section_type, &keep);
+
       if (name == NULL)
        {
          gold_debug(DEBUG_SCRIPT, _("Unable to create output section '%s' "
index 4643e325d5015358a9f6b1a004c5b3fda3984899..fe5c696f2a70e361b1a3d29cf472ee293b350929 100644 (file)
@@ -920,6 +920,11 @@ class Layout
   section_list() const
   { return this->section_list_; }
 
+  // Returns TRUE iff NAME (an input section from RELOBJ) will
+  // be mapped to an output section that should be KEPT.
+  bool
+  keep_input_section(const Relobj*, const char*);
+  
  private:
   Layout(const Layout&);
   Layout& operator=(const Layout&);
index fc8533e817d8799600d78d252662f62708c5bfc5..417ccfc7c4988247c735e26c23483e95027cdaf4 100644 (file)
@@ -1494,6 +1494,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
       if (is_gc_pass_one && parameters->options().gc_sections())
        {
          if (this->is_section_name_included(name)
+             || layout->keep_input_section (this, name)
              || shdr.get_sh_type() == elfcpp::SHT_INIT_ARRAY
              || shdr.get_sh_type() == elfcpp::SHT_FINI_ARRAY)
            {
index f90c0b3752d69054f5bd63163570fc10c55d8b50..e5d3a93b2a1aac6b5c09dbc66596b322c9b13cd3 100644 (file)
@@ -582,7 +582,7 @@ class Sections_element
   // Output_section_definition.
   virtual const char*
   output_section_name(const char*, const char*, Output_section***,
-                     Script_sections::Section_type*)
+                     Script_sections::Section_type*, bool*)
   { return NULL; }
 
   // Initialize OSP with an output section.
@@ -800,7 +800,7 @@ class Output_section_element
   // Return whether this element matches FILE_NAME and SECTION_NAME.
   // The only real implementation is in Output_section_element_input.
   virtual bool
-  match_name(const char*, const char*) const
+  match_name(const char*, const char*, bool *) const
   { return false; }
 
   // Set section addresses.  This includes applying assignments if the
@@ -1238,10 +1238,10 @@ class Output_section_element_input : public Output_section_element
     *dot_section = this->final_dot_section_;
   }
 
-  // See whether we match FILE_NAME and SECTION_NAME as an input
-  // section.
+  // See whether we match FILE_NAME and SECTION_NAME as an input section.
+  // If we do then also indicate whether the section should be KEPT.
   bool
-  match_name(const char* file_name, const char* section_name) const;
+  match_name(const char* file_name, const char* section_name, bool* keep) const;
 
   // Set the section address.
   void
@@ -1393,15 +1393,19 @@ Output_section_element_input::match_file_name(const char* file_name) const
   return true;
 }
 
-// See whether we match FILE_NAME and SECTION_NAME.
+// See whether we match FILE_NAME and SECTION_NAME.  If we do then
+// KEEP indicates whether the section should survive garbage collection.
 
 bool
 Output_section_element_input::match_name(const char* file_name,
-                                        const char* section_name) const
+                                        const char* section_name,
+                                        bool *keep) const
 {
   if (!this->match_file_name(file_name))
     return false;
 
+  *keep = this->keep_;
+
   // If there are no section name patterns, then we match.
   if (this->input_section_patterns_.empty())
     return true;
@@ -1861,7 +1865,8 @@ class Output_section_definition : public Sections_element
   // section name.
   const char*
   output_section_name(const char* file_name, const char* section_name,
-                     Output_section***, Script_sections::Section_type*);
+                     Output_section***, Script_sections::Section_type*,
+                     bool*);
 
   // Initialize OSP with an output section.
   void
@@ -2146,14 +2151,15 @@ Output_section_definition::output_section_name(
     const char* file_name,
     const char* section_name,
     Output_section*** slot,
-    Script_sections::Section_type* psection_type)
+    Script_sections::Section_type* psection_type,
+    bool* keep)
 {
   // Ask each element whether it matches NAME.
   for (Output_section_elements::const_iterator p = this->elements_.begin();
        p != this->elements_.end();
        ++p)
     {
-      if ((*p)->match_name(file_name, section_name))
+      if ((*p)->match_name(file_name, section_name, keep))
        {
          // We found a match for NAME, which means that it should go
          // into this output section.
@@ -3365,7 +3371,8 @@ Script_sections::output_section_name(
     const char* file_name,
     const char* section_name,
     Output_section*** output_section_slot,
-    Script_sections::Section_type* psection_type)
+    Script_sections::Section_type* psection_type,
+    bool* keep)
 {
   for (Sections_elements::const_iterator p = this->sections_elements_->begin();
        p != this->sections_elements_->end();
@@ -3373,7 +3380,7 @@ Script_sections::output_section_name(
     {
       const char* ret = (*p)->output_section_name(file_name, section_name,
                                                  output_section_slot,
-                                                 psection_type);
+                                                 psection_type, keep);
 
       if (ret != NULL)
        {
index 5b781524276a6b8d0ab1f38bf77f1829be66e363..9ff44ea3d27374fbfa6ea8630b659f6755380a60 100644 (file)
@@ -163,10 +163,12 @@ class Script_sections
   // PSCRIPT_SECTION_TYPE points to a location for returning the section
   // type specified in script.  This can be SCRIPT_SECTION_TYPE_NONE if
   // no type is specified.
+  // *KEEP indicates whether the section should survive garbage collection.
   const char*
   output_section_name(const char* file_name, const char* section_name,
                      Output_section*** output_section_slot,
-                     Section_type* pscript_section_type);
+                     Section_type* pscript_section_type,
+                     bool* keep);
 
   // Place a marker for an orphan output section into the SECTIONS
   // clause.
index b8b88e869d6c41c14f92b84879ce13d86f2009d8..0e98e6ad32d67ff03e93565ac5b71fe2834e3e03 100644 (file)
@@ -164,6 +164,16 @@ gc_orphan_section_test:gc_orphan_section_test.o gcctestdir/ld
 gc_orphan_section_test.stdout: gc_orphan_section_test
        $(TEST_NM) gc_orphan_section_test > gc_orphan_section_test.stdout
 
+check_SCRIPTS += pr14265.sh
+check_DATA += pr14265.stdout
+MOSTLYCLEANFILES += pr14265
+pr14265.o: pr14265.c
+       $(COMPILE) -O0 -c -o $@ $<
+pr14265: pr14265.o 
+       $(LINK) -Bgcctestdir/ -Wl,--gc-sections -T $(srcdir)/pr14265.t -o $@ $<
+pr14265.stdout: pr14265
+       $(TEST_NM) --format=bsd --numeric-sort $< > $@
+
 check_SCRIPTS += icf_test.sh
 check_DATA += icf_test.stdout
 MOSTLYCLEANFILES += icf_test
index 48878278e171d5f7bb2923ea98b765ab499a9640..a3a4506fab064cbfc79a664c3b1f35d9e140eb21 100644 (file)
@@ -76,7 +76,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_2 = incremental_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_comdat_test.sh gc_tls_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_orphan_section_test.sh \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_test.sh \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ pr14265.sh icf_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test.sh \
@@ -104,7 +104,7 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_comdat_test.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_tls_test.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_orphan_section_test.stdout \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_test.stdout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ pr14265.stdout icf_test.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test_1.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test_2.stdout \
@@ -118,8 +118,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_plt_shared.so debug_msg.err
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_4 = incremental_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_comdat_test gc_tls_test \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_orphan_section_test icf_test \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_orphan_section_test pr14265 \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_test icf_keep_unique_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test icf_safe_so_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ final_layout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_virtual_function_folding_test \
@@ -3661,6 +3661,8 @@ gc_tls_test.sh.log: gc_tls_test.sh
        @p='gc_tls_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 gc_orphan_section_test.sh.log: gc_orphan_section_test.sh
        @p='gc_orphan_section_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+pr14265.sh.log: pr14265.sh
+       @p='pr14265.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 icf_test.sh.log: icf_test.sh
        @p='icf_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 icf_keep_unique_test.sh.log: icf_keep_unique_test.sh
@@ -4272,6 +4274,12 @@ uninstall-am:
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--gc-sections gc_orphan_section_test.o
 @GCC_TRUE@@NATIVE_LINKER_TRUE@gc_orphan_section_test.stdout: gc_orphan_section_test
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) gc_orphan_section_test > gc_orphan_section_test.stdout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@pr14265.o: pr14265.c
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -O0 -c -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@pr14265: pr14265.o 
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -Wl,--gc-sections -T $(srcdir)/pr14265.t -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@pr14265.stdout: pr14265
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) --format=bsd --numeric-sort $< > $@
 @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_test.o: icf_test.cc 
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -g -o $@ $<
 @GCC_TRUE@@NATIVE_LINKER_TRUE@icf_test: icf_test.o gcctestdir/ld
diff --git a/gold/testsuite/pr14265.c b/gold/testsuite/pr14265.c
new file mode 100644 (file)
index 0000000..6bb8f9a
--- /dev/null
@@ -0,0 +1,20 @@
+int foo0 __attribute__((used,section(".foo0.0")));
+int foo1 __attribute__((used,section(".foo1.0")));
+int foo2 __attribute__((used,section(".foo2.0")));
+
+extern unsigned long    __foo0_start;
+extern unsigned long    __foo0_end;
+
+extern unsigned long    __foo1_start;
+extern unsigned long    __foo1_end;
+
+extern unsigned long    __foo2_start;
+extern unsigned long    __foo2_end;
+
+int
+main (void)
+{
+  return ((__foo0_end - __foo0_start) -
+         (__foo1_end - __foo1_start) -
+         (__foo2_end - __foo2_start));
+}
diff --git a/gold/testsuite/pr14265.sh b/gold/testsuite/pr14265.sh
new file mode 100755 (executable)
index 0000000..4e477b2
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+# pr14265.sh -- test --gc-sections with KEEP
+
+# Copyright 2012 Free Software Foundation, Inc.
+# Written by Nick Clifton  <nickc@redhat.com>
+
+# This file is part of gold.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+
+check()
+{
+    if ! grep -q "$2" "$1"
+    then
+        echo "Garbage collection failed to KEEP :"
+        echo "   $2"
+       exit 1
+    fi
+}
+
+check pr14265.stdout "foo1_start"
+check pr14265.stdout "foo1_end"
+check pr14265.stdout "foo2_start"
+check pr14265.stdout "foo2_end"
+
diff --git a/gold/testsuite/pr14265.t b/gold/testsuite/pr14265.t
new file mode 100644 (file)
index 0000000..eec56e7
--- /dev/null
@@ -0,0 +1,23 @@
+SECTIONS
+{
+    .text : { *(.text) }
+
+    __foo0_start = .;
+    .foo0 : { *(.foo0.*) }
+    __foo0_end = .;
+
+    __foo1_start = .;
+    .foo1 : { KEEP(*(.foo1.*)) }
+    __foo1_end = .;
+
+    .foo2 : {
+        __foo2_start = .;
+        KEEP(*(.foo2.*))
+        __foo2_end = .;
+    }
+}
+
+
+ASSERT (__foo1_start < __foo1_end, "foo1 not KEPT");
+ASSERT ((__foo1_end - __foo1_start) == (__foo2_end - __foo2_start),"foo2 not KEPT");
+
index 34edbe10efc3df9dd478efd67c63c21211815cfd..28c978c94160c7ed96259c4abdab64a1e9773861 100644 (file)
@@ -1,3 +1,11 @@
+2012-08-14  Nick Clifton  <nickc@redhat.com>
+
+       PR ld/14265
+       * ld-gc/gc.exp: Add a new test.
+       * ld-gc/pr14265.c: Source file for the new test.
+       * ld-gc/pr14265.t: Linker script for the new test.
+       * ld-gc/pr14265.d: Expected symbol dump.
+
 2012-08-13  Maciej W. Rozycki  <macro@codesourcery.com>
 
        * ld-mips-elf/export-class-call16-o32.dd: New test.
index 7a59ad3365dcf1c23848b540664e935509f85fc1..ddbbd519f1dd3041eb936a7cfe017d88ae6ac0b3 100644 (file)
@@ -131,3 +131,8 @@ if { [is_remote host] || [which $CC] != 0 } {
        ld_compile "$CC $CFLAGS $cflags" $srcdir/$subdir/pr13683.c tmpdir/pr13683.o
        run_dump_test "pr13683"
 }
+
+if { [is_remote host] || [which $CC] != 0 } {
+    ld_compile "$CC $CFLAGS $cflags" $srcdir/$subdir/pr14265.c tmpdir/pr14265.o
+    run_dump_test "pr14265"
+}
diff --git a/ld/testsuite/ld-gc/pr14265.c b/ld/testsuite/ld-gc/pr14265.c
new file mode 100644 (file)
index 0000000..6bb8f9a
--- /dev/null
@@ -0,0 +1,20 @@
+int foo0 __attribute__((used,section(".foo0.0")));
+int foo1 __attribute__((used,section(".foo1.0")));
+int foo2 __attribute__((used,section(".foo2.0")));
+
+extern unsigned long    __foo0_start;
+extern unsigned long    __foo0_end;
+
+extern unsigned long    __foo1_start;
+extern unsigned long    __foo1_end;
+
+extern unsigned long    __foo2_start;
+extern unsigned long    __foo2_end;
+
+int
+main (void)
+{
+  return ((__foo0_end - __foo0_start) -
+         (__foo1_end - __foo1_start) -
+         (__foo2_end - __foo2_start));
+}
diff --git a/ld/testsuite/ld-gc/pr14265.d b/ld/testsuite/ld-gc/pr14265.d
new file mode 100644 (file)
index 0000000..04af982
--- /dev/null
@@ -0,0 +1,13 @@
+#name: --gc-sections with KEEP
+#source: dummy.s
+#ld: --gc-sections -T pr14265.t -e 0 tmpdir/pr14265.o
+#nm: --format=bsd --numeric-sort
+
+#...
+[0-9a-f]+[     ]d[     ]_*foo1_start
+[0-9a-f]+[     ]D[     ]_*foo1
+[0-9a-f]+[     ]d[     ]_*foo1_end
+[0-9a-f]+[     ]d[     ]_*foo2_start
+[0-9a-f]+[     ]D[     ]_*foo2
+[0-9a-f]+[     ]d[     ]_*foo2_end
+#...
diff --git a/ld/testsuite/ld-gc/pr14265.t b/ld/testsuite/ld-gc/pr14265.t
new file mode 100644 (file)
index 0000000..12a2d67
--- /dev/null
@@ -0,0 +1,22 @@
+SECTIONS
+{
+    .text : { *(.text) }
+
+    __foo0_start = .;
+    .foo0 : { *(.foo0.*) }
+    __foo0_end = .;
+
+    __foo1_start = .;
+    .foo1 : { KEEP(*(.foo1.*)) }
+    __foo1_end = .;
+
+    .foo2 : {
+        __foo2_start = .;
+        KEEP(*(.foo2.*))
+        __foo2_end = .;
+    }
+    /DISCARD/ : { *(*) }
+}
+
+ASSERT (__foo1_start < __foo1_end, "foo1 not KEPT");
+ASSERT ((__foo1_end - __foo1_start) == (__foo2_end - __foo2_start),"foo2 not KEPT");