2009-11-25 Doug Kwan <dougkwan@google.com>

* arm.cc (Target_arm::Target_arm): Move method definition outside of
	class definition.  Add code to handle --target1-rel, --target1-abs
	and --target2= options.
	(Target_arm::get_reloc_reloc_type): Change method to be non-static
	and const.
	(Target_arm::target1_is_rel_, Target_arm::target2_reloc_): New data
	member declaration.
	(Target_arm::Scan::local, Target_arm::Scan::global,
	Target_arm::Relocate::relocate,
	Target_arm::Relocatable_size_for_reloc::get_size_for_reloc): Adjust
	call to Target_arm::get_real_reloc_type.
	(Target_arm::get_real_reloc_type): Use command line options to
	determine real types of R_ARM_TARGET1 and R_ARM_TARGET2.
	* options.h (--target1-rel, --target1-abs, --target2): New ARM-only
	options.
This commit is contained in:
Doug Kwan 2009-11-25 04:32:36 +00:00
parent 5193828376
commit 50aeb7d431
3 changed files with 91 additions and 19 deletions

View File

@ -1,3 +1,21 @@
2009-11-25 Doug Kwan <dougkwan@google.com>
* arm.cc (Target_arm::Target_arm): Move method definition outside of
class definition. Add code to handle --target1-rel, --target1-abs
and --target2= options.
(Target_arm::get_reloc_reloc_type): Change method to be non-static
and const.
(Target_arm::target1_is_rel_, Target_arm::target2_reloc_): New data
member declaration.
(Target_arm::Scan::local, Target_arm::Scan::global,
Target_arm::Relocate::relocate,
Target_arm::Relocatable_size_for_reloc::get_size_for_reloc): Adjust
call to Target_arm::get_real_reloc_type.
(Target_arm::get_real_reloc_type): Use command line options to
determine real types of R_ARM_TARGET1 and R_ARM_TARGET2.
* options.h (--target1-rel, --target1-abs, --target2): New ARM-only
options.
2009-11-25 Doug Kwan <dougkwan@google.com>
* arm.cc (Target_arm::may_use_thumb2_nop): New method definition.

View File

