Index: gc.cc =================================================================== RCS file: /cvs/src/src/gold/gc.cc,v retrieving revision 1.1 diff -u -u -p -r1.1 gc.cc --- gc.cc 28 Jan 2009 02:25:33 -0000 1.1 +++ gc.cc 7 Jan 2010 00:46:50 -0000 @@ -1,6 +1,6 @@ // gc.cc -- garbage collection of unused sections -// Copyright 2009 Free Software Foundation, Inc. +// Copyright 2009, 2010 Free Software Foundation, Inc. // Written by Sriraman Tallam . // This file is part of gold. @@ -66,9 +66,40 @@ Garbage_collection::do_transitive_closur this->worklist().push(*it_v); } } + // Add the orphan sections referenced by this section. + Garbage_collection::Tracked_orphan_section_range key_range = + this->tracked_orphan_sections_.equal_range(entry); + Garbage_collection::Tracked_orphan_section_map::iterator it; + for (it = key_range.first; it != key_range.second; ++it) + { + std::string orphan_section_name = it->second; + Garbage_collection::Orphan_section_map::iterator ele = + this->orphan_sections_.find(orphan_section_name); + gold_assert (ele != this->orphan_sections_.end()); + Garbage_collection::Sections_reachable v = ele->second; + for (Garbage_collection::Sections_reachable::iterator it_v + = v.begin(); + it_v != v.end(); + ++it_v) + { + if (it_v->first == NULL) + continue; + this->worklist().push(*it_v); + } + } } this->worklist_ready(); } +void +Garbage_collection::track_orphan_section(Section_id secn, + std::string section_name) +{ + this->tracked_orphan_sections_.insert(std::make_pair(secn, section_name)); + if (this->orphan_sections_.find(section_name) + == this->orphan_sections_.end()) + this->orphan_sections_[section_name].insert(Section_id(NULL, 0)); +} + } // End namespace gold. Index: gc.h =================================================================== RCS file: /cvs/src/src/gold/gc.h,v retrieving revision 1.6 diff -u -u -p -r1.6 gc.h --- gc.h 4 Jan 2010 19:08:39 -0000 1.6 +++ gc.h 7 Jan 2010 00:46:50 -0000 @@ -60,6 +60,17 @@ class Garbage_collection typedef Unordered_set Sections_reachable; typedef std::map Section_ref; typedef std::queue Worklist_type; + // This maps a section to the name of the orphan section it references. + // A section can reference more than one orphan section. + typedef Unordered_multimap + Tracked_orphan_section_map; + typedef std::pair + Tracked_orphan_section_range; + // This maps the name of the orphan section to the list of sections that + // have that name. Different object files can have orphan sections with + // the same name. + typedef std::map Orphan_section_map; Garbage_collection() : is_worklist_ready_(false) @@ -94,12 +105,26 @@ class Garbage_collection is_section_garbage(Object* obj, unsigned int shndx) { return (this->referenced_list().find(Section_id(obj, shndx)) == this->referenced_list().end()); } + + void + track_orphan_section(Section_id secn, std::string section_name); + + Tracked_orphan_section_map& + tracked_orphan_sections() + { return tracked_orphan_sections_; } + + Orphan_section_map& + orphan_sections() + { return orphan_sections_; } + private: Worklist_type work_list_; bool is_worklist_ready_; Section_ref section_reloc_map_; Sections_reachable referenced_list_; + Tracked_orphan_section_map tracked_orphan_sections_; + Orphan_section_map orphan_sections_; }; // Data to pass between successive invocations of do_layout @@ -217,7 +242,23 @@ gc_process_relocs( dst_indx = gsym->shndx(&is_ordinary); if (!is_ordinary) continue; + Section_id src_id(src_obj, src_indx); Section_id dst_id(dst_obj, dst_indx); + // If the symbol name matches '__start_XXX' then the orphan + // section with the name 'XXX' should not be garbage collected. + // A similar treatment to symbols with the name '__stop_XXX'. + if (is_prefix_of("__start_", gsym->name())) + { + symtab->gc()->track_orphan_section(src_id, + std::string(gsym->name() + + strlen("__start_"))); + } + else if (is_prefix_of("__stop_", gsym->name())) + { + symtab->gc()->track_orphan_section(src_id, + std::string(gsym->name() + + strlen("__stop_"))); + } if (is_icf_tracked) { (*secvec).push_back(dst_id); Index: gold.cc =================================================================== RCS file: /cvs/src/src/gold/gold.cc,v retrieving revision 1.76 diff -u -u -p -r1.76 gold.cc --- gold.cc 6 Jan 2010 05:30:24 -0000 1.76 +++ gold.cc 7 Jan 2010 00:46:50 -0000 @@ -326,6 +326,7 @@ queue_middle_tasks(const General_options } // Symbols named with -u should not be considered garbage. symtab->gc_mark_undef_symbols(); + symtab->gc_update_orphan_sections(input_objects); gold_assert(symtab->gc() != NULL); // Do a transitive closure on all references to determine the worklist. symtab->gc()->do_transitive_closure(); Index: symtab.cc =================================================================== RCS file: /cvs/src/src/gold/symtab.cc,v retrieving revision 1.136 diff -u -u -p -r1.136 symtab.cc --- symtab.cc 5 Jan 2010 19:29:15 -0000 1.136 +++ symtab.cc 7 Jan 2010 00:46:50 -0000 @@ -524,6 +524,28 @@ Symbol_table::is_section_folded(Object* && this->icf_->is_section_folded(obj, shndx)); } +// Find the orphan sections that are tracked. + +void +Symbol_table::gc_update_orphan_sections(const Input_objects* input_objects) +{ + for (Input_objects::Relobj_iterator p = input_objects->relobj_begin(); + p != input_objects->relobj_end(); + ++p) + { + for (unsigned int i = 0;i < (*p)->shnum(); ++i) + { + std::string section_name = (*p)->section_name(i); + Garbage_collection::Orphan_section_map::iterator it = + this->gc_->orphan_sections().find(section_name); + if (it == this->gc_->orphan_sections().end()) + continue; + Garbage_collection::Sections_reachable& v(it->second); + v.insert(Section_id(*p, i)); + } + } +} + // For symbols that have been listed with -u option, add them to the // work list to avoid gc'ing them. Index: symtab.h =================================================================== RCS file: /cvs/src/src/gold/symtab.h,v retrieving revision 1.103 diff -u -u -p -r1.103 symtab.h --- symtab.h 31 Dec 2009 05:07:21 -0000 1.103 +++ symtab.h 7 Jan 2010 00:46:50 -0000 @@ -1,6 +1,6 @@ // symtab.h -- the gold symbol table -*- C++ -*- -// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. // Written by Ian Lance Taylor . // This file is part of gold. @@ -1230,6 +1230,9 @@ class Symbol_table gc() const { return this->gc_; } + void + gc_update_orphan_sections(const Input_objects* input_objects); + // During garbage collection, this keeps undefined symbols. void gc_mark_undef_symbols(); cvs diff: Diffing po cvs diff: Diffing testsuite Index: testsuite/Makefile.am =================================================================== RCS file: /cvs/src/src/gold/testsuite/Makefile.am,v retrieving revision 1.115 diff -u -u -p -r1.115 Makefile.am --- testsuite/Makefile.am 31 Dec 2009 05:07:22 -0000 1.115 +++ testsuite/Makefile.am 7 Jan 2010 00:46:51 -0000 @@ -139,6 +139,16 @@ gc_tls_test:gc_tls_test.o gcctestdir/ld gc_tls_test.stdout: gc_tls_test $(TEST_NM) -C gc_tls_test > gc_tls_test.stdout +check_SCRIPTS += gc_orphan_section_test.sh +check_DATA += gc_orphan_section_test.stdout +MOSTLYCLEANFILES += gc_orphan_section_test +gc_orphan_section_test.o: gc_orphan_section_test.cc + $(CXXCOMPILE) -O0 -c -g -o $@ $< +gc_orphan_section_test:gc_orphan_section_test.o gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -Wl,--gc-sections gc_orphan_section_test.o +gc_orphan_section_test.stdout: gc_orphan_section_test + $(TEST_NM) gc_orphan_section_test > gc_orphan_section_test.stdout + check_SCRIPTS += icf_test.sh check_DATA += icf_test.stdout MOSTLYCLEANFILES += icf_test Index: testsuite/gc_orphan_section_test.cc =================================================================== RCS file: testsuite/gc_orphan_section_test.cc diff -N testsuite/gc_orphan_section_test.cc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gc_orphan_section_test.cc 7 Jan 2010 00:46:51 -0000 @@ -0,0 +1,36 @@ +// gc_orphan_section_test.cc -- a test case for gold + +// Copyright 2010 Free Software Foundation, Inc. +// Written by Sriraman Tallam . + +// 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. + +// The goal of this program is to verify if garbage collection does not +// discard orphan sections when references to them through __start_XXX +// and __stop_XXX are present. Here section _foo must not be gc'ed but +// _boo should be gc'ed. + +extern const int *__start__foo; +int foo __attribute__((__section__("_foo"))) = 1; +int boo __attribute__((__section__("_boo"))) = 1; + +int main() +{ + return *__start__foo; +} + Index: testsuite/gc_orphan_section_test.sh =================================================================== RCS file: testsuite/gc_orphan_section_test.sh diff -N testsuite/gc_orphan_section_test.sh --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ testsuite/gc_orphan_section_test.sh 7 Jan 2010 00:46:51 -0000 @@ -0,0 +1,46 @@ +#!/bin/sh + +# gc_orphan_section_test.sh -- test --gc-sections + +# Copyright 2010 Free Software Foundation, Inc. +# Written by Sriraman Tallam . + +# 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. + +# The goal of this program is to verify if gc-sections works as expected +# with orphan sections. +# File gc_orphan_sections_test.cc is in this test. This program checks if +# the orphan sections are retained when they are referenced through +# __start_XXX and __stop_XXX symbols. + +check() +{ + if grep -q " boo" "$1" + then + echo "Garbage collection failed to collect boo" + exit 1 + fi + grep_foo=`grep -q " foo" $1` + if [ $? != 0 ]; + then + echo "Garbage collection should not discard foo" + exit 1 + fi +} + +check gc_orphan_section_test.stdout