static link with gold + gc-sections does not flush stdout buffer to file.
Sriraman Tallam
tmsriram@google.com
Thu Jan 7 07:16:00 GMT 2010
I made the changes and committed this patch.
2010-01-06 Sriraman Tallam <tmsriram@google.com>
* gc.h (Garbage_collection::Cident_section_map): New typedef.
(Garbage_collection::cident_sections): New function.
(Garbage_collection::add_cident_section): New function.
(Garbage_collection::cident_sections_): New member.
(gc_process_relocs): Add references to sections whose names are C
identifiers.
* gold.h (cident_section_start_prefix): New constant.
(cident_section_stop_prefix): New constant.
(is_cident): New function.
* layout.cc (Layout::define_section_symbols): Replace string constants
with the newly defined constants.
* object.cc (Sized_relobj::do_layout): Track sections whose names are
C identifiers.
* testsuite/Makefile.am: Add gc_orphan_section_test.
* testsuite/Makefile.in: Regenerate.
* testsuite/gc_orphan_section_test.cc: New file.
* testsuite/gc_orphan_section_test.sh: New file.
On Wed, Jan 6, 2010 at 9:26 PM, Ian Lance Taylor <iant@google.com> wrote:
> Sriraman Tallam <tmsriram@google.com> writes:
>
>> 2010-01-06 Sriraman Tallam <tmsriram@google.com>
>>
>> * gc.h (Garbage_collection::Cident_section_map): New typedef.
>> (Garbage_collection::cident_sections): New function.
>> (Garbage_collection::cident_sections_): New member.
>> (gc_process_relocs): Add references to sections whose names are C
>> identifiers.
>> * gold.cc (cident_section_start_prefix): New constant.
>> (cident_section_stop_prefix): New constant.
>> * gold.h (cident_section_start_prefix): New constant.
>> (cident_section_stop_prefix): New constant.
>> * layout.cc (Layout::define_section_symbols): Replace string constants
>> with the newly defined constants.
>> * object.cc (Sized_relobj::do_layout): Track sections whose names are
>> C identifiers.
>> * testsuite/Makefile.am: Add gc_orphan_section_test.
>> * testsuite/Makefile.in: Regenerate.
>> * testsuite/gc_orphan_section_test.cc: New file.
>> * testsuite/gc_orphan_section_test.sh: New file.
>
>
>> + Cident_section_map&
>> + cident_sections()
>> + { return cident_sections_; }
>
> I don't know if this is always followed, but the general rule should
> be that if a class returns a reference, it should be a const
> reference. Since code needs to modify this map, this should return a
> pointer, not a reference. Alternatively and probably preferably, you
> should write tiny functions which do the operations which need to be
> done on cident_sections_.
>
>
>> + if (cident_section_name)
>
> Write if (cident_section_name != NULL)
>
>> + {
>> + Garbage_collection::Sections_reachable&
>> + v(symtab->gc()->section_reloc_map()[src_id]);
>> + Garbage_collection::Cident_section_map::iterator ele =
>> + symtab->gc()->cident_sections().find(std::string(cident_section_name));
>> + if (ele == symtab->gc()->cident_sections().end())
>> + continue;
>> + Garbage_collection::Sections_reachable& cident_secn(ele->second);
>> + for (Garbage_collection::Sections_reachable::iterator it_v
>> + = cident_secn.begin();
>> + it_v != cident_secn.end();
>> + ++it_v)
>> + {
>> + v.insert(*it_v);
>> + }
>> + }
>
> Move the definition of v to below the continue statement.
>
>
>> 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 05:04:33 -0000
>> @@ -49,6 +49,8 @@ namespace gold
>> {
>>
>> const char* program_name;
>> +const char* cident_section_start_prefix = "__start_";
>> +const char* cident_section_stop_prefix = "__stop_";
>>
>> void
>> gold_exit(bool status)
>
> Move these to gold.h and write them as
>
> const char* const cident_section_start_prefix = "__start_";
> const char* const cident_section_stop_prefix = "__stop_";
>
>
>> + // If the section name XXX can be represented as a C identifier
>> + // it cannot be discarded if there are references to
>> + // __start_XXX and __stop_XXX symbols. These need to be
>> + // specially handled.
>> + if (is_cident(name))
>> + {
>> + Garbage_collection::Cident_section_map::iterator it =
>> + symtab->gc()->cident_sections().find(std::string(name));
>> + if (it == symtab->gc()->cident_sections().end())
>> + {
>> + symtab->gc()->cident_sections()[name].insert(
>> + Section_id(this, i));
>> + }
>> + else
>> + {
>> + Garbage_collection::Sections_reachable& v(it->second);
>> + v.insert(Section_id(this, i));
>> + }
>> + }
>
> This is a case where you are always going to insert, and you are
> always going to do the same thing if you do insert, so here I don't
> think it helps to do a find. I think you can just write
>
> symtab->gc()->cident_sections()[name].insert(Section_id(this, i));
>
> except it should probably be more like
>
> symtab->gc()->add_cident_section(name, this, i);
>
>
> This is OK with those changes.
>
> Thanks.
>
> Ian
>
-------------- next part --------------
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 07:12:01 -0000
@@ -60,6 +60,10 @@ class Garbage_collection
typedef Unordered_set<Section_id, Section_id_hash> Sections_reachable;
typedef std::map<Section_id, Sections_reachable> Section_ref;
typedef std::queue<Section_id> Worklist_type;
+ // This maps the name of the section which can be represented as a C
+ // identifier (cident) to the list of sections that have that name.
+ // Different object files can have cident sections with the same name.
+ typedef std::map<std::string, Sections_reachable> Cident_section_map;
Garbage_collection()
: is_worklist_ready_(false)
@@ -94,12 +98,23 @@ class Garbage_collection
is_section_garbage(Object* obj, unsigned int shndx)
{ return (this->referenced_list().find(Section_id(obj, shndx))
== this->referenced_list().end()); }
+
+ Cident_section_map*
+ cident_sections()
+ { return &cident_sections_; }
+
+ void
+ add_cident_section(std::string section_name,
+ Section_id secn)
+ { this->cident_sections_[section_name].insert(secn); }
+
private:
Worklist_type work_list_;
bool is_worklist_ready_;
Section_ref section_reloc_map_;
Sections_reachable referenced_list_;
+ Cident_section_map cident_sections_;
};
// Data to pass between successive invocations of do_layout
@@ -161,6 +176,7 @@ gc_process_relocs(
std::vector<Symbol*>* symvec = NULL;
std::vector<std::pair<long long, long long> >* addendvec = NULL;
bool is_icf_tracked = false;
+ const char* cident_section_name = NULL;
if (parameters->options().icf_enabled()
&& is_section_foldable_candidate(src_obj->section_name(src_indx).c_str()))
@@ -218,6 +234,19 @@ gc_process_relocs(
if (!is_ordinary)
continue;
Section_id dst_id(dst_obj, dst_indx);
+ // If the symbol name matches '__start_XXX' then the section with
+ // the C identifier like name 'XXX' should not be garbage collected.
+ // A similar treatment to symbols with the name '__stop_XXX'.
+ if (is_prefix_of(cident_section_start_prefix, gsym->name()))
+ {
+ cident_section_name = (gsym->name()
+ + strlen(cident_section_start_prefix));
+ }
+ else if (is_prefix_of(cident_section_stop_prefix, gsym->name()))
+ {
+ cident_section_name = (gsym->name()
+ + strlen(cident_section_stop_prefix));
+ }
if (is_icf_tracked)
{
(*secvec).push_back(dst_id);
@@ -245,6 +274,23 @@ gc_process_relocs(
Garbage_collection::Sections_reachable& v(map_it->second);
v.insert(dst_id);
}
+ if (cident_section_name != NULL)
+ {
+ Garbage_collection::Cident_section_map::iterator ele =
+ symtab->gc()->cident_sections()->find(std::string(cident_section_name));
+ if (ele == symtab->gc()->cident_sections()->end())
+ continue;
+ Garbage_collection::Sections_reachable&
+ v(symtab->gc()->section_reloc_map()[src_id]);
+ Garbage_collection::Sections_reachable& cident_secn(ele->second);
+ for (Garbage_collection::Sections_reachable::iterator it_v
+ = cident_secn.begin();
+ it_v != cident_secn.end();
+ ++it_v)
+ {
+ v.insert(*it_v);
+ }
+ }
}
}
return;
Index: gold.h
===================================================================
RCS file: /cvs/src/src/gold/gold.h,v
retrieving revision 1.41
diff -u -u -p -r1.41 gold.h
--- gold.h 21 Oct 2009 08:08:41 -0000 1.41
+++ gold.h 7 Jan 2010 07:12:01 -0000
@@ -1,6 +1,6 @@
// gold.h -- general definitions for gold -*- 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 <iant@google.com>.
// This file is part of gold.
@@ -349,6 +349,21 @@ is_prefix_of(const char* prefix, const c
return strncmp(prefix, str, strlen(prefix)) == 0;
}
+const char* const cident_section_start_prefix = "__start_";
+const char* const cident_section_stop_prefix = "__stop_";
+
+// Returns true if the name is a valid C identifier
+inline bool
+is_cident(const char* name)
+{
+ return (name[strspn(name,
+ ("0123456789"
+ "ABCDEFGHIJKLMNOPWRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "_"))]
+ == '\0');
+}
+
// We sometimes need to hash strings. Ideally we should use std::tr1::hash or
// __gnu_cxx::hash on some systems but there is no guarantee that either
// one is available. For portability, we define simple string hash functions.
Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.157
diff -u -u -p -r1.157 layout.cc
--- layout.cc 7 Jan 2010 06:05:23 -0000 1.157
+++ layout.cc 7 Jan 2010 07:12:01 -0000
@@ -1,6 +1,6 @@
// layout.cc -- lay out output file sections for gold
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
@@ -1232,16 +1232,13 @@ Layout::define_section_symbols(Symbol_ta
++p)
{
const char* const name = (*p)->name();
- if (name[strspn(name,
- ("0123456789"
- "ABCDEFGHIJKLMNOPWRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "_"))]
- == '\0')
+ if (is_cident(name))
{
const std::string name_string(name);
- const std::string start_name("__start_" + name_string);
- const std::string stop_name("__stop_" + name_string);
+ const std::string start_name(cident_section_start_prefix
+ + name_string);
+ const std::string stop_name(cident_section_stop_prefix
+ + name_string);
symtab->define_in_output_data(start_name.c_str(),
NULL, // version
Index: object.cc
===================================================================
RCS file: /cvs/src/src/gold/object.cc,v
retrieving revision 1.114
diff -u -u -p -r1.114 object.cc
--- object.cc 5 Jan 2010 21:52:51 -0000 1.114
+++ object.cc 7 Jan 2010 07:12:01 -0000
@@ -1180,6 +1180,14 @@ Sized_relobj<size, big_endian>::do_layou
{
symtab->gc()->worklist().push(Section_id(this, i));
}
+ // If the section name XXX can be represented as a C identifier
+ // it cannot be discarded if there are references to
+ // __start_XXX and __stop_XXX symbols. These need to be
+ // specially handled.
+ if (is_cident(name))
+ {
+ symtab->gc()->add_cident_section(name, Section_id(this, i));
+ }
}
// When doing a relocatable link we are going to copy input
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 07:12:01 -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 07:12:01 -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 <tmsriram@google.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.
+
+// 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 07:12:01 -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 <tmsriram@google.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.
+
+# 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
More information about the Binutils
mailing list