@ -1142,14 +1142,7 @@ class Target_arm : public Sized_target<32, big_endian>
// When were are relocating a stub, we pass this as the relocation number.
static const size_t fake_relnum_for_stubs = static_cast<size_t>(-1);
Target_arm()
: Sized_target<32, big_endian>(&arm_info),
got_(NULL), plt_(NULL), got_plt_(NULL), rel_dyn_(NULL),
copy_relocs_(elfcpp::R_ARM_COPY), dynbss_(NULL), stub_tables_(),
stub_factory_(Stub_factory::get_instance()),
may_use_blx_(true), should_force_pic_veneer_(false),
arm_input_section_map_()
{ }
Target_arm();
// Whether we can use BLX.
bool
@ -1298,8 +1291,8 @@ class Target_arm : public Sized_target<32, big_endian>
}
// Map platform-specific reloc types
static unsigned int
get_real_reloc_type (unsigned int r_type);
unsigned int
get_real_reloc_type (unsigned int r_type) const;
//
// Methods to support stub-generations.
@ -1631,6 +1624,11 @@ class Target_arm : public Sized_target<32, big_endian>
Stub_table_list stub_tables_;
// Stub factory.
const Stub_factory &stub_factory_;
// Whether R_ARM_TARGET1 maps to R_ARM_REL32 or R_ARM_ABS32.
bool target1_is_rel_;
// What R_ARM_TARGET2 maps to. It should be one of R_ARM_REL32, R_ARM_ABS32
// and R_ARM_GOT_PREL.
unsigned int target2_reloc_;
// Whether we can use BLX.
bool may_use_blx_;
// Whether we force PIC branch veneers.
@ -2310,6 +2308,51 @@ Arm_relocate_functions<big_endian>::arm_branch_common(
? This::STATUS_OVERFLOW : This::STATUS_OKAY);
}
template<bool big_endian>
Target_arm<big_endian>::Target_arm()
: Sized_target<32, big_endian>(&arm_info),
got_(NULL), plt_(NULL), got_plt_(NULL), rel_dyn_(NULL),
copy_relocs_(elfcpp::R_ARM_COPY), dynbss_(NULL), stub_tables_(),
stub_factory_(Stub_factory::get_instance()), target1_is_rel_(false),
may_use_blx_(true), should_force_pic_veneer_(false),
arm_input_section_map_()
{
// FIXME: This is not strictly compatible with ld, which allows both
// --target1-abs and --target-rel to be given.
if (parameters->options().user_set_target1_abs()
&& parameters->options().user_set_target1_rel())
{
gold_error(_("Cannot use both --target1-abs and --target1-rel."));
}
else if (parameters->options().user_set_target1_rel())
this->target1_is_rel_ = true;
else if (parameters->options().user_set_target1_abs())
this->target1_is_rel_ = false;
if (parameters->options().user_set_target2())
{
if (strcmp(parameters->options().target2(), "rel") == 0)
this->target2_reloc_ = elfcpp::R_ARM_REL32;
else if (strcmp(parameters->options().target2(), "abs") == 0)
this->target2_reloc_ = elfcpp::R_ARM_ABS32;
else if (strcmp(parameters->options().target2(), "got-rel") == 0)
this->target2_reloc_ = elfcpp::R_ARM_GOT_PREL;
else
gold_unreachable();
}
else
{
// Default values for R_ARM_TARGET2:
//
// R_ARM_REL32 (arm*-*-elf, arm*-*-eabi)
// R_ARM_ABS32 (arm*-*-symbianelf)
// R_ARM_GOT_PREL (arm*-*-linux, arm*-*-*bsd)
// This is the default value for EABI.
this->target2_reloc_ = elfcpp::R_ARM_REL32;
}
}
// Relocate THUMB long branches. This handles relocation types
// R_ARM_THM_CALL, R_ARM_THM_JUMP24 and R_ARM_THM_XPC22.
// If IS_WEAK_UNDEFINED_WITH_PLT is true. The target symbol is weakly
@ -4166,7 +4209,7 @@ Target_arm<big_endian>::Scan::local(Symbol_table* symtab,
unsigned int r_type,
const elfcpp::Sym<32, big_endian>&)
{
r_type = get_real_reloc_type(r_type);
r_type = target->get_real_reloc_type(r_type);
switch (r_type)
{
case elfcpp::R_ARM_NONE:
@ -4293,7 +4336,7 @@ Target_arm<big_endian>::Scan::global(Symbol_table* symtab,
unsigned int r_type,
Symbol* gsym)
{
r_type = get_real_reloc_type(r_type);
r_type = target->get_real_reloc_type(r_type);
switch (r_type)
{
case elfcpp::R_ARM_NONE:
@ -4705,7 +4748,7 @@ Target_arm<big_endian>::Relocate::relocate(
{
typedef Arm_relocate_functions<big_endian> Arm_relocate_functions;
r_type = get_real_reloc_type(r_type);
r_type = target->get_real_reloc_type(r_type);
const Arm_relobj<big_endian>* object =
Arm_relobj<big_endian>::as_arm_relobj(relinfo->object);
@ -5170,7 +5213,9 @@ Target_arm<big_endian>::Relocatable_size_for_reloc::get_size_for_reloc(
unsigned int r_type,
Relobj* object)
{
r_type = get_real_reloc_type(r_type);
const Target_arm<big_endian>* arm_target =
Target_arm<big_endian>::default_target();
r_type = arm_target->get_real_reloc_type(r_type);
switch (r_type)
{
case elfcpp::R_ARM_NONE:
@ -5315,17 +5360,15 @@ Target_arm<big_endian>::do_dynsym_value(const Symbol* gsym) const
//
template<bool big_endian>
unsigned int
Target_arm<big_endian>::get_real_reloc_type (unsigned int r_type)
Target_arm<big_endian>::get_real_reloc_type (unsigned int r_type) const
{
switch (r_type)
{
case elfcpp::R_ARM_TARGET1:
// This is either R_ARM_ABS32 or R_ARM_REL32;
return elfcpp::R_ARM_ABS32;
return this->target1_is_rel_? elfcpp::R_ARM_REL32 : elfcpp::R_ARM_ABS32;
case elfcpp::R_ARM_TARGET2:
// This can be any reloc type but ususally is R_ARM_GOT_PREL
return elfcpp::R_ARM_GOT_PREL;
return this->target2_reloc_;
default:
return r_type;

View File

@ -884,6 +884,17 @@ class General_options
DEFINE_string(sysroot, options::TWO_DASHES, '\0', "",
N_("Set target system root directory"), N_("DIR"));
DEFINE_bool(target1_rel, options::TWO_DASHES, '\0', false,
N_("(ARM only) Force R_ARM_TARGET1 type to R_ARM_REL32"),
NULL);
DEFINE_bool(target1_abs, options::TWO_DASHES, '\0', false,
N_("(ARM only) Force R_ARM_TARGET1 type to R_ARM_ABS32"),
NULL);
DEFINE_enum(target2, options::TWO_DASHES, '\0', "default",
N_("(ARM only) Set R_ARM_TARGET2 relocation type"),
N_("[default, rel, abs, got-rel"),
{"default", "rel", "abs", "got-rel"});
DEFINE_bool(trace, options::TWO_DASHES, 't', false,
N_("Print the name of each input file"), NULL);