aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog14
-rw-r--r--gold/i386.cc88
-rw-r--r--gold/icf.h1
-rw-r--r--gold/testsuite/icf_safe_so_test.cc3
-rwxr-xr-xgold/testsuite/icf_safe_so_test.sh64
-rw-r--r--gold/testsuite/icf_safe_test.cc8
-rwxr-xr-xgold/testsuite/icf_safe_test.sh6
7 files changed, 148 insertions, 36 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index 2610909..33b7307 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -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>
diff --git a/gold/i386.cc b/gold/i386.cc
index eb4ef0a..e7b700c 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -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
diff --git a/gold/icf.h b/gold/icf.h
index c1db8e5..27bbbba 100644
--- a/gold/icf.h
+++ b/gold/icf.h
@@ -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()));
}
diff --git a/gold/testsuite/icf_safe_so_test.cc b/gold/testsuite/icf_safe_so_test.cc
index 5e4453b..0f50ad6 100644
--- a/gold/testsuite/icf_safe_so_test.cc
+++ b/gold/testsuite/icf_safe_so_test.cc
@@ -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()
diff --git a/gold/testsuite/icf_safe_so_test.sh b/gold/testsuite/icf_safe_so_test.sh
index db2e73e..262daef 100755
--- a/gold/testsuite/icf_safe_so_test.sh
+++ b/gold/testsuite/icf_safe_so_test.sh
@@ -25,8 +25,26 @@
# 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"
diff --git a/gold/testsuite/icf_safe_test.cc b/gold/testsuite/icf_safe_test.cc
index 3edb865..87294dc 100644
--- a/gold/testsuite/icf_safe_test.cc
+++ b/gold/testsuite/icf_safe_test.cc
@@ -22,10 +22,10 @@
// 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
{
diff --git a/gold/testsuite/icf_safe_test.sh b/gold/testsuite/icf_safe_test.sh
index 540dcc2..23e4e29 100755
--- a/gold/testsuite/icf_safe_test.sh
+++ b/gold/testsuite/icf_safe_test.sh
@@ -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