From e242ece1e890b66d226b38b489a7edd79b3656d5 Mon Sep 17 00:00:00 2001 From: Vladimir Radosavljevic Date: Wed, 15 Feb 2017 00:47:36 -0800 Subject: [PATCH] Add support for R_MIPS_HIGHER/HIGHEST, R_MICROMIPS_HIGHER/HIGHEST relocations. 2017-02-15 Vladimir Radosavljevic PR gold/21111 * mips.cc (Mips_relocate_functions::relhigher): New method. (Mips_relocate_functions::relhighest): Likewise. (mips_get_size_for_reloc): Add support for relocs: R_MIPS_HIGHER and R_MIPS_HIGHEST. (Target_mips::Scan::local): Add support for relocs: R_MIPS_HIGHER, R_MIPS_HIGHEST, R_MICROMIPS_HIGHER and R_MICROMIPS_HIGHEST. (Target_mips::Scan::global): Likewise. (Target_mips::Scan::get_reference_flags): Likewise. (Target_mips::Relocate::relocate): Call static methods for resolving HIGHER and HIGHEST relocations. --- gold/ChangeLog | 14 ++++++++++ gold/mips.cc | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/gold/ChangeLog b/gold/ChangeLog index e811b8ea6de..9b8abc7a83d 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,17 @@ +2017-02-15 Vladimir Radosavljevic + + PR gold/21111 + * mips.cc (Mips_relocate_functions::relhigher): New method. + (Mips_relocate_functions::relhighest): Likewise. + (mips_get_size_for_reloc): Add support for relocs: R_MIPS_HIGHER and + R_MIPS_HIGHEST. + (Target_mips::Scan::local): Add support for relocs: R_MIPS_HIGHER, + R_MIPS_HIGHEST, R_MICROMIPS_HIGHER and R_MICROMIPS_HIGHEST. + (Target_mips::Scan::global): Likewise. + (Target_mips::Scan::get_reference_flags): Likewise. + (Target_mips::Relocate::relocate): Call static methods for resolving + HIGHER and HIGHEST relocations. + 2017-02-03 Rahul Chaudhry * x86_64.cc (Target_x86_64::do_can_check_for_function_pointers): diff --git a/gold/mips.cc b/gold/mips.cc index 56af570651e..7b19e4c62cb 100644 --- a/gold/mips.cc +++ b/gold/mips.cc @@ -5579,6 +5579,52 @@ class Mips_relocate_functions : public Relocate_functions return This::STATUS_OKAY; } + // R_MIPS_HIGHER, R_MICROMIPS_HIGHER + static inline typename This::Status + relhigher(unsigned char* view, const Mips_relobj* object, + const Symbol_value* psymval, Mips_address addend_a, + bool extract_addend, bool calculate_only, Valtype* calculated_value) + { + Valtype32* wv = reinterpret_cast(view); + Valtype32 val = elfcpp::Swap<32, big_endian>::readval(wv); + Valtype addend = (extract_addend ? Bits<16>::sign_extend32(val & 0xffff) + : addend_a); + + Valtype x = psymval->value(object, addend); + x = ((x + (uint64_t) 0x80008000) >> 32) & 0xffff; + val = Bits<32>::bit_select32(val, x, 0xffff); + + if (calculate_only) + *calculated_value = x; + else + elfcpp::Swap<32, big_endian>::writeval(wv, val); + + return This::STATUS_OKAY; + } + + // R_MIPS_HIGHEST, R_MICROMIPS_HIGHEST + static inline typename This::Status + relhighest(unsigned char* view, const Mips_relobj* object, + const Symbol_value* psymval, Mips_address addend_a, + bool extract_addend, bool calculate_only, + Valtype* calculated_value) + { + Valtype32* wv = reinterpret_cast(view); + Valtype32 val = elfcpp::Swap<32, big_endian>::readval(wv); + Valtype addend = (extract_addend ? Bits<16>::sign_extend32(val & 0xffff) + : addend_a); + + Valtype x = psymval->value(object, addend); + x = ((x + (uint64_t) 0x800080008000) >> 48) & 0xffff; + val = Bits<32>::bit_select32(val, x, 0xffff); + + if (calculate_only) + *calculated_value = x; + else + elfcpp::Swap<32, big_endian>::writeval(wv, val); + + return This::STATUS_OKAY; + } }; template @@ -9935,6 +9981,8 @@ mips_get_size_for_reloc(unsigned int r_type, Relobj* object) case elfcpp::R_MIPS_16: case elfcpp::R_MIPS_HI16: case elfcpp::R_MIPS_LO16: + case elfcpp::R_MIPS_HIGHER: + case elfcpp::R_MIPS_HIGHEST: case elfcpp::R_MIPS_GPREL16: case elfcpp::R_MIPS16_HI16: case elfcpp::R_MIPS16_LO16: @@ -10673,7 +10721,11 @@ Target_mips::Scan::local( { case elfcpp::R_MIPS16_HI16: case elfcpp::R_MIPS_HI16: + case elfcpp::R_MIPS_HIGHER: + case elfcpp::R_MIPS_HIGHEST: case elfcpp::R_MICROMIPS_HI16: + case elfcpp::R_MICROMIPS_HIGHER: + case elfcpp::R_MICROMIPS_HIGHEST: // Don't refuse a high part relocation if it's against // no symbol (e.g. part of a compound relocation). if (r_sym == 0) @@ -11176,7 +11228,11 @@ Target_mips::Scan::global( { case elfcpp::R_MIPS16_HI16: case elfcpp::R_MIPS_HI16: + case elfcpp::R_MIPS_HIGHER: + case elfcpp::R_MIPS_HIGHEST: case elfcpp::R_MICROMIPS_HI16: + case elfcpp::R_MICROMIPS_HIGHER: + case elfcpp::R_MICROMIPS_HIGHEST: // Don't refuse a high part relocation if it's against // no symbol (e.g. part of a compound relocation). if (r_sym == 0) @@ -12121,6 +12177,19 @@ Target_mips::Relocate::relocate( extract_addend, calculate_only, &calculated_value); break; + case elfcpp::R_MIPS_HIGHER: + case elfcpp::R_MICROMIPS_HIGHER: + reloc_status = Reloc_funcs::relhigher(view, object, psymval, r_addend, + extract_addend, calculate_only, + &calculated_value); + break; + case elfcpp::R_MIPS_HIGHEST: + case elfcpp::R_MICROMIPS_HIGHEST: + reloc_status = Reloc_funcs::relhighest(view, object, psymval, + r_addend, extract_addend, + calculate_only, + &calculated_value); + break; default: gold_error_at_location(relinfo, relnum, r_offset, _("unsupported reloc %u"), r_types[i]); @@ -12186,10 +12255,14 @@ Target_mips::Scan::get_reference_flags( case elfcpp::R_MIPS_64: case elfcpp::R_MIPS_HI16: case elfcpp::R_MIPS_LO16: + case elfcpp::R_MIPS_HIGHER: + case elfcpp::R_MIPS_HIGHEST: case elfcpp::R_MIPS16_HI16: case elfcpp::R_MIPS16_LO16: case elfcpp::R_MICROMIPS_HI16: case elfcpp::R_MICROMIPS_LO16: + case elfcpp::R_MICROMIPS_HIGHER: + case elfcpp::R_MICROMIPS_HIGHEST: return Symbol::ABSOLUTE_REF; case elfcpp::R_MIPS_26: -- 2.30.2