This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][gold] PR 21111: Mips: Add HIGHER and HIGHEST relocations


This patch adds support for R_MIPS_HIGHER, R_MIPS_HIGHEST, R_MICROMIPS_HIGHER
and R_MICROMIPS_HIGHEST relocations.

Regards,
Vladimir

ChangeLog -

	* 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.
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:

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]