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.
This commit is contained in:
Doug Kwan 2010-06-25 00:37:40 +00:00
parent 4f2a93bda2
commit 8a75a161b2
4 changed files with 120 additions and 8 deletions

View 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

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

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

View 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