[PATCH][GOLD] Handle .ARM.exidx sections in garbage collection.

Doug Kwan (關振德) dougkwan@google.com
Tue Jan 12 01:16:00 GMT 2010


Hi

    Here is an updated patch.  I factored out the code for adding a
reference between two sections into a new method
Garbage_collection::add_reference and used it to avoid code
duplication.  I also changed the call to define_in_output_data as Ian
suggested.  Since this
now changes non-ARM code.  I also ran the tests on x86_64.

-Doug

2010-01-11  Doug Kwan  <dougkwan@google.com>

        * arm.cc (Arm_relobj::do_gc_process_relocs): New method.
        (Target_arm::do_finalize_sections): Define special EXIDX section
        symbols only if referenced.
        * gc.h (Garbage_collection::add_reference): New method.
        (gc_process_relocs): Use Garbage_collection::add_reference to avoid
        code duplication.
-------------- next part --------------
Index: gold/arm.cc
===================================================================
RCS file: /cvs/src/src/gold/arm.cc,v
retrieving revision 1.49
diff -u -u -p -r1.49 arm.cc
--- gold/arm.cc	9 Jan 2010 01:55:14 -0000	1.49
+++ gold/arm.cc	12 Jan 2010 00:59:41 -0000
@@ -1178,6 +1178,10 @@ class Arm_relobj : public Sized_relobj<3
   void
   do_read_symbols(Read_symbols_data* sd);
 
+  // Process relocs for garbage collection.
+  void
+  do_gc_process_relocs(Symbol_table*, Layout*, Read_relocs_data*);
+
  private:
   // List of stub tables.
   typedef std::vector<Stub_table<big_endian>*> Stub_table_list;
@@ -4235,6 +4239,44 @@ Arm_relobj<big_endian>::do_read_symbols(
     read_arm_attributes_section<big_endian>(this, sd); 
 }
 
+// Process relocations for garbage collection.  The ARM target uses .ARM.exidx
+// sections for unwinding.  These sections are referenced implicitly by 
+// text sections linked in the section headers.  If we ignore these implict
+// references, the .ARM.exidx sections and any .ARM.extab sections they use
+// will be garbage-collected incorrectly.  Hence we override the same function
+// in the base class to handle these implicit references.
+
+template<bool big_endian>
+void
+Arm_relobj<big_endian>::do_gc_process_relocs(Symbol_table* symtab,
+					     Layout* layout,
+					     Read_relocs_data* rd)
+{
+  // First, call base class method to process relocations in this object.
+  Sized_relobj<32, big_endian>::do_gc_process_relocs(symtab, layout, rd);
+
+  unsigned int shnum = this->shnum();
+  const unsigned int shdr_size = elfcpp::Elf_sizes<32>::shdr_size;
+  const unsigned char* pshdrs = this->get_view(this->elf_file()->shoff(),
+					       shnum * shdr_size,
+					       true, true);
+
+  // Scan section headers for sections of type SHT_ARM_EXIDX.  Add references
+  // to these from the linked text sections.
+  const unsigned char* ps = pshdrs + shdr_size;
+  for (unsigned int i = 1; i < shnum; ++i, ps += shdr_size)
+    {
+      elfcpp::Shdr<32, big_endian> shdr(ps);
+      if (shdr.get_sh_type() == elfcpp::SHT_ARM_EXIDX)
+	{
+	  // Found an .ARM.exidx section, add it to the set of reachable
+	  // sections from its linked text section.
+	  unsigned int text_shndx = this->adjust_shndx(shdr.get_sh_link());
+	  symtab->gc()->add_reference(this, text_shndx, this, i);
+	}
+    }
+}
+
 // Arm_dynobj methods.
 
 // Read the symbol information.
@@ -5081,12 +5123,12 @@ Target_arm<big_endian>::do_finalize_sect
 				    Symbol_table::PREDEFINED,
 				    exidx_section, 0, 0, elfcpp::STT_OBJECT,
 				    elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN, 0,
-				    false, false);
+				    false, true);
       symtab->define_in_output_data("__exidx_end", NULL,
 				    Symbol_table::PREDEFINED,
 				    exidx_section, 0, 0, elfcpp::STT_OBJECT,
 				    elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN, 0,
-				    true, false);
+				    true, true);
 
       // For the ARM target, we need to add a PT_ARM_EXIDX segment for
       // the .ARM.exidx section.
Index: gold/gc.h
===================================================================
RCS file: /cvs/src/src/gold/gc.h,v
retrieving revision 1.7
diff -u -u -p -r1.7 gc.h
--- gold/gc.h	7 Jan 2010 07:14:29 -0000	1.7
+++ gold/gc.h	12 Jan 2010 00:59:41 -0000
@@ -108,6 +108,21 @@ class Garbage_collection
 		     Section_id secn)
   { this->cident_sections_[section_name].insert(secn); }
 
+  // Add a reference from the SRC_SHNDX-th section of SRC_OBJECT to
+  // DST_SHNDX-th section of DST_OBJECT.
+  void
+  add_reference(Object* src_object, unsigned int src_shndx,
+		Object* dst_object, unsigned int dst_shndx)
+  {
+    Section_id src_id(src_object, src_shndx);
+    Section_id dst_id(dst_object, dst_shndx);
+    Section_ref::iterator p = this->section_reloc_map_.find(src_id);
+    if (p == this->section_reloc_map_.end())
+      this->section_reloc_map_[src_id].insert(dst_id);
+    else
+      p->second.insert(dst_id);
+  }
+
  private:
 
   Worklist_type work_list_;
@@ -261,25 +276,14 @@ gc_process_relocs(
         }
       if (parameters->options().gc_sections())
         {
-          Section_id src_id(src_obj, src_indx);
-          Section_id dst_id(dst_obj, dst_indx);
-          Garbage_collection::Section_ref::iterator map_it;
-          map_it = symtab->gc()->section_reloc_map().find(src_id);
-          if (map_it == symtab->gc()->section_reloc_map().end())
-            {
-              symtab->gc()->section_reloc_map()[src_id].insert(dst_id);
-            }
-          else
-            {
-              Garbage_collection::Sections_reachable& v(map_it->second);
-              v.insert(dst_id);
-            }
+	  symtab->gc()->add_reference(src_obj, src_indx, dst_obj, dst_indx);
           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;
+	      Section_id src_id(src_obj, src_indx);
               Garbage_collection::Sections_reachable&
                 v(symtab->gc()->section_reloc_map()[src_id]);
               Garbage_collection::Sections_reachable& cident_secn(ele->second);


More information about the Binutils mailing list