* arm.cc (Target_arm::relocate::reloc_is_non_pic): Return true for

R_ARM_THM_ABS5, R_ARM_ABS8, R_ARM_ABS12, R_ARM_ABS16,
	R_ARM_BASE_ABS.
	(Arm_relocate_functions::abs8): Remove has_thumb_bit parameter.
	(Arm_relocate_functions::thm_abs5): New function.
	(Arm_relocate_functions::abs12): New function.
	(Arm_relocate_functions::abs16): New function.
	(Arm_relocate_functions::base_abs): New function.
	(Scan::check_non_pic): Handle R_ARM_ABS32_NOI.
	(Scan::local): Remove special handling of R_ARM_ABS8.  Handle
	R_ARM_ABS32_NOI, R_ARM_THM_ABS5, R_ARM_ABS12, R_ARM_ABS16, and
	R_ARM_BASE_ABS.
	(Scan::global): Likewise.
	(Relocate::relocate): Handle R_ARM_ABS12, R_ARM_ABS16,
	R_ARM_ABS32_NOI, R_ARM_THM_ABS5, and R_ARM_BASE_ABS.
	(Relocatable_size_for_reloc::get_size_for_reloc): Handle
	R_ARM_ABS16, R_ARM_THM_ABS5, R_ARM_ABS32_NOI, R_ARM_ABS12, and
	R_ARM_BASE_ABS.
This commit is contained in:
Ian Lance Taylor 2009-10-09 22:56:41 +00:00
parent c2a122b635
commit be8fcb7563
2 changed files with 188 additions and 23 deletions

View File

@ -1,3 +1,24 @@
2009-10-09 Viktor Kutuzov <vkutuzov@accesssoftek.com>
* arm.cc (Target_arm::relocate::reloc_is_non_pic): Return true for
R_ARM_THM_ABS5, R_ARM_ABS8, R_ARM_ABS12, R_ARM_ABS16,
R_ARM_BASE_ABS.
(Arm_relocate_functions::abs8): Remove has_thumb_bit parameter.
(Arm_relocate_functions::thm_abs5): New function.
(Arm_relocate_functions::abs12): New function.
(Arm_relocate_functions::abs16): New function.
(Arm_relocate_functions::base_abs): New function.
(Scan::check_non_pic): Handle R_ARM_ABS32_NOI.
(Scan::local): Remove special handling of R_ARM_ABS8. Handle
R_ARM_ABS32_NOI, R_ARM_THM_ABS5, R_ARM_ABS12, R_ARM_ABS16, and
R_ARM_BASE_ABS.
(Scan::global): Likewise.
(Relocate::relocate): Handle R_ARM_ABS12, R_ARM_ABS16,
R_ARM_ABS32_NOI, R_ARM_THM_ABS5, and R_ARM_BASE_ABS.
(Relocatable_size_for_reloc::get_size_for_reloc): Handle
R_ARM_ABS16, R_ARM_THM_ABS5, R_ARM_ABS32_NOI, R_ARM_ABS12, and
R_ARM_BASE_ABS.
2009-10-09 Viktor Kutuzov <vkutuzov@accesssoftek.com>
* arm.cc (Arm_relocate_functions::movw_prel_nc): New function.

View File

