* gc.h (Garbage_collection::Cident_section_map): New typedef.
[external/binutils.git] / gold / gc.h
index f61a2f6..838b7db 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;