diff options
author | Ian Lance Taylor <ian@airs.com> | 2009-10-09 22:56:41 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2009-10-09 22:56:41 +0000 |
commit | be8fcb75638b96c52854e0ed549a11a38349719b (patch) | |
tree | 3fa990f28a96476f924ce1226ce5ae83f1305180 /gold/arm.cc | |
parent | c2a122b6358d2bc183e574addf31312265380d23 (diff) | |
download | gdb-be8fcb75638b96c52854e0ed549a11a38349719b.zip gdb-be8fcb75638b96c52854e0ed549a11a38349719b.tar.gz gdb-be8fcb75638b96c52854e0ed549a11a38349719b.tar.bz2 |
* 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.
Diffstat (limited to 'gold/arm.cc')
-rw-r--r-- | gold/arm.cc | 190 |
1 files changed, 167 insertions, 23 deletions
diff --git a/gold/arm.cc b/gold/arm.cc index edfd35c..7067de7 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -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: |