[GOLD][PATCH] Handle ARM relocations in safe ICF.

Doug Kwan (關振德) dougkwan@google.com
Wed Jun 23 18:49:00 GMT 2010


Hi,

   This patch adds code to handle relocations in safe ICF so that we
can fold more functions than just constructors and destructor.  I also
added code to exempt construction vtables.

-Doug


010-06-23  Doug Kwan  <dougkwan@google.com>

        * arm.cc (Target_arm::can_check_for_functions_pointers): Return true.
        (Target_arm::section_may_have_icf_unsafe_pointers): New method
        definition.
        (Target_arm::Scan::local_reloc_may_be_function_pointer,
        Target_arm::Scan::global_reloc_may_be_function_pointer): Implement
        target hook to detect function points.
        (Target_arm::Scan::possible_function_pointer_reloc): New method.
        * icf.h (Icf::check_section_for_function_pointers): Change type of
        parameter SECTION_NAME to const reference to std::string.  Use
        target hook to determine if section may have unsafe pointers.
        * target.h (Target::section_may_have_icf_unsafe_pointers): New
        method definition.
-------------- next part --------------
Index: gold/arm.cc
===================================================================
RCS file: /cvs/src/src/gold/arm.cc,v
retrieving revision 1.109
diff -u -u -p -r1.109 arm.cc
--- gold/arm.cc	16 Jun 2010 18:19:18 -0000	1.109
+++ gold/arm.cc	23 Jun 2010 17:37:21 -0000
@@ -2109,6 +2109,23 @@ class Target_arm : public Sized_target<3
       fix_cortex_a8_(false), cortex_a8_relocs_info_()
   { }
 
+  // Virtual function which is set to return true by a target if
+  // it can use relocation types to determine if a function's
+  // pointer is taken.
+  virtual bool
+  can_check_for_function_pointers() const
+  { return true; }
+
+  // Whether a section called SECTION_NAME may have function pointers that
+  // make pointed sections not eligible for safe ICF folding.
+  virtual bool
+  section_may_have_icf_unsafe_pointers(const char* section_name) const
+  {
+    return !is_prefix_of(".ARM.exidx", section_name)
+      && !is_prefix_of(".ARM.extab", section_name)
+      && Target::section_may_have_icf_unsafe_pointers(section_name);
+  }
+  
   // Whether we can use BLX.
   bool
   may_use_blx() const
@@ -2474,8 +2491,7 @@ class Target_arm : public Sized_target<3
   	          			Output_section* ,
 	          			const elfcpp::Rel<32, big_endian>& ,
 					unsigned int ,
- 	          			const elfcpp::Sym<32, big_endian>&)
-    { return false; }
+ 	          			const elfcpp::Sym<32, big_endian>&);
 
     inline bool
     global_reloc_may_be_function_pointer(Symbol_table* , Layout* , Target_arm* ,
@@ -2483,8 +2499,7 @@ class Target_arm : public Sized_target<3
 	           			 unsigned int ,
 	           			 Output_section* ,
 	           			 const elfcpp::Rel<32, big_endian>& ,
-					 unsigned int , Symbol*)
-    { return false; }
+					 unsigned int , Symbol*);
 
    private:
     static void
@@ -2515,6 +2530,9 @@ class Target_arm : public Sized_target<3
 		  || sym->is_preemptible()));
     }
 
+    inline bool
+    possible_function_pointer_reloc(unsigned int r_type);
+
     // Whether we have issued an error about a non-PIC compilation.
     bool issued_non_pic_error_;
   };
@@ -7688,6 +7706,72 @@ Target_arm<big_endian>::Scan::unsupporte
 	     object->name().c_str(), r_type, gsym->demangled_name().c_str());
 }
 
