[ELF][MIPS] Support R_MIPS_PC32 relocation handling
authorSimon Atanasyan <simon@atanasyan.com>
Thu, 4 Feb 2016 12:31:39 +0000 (12:31 +0000)
committerSimon Atanasyan <simon@atanasyan.com>
Thu, 4 Feb 2016 12:31:39 +0000 (12:31 +0000)
llvm-svn: 259782

lld/ELF/Target.cpp
lld/test/ELF/mips-pc-relocs.s

index 7782c0f..2b1e9f7 100644 (file)
@@ -1437,16 +1437,17 @@ bool MipsTargetInfo<ELFT>::needsPlt(uint32_t Type, const SymbolBody &S) const {
 
 static uint16_t mipsHigh(uint64_t V) { return (V + 0x8000) >> 16; }
 
-template <endianness E, uint8_t BSIZE>
+template <endianness E, uint8_t BSIZE, uint8_t SHIFT>
 static void applyMipsPcReloc(uint8_t *Loc, uint32_t Type, uint64_t P,
                              uint64_t SA) {
-  uint32_t Mask = ~(0xffffffff << BSIZE);
+  uint32_t Mask = 0xffffffff >> (32 - BSIZE);
   uint32_t Instr = read32<E>(Loc);
-  int64_t A = SignExtend64<BSIZE + 2>((Instr & Mask) << 2);
-  checkAlignment<4>(SA + A, Type);
+  int64_t A = SignExtend64<BSIZE + SHIFT>((Instr & Mask) << SHIFT);
+  if (SHIFT > 0)
+    checkAlignment<(1 << SHIFT)>(SA + A, Type);
   int64_t V = SA + A - P;
-  checkInt<BSIZE + 2>(V, Type);
-  write32<E>(Loc, (Instr & ~Mask) | ((V >> 2) & Mask));
+  checkInt<BSIZE + SHIFT>(V, Type);
+  write32<E>(Loc, (Instr & ~Mask) | ((V >> SHIFT) & Mask));
 }
 
 template <class ELFT>
@@ -1498,16 +1499,19 @@ void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
     break;
   }
   case R_MIPS_PC16:
-    applyMipsPcReloc<E, 16>(Loc, Type, P, SA);
+    applyMipsPcReloc<E, 16, 2>(Loc, Type, P, SA);
     break;
   case R_MIPS_PC19_S2:
-    applyMipsPcReloc<E, 19>(Loc, Type, P, SA);
+    applyMipsPcReloc<E, 19, 2>(Loc, Type, P, SA);
     break;
   case R_MIPS_PC21_S2:
-    applyMipsPcReloc<E, 21>(Loc, Type, P, SA);
+    applyMipsPcReloc<E, 21, 2>(Loc, Type, P, SA);
     break;
   case R_MIPS_PC26_S2:
-    applyMipsPcReloc<E, 26>(Loc, Type, P, SA);
+    applyMipsPcReloc<E, 26, 2>(Loc, Type, P, SA);
+    break;
+  case R_MIPS_PC32:
+    applyMipsPcReloc<E, 32, 0>(Loc, Type, P, SA);
     break;
   case R_MIPS_PCHI16: {
     uint32_t Instr = read32<E>(Loc);
@@ -1546,6 +1550,7 @@ bool MipsTargetInfo<ELFT>::isRelRelative(uint32_t Type) const {
   case R_MIPS_PC19_S2:
   case R_MIPS_PC21_S2:
   case R_MIPS_PC26_S2:
+  case R_MIPS_PC32:
   case R_MIPS_PCHI16:
   case R_MIPS_PCLO16:
     return true;
index 631dd43..b659b9c 100644 (file)
@@ -5,7 +5,7 @@
 # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
 # RUN:         -mcpu=mips32r6 %S/Inputs/mips-dynamic.s -o %t2.o
 # RUN: ld.lld %t1.o %t2.o -o %t.exe
-# RUN: llvm-objdump -mcpu=mips32r6 -d -t %t.exe | FileCheck %s
+# RUN: llvm-objdump -mcpu=mips32r6 -d -t -s %t.exe | FileCheck %s
 
 # REQUIRES: mips
 
@@ -19,6 +19,9 @@ __start:
   aluipc    $2, %pcrel_hi(_foo)     # R_MIPS_PCHI16
   addiu     $2, $2, %pcrel_lo(_foo) # R_MIPS_PCLO16
 
+  .data
+  .word _foo+8-.                    # R_MIPS_PC32
+
 # CHECK:      Disassembly of section .text:
 # CHECK-NEXT: __start:
 # CHECK-NEXT:    20000:       ec c8 00 08     lwpc    $6, 32
@@ -34,5 +37,9 @@ __start:
 # CHECK-NEXT:    20014:       24 42 00 0c     addiu   $2, $2, 12
 #                                      ^-- %lo(0x20020-0x20014)
 
+# CHECK: Contents of section .data:
+# CHECK-NEXT: 30000 ffff0028 00000000 00000000 00000000
+#                   ^-- 0x20020 + 8 - 0x30000
+
 # CHECK: 00020000         .text           00000000 __start
 # CHECK: 00020020         .text           00000000 _foo