* gc.h (Garbage_collection::Cident_section_map): New typedef.
authorSriraman Tallam <tmsriram@google.com>
Thu, 7 Jan 2010 07:14:30 +0000 (07:14 +0000)
committerSriraman Tallam <tmsriram@google.com>
Thu, 7 Jan 2010 07:14:30 +0000 (07:14 +0000)
(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.

gold/ChangeLog
gold/gc.h
gold/gold.h
gold/layout.cc
gold/object.cc
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/gc_orphan_section_test.cc [new file with mode: 0644]
gold/testsuite/gc_orphan_section_test.sh [new file with mode: 0755]

index b52505ff8d7acacda58fb806b69a5bae5743f1be..65c0c9035a261e49521c55c5cab0a3984e999af6 100644 (file)
@@ -1,3 +1,23 @@
+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.
+
 2010-01-06  Ian Lance Taylor  <iant@google.com>
 
        PR 10980
index f61a2f68136899178afe474352e5caa34ca8e7ce..838b7db48c336efe1d47f750d50c602de08efe8b 100644 (file)
--- a/gold/gc.h
+++ b/gold/gc.h
@@ -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 dc5a1c1b3521dc90e443ba9fde29dfdc07aee3ae..5c98de04684daf8d7f945be211c3f103e198859f 100644 (file)
@@ -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 char* str)
   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 f3deb9aa3e4b3d2cce47515e25aec45f331eefa3..f427af5079da3b61839caa04ebf76ca243718497 100644 (file)
@@ -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_table* symtab)
        ++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 3fedcf83cf9dd868ad802799ac670422f3e21cb1..89ff34ce6fbbf12d0b079f47a3a7b93c70b98598 100644 (file)
@@ -1180,6 +1180,14 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab,
             {
               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
index 7b5532ea1cd637f4d927da26a2680e0be69f0473..2bf5bbe6b0872755480aeafa1fc968895461fe73 100644 (file)
@@ -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 291eab77ceb58482aac74957a20082081b9e9af0..21fca3da2a337939317de32ca0308b06fcb5ba0d 100644 (file)
@@ -57,6 +57,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
 # and --dynamic-list-cpp-typeinfo
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_1 = 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@ icf_keep_unique_test.sh \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test.sh \
@@ -82,6 +83,7 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_2 = incremental_test.stdout \
 @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@ icf_keep_unique_test.stdout \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test.stdout \
@@ -103,7 +105,8 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ dynamic_list.stdout
 @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_3 = incremental_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_comdat_test gc_tls_test \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_test icf_keep_unique_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@ icf_safe_test \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.dbg \
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/weak_undef_lib.so
@@ -2582,6 +2585,12 @@ uninstall-am:
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--gc-sections gc_tls_test.o
 @GCC_TRUE@@NATIVE_LINKER_TRUE@gc_tls_test.stdout: gc_tls_test
 @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) -C gc_tls_test > gc_tls_test.stdout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@gc_orphan_section_test.o: gc_orphan_section_test.cc
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -g -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@gc_orphan_section_test:gc_orphan_section_test.o gcctestdir/ld
+@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@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/gc_orphan_section_test.cc b/gold/testsuite/gc_orphan_section_test.cc
new file mode 100644 (file)
index 0000000..3443f8d
--- /dev/null
@@ -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;
+}
+
diff --git a/gold/testsuite/gc_orphan_section_test.sh b/gold/testsuite/gc_orphan_section_test.sh
new file mode 100755 (executable)
index 0000000..6ce524d
--- /dev/null
@@ -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