static link with gold + gc-sections does not flush stdout buffer to file.

Sriraman Tallam tmsriram@google.com
Thu Jan 7 02:32:00 GMT 2010


On Wed, Jan 6, 2010 at 5:48 PM, Ian Lance Taylor <iant@google.com> wrote:
> Sriraman Tallam <tmsriram@google.com> writes:
>
>> +      // Add the orphan sections referenced by this section.
>
> Orphan sections is GNU ld phrasing.  The sections are orphaned because
> they are not explicitly mentioned in the linker script.  In gold these
> sections should have a different name.
>
>
>> +      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());
>
> Remove space before parenthesis.
>
>> +          Garbage_collection::Sections_reachable v = ele->second;
>> +          for (Garbage_collection::Sections_reachable::iterator it_v
>> +               = v.begin();
>> +               it_v != v.end();
>> +               ++it_v)
>
> Indent "= v.begin();" two more spaces, I think.
>
>> +            {
>> +              if (it_v->first == NULL)
>> +                continue;
>> +              this->worklist().push(*it_v);
>> +            }
>> +        }
>
>
>
>> +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<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 a section to the name of the orphan section it references.
>> +  // A section can reference more than one orphan section.
>> +  typedef Unordered_multimap<Section_id, std::string, Section_id_hash>
>> +    Tracked_orphan_section_map;
>> +  typedef std::pair<Tracked_orphan_section_map::iterator,
>> +                    Tracked_orphan_section_map::iterator>
>> +    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<std::string, Sections_reachable> 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()))
>
> Let's make __start and __stop_ constants somewhere, rather than
> repeating them here and in layout.cc.
>
>> +            {
>> +              symtab->gc()->track_orphan_section(src_id,
>> +                                                 std::string(gsym->name()
>> +                                                 + strlen("__start_")));
>
> Use parentheses around the + expression so that the + is indented one space.
>
>> +            }
>> +          else if (is_prefix_of("__stop_", gsym->name()))
>> +            {
>> +              symtab->gc()->track_orphan_section(src_id,
>> +                                                 std::string(gsym->name()
>> +                                                 + strlen("__stop_")));
>
> Parentheses here too.
>
>
>> 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)
>
> Space after first semicolon.
>
>> +        {
>> +          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));
>> +        }
>> +    }
>> +}
>
> This loop is going to be very slow, because section_name() is a slow
> call.  This is not a good way to do this.
>
> For the case that matters, you can look for an output section with the
> name that matters.  Then you need to find all the input sections that
> are attached to that output section.  You can do this if you change
> Output_section::add_input_section to use the
> this->input_sections_.push_back line when you are garbage collecting

Thanks for the quick feed-back.

I am not sure I understand this. The output_sections are not assigned
in the first pass of do_layout and I need to find the orphaned
sections well before gc can start its transitive closure, right ?
add_input_section kicks in only after gc is finished and during when
do_layout is called the second time.

>
>
>> +
>>  // 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 <iant@google.com>.
>>
>>  // 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 <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 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 <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