* i386.cc (Target_i386::can_check_for_function_pointers): New function.
authorSriraman Tallam <tmsriram@google.com>
Thu, 4 Mar 2010 01:33:22 +0000 (01:33 +0000)
committerSriraman Tallam <tmsriram@google.com>
Thu, 4 Mar 2010 01:33:22 +0000 (01:33 +0000)
(Scan::possible_function_pointer_reloc): New function.
(Scan::local_reloc_may_be_function_pointer): Change to call
possible_function_pointer_reloc.
(Scan::global_reloc_may_be_function_pointer): Ditto.
* icf.h (Icf::check_section_for_function_pointers): Change to reject
relocations in ".data.rel.ro._ZTV" section.
* testsuite/icf_safe_so_test.sh: Change to pass i386.
* testsuite/icf_safe_so_test.cc: Ditto.
* testsuite/icf_safe_test.cc: Ditto.
* testsuite/icf_safe_test.sh: Ditto.

gold/ChangeLog
gold/i386.cc
gold/icf.h
gold/testsuite/icf_safe_so_test.cc
gold/testsuite/icf_safe_so_test.sh
gold/testsuite/icf_safe_test.cc
gold/testsuite/icf_safe_test.sh

index 2610909..33b7307 100644 (file)
@@ -1,3 +1,17 @@
+2010-03-03  Sriraman Tallam  <tmsriram@google.com>
+
+       * i386.cc (Target_i386::can_check_for_function_pointers): New function.
+       (Scan::possible_function_pointer_reloc): New function.
+       (Scan::local_reloc_may_be_function_pointer): Change to call
+       possible_function_pointer_reloc.
+       (Scan::global_reloc_may_be_function_pointer): Ditto.
+       * icf.h (Icf::check_section_for_function_pointers): Change to reject
+       relocations in ".data.rel.ro._ZTV" section.
+       * testsuite/icf_safe_so_test.sh: Change to pass i386.
+       * testsuite/icf_safe_so_test.cc: Ditto.
+       * testsuite/icf_safe_test.cc: Ditto.
+       * testsuite/icf_safe_test.sh: Ditto.
+
 2010-03-03  Viktor Kutuzov  <vkutuzov@accesssoftek.com>
            Ian Lance Taylor  <iant@google.com>
 
index eb4ef0a..e7b700c 100644 (file)
@@ -64,6 +64,10 @@ class Target_i386 : public Target_freebsd<32, false>
       got_mod_index_offset_(-1U), tls_base_symbol_defined_(false)
   { }
 
+  inline bool
+  can_check_for_function_pointers() const
+  { return true; }
+
   // Process the relocations to determine unreferenced sections for 
   // garbage collection.
   void
@@ -203,24 +207,27 @@ class Target_i386 : public Target_freebsd<32, false>
           Symbol* gsym);
 
     inline bool
-    local_reloc_may_be_function_pointer(Symbol_table* , Layout* , Target_i386* ,
-                                       Sized_relobj<32, false>* ,
-                                       unsigned int ,
-                                       Output_section* ,
-                                       const elfcpp::Rel<32, false>& ,
-                                       unsigned int ,
-                                       const elfcpp::Sym<32, false>&)
-    { return false; }
+    local_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
+                                       Target_i386* target,
+                                       Sized_relobj<32, false>* object,
+                                       unsigned int data_shndx,
+                                       Output_section* output_section,
+                                       const elfcpp::Rel<32, false>& reloc,
+                                       unsigned int r_type,
+                                       const elfcpp::Sym<32, false>& lsym);
+
+    inline bool
+    global_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
+                                        Target_i386* target,
+                                        Sized_relobj<32, false>* object,
+                                        unsigned int data_shndx,
+                                        Output_section* output_section,
+                                        const elfcpp::Rel<32, false>& reloc,
+                                        unsigned int r_type,
+                                        Symbol* gsym);
 
     inline bool
