[lld] r256172 - [ELF][MIPS] Support some of R_MIPS_PCxxx relocations

Simon Atanasyan via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 21 09:36:40 PST 2015


Author: atanasyan
Date: Mon Dec 21 11:36:40 2015
New Revision: 256172

URL: http://llvm.org/viewvc/llvm-project?rev=256172&view=rev
Log:
[ELF][MIPS] Support some of R_MIPS_PCxxx relocations

The patch adds support for R_MIPS_PC16, R_MIPS_PC19_S2, R_MIPS_PC21_S2,
R_MIPS_PC26_S2, R_MIPS_PCHI16, R_MIPS_PCLO16 relocations handling.

Added:
    lld/trunk/test/ELF/mips-pc-relocs.s
Modified:
    lld/trunk/ELF/Target.cpp

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=256172&r1=256171&r2=256172&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Mon Dec 21 11:36:40 2015
@@ -206,6 +206,7 @@ public:
   void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
                    uint64_t SA, uint64_t ZA = 0,
                    uint8_t *PairedLoc = nullptr) const override;
+  bool isRelRelative(uint32_t Type) const override;
 };
 } // anonymous namespace
 
@@ -1352,6 +1353,18 @@ bool MipsTargetInfo<ELFT>::relocNeedsPlt
 
 static uint16_t mipsHigh(uint64_t V) { return (V + 0x8000) >> 16; }
 
+template <endianness E, uint8_t BSIZE>
+static void applyMipsPcReloc(uint8_t *Loc, uint32_t Type, uint64_t P,
+                             uint64_t SA) {
+  uint32_t Mask = ~(0xffffffff << BSIZE);
+  uint32_t Instr = read32<E>(Loc);
+  int64_t A = SignExtend64<BSIZE + 2>((Instr & Mask) << 2);
+  checkAlignment<4>(SA + A, Type);
+  int64_t V = SA + A - P;
+  checkInt<BSIZE + 2>(V, Type);
+  write32<E>(Loc, (Instr & ~Mask) | ((V >> 2) & Mask));
+}
+
 template <class ELFT>
 void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
                                        uint32_t Type, uint64_t P, uint64_t SA,
@@ -1390,11 +1403,56 @@ void MipsTargetInfo<ELFT>::relocateOne(u
     write32<E>(Loc, (Instr & 0xffff0000) | ((SA + AHL) & 0xffff));
     break;
   }
+  case R_MIPS_PC16:
+    applyMipsPcReloc<E, 16>(Loc, Type, P, SA);
+    break;
+  case R_MIPS_PC19_S2:
+    applyMipsPcReloc<E, 19>(Loc, Type, P, SA);
+    break;
+  case R_MIPS_PC21_S2:
+    applyMipsPcReloc<E, 21>(Loc, Type, P, SA);
+    break;
+  case R_MIPS_PC26_S2:
+    applyMipsPcReloc<E, 26>(Loc, Type, P, SA);
+    break;
+  case R_MIPS_PCHI16: {
+    uint32_t Instr = read32<E>(Loc);
+    if (PairedLoc) {
+      uint64_t AHL = ((Instr & 0xffff) << 16) +
+                     SignExtend64<16>(read32<E>(PairedLoc) & 0xffff);
+      write32<E>(Loc, (Instr & 0xffff0000) | mipsHigh(SA + AHL - P));
+    } else {
+      warning("Can't find matching R_MIPS_PCLO16 relocation for R_MIPS_PCHI16");
+      write32<E>(Loc, (Instr & 0xffff0000) | mipsHigh(SA - P));
+    }
+    break;
+  }
+  case R_MIPS_PCLO16: {
+    uint32_t Instr = read32<E>(Loc);
+    int64_t AHL = SignExtend64<16>(Instr & 0xffff);
+    write32<E>(Loc, (Instr & 0xffff0000) | ((SA + AHL - P) & 0xffff));
+    break;
+  }
   default:
     error("unrecognized reloc " + Twine(Type));
   }
 }
 
+template <class ELFT>
+bool MipsTargetInfo<ELFT>::isRelRelative(uint32_t Type) const {
+  switch (Type) {
+  default:
+    return false;
+  case R_MIPS_PC16:
+  case R_MIPS_PC19_S2:
+  case R_MIPS_PC21_S2:
+  case R_MIPS_PC26_S2:
+  case R_MIPS_PCHI16:
+  case R_MIPS_PCLO16:
+    return true;
+  }
+}
+
 template <class ELFT> typename ELFFile<ELFT>::uintX_t getMipsGpAddr() {
   const unsigned GPOffset = 0x7ff0;
   return Out<ELFT>::Got->getVA() ? (Out<ELFT>::Got->getVA() + GPOffset) : 0;

Added: lld/trunk/test/ELF/mips-pc-relocs.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-pc-relocs.s?rev=256172&view=auto
==============================================================================
--- lld/trunk/test/ELF/mips-pc-relocs.s (added)
+++ lld/trunk/test/ELF/mips-pc-relocs.s Mon Dec 21 11:36:40 2015
@@ -0,0 +1,38 @@
+# Check R_MIPS_PCxxx relocations calculation.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN:         -mcpu=mips32r6 %s -o %t1.o
+# 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
+
+# REQUIRES: mips
+
+  .text
+  .globl  __start
+__start:
+  lwpc      $6, _foo                # R_MIPS_PC19_S2
+  beqc      $5, $6, _foo            # R_MIPS_PC16
+  beqzc     $9, _foo                # R_MIPS_PC21_S2
+  bc        _foo                    # R_MIPS_PC26_S2
+  aluipc    $2, %pcrel_hi(_foo)     # R_MIPS_PCHI16
+  addiu     $2, $2, %pcrel_lo(_foo) # R_MIPS_PCLO16
+
+# CHECK:      Disassembly of section .text:
+# CHECK-NEXT: __start:
+# CHECK-NEXT:    20000:       ec c8 00 08     lwpc    $6, 32
+#                                      ^-- (0x20020-0x20000)>>2
+# CHECK-NEXT:    20004:       20 a6 00 06     beqc    $5, $6, 24
+#                                      ^-- (0x20020-4-0x20004)>>2
+# CHECK-NEXT:    20008:       d9 20 00 05     beqzc   $9, 20
+#                                      ^-- (0x20020-4-0x20008)>>2
+# CHECK-NEXT:    2000c:       c8 00 00 04     bc      16
+#                                      ^-- (0x20020-4-0x2000c)>>2
+# CHECK-NEXT:    20010:       ec 5f 00 00     aluipc  $2, 0
+#                                      ^-- %hi(0x20020-0x20010)
+# CHECK-NEXT:    20014:       24 42 00 0c     addiu   $2, $2, 12
+#                                      ^-- %lo(0x20020-0x20014)
+
+# CHECK: 00020000         .text           00000000 __start
+# CHECK: 00020020         .text           00000000 _foo




More information about the llvm-commits mailing list