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: [patch/rfc][pr17902] GC unused parts of mergeable sections


> While working on it I noticed how remarkably similar the code is to
> the existing merge map. I now think the merge map can be reused for
> this.

A version using the existing merge_map. It still needs cleanups and
tests, but it is probably better to do that after the other patches
are in.

Cheers,
Rafael
diff --git a/gold/gc.cc b/gold/gc.cc
index 843b2b8..2bf6472 100644
--- a/gold/gc.cc
+++ b/gold/gc.cc
@@ -25,10 +25,45 @@
 #include "object.h"
 #include "gc.h"
 #include "symtab.h"
+#include "merge.h"
 
 namespace gold
 {
 
+void Worklist::just_push(const Section_id &val) { this->work_list_.push(val); }
+
+void Worklist::push(const Section_id &val) {
+  this->work_list_.push(val);
+  Object *obj = val.first;
+  unsigned int shndx = val.second;
+  uint64_t flags = obj->section_flags(shndx);
+  gold_assert((flags & elfcpp::SHF_MERGE) == 0);
+}
+
+static void
+add_referenced_offset(Object *obj, unsigned int shndx, uint64_t offset) {
+  // FIXME: what is the safe way to do this cast?
+  Relobj* r_obj = static_cast<Relobj*>(obj);
+  Object_merge_map* object_merge_map = r_obj->get_or_create_merge_map();
+
+  // In the case of strings, findind the start and length  requires reading the
+  // contents, which requires decompression. To do that only once,
+  // we record only the reference offset here and computed the start and length
+  // do_add_input_section.
+  object_merge_map->add_reference(shndx, offset);
+}
+
+void Worklist::push(const Section_id &val, uint64_t offset) {
+  this->work_list_.push(val);
+  Object *obj = val.first;
+  unsigned int shndx = val.second;
+  uint64_t flags = obj->section_flags(shndx);
+  if ((flags & elfcpp::SHF_MERGE) == 0)
+    return;
+
+  add_referenced_offset(obj, shndx, offset);
+}
+
 // Garbage collection uses a worklist style algorithm to determine the 
 // transitive closure of all referenced sections.
 void 
@@ -63,11 +98,25 @@ Garbage_collection::do_transitive_closure()
           if (this->referenced_list().find(*it_v)
               == this->referenced_list().end())
             {
-              this->worklist().push(*it_v);   
+              this->worklist().just_push(*it_v);   
             }
         }
     }
   this->worklist_ready();
+  for (Sections_reachable::iterator I = this->referenced_list().begin(),
+                                    E = this->referenced_list().end();
+       I != E; ++I) {
+    Atom_reachable &atoms = this->atom_reloc_map()[*I];
+    for (Atom_reachable::iterator I2 = atoms.begin(), E2 = atoms.end();
+         I2 != E2; ++I2) {
+      const Atom &atom = *I2;
+      const Section_id id = atom.first;
+      Object* obj = id.first;
+      unsigned int sec_num = id.second;
+      uint64_t new_offset = atom.second;
+      add_referenced_offset(obj, sec_num, new_offset);
+    }
+  }
 }
 
 } // End namespace gold.
diff --git a/gold/gc.h b/gold/gc.h
index 2db7cb9..7effbe1 100644
--- a/gold/gc.h
+++ b/gold/gc.h
@@ -46,18 +46,49 @@ class Output_section;
 class General_options;
 class Layout;
 
+class Worklist
+{
+ public:
+  bool empty() const {
+    return work_list_.empty();
+  }
+  Section_id &front() {
+    return work_list_.front();
+  }
+  void pop() {
+    work_list_.pop();
+  }
+  void just_push(const Section_id& val);
+  void push(const Section_id& val);
+  void push(const Section_id& val, uint64_t offset);
+
+ private:
+  typedef std::queue<Section_id> Worklist_type;
+  Worklist_type work_list_;
+};
+
 class Garbage_collection
 {
  public:
 
   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;
 
+  typedef std::pair<Section_id, uint64_t> Atom;
+  struct Atom_hash {
+    size_t operator()(const Atom &a) const {
+      const Section_id &s = a.first;
+      return reinterpret_cast<uintptr_t>(s.first) ^ s.second ^ a.second;
+    }
+  };
+  typedef Unordered_set<Atom, Atom_hash> Atom_reachable;
+  typedef std::map<Section_id, Atom_reachable> Atom_ref;
+
   Garbage_collection()
   : is_worklist_ready_(false)
   { }
@@ -72,7 +103,11 @@ class Garbage_collection
   section_reloc_map()
   { return this->section_reloc_map_; }
 
-  Worklist_type&
+  Atom_ref&
+  atom_reloc_map()
+  { return this->atom_reloc_map_; }
+
+  Worklist&
   worklist()
   { return this->work_list_; }
 
@@ -116,13 +151,26 @@ class Garbage_collection
       p->second.insert(dst_id);
   }
 
