--- binutils.orig/src/gold/arm.cc 2009-09-17 17:45:53.000000000 -0700 +++ binutils.gold/src/gold/arm.cc 2009-10-01 15:07:57.000000000 -0700 @@ -59,6 +59,12 @@ // // 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 @@ -355,6 +361,11 @@ 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; @@ -577,14 +588,14 @@ 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(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) @@ -592,6 +603,63 @@ : 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(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(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(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, @@ -671,6 +739,15 @@ 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, @@ -1064,6 +1141,7 @@ 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. @@ -1111,16 +1189,8 @@ 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 @@ -1145,6 +1215,11 @@ 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: break; case elfcpp::R_ARM_GOTOFF32: @@ -1233,17 +1308,8 @@ 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)) @@ -1274,6 +1340,23 @@ } 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: { @@ -1654,8 +1737,19 @@ 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: @@ -1665,11 +1759,25 @@ 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_REL32: reloc_status = Arm_relocate_functions::rel32(view, object, psymval, 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); @@ -1704,6 +1812,35 @@ } 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); @@ -1830,7 +1967,14 @@ 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: