* 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.
This commit is contained in:
Sriraman Tallam 2010-03-04 01:33:22 +00:00
parent 390a8acaa3
commit 0897ed3bdb
7 changed files with 148 additions and 36 deletions

View 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>

View 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* , Layout* ,
Target_i386* ,
Sized_relobj<32, false>* ,
unsigned int ,
Output_section* ,
const elfcpp::Rel<32, false>& ,
unsigned int , Symbol*)
{ return false; }
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
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

View 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()));
}

View 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()

View File

@ -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"

View File

@ -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
{

View File

@ -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