+  void add_reference_to_merge_section(Object *src_object,
+                                      unsigned int src_shndx,
+                                      Object *dst_object,
+                                      unsigned int dst_shndx, uint64_t offset) {
+    add_reference(src_object, src_shndx, dst_object, dst_shndx);
+    Section_id src_id(src_object, src_shndx);
+    Section_id dst_id(dst_object, dst_shndx);
+    Atom atom(dst_id, offset);
+    this->atom_reloc_map_[src_id].insert(atom);
+  }
+
  private:
 
-  Worklist_type work_list_;
+  Worklist work_list_;
   bool is_worklist_ready_;
   Section_ref section_reloc_map_;
   Sections_reachable referenced_list_;
   Cident_section_map cident_sections_;
+
+  Atom_ref atom_reloc_map_;
 };
 
 // Data to pass between successive invocations of do_layout
@@ -238,6 +286,10 @@ gc_process_relocs(
       typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
       Address dst_off;
 
+      // If the relocation points to a section, this includes the addend.
+      // Otherwise it doesn't.
+      Address gc_ref_off;
+
       if (r_sym < local_count)
         {
           gold_assert(plocal_syms != NULL);
@@ -247,7 +299,10 @@ gc_process_relocs(
           bool is_ordinary;
 	  dst_indx = src_obj->adjust_sym_shndx(r_sym, dst_indx, &is_ordinary);
           dst_obj = src_obj;
-	  dst_off = lsym.get_st_value() + addend;
+	  gc_ref_off = dst_off = lsym.get_st_value();
+	  dst_off += addend;
+	  if (lsym.get_st_type() == elfcpp::STT_SECTION)
+	    gc_ref_off += addend;
 
           if (is_icf_tracked)
             {
@@ -299,6 +354,7 @@ gc_process_relocs(
               dst_indx = gsym->shndx(&is_ordinary);
             }
 	  dst_off = static_cast<const Sized_symbol<size>*>(gsym)->value();
+	  gc_ref_off = dst_off;
 	  dst_off += addend;
 
 	  // When doing safe folding, check to see if this relocation is that
@@ -351,7 +407,14 @@ gc_process_relocs(
         }
       if (parameters->options().gc_sections())
         {
-	  symtab->gc()->add_reference(src_obj, src_indx, dst_obj, dst_indx);
+	  Garbage_collection* gc = symtab->gc();
+	  uint64_t dst_flags = dst_obj->section_flags(dst_indx);
+	  if (dst_flags & elfcpp::SHF_MERGE)
+	    gc->add_reference_to_merge_section(src_obj, src_indx, dst_obj,
+					       dst_indx, gc_ref_off);
+	  else
+	    gc->add_reference(src_obj, src_indx, dst_obj, dst_indx);
+
 	  parameters->sized_target<size, big_endian>()
 	    ->gc_add_reference(symtab, src_obj, src_indx,
 			       dst_obj, dst_indx, dst_off);
diff --git a/gold/merge.cc b/gold/merge.cc
index 7a532cc..1d3b2b4 100644
--- a/gold/merge.cc
+++ b/gold/merge.cc
@@ -53,7 +53,7 @@ Object_merge_map::Input_merge_map::add_mapping(
 	  gold_assert(input_offset < entry.input_offset);
 	  gold_assert(input_offset_u + length
 		      <= static_cast<section_size_type>(entry.input_offset));
-	  this->sorted = false;
+	  this->sorted_ = false;
 	}
       else if (entry.input_offset + entry.length == input_offset_u
 	       && (output_offset == -1
@@ -72,6 +72,61 @@ Object_merge_map::Input_merge_map::add_mapping(
   this->entries.push_back(entry);
 }
 
+void
+Object_merge_map::Input_merge_map::add_reference(
+    section_offset_type input_offset) {
+  this->sorted_ = false;
+  Input_merge_entry entry;
+  entry.input_offset = input_offset;
+  entry.length = -1;
+  entry.output_offset = -1;
+  this->entries.push_back(entry);
+}
+
+void
+Object_merge_map::Input_merge_map::ensure_sorted() {
+  if (this->sorted_)
+    return;
+  std::sort(this->entries.begin(), this->entries.end(), Input_merge_less());
+  this->sorted_ = true;
+}
+
+void
+Object_merge_map::Input_merge_map::unique() {
+  ensure_sorted();
+  Entries::iterator I = std::unique(this->entries.begin(), this->entries.end(),
+                                    Input_merge_same_offset());
+  entries.erase(I, entries.end());
+}
+
+bool
+Object_merge_map::Input_merge_map::get_output_offset(
+    section_offset_type input_offset, section_offset_type *output_offset) {
+  this->ensure_sorted();
+
+  Input_merge_entry entry;
+  entry.input_offset = input_offset;
+  std::vector<Input_merge_entry>::const_iterator p =
+    std::lower_bound(this->entries.begin(), this->entries.end(),
+		     entry, Input_merge_less());
+  if (p == this->entries.end() || p->input_offset > input_offset)
+    {
+      if (p == this->entries.begin())
+	return false;
+      --p;
+      gold_assert(p->input_offset <= input_offset);
+    }
+
+  if (input_offset - p->input_offset
+      >= static_cast<section_offset_type>(p->length))
+    return false;
+
+  *output_offset = p->output_offset;
+  if (*output_offset != -1)
+    *output_offset += (input_offset - p->input_offset);
+  return true;
+}
+
 // Destructor.
 
 Object_merge_map::~Object_merge_map()
@@ -136,6 +191,12 @@ Object_merge_map::add_mapping(unsigned int shndx,
   map->add_mapping(input_offset, length, output_offset);
 }
 
+void Object_merge_map::add_reference(unsigned int shndx,
+                                     section_offset_type input_offset) {
+  Input_merge_map* map = this->get_or_make_input_merge_map(shndx);
+  map->add_reference(input_offset);
+}
+
 // Get the output offset for an input address.
 
 bool
@@ -147,34 +208,7 @@ Object_merge_map::get_output_offset(unsigned int shndx,
   if (map == NULL)
     return false;
 
-  if (!map->sorted)
-    {
-      std::sort(map->entries.begin(), map->entries.end(),
-		Input_merge_compare());
-      map->sorted = true;
-    }
-
-  Input_merge_entry entry;
-  entry.input_offset = input_offset;
-  std::vector<Input_merge_entry>::const_iterator p =
-    std::lower_bound(map->entries.begin(), map->entries.end(),
-		     entry, Input_merge_compare());
-  if (p == map->entries.end() || p->input_offset > input_offset)
-    {
-      if (p == map->entries.begin())
-	return false;
-      --p;
-      gold_assert(p->input_offset <= input_offset);
-    }
-
-  if (input_offset - p->input_offset
-      >= static_cast<section_offset_type>(p->length))
-    return false;
-
-  *output_offset = p->output_offset;
-  if (*output_offset != -1)
-    *output_offset += (input_offset - p->input_offset);
-  return true;
+  return map->get_output_offset(input_offset, output_offset);
 }
 
 // Initialize a mapping from input offsets to output addresses.
@@ -349,9 +383,42 @@ Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
   Object_merge_map* merge_map = object->get_or_create_merge_map();
   Object_merge_map::Input_merge_map* input_merge_map =
     merge_map->get_or_make_input_merge_map(shndx);
+  uint64_t flags = object->section_flags(shndx);
+
+  bool gc = parameters->options().gc_sections() && (flags & elfcpp::SHF_ALLOC);
+  Object_merge_map::Input_merge_map::Entries &entries =
+      input_merge_map->entries;
+
+  if (gc) {
+    for (Object_merge_map::Input_merge_map::Entries::iterator
+             I = entries.begin(),
+             E = entries.end();
+         I != E; ++I) {
+      I->input_offset &= ~(entsize - 1);
+      I->length = entsize;
+    }
+
+    input_merge_map->unique();
+  }
 
-  for (section_size_type i = 0; i < len; i += entsize, p += entsize)
+  Object_merge_map::Input_merge_map::Entries::iterator entry_i =
+    entries.begin();
+  Object_merge_map::Input_merge_map::Entries::iterator entry_e =
+    entries.end();
+
+  section_offset_type len_u = len;
+  for (section_offset_type i = 0; i < len_u; i += entsize, p += entsize)
     {
+      if (gc)
+        {
+          while (entry_i != entry_e && entry_i->input_offset < i)
+            ++entry_i;
+          if (entry_i == entry_e)
+            break;
+          if (entry_i->input_offset != i)
+            continue;
+        }
+
       // Add the constant to the section contents.  If we find that it
       // is already in the hash table, we will remove it again.
       Merge_data_key k = this->len_;
@@ -368,7 +435,15 @@ Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
 	}
 
       // Record the offset of this constant in the output section.
-      input_merge_map->add_mapping(i, entsize, k);
+      if (gc)
+        {
+          entry_i->length = entsize;
+          entry_i->output_offset = k;
+        }
+      else
+        {
+          input_merge_map->add_mapping(i, entsize, k);
+        }
     }
 
   // For script processing, we keep the input sections.
@@ -483,6 +558,31 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
     ++count;
   merged_strings.reserve(count + 1);
 
+  Object_merge_map* merge_map = object->get_or_create_merge_map();
+  Object_merge_map::Input_merge_map* input_merge_map =
+    merge_map->get_or_make_input_merge_map(shndx);
+
+  uint64_t flags = object->section_flags(shndx);
+  bool gc = parameters->options().gc_sections() && (flags & elfcpp::SHF_ALLOC);
+  Object_merge_map::Input_merge_map::Entries &entries =
+      input_merge_map->entries;
+
+  if (gc) {
+    for (Object_merge_map::Input_merge_map::Entries::iterator
+             I = entries.begin(),
+             E = entries.end();
+         I != E; ++I) {
+      section_offset_type start_offset = I->input_offset;
+      while (start_offset > 0 && pdata[start_offset - 1] != 0)
+        --start_offset;
+      I->input_offset = start_offset;
+
+      I->length = (string_length(&pdata[start_offset]) + 1) * sizeof(Char_type);
+    }
+
+    input_merge_map->unique();
+  }
+
   // The index I is in bytes, not characters.
   section_size_type i = 0;
 
@@ -503,10 +603,12 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
 	      != init_align_modulo))
 	  has_misaligned_strings = true;
 
-      Stringpool::Key key;
-      this->stringpool_.add_with_length(p, len, true, &key);
+      if (object->is_offset_referenced(shndx, i)) {
+        Stringpool::Key key;
+        this->stringpool_.add_with_length(p, len, true, &key);
 
-      merged_strings.push_back(Merged_string(i, key));
+        merged_strings.push_back(Merged_string(i, key));
+      }
       p += len + 1;
       i += (len + 1) * sizeof(Char_type);
     }
@@ -552,8 +654,20 @@ Output_merge_string<Char_type>::finalize_merged_data()
       section_offset_type last_output_offset = 0;
       Relobj *object = (*l)->object;
       Object_merge_map* merge_map = object->get_or_create_merge_map();
+      unsigned shndx = (*l)->shndx;
       Object_merge_map::Input_merge_map* input_merge_map =
-        merge_map->get_or_make_input_merge_map((*l)->shndx);
+        merge_map->get_or_make_input_merge_map(shndx);
+
+      uint64_t flags = object->section_flags(shndx);
+      bool gc =
+          parameters->options().gc_sections() && (flags & elfcpp::SHF_ALLOC);
+      Object_merge_map::Input_merge_map::Entries &entries =
+        input_merge_map->entries;
+
+      Object_merge_map::Input_merge_map::Entries::iterator entry_i =
+        entries.begin();
+      Object_merge_map::Input_merge_map::Entries::iterator entry_e =
+        entries.end();
 
       for (typename Merged_strings::const_iterator p =
 	     (*l)->merged_strings.begin();
@@ -561,9 +675,20 @@ Output_merge_string<Char_type>::finalize_merged_data()
 	   ++p)
 	{
 	  section_size_type length = p->offset - last_input_offset;
-	  if (length > 0)
-            input_merge_map->add_mapping(last_input_offset, length,
-                                         last_output_offset);
+	  if (length > 0) {
+	    if (gc) {
+              while (entry_i != entry_e &&
+                     entry_i->input_offset < last_input_offset)
+                ++entry_i;
+	      if (entry_i == entry_e)
+		break;
+	      if (entry_i->input_offset == last_input_offset)
+		entry_i->output_offset = last_output_offset;
+	    } else {
+	      input_merge_map->add_mapping(last_input_offset, length,
+					   last_output_offset);
+	    }
+	  }
           last_input_offset = p->offset;
 	  if (p->stringpool_key != 0)
 	    last_output_offset =
diff --git a/gold/merge.h b/gold/merge.h
index 56c084a..aaa3f5a 100644
--- a/gold/merge.h
+++ b/gold/merge.h
@@ -58,6 +58,9 @@ class Object_merge_map
   add_mapping(unsigned int shndx, section_offset_type offset,
 	      section_size_type length, section_offset_type output_offset);
 
+  void
+  add_reference(unsigned int shndx, section_offset_type offset);
+
   // Get the output offset for an input address.  MERGE_MAP is the map
   // we are looking for, or NULL if we don't care.  The input address
   // is at offset OFFSET in section SHNDX.  This sets *OUTPUT_OFFSET
@@ -97,19 +100,31 @@ class Object_merge_map
   // A list of entries for a particular input section.
   struct Input_merge_map
   {
-    void add_mapping(section_offset_type input_offset, section_size_type length,
-                     section_offset_type output_offset);
+    void
+    add_mapping(section_offset_type input_offset, section_size_type length,
+                section_offset_type output_offset);
+
+    void
+    add_reference(section_offset_type input_offset);
+
+    bool
+    get_output_offset(section_offset_type input_offset,
+                      section_offset_type *output_offset);
 
     typedef std::vector<Input_merge_entry> Entries;
 
     // The list of mappings.
     Entries entries;
-    // Whether the ENTRIES field is sorted by input_offset.
-    bool sorted;
 
     Input_merge_map()
-      : entries(), sorted(true)
+      : entries(), sorted_(true)
     { }
+
+    void unique();
+    void ensure_sorted();
+    private:
+    // Whether the ENTRIES field is sorted by input_offset.
+    bool sorted_;
   };
 
   // Get or make the Input_merge_map to use for the section SHNDX
@@ -119,13 +134,20 @@ class Object_merge_map
 
   private:
   // A less-than comparison routine for Input_merge_entry.
-  struct Input_merge_compare
+  struct Input_merge_less
   {
     bool
     operator()(const Input_merge_entry& i1, const Input_merge_entry& i2) const
     { return i1.input_offset < i2.input_offset; }
   };
 
+  struct Input_merge_same_offset
+  {
+    bool
+    operator()(const Input_merge_entry& i1, const Input_merge_entry& i2) const
+    { return i1.input_offset == i2.input_offset; }
+  };
+
   // Map input section indices to merge maps.
   typedef std::map<unsigned int, Input_merge_map*> Section_merge_maps;
 
diff --git a/gold/object.cc b/gold/object.cc
index c3eaf77..287a6e3 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -386,6 +386,23 @@ Relobj::finalize_incremental_relocs(Layout* layout, bool clear_counts)
   layout->incremental_inputs()->set_reloc_count(rindex);
 }
 
+bool Relobj::is_offset_referenced(unsigned int shndx, uint64_t offset) {
+  if (!parameters->options().gc_sections())
+    return true;
+
+  uint64_t flags = this->section_flags(shndx);
+  // We don't gc non alloc sections.
+  if ((flags & elfcpp::SHF_ALLOC) == 0)
+    return true;
+
+  // Only SHF_MERGE sections are partially gced.
+  if ((flags & elfcpp::SHF_MERGE) == 0)
+    return true;
+
+  section_offset_type output_offset;
+  return this->merge_output_offset(shndx, offset, &output_offset);
+}
+
 Object_merge_map*
 Relobj::get_or_create_merge_map()
 {
@@ -2180,7 +2197,9 @@ Sized_relobj_file<size, big_endian>::do_count_local_symbols(Stringpool* pool,
 
       // Decide whether this symbol should go into the output file.
 
-      if ((shndx < shnum && out_sections[shndx] == NULL)
+      if ((shndx < shnum
+	   && (out_sections[shndx] == NULL ||
+	       !this->is_offset_referenced(shndx, sym.get_st_value())))
 	  || shndx == this->discarded_eh_frame_shndx_)
 	{
 	  lv.set_no_output_symtab_entry();
@@ -2251,6 +2270,9 @@ Sized_relobj_file<size, big_endian>::do_count_local_symbols(Stringpool* pool,
 	  continue;
 	}
 
+      // FIXME: explain
+      lv.set_must_have_output_symtab_entry();
+
       // Add the symbol to the symbol table string pool.
       pool->add(name, true, NULL);
       ++count;
@@ -2353,6 +2375,9 @@ Sized_relobj_file<size, big_endian>::compute_final_local_value_internal(
 	    }
 	  else if (!lv_in->is_section_symbol())
 	    {
+              if (!lv_in->will_have_output_symtab_entry())
+                return This::CFLV_DISCARDED;
+
 	      // This is not a section symbol.  We can determine
 	      // the final value now.
 	      lv_out->set_output_value(
@@ -2615,7 +2640,7 @@ Sized_relobj_file<size, big_endian>::write_local_symbols(
     dyn_oview = of->get_output_view(this->local_dynsym_offset_,
 				    dyn_output_size);
 
-  const Output_sections out_sections(this->output_sections());
+  const Output_sections& out_sections(this->output_sections());
 
   gold_assert(this->local_values_.size() == loccount);
 
diff --git a/gold/object.h b/gold/object.h
index 167513b..4b2b676 100644
--- a/gold/object.h
+++ b/gold/object.h
@@ -323,6 +323,8 @@ class Object
 {
  public:
   typedef std::vector<Symbol*> Symbols;
+  typedef std::vector<uint64_t> Offsets_reachable;
+  typedef std::map<unsigned int, Offsets_reachable> Offset_ref;
 
   // NAME is the name of the object as we would report it to the user
   // (e.g., libfoo.a(bar.o) if this is in an archive.  INPUT_FILE is
@@ -1260,6 +1262,9 @@ class Relobj : public Object
   is_big_endian() const
   { return this->do_is_big_endian(); }
 
+  bool
+  is_offset_referenced(unsigned int shndx, uint64_t offset);
+
  protected:
   // The output section to be used for each input section, indexed by
   // the input section number.  The output section is NULL if the
@@ -1666,6 +1671,17 @@ class Symbol_value
     return this->output_symtab_index_ != -1U;
   }
 
+  bool
+  will_have_output_symtab_entry() const
+  {
+    // 0       -> we don't know if it will be in the symtab
+    // -1      -> it will not be in the symtab.
+    // -2      -> it will be in the symtab but we don't know where.
+    // other I -> it will be in the symtab at index I
+    gold_assert(this->output_symtab_index_ != 0);
+    return this->output_symtab_index_ != -1U;
+  }
+
   // Return the index in the output symbol table.
   unsigned int
   output_symtab_index() const
diff --git a/gold/symtab.cc b/gold/symtab.cc
index 045327a..435ee5d 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -637,8 +637,9 @@ Symbol_table::gc_mark_undef_symbols(Layout* layout)
     }
 }
 
+template<int size>
 void
-Symbol_table::gc_mark_symbol(Symbol* sym)
+Symbol_table::gc_mark_sized_symbol(Sized_symbol<size>* sym)
 {
   // Add the object and section to the work list.
   bool is_ordinary;
@@ -646,11 +647,22 @@ Symbol_table::gc_mark_symbol(Symbol* sym)
   if (is_ordinary && shndx != elfcpp::SHN_UNDEF)
     {
       gold_assert(this->gc_!= NULL);
-      this->gc_->worklist().push(Section_id(sym->object(), shndx));
+      this->gc_->worklist().push(Section_id(sym->object(), shndx),
+                                 sym->value());
     }
   parameters->target().gc_mark_symbol(this, sym);
 }
 
+void
+Symbol_table::gc_mark_symbol(Symbol* sym)
+{
+  const int size = parameters->target().get_size();
+  if (size == 32)
+    gc_mark_sized_symbol(this->get_sized_symbol<32>(sym));
+  else
+    gc_mark_sized_symbol(this->get_sized_symbol<64>(sym));
+}
+
 // When doing garbage collection, keep symbols that have been seen in
 // dynamic objects.
 inline void 
diff --git a/gold/symtab.h b/gold/symtab.h
index aa0cb68..5f245c6 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -1387,6 +1387,10 @@ class Symbol_table
   gc_mark_undef_symbols(Layout*);
 
   // This tells garbage collection that this symbol is referenced.
+  template<int size>
+  void
+  gc_mark_sized_symbol(Sized_symbol<size>* sym);
+
   void
   gc_mark_symbol(Symbol* sym);
 

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