@ -59,6 +59,12 @@ class Output_data_plt_arm;
//
// R_ARM_NONE
// R_ARM_ABS32
// R_ARM_ABS32_NOI
// R_ARM_ABS16
// R_ARM_ABS12
// R_ARM_ABS8
// R_ARM_THM_ABS5
// R_ARM_BASE_ABS
// R_ARM_REL32
// R_ARM_THM_CALL
// R_ARM_COPY
@ -366,6 +372,11 @@ class Target_arm : public Sized_target<32, big_endian>
case elfcpp::R_ARM_CALL:
case elfcpp::R_ARM_JUMP24:
case elfcpp::R_ARM_PREL31:
case elfcpp::R_ARM_THM_ABS5:
case elfcpp::R_ARM_ABS8:
case elfcpp::R_ARM_ABS12:
case elfcpp::R_ARM_ABS16:
case elfcpp::R_ARM_BASE_ABS:
return true;
default:
return false;
@ -659,14 +670,14 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
static inline typename This::Status
abs8(unsigned char *view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval, bool has_thumb_bit)
const Symbol_value<32>* psymval)
{
typedef typename elfcpp::Swap<8, big_endian>::Valtype Valtype;
typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
Valtype val = elfcpp::Swap<8, big_endian>::readval(wv);
Reltype addend = utils::sign_extend<8>(val);
Reltype x = This::arm_symbol_value(object, psymval, addend, has_thumb_bit);
Reltype x = This::arm_symbol_value(object, psymval, addend, false);
val = utils::bit_select(val, x, 0xffU);
elfcpp::Swap<8, big_endian>::writeval(wv, val);
return (utils::has_signed_unsigned_overflow<8>(x)
@ -674,6 +685,63 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
: This::STATUS_OKAY);
}
// R_ARM_THM_ABS5: S + A
static inline typename This::Status
thm_abs5(unsigned char *view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval)
{
typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
Reltype addend = (val & 0x7e0U) >> 6;
Reltype x = This::arm_symbol_value(object, psymval, addend, false);
val = utils::bit_select(val, x << 6, 0x7e0U);
elfcpp::Swap<16, big_endian>::writeval(wv, val);
return (utils::has_overflow<5>(x)
? This::STATUS_OVERFLOW
: This::STATUS_OKAY);
}
// R_ARM_ABS12: S + A
static inline typename This::Status
abs12(unsigned char *view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval)
{
typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
Reltype addend = val & 0x0fffU;
Reltype x = This::arm_symbol_value(object, psymval, addend, false);
val = utils::bit_select(val, x, 0x0fffU);
elfcpp::Swap<32, big_endian>::writeval(wv, val);
return (utils::has_overflow<12>(x)
? This::STATUS_OVERFLOW
: This::STATUS_OKAY);
}
// R_ARM_ABS16: S + A
static inline typename This::Status
abs16(unsigned char *view,
const Sized_relobj<32, big_endian>* object,
const Symbol_value<32>* psymval)
{
typedef typename elfcpp::Swap<16, big_endian>::Valtype Valtype;
typedef typename elfcpp::Swap<32, big_endian>::Valtype Reltype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
Valtype val = elfcpp::Swap<16, big_endian>::readval(wv);
Reltype addend = utils::sign_extend<16>(val);
Reltype x = This::arm_symbol_value(object, psymval, addend, false);
val = utils::bit_select(val, x, 0xffffU);
elfcpp::Swap<16, big_endian>::writeval(wv, val);
return (utils::has_signed_unsigned_overflow<16>(x)
? This::STATUS_OVERFLOW
: This::STATUS_OKAY);
}
// R_ARM_ABS32: (S + A) | T
static inline typename This::Status
abs32(unsigned char *view,
@ -753,6 +821,15 @@ class Arm_relocate_functions : public Relocate_functions<32, big_endian>
return STATUS_OKAY;
}
// R_ARM_BASE_ABS: B(S) + A
static inline typename This::Status
base_abs(unsigned char* view,
elfcpp::Elf_types<32>::Elf_Addr origin)
{
Base::rel32(view, origin);
return STATUS_OKAY;
}
// R_ARM_GOT_BREL: GOT(S) + A - GOT_ORG
static inline typename This::Status
got_brel(unsigned char* view,
@ -1308,6 +1385,7 @@ Target_arm<big_endian>::Scan::check_non_pic(Relobj* object,
case elfcpp::R_ARM_GLOB_DAT:
case elfcpp::R_ARM_JUMP_SLOT:
case elfcpp::R_ARM_ABS32:
case elfcpp::R_ARM_ABS32_NOI:
case elfcpp::R_ARM_PC24:
// FIXME: The following 3 types are not supported by Android's dynamic
// linker.
@ -1355,16 +1433,8 @@ Target_arm<big_endian>::Scan::local(const General_options&,
case elfcpp::R_ARM_NONE:
break;
case elfcpp::R_ARM_ABS8:
if (parameters->options().output_is_position_independent())
{
// FIXME: Create a dynamic relocation for this location.
gold_error(_("%s: gold bug: need dynamic ABS8 reloc"),
object->name().c_str());
}
break;
case elfcpp::R_ARM_ABS32:
case elfcpp::R_ARM_ABS32_NOI:
// If building a shared library (or a position-independent
// executable), we need to create a dynamic relocation for
// this location. The relocation applied at link time will
@ -1389,6 +1459,11 @@ Target_arm<big_endian>::Scan::local(const General_options&,
case elfcpp::R_ARM_PREL31:
case elfcpp::R_ARM_JUMP24:
case elfcpp::R_ARM_PLT32:
case elfcpp::R_ARM_THM_ABS5:
case elfcpp::R_ARM_ABS8:
case elfcpp::R_ARM_ABS12:
case elfcpp::R_ARM_ABS16:
case elfcpp::R_ARM_BASE_ABS:
case elfcpp::R_ARM_MOVW_ABS_NC:
case elfcpp::R_ARM_MOVT_ABS:
case elfcpp::R_ARM_THM_MOVW_ABS_NC:
@ -1486,17 +1561,8 @@ Target_arm<big_endian>::Scan::global(const General_options&,
case elfcpp::R_ARM_NONE:
break;
case elfcpp::R_ARM_ABS8:
// Make a dynamic relocation if necessary.
if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF))
{
// FIXME: Create a dynamic relocation for this location.
gold_error(_("%s: gold bug: need dynamic ABS8 reloc for %s"),
object->name().c_str(), gsym->demangled_name().c_str());
}
break;
case elfcpp::R_ARM_ABS32:
case elfcpp::R_ARM_ABS32_NOI:
{
// Make a dynamic relocation if necessary.
if (gsym->needs_dynamic_reloc(Symbol::ABSOLUTE_REF))
@ -1537,6 +1603,23 @@ Target_arm<big_endian>::Scan::global(const General_options&,
case elfcpp::R_ARM_THM_MOVT_PREL:
break;
case elfcpp::R_ARM_THM_ABS5:
case elfcpp::R_ARM_ABS8:
case elfcpp::R_ARM_ABS12:
case elfcpp::R_ARM_ABS16:
case elfcpp::R_ARM_BASE_ABS:
{
// No dynamic relocs of this kinds.
// Report the error in case of PIC.
int flags = Symbol::NON_PIC_REF;
if (gsym->type() == elfcpp::STT_FUNC
|| gsym->type() == elfcpp::STT_ARM_TFUNC)
flags |= Symbol::FUNCTION_CALL;
if (gsym->needs_dynamic_reloc(flags))
check_non_pic(object, r_type);
}
break;
case elfcpp::R_ARM_REL32:
case elfcpp::R_ARM_PREL31:
{
@ -1919,8 +2002,19 @@ Target_arm<big_endian>::Relocate::relocate(
case elfcpp::R_ARM_ABS8:
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
output_section))
reloc_status = Arm_relocate_functions::abs8(view, object, psymval,
has_thumb_bit);
reloc_status = Arm_relocate_functions::abs8(view, object, psymval);
break;
case elfcpp::R_ARM_ABS12:
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
output_section))
reloc_status = Arm_relocate_functions::abs12(view, object, psymval);
break;
case elfcpp::R_ARM_ABS16:
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
output_section))
reloc_status = Arm_relocate_functions::abs16(view, object, psymval);
break;
case elfcpp::R_ARM_ABS32:
@ -1930,6 +2024,14 @@ Target_arm<big_endian>::Relocate::relocate(
has_thumb_bit);
break;
case elfcpp::R_ARM_ABS32_NOI:
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true,
output_section))
// No thumb bit for this relocation: (S + A)
reloc_status = Arm_relocate_functions::abs32(view, object, psymval,
false);
break;
case elfcpp::R_ARM_MOVW_ABS_NC:
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true,
output_section))
@ -1998,6 +2100,12 @@ Target_arm<big_endian>::Relocate::relocate(
address, has_thumb_bit);
break;
case elfcpp::R_ARM_THM_ABS5:
if (should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, false,
output_section))
reloc_status = Arm_relocate_functions::thm_abs5(view, object, psymval);
break;
case elfcpp::R_ARM_THM_CALL:
reloc_status = Arm_relocate_functions::thm_call(view, object, psymval,
address, has_thumb_bit);
@ -2032,6 +2140,35 @@ Target_arm<big_endian>::Relocate::relocate(
}
break;
case elfcpp::R_ARM_BASE_ABS:
{
if (!should_apply_static_reloc(gsym, Symbol::ABSOLUTE_REF, true,
output_section))
break;
uint32_t origin;
// Get the addressing origin of the output segment defining
// the symbol gsym (AAELF 4.6.1.2 Relocation types).
if (gsym == NULL)
// R_ARM_BASE_ABS with the NULL symbol will give the
// absolute address of the GOT origin (GOT_ORG) (see ARM IHI
// 0044C (AAELF): 4.6.1.8 Proxy generating relocations).
origin = target->got_plt_section()->address();
else if (gsym->source() == Symbol::IN_OUTPUT_SEGMENT)
origin = gsym->output_segment()->vaddr();
else if (gsym->source () == Symbol::IN_OUTPUT_DATA)
origin = gsym->output_data()->address();
else
{
gold_error_at_location(relinfo, relnum, rel.get_r_offset(),
_("cannot find origin of R_ARM_BASE_ABS"));
return true;
}
reloc_status = Arm_relocate_functions::base_abs(view, origin);
}
break;
case elfcpp::R_ARM_GOT_BREL:
gold_assert(have_got_offset);
reloc_status = Arm_relocate_functions::got_brel(view, got_offset);
@ -2172,7 +2309,14 @@ Target_arm<big_endian>::Relocatable_size_for_reloc::get_size_for_reloc(
case elfcpp::R_ARM_ABS8:
return 1;
case elfcpp::R_ARM_ABS16:
case elfcpp::R_ARM_THM_ABS5:
return 2;
case elfcpp::R_ARM_ABS32:
case elfcpp::R_ARM_ABS32_NOI:
case elfcpp::R_ARM_ABS12:
case elfcpp::R_ARM_BASE_ABS:
case elfcpp::R_ARM_REL32:
case elfcpp::R_ARM_THM_CALL:
case elfcpp::R_ARM_GOTOFF32: