This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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 


> +
>  // 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]