2010-06-25 Doug Kwan <dougkwan@google.com>
authorDoug Kwan <dougkwan@google.com>
Fri, 25 Jun 2010 00:37:40 +0000 (00:37 +0000)
committerDoug Kwan <dougkwan@google.com>
Fri, 25 Jun 2010 00:37:40 +0000 (00:37 +0000)
* 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.

gold/ChangeLog
gold/arm.cc
gold/icf.h
gold/target.h

index 304a4ae7c7f6fb57bd42147cd279dd0d66180779..50c1affb7f0d98bca1058f26f43420523b38aea7 100644 (file)
@@ -1,3 +1,18 @@
+2010-06-25  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.
+
 2010-06-21  Rafael Espindola  <espindola@google.com>
 
        * fileread.cc (Input_file::find_fie): New
index d9aa76795f920ba80e9c4c107fd40641aa17a7fd..d19d04c4bc25de52d934a254a9639bc765b0e8e1 100644 (file)
@@ -2109,6 +2109,23 @@ class Target_arm : public Sized_target<32, big_endian>
       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 to
+  // 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<32, big_endian>
                                        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<32, big_endian>
                                         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<32, big_endian>
                  || 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::unsupported_reloc_global(
             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 27bbbba0fe5f461dc73eea2e155985c02a842e3e..c968c9daa2219d4e778f4ef172bb4c33dddf743f 100644 (file)
@@ -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 a0ec0b3f60d145d399a648ac0b4159c1091426b7..9f9c4f9dfab7308603f35ac9da179fbdc168c483 100644 (file)
@@ -71,6 +71,20 @@ class Target
   can_check_for_function_pointers() const
   { return false; }
 
+  // Whether a section called SECTION_NAME may have function pointers to
+  // 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