aboutsummaryrefslogtreecommitdiff
path: root/gold/mips.cc
diff options
context:
space:
mode:
authorVladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com>2017-02-15 00:47:36 -0800
committerCary Coutant <ccoutant@gmail.com>2017-02-15 00:55:36 -0800
commite242ece1e890b66d226b38b489a7edd79b3656d5 (patch)
tree003dfbe319db848bbae57b7392bb0cc1efa295ca /gold/mips.cc
parent66a5a74065ac79b90618b02f4c550904b50a59f5 (diff)
downloadgdb-e242ece1e890b66d226b38b489a7edd79b3656d5.zip
gdb-e242ece1e890b66d226b38b489a7edd79b3656d5.tar.gz
gdb-e242ece1e890b66d226b38b489a7edd79b3656d5.tar.bz2
Add support for R_MIPS_HIGHER/HIGHEST, R_MICROMIPS_HIGHER/HIGHEST relocations.
2017-02-15 Vladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com> 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.
Diffstat (limited to 'gold/mips.cc')
-rw-r--r--gold/mips.cc73
1 files changed, 73 insertions, 0 deletions
diff --git a/gold/mips.cc b/gold/mips.cc
index 56af570..7b19e4c 100644
--- a/gold/mips.cc
+++ b/gold/mips.cc
@@ -5579,6 +5579,52 @@ class Mips_relocate_functions : public Relocate_functions<size, big_endian>
return This::STATUS_OKAY;
}
+ // R_MIPS_HIGHER, R_MICROMIPS_HIGHER
+ static inline typename This::Status
+ relhigher(unsigned char* view, const Mips_relobj<size, big_endian>* object,
+ const Symbol_value<size>* psymval, Mips_address addend_a,
+ bool extract_addend, bool calculate_only, Valtype* calculated_value)
+ {
+ Valtype32* wv = reinterpret_cast<Valtype32*>(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<size, big_endian>* object,
+ const Symbol_value<size>* psymval, Mips_address addend_a,
+ bool extract_addend, bool calculate_only,
+ Valtype* calculated_value)
+ {
+ Valtype32* wv = reinterpret_cast<Valtype32*>(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<int size, bool big_endian>
@@ -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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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<size, big_endian>::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: