[lld] r239221 - [Mips] Handle all grouped relocations in a uniform way

Simon Atanasyan simon at atanasyan.com
Sat Jun 6 10:25:58 PDT 2015


Author: atanasyan
Date: Sat Jun  6 12:25:58 2015
New Revision: 239221

URL: http://llvm.org/viewvc/llvm-project?rev=239221&view=rev
Log:
[Mips] Handle all grouped relocations in a uniform way

No functional changes.

Modified:
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp

Modified: lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp?rev=239221&r1=239220&r2=239221&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp Sat Jun  6 12:25:58 2015
@@ -187,15 +187,14 @@ static uint32_t relocpc32(uint64_t P, ui
 /// local   : ((A | ((P + 4) & 0x3F000000)) + S) >> 2
 static uint32_t reloc26loc(uint64_t P, uint64_t S, int32_t A, uint32_t shift) {
   uint32_t result = (A | ((P + 4) & (0xfc000000 << shift))) + S;
-  return result >> shift;
+  return result;
 }
 
 /// \brief LLD_R_MIPS_GLOBAL_26, LLD_R_MICROMIPS_GLOBAL_26_S1
 /// external: (sign-extend(A) + S) >> 2
 static uint32_t reloc26ext(uint64_t S, int32_t A, uint32_t shift) {
-  int32_t result =
-      shift == 1 ? llvm::SignExtend32<27>(A) : llvm::SignExtend32<28>(A);
-  return (result + S) >> shift;
+  A = shift == 1 ? llvm::SignExtend32<27>(A) : llvm::SignExtend32<28>(A);
+  return A + S;
 }
 
 /// \brief R_MIPS_HI16, R_MIPS_TLS_DTPREL_HI16, R_MIPS_TLS_TPREL_HI16,
@@ -283,7 +282,7 @@ static uint32_t relocPc18(uint64_t P, ui
   A = llvm::SignExtend32<21>(A);
   // FIXME (simon): Check that S + A has 8-byte alignment
   int32_t result = S + A - ((P | 7) ^ 7);
-  return result >> 3;
+  return result;
 }
 
 /// \brief R_MIPS_PC19_S2, R_MICROMIPS_PC19_S2
@@ -292,7 +291,7 @@ static uint32_t relocPc19(uint64_t P, ui
   A = llvm::SignExtend32<21>(A);
   // FIXME (simon): Check that S + A has 4-byte alignment
   int32_t result = S + A - P;
-  return result >> 2;
+  return result;
 }
 
 /// \brief R_MIPS_PC21_S2, R_MICROMIPS_PC21_S2
@@ -301,7 +300,7 @@ static uint32_t relocPc21(uint64_t P, ui
   A = llvm::SignExtend32<23>(A);
   // FIXME (simon): Check that S + A has 4-byte alignment
   int32_t result = S + A - P;
-  return result >> 2;
+  return result;
 }
 
 /// \brief R_MIPS_PC26_S2, R_MICROMIPS_PC26_S2
@@ -310,28 +309,28 @@ static uint32_t relocPc26(uint64_t P, ui
   A = llvm::SignExtend32<28>(A);
   // FIXME (simon): Check that S + A has 4-byte alignment
   int32_t result = S + A - P;
-  return result >> 2;
+  return result;
 }
 
 /// \brief R_MICROMIPS_PC7_S1
 static uint32_t relocPc7(uint64_t P, uint64_t S, int64_t A) {
   A = llvm::SignExtend32<8>(A);
   int32_t result = S + A - P;
-  return result >> 1;
+  return result;
 }
 
 /// \brief R_MICROMIPS_PC10_S1
 static uint32_t relocPc10(uint64_t P, uint64_t S, int64_t A) {
   A = llvm::SignExtend32<11>(A);
   int32_t result = S + A - P;
-  return result >> 1;
+  return result;
 }
 
 /// \brief R_MICROMIPS_PC16_S1
 static uint32_t relocPc16(uint64_t P, uint64_t S, int64_t A) {
   A = llvm::SignExtend32<17>(A);
   int32_t result = S + A - P;
-  return result >> 1;
+  return result;
 }
 
 /// \brief R_MICROMIPS_PC23_S2
@@ -344,7 +343,7 @@ static uint32_t relocPc23(uint64_t P, ui
     llvm::errs() << "The addiupc instruction immediate "
                  << llvm::format_hex(result, 10) << " is out of range.\n";
 
-  return result >> 2;
+  return result;
 }
 
 /// \brief LLD_R_MIPS_32_HI16, LLD_R_MIPS_64_HI16
@@ -352,6 +351,14 @@ static uint64_t relocMaskLow16(uint64_t
   return S + A + 0x8000;
 }
 
+static int64_t relocRel32(int64_t A) {
+  // If output relocation format is REL and the input one is RELA, the only
+  // method to transfer the relocation addend from the input relocation
+  // to the output dynamic relocation is to save this addend to the location
+  // modified by R_MIPS_REL32.
+  return A;
+}
+
 static std::error_code adjustJumpOpCode(uint64_t &ins, uint64_t tgt,
                                         CrossJumpMode mode) {
   if (mode == CrossJumpMode::None)
@@ -409,8 +416,11 @@ static ErrorOr<uint64_t> calculateReloca
                                              Reference::Addend addend,
                                              uint64_t tgtAddr, uint64_t relAddr,
                                              uint64_t gpAddr, bool isGP,
-                                             CrossJumpMode jumpMode) {
-  bool isCrossJump = jumpMode !=  CrossJumpMode::None;
+                                             bool isCrossJump) {
+  if (!tgtAddr) {
+    isGP = false;
+    isCrossJump = false;
+  }
   switch (kind) {
   case R_MIPS_NONE:
     return 0;
@@ -504,6 +514,7 @@ static ErrorOr<uint64_t> calculateReloca
     // We do not do JALR optimization now.
     return 0;
   case R_MIPS_REL32:
+    return relocRel32(addend);
   case R_MIPS_JUMP_SLOT:
   case R_MIPS_COPY:
   case R_MIPS_TLS_DTPMOD32:
@@ -572,6 +583,20 @@ static void relocWrite(uint64_t data, co
   }
 }
 
+static uint32_t getRelKind(const Reference &ref, size_t num) {
+  if (num == 0)
+    return ref.kindValue();
+  return (ref.tag() >> (8 * (num - 1))) & 0xff;
+}
+
+static uint8_t getRelShift(Reference::KindValue kind, bool isCrossJump) {
+  uint8_t shift = getRelocationParams(kind)._shift;
+  if (isCrossJump &&
+      (kind == R_MICROMIPS_26_S1 || kind == LLD_R_MICROMIPS_GLOBAL_26_S1))
+    return 2;
+  return shift;
+}
+
 template <class ELFT>
 std::error_code RelocationHandler<ELFT>::applyRelocation(
     ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
@@ -592,33 +617,28 @@ std::error_code RelocationHandler<ELFT>:
     tgtAddr |= 1;
 
   CrossJumpMode jumpMode = getCrossJumpMode(ref);
+  bool isCrossJump = jumpMode != CrossJumpMode::None;
 
-  ErrorOr<uint64_t> res =
-      calculateRelocation(ref.kindValue(), ref.addend(), tgtAddr, relAddr,
-                          gpAddr, isGpDisp, jumpMode);
-  if (auto ec = res.getError())
-    return ec;
-
-  // If output relocation format is REL and the input one is RELA, the only
-  // method to transfer the relocation addend from the input relocation
-  // to the output dynamic relocation is to save this addend to the location
-  // modified by R_MIPS_REL32.
-  if (ref.kindValue() == R_MIPS_REL32 && !_ctx.isRelaOutputFormat())
-    res = ref.addend();
-
-  Reference::KindValue op = ref.kindValue();
-
-  // FIXME (simon): Handle r_ssym value.
-  for (auto tag = (ref.tag() & 0xffff); tag & 0xff; tag >>= 8) {
-    op = tag & 0xff;
-    res = calculateRelocation(op, *res, 0, relAddr, gpAddr, isGpDisp, jumpMode);
+  uint64_t sym = tgtAddr;
+  ErrorOr<int64_t> res = ref.addend();
+  Reference::KindValue lastRel = R_MIPS_NONE;
+
+  for (size_t relNum = 0; relNum < 3; ++relNum) {
+    Reference::KindValue kind = getRelKind(ref, relNum);
+    if (kind == R_MIPS_NONE)
+      break;
+    res = calculateRelocation(kind, *res, sym, relAddr, gpAddr, isGpDisp,
+                              isCrossJump);
     if (auto ec = res.getError())
       return ec;
+    res = *res >> getRelShift(kind, isCrossJump);
+    // FIXME (simon): Handle r_ssym value.
+    sym = 0;
+    lastRel = kind;
   }
 
-  auto params = getRelocationParams(op);
+  auto params = getRelocationParams(lastRel);
   uint64_t ins = relocRead(params, location);
-
   if (auto ec = adjustJumpOpCode(ins, tgtAddr, jumpMode))
     return ec;
 





More information about the llvm-commits mailing list