+template<bool big_endian>
+inline bool
+Target_arm<big_endian>::Scan::possible_function_pointer_reloc(
+    unsigned int r_type)
+{
+  switch (r_type)
+    {
+    case elfcpp::R_ARM_PC24:
+    case elfcpp::R_ARM_THM_CALL:
+    case elfcpp::R_ARM_PLT32:
+    case elfcpp::R_ARM_CALL:
+    case elfcpp::R_ARM_JUMP24:
+    case elfcpp::R_ARM_THM_JUMP24:
+    case elfcpp::R_ARM_SBREL31:
+    case elfcpp::R_ARM_PREL31:
+    case elfcpp::R_ARM_THM_JUMP19:
+    case elfcpp::R_ARM_THM_JUMP6:
+    case elfcpp::R_ARM_THM_JUMP11:
+    case elfcpp::R_ARM_THM_JUMP8:
+      // All the relocations above are branches except SBREL31 and PREL31.
+      return false;
+
+    default:
+      // Be conservative and assume this is a function pointer.
+      return true;
+    }
+}
+
+template<bool big_endian>
+inline bool
+Target_arm<big_endian>::Scan::local_reloc_may_be_function_pointer(
+  Symbol_table*,
+  Layout*,
+  Target_arm<big_endian>* target,
+  Sized_relobj<32, big_endian>*,
+  unsigned int,
+  Output_section*,
+  const elfcpp::Rel<32, big_endian>&,
+  unsigned int r_type,
+  const elfcpp::Sym<32, big_endian>&)
+{
+  r_type = target->get_real_reloc_type(r_type);
+  return possible_function_pointer_reloc(r_type);
+}
+
+template<bool big_endian>
+inline bool
+Target_arm<big_endian>::Scan::global_reloc_may_be_function_pointer(
+  Symbol_table*,
+  Layout*,
+  Target_arm<big_endian>* target,
+  Sized_relobj<32, big_endian>*,
+  unsigned int,
+  Output_section*,
+  const elfcpp::Rel<32, big_endian>&,
+  unsigned int r_type,
+  Symbol* gsym)
+{
+  // GOT is not a function.
+  if (strcmp(gsym->name(), "_GLOBAL_OFFSET_TABLE_") == 0)
+    return false;
+
+  r_type = target->get_real_reloc_type(r_type);
+  return possible_function_pointer_reloc(r_type);
+}
+
 // Scan a relocation for a global symbol.
 
 template<bool big_endian>
Index: gold/icf.h
===================================================================
RCS file: /cvs/src/src/gold/icf.h,v
retrieving revision 1.7
diff -u -u -p -r1.7 icf.h
--- gold/icf.h	4 Mar 2010 01:33:22 -0000	1.7
+++ gold/icf.h	23 Jun 2010 17:37:21 -0000
@@ -121,14 +121,13 @@ class Icf
   // corresponding to taken function pointers.  Ignores eh_frame
   // and vtable sections.
   inline bool
-  check_section_for_function_pointers(std::string section_name,
+  check_section_for_function_pointers(const std::string& section_name,
                                       Target* target)
   {
     return (parameters->options().icf_safe_folding()
 	    && target->can_check_for_function_pointers()
-            && !is_prefix_of(".rodata._ZTV", section_name.c_str())
-            && !is_prefix_of(".data.rel.ro._ZTV", section_name.c_str())
-            && !is_prefix_of(".eh_frame", section_name.c_str()));
+	    && target->section_may_have_icf_unsafe_pointers(
+	        section_name.c_str()));
   }
 
   // Returns a map of a section to info (Reloc_info) about its relocations.
Index: gold/target.h
===================================================================
RCS file: /cvs/src/src/gold/target.h,v
retrieving revision 1.48
diff -u -u -p -r1.48 target.h
--- gold/target.h	26 May 2010 03:33:59 -0000	1.48
+++ gold/target.h	23 Jun 2010 17:37:21 -0000
@@ -71,6 +71,20 @@ class Target
   can_check_for_function_pointers() const
   { return false; }
 
+  // Whether a section called SECTION_NAME may have function pointers that
+  // make pointed sections not eligible for safe ICF folding.
+  virtual bool
+  section_may_have_icf_unsafe_pointers(const char* section_name) const
+  {
+    // We recognize sections for normal vtables, construction vtables and
+    // EH frames.
+    return !is_prefix_of(".rodata._ZTV", section_name)
+      && !is_prefix_of(".data.rel.ro._ZTV", section_name)
+      && !is_prefix_of(".rodata._ZTC", section_name)
+      && !is_prefix_of(".data.rel.ro._ZTC", section_name)
+      && !is_prefix_of(".eh_frame", section_name);
+  }
+
   // Return the bit size that this target implements.  This should
   // return 32 or 64.
   int


More information about the Binutils mailing list