-    global_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
-                                        Target_i386* ,
-                                        Sized_relobj<32, false>* ,
-                                        unsigned int ,
-                                        Output_section* ,
-                                        const elfcpp::Rel<32, false>& ,
-                                        unsigned int , Symbol*)
-    { return false; }
+    possible_function_pointer_reloc(unsigned int r_type);
 
     static void
     unsupported_reloc_local(Sized_relobj<32, false>*, unsigned int r_type);
@@ -1234,6 +1241,55 @@ Target_i386::Scan::unsupported_reloc_global(Sized_relobj<32, false>* object,
             object->name().c_str(), r_type, gsym->demangled_name().c_str());
 }
 
+inline bool
+Target_i386::Scan::possible_function_pointer_reloc(unsigned int r_type)
+{
+  switch (r_type)
+    {
+    case elfcpp::R_386_32:
+    case elfcpp::R_386_16:
+    case elfcpp::R_386_8:
+    case elfcpp::R_386_GOTOFF:
+    case elfcpp::R_386_GOT32:
+      {
+        return true;
+      }
+    default:
+      return false;
+    }
+  return false;
+}
+
+inline bool
+Target_i386::Scan::local_reloc_may_be_function_pointer(
+  Symbol_table* ,
+  Layout* ,
+  Target_i386* ,
+  Sized_relobj<32, false>* ,
+  unsigned int ,
+  Output_section* ,
+  const elfcpp::Rel<32, false>& ,
+  unsigned int r_type,
+  const elfcpp::Sym<32, false>&)
+{
+  return possible_function_pointer_reloc(r_type);
+}
+
+inline bool
+Target_i386::Scan::global_reloc_may_be_function_pointer(
+  Symbol_table* ,
+  Layout* ,
+  Target_i386* ,
+  Sized_relobj<32, false>* ,
+  unsigned int ,
+  Output_section* ,
+  const elfcpp::Rel<32, false>& ,
+  unsigned int r_type,
+  Symbol*)
+{
+  return possible_function_pointer_reloc(r_type);
+}
+
 // Scan a relocation for a global symbol.
 
 inline void
index c1db8e5..27bbbba 100644 (file)
@@ -127,6 +127,7 @@ class Icf
     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()));
   }
 
index 5e4453b..0f50ad6 100644 (file)
@@ -24,7 +24,8 @@
 // in safe mode correctly folds functions in a shared object. The
 // foo_* functions below should not be folded.  For x86-64,
 // foo_glob and bar_glob should be folded as their function pointers
-// are addresses of PLT entries in shared objects.
+// are addresses of PLT entries in shared objects.  For 32-bit X86,
+// the hidden protected and internal symbols can be folded.
 
 int  __attribute__ ((visibility ("protected")))
 foo_prot()
index db2e73e..262daef 100755 (executable)
 # to verify if identical code folding in safe mode correctly folds
 # functions in a shared object.
 
+error_if_symbol_absent()
+{
+    is_symbol_present $1 $2
+    if [ $? != 0 ];
+    then
+      echo "Symbol" $2 "not present, possibly folded."
+      exit 1
+    fi
+}
+
+is_symbol_present()
+{
+    result=`grep $2 $1`
+    return $?
+}
+
 check_nofold()
 {
+    error_if_symbol_absent $1 $2
+    error_if_symbol_absent $1 $3
     func_addr_1=`grep $2 $1 | awk '{print $1}'`
     func_addr_2=`grep $3 $1 | awk '{print $1}'`
     if [ $func_addr_1 = $func_addr_2 ];
@@ -38,6 +56,18 @@ check_nofold()
 
 check_fold()
 {
+    is_symbol_present $1 $2
+    if [ $? != 0 ];
+    then
+      return 0
+    fi
+
+    is_symbol_present $1 $3
+    if [ $? != 0 ];
+    then
+      return 0
+    fi
+
     func_addr_1=`grep $2 $1 | awk '{print $1}'`
     func_addr_2=`grep $3 $1 | awk '{print $1}'`
     if [ $func_addr_1 != $func_addr_2 ];
@@ -49,21 +79,31 @@ check_fold()
 
 arch_specific_safe_fold()
 {
-    grep_x86_64=`grep -q "Advanced Micro Devices X86-64" $2`
-    if [ $? == 0 ];
+    if [ $1 == 0 ];
     then
-      check_fold $1 $3 $4
+      check_fold $2 $3 $4
     else
-      check_nofold $1 $3 $4
+      check_nofold $2 $3 $4
     fi
 }
 
-check_nofold icf_safe_so_test_1.stdout "foo_prot" "foo_hidden"
-check_nofold icf_safe_so_test_1.stdout "foo_prot" "foo_internal"
-check_nofold icf_safe_so_test_1.stdout "foo_prot" "foo_static"
-check_nofold icf_safe_so_test_1.stdout "foo_hidden" "foo_internal"
-check_nofold icf_safe_so_test_1.stdout "foo_hidden" "foo_static"
-check_nofold icf_safe_so_test_1.stdout "foo_internal" "foo_static"
-arch_specific_safe_fold icf_safe_so_test_1.stdout icf_safe_so_test_2.stdout \
-  "foo_glob" "bar_glob"
+X86_32_specific_safe_fold()
+{
+    grep -q -e "Intel 80386" $1 >& /dev/null
+    arch_specific_safe_fold $? $2 $3 $4
+}
 
+X86_64_specific_safe_fold()
+{
+    grep -q -e "Advanced Micro Devices X86-64" $1 >& /dev/null
+    arch_specific_safe_fold $? $2 $3 $4
+}
+
+X86_32_specific_safe_fold icf_safe_so_test_2.stdout icf_safe_so_test_1.stdout "foo_prot" "foo_hidden"
+X86_32_specific_safe_fold icf_safe_so_test_2.stdout icf_safe_so_test_1.stdout "foo_prot" "foo_internal"
+X86_32_specific_safe_fold icf_safe_so_test_2.stdout icf_safe_so_test_1.stdout "foo_prot" "foo_static"
+X86_32_specific_safe_fold icf_safe_so_test_2.stdout icf_safe_so_test_1.stdout "foo_hidden" "foo_internal"
+X86_32_specific_safe_fold icf_safe_so_test_2.stdout icf_safe_so_test_1.stdout "foo_hidden" "foo_static"
+X86_32_specific_safe_fold icf_safe_so_test_2.stdout icf_safe_so_test_1.stdout "foo_internal" "foo_static"
+X86_64_specific_safe_fold icf_safe_so_test_2.stdout icf_safe_so_test_1.stdout \
+  "foo_glob" "bar_glob"
index 3edb865..87294dc 100644 (file)
 
 // The goal of this program is to verify if identical code folding
 // in safe mode correctly folds only ctors and dtors. kept_func_1 must
-// not be folded into kept_func_2 other than for X86-64 which can
-// use relocation types to determine if function pointers are taken.
-// kept_func_3 should never be folded as its pointer is taken. The ctor
-// and dtor of class A must be folded.
+// not be folded into kept_func_2 other than for X86 (32 and 64 bit)
+// which can use relocation types to determine if function pointers are
+// taken.  kept_func_3 should never be folded as its pointer is taken.
+// The ctor and dtor of class A must be folded.
 
 class A
 {
index 540dcc2..23e4e29 100755 (executable)
@@ -22,8 +22,8 @@
 
 # The goal of this program is to verify if --icf=safe  works as expected.
 # File icf_safe_test.cc is in this test. This program checks if only
-# ctors and dtors are folded, except for x86-64, which uses relocation
-# types to detect if function pointers are taken.
+# ctors and dtors are folded, except for x86 (32 and 64 bit), which
+# uses relocation types to detect if function pointers are taken.
 
 check_nofold()
 {
@@ -49,7 +49,7 @@ check_fold()
 
 arch_specific_safe_fold()
 {
-    grep_x86_64=`grep -q "Advanced Micro Devices X86-64" $2`
+    grep_x86=`grep -q -e "Advanced Micro Devices X86-64" -e "Intel 80386" $2`
     if [ $? == 0 ];
     then
       check_fold $1 $3 $4