From b9b2ae8bbf911b7762fe41ecbb5dbc64a8e2b5a7 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 14 Aug 2012 08:31:57 +0000 Subject: [PATCH] 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. * 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. --- gold/ChangeLog | 22 ++++++++++++++++++++ gold/layout.cc | 24 +++++++++++++++++++++- gold/layout.h | 5 +++++ gold/object.cc | 1 + gold/script-sections.cc | 31 +++++++++++++++++----------- gold/script-sections.h | 4 +++- gold/testsuite/Makefile.am | 10 +++++++++ gold/testsuite/Makefile.in | 16 +++++++++++---- gold/testsuite/pr14265.c | 20 ++++++++++++++++++ gold/testsuite/pr14265.sh | 40 ++++++++++++++++++++++++++++++++++++ gold/testsuite/pr14265.t | 23 +++++++++++++++++++++ ld/testsuite/ChangeLog | 8 ++++++++ ld/testsuite/ld-gc/gc.exp | 5 +++++ ld/testsuite/ld-gc/pr14265.c | 20 ++++++++++++++++++ ld/testsuite/ld-gc/pr14265.d | 13 ++++++++++++ ld/testsuite/ld-gc/pr14265.t | 22 ++++++++++++++++++++ 16 files changed, 246 insertions(+), 18 deletions(-) create mode 100644 gold/testsuite/pr14265.c create mode 100755 gold/testsuite/pr14265.sh create mode 100644 gold/testsuite/pr14265.t create mode 100644 ld/testsuite/ld-gc/pr14265.c create mode 100644 ld/testsuite/ld-gc/pr14265.d create mode 100644 ld/testsuite/ld-gc/pr14265.t diff --git a/gold/ChangeLog b/gold/ChangeLog index 70c15b79f8d..fd1952927e7 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,25 @@ +2012-08-14 Nick Clifton + + 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 * target.h (Target::output_section_name): New function. diff --git a/gold/layout.cc b/gold/layout.cc index 006afefc305..1e31ccef912 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -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' " diff --git a/gold/layout.h b/gold/layout.h index 4643e325d50..fe5c696f2a7 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -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&); diff --git a/gold/object.cc b/gold/object.cc index fc8533e817d..417ccfc7c49 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -1494,6 +1494,7 @@ Sized_relobj_file::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) { diff --git a/gold/script-sections.cc b/gold/script-sections.cc index f90c0b3752d..e5d3a93b2a1 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -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) { diff --git a/gold/script-sections.h b/gold/script-sections.h index 5b781524276..9ff44ea3d27 100644 --- a/gold/script-sections.h +++ b/gold/script-sections.h @@ -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. diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index b8b88e869d6..0e98e6ad32d 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -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 diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 48878278e17..a3a4506fab0 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -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 index 00000000000..6bb8f9aa16a --- /dev/null +++ b/gold/testsuite/pr14265.c @@ -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 index 00000000000..4e477b22a67 --- /dev/null +++ b/gold/testsuite/pr14265.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +# pr14265.sh -- test --gc-sections with KEEP + +# Copyright 2012 Free Software Foundation, Inc. +# Written by Nick Clifton + +# 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 index 00000000000..eec56e77299 --- /dev/null +++ b/gold/testsuite/pr14265.t @@ -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"); + diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 34edbe10efc..28c978c9416 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2012-08-14 Nick Clifton + + 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 * ld-mips-elf/export-class-call16-o32.dd: New test. diff --git a/ld/testsuite/ld-gc/gc.exp b/ld/testsuite/ld-gc/gc.exp index 7a59ad3365d..ddbbd519f1d 100644 --- a/ld/testsuite/ld-gc/gc.exp +++ b/ld/testsuite/ld-gc/gc.exp @@ -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 index 00000000000..6bb8f9aa16a --- /dev/null +++ b/ld/testsuite/ld-gc/pr14265.c @@ -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 index 00000000000..04af9825c1d --- /dev/null +++ b/ld/testsuite/ld-gc/pr14265.d @@ -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 index 00000000000..12a2d6715f4 --- /dev/null +++ b/ld/testsuite/ld-gc/pr14265.t @@ -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");