[lld] r239224 - [Mips] Perform an overflow checking for relocations results

Simon Atanasyan simon at atanasyan.com
Sat Jun 6 10:26:19 PDT 2015


Author: atanasyan
Date: Sat Jun  6 12:26:18 2015
New Revision: 239224

URL: http://llvm.org/viewvc/llvm-project?rev=239224&view=rev
Log:
[Mips] Perform an overflow checking for relocations results

Added:
    lld/trunk/test/elf/Mips/hilo16-3-overflow.test
    lld/trunk/test/elf/Mips/rel-gprel16-overflow.test
    lld/trunk/test/elf/Mips/rel-pc21-s2-overflow.test
Modified:
    lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
    lld/trunk/test/elf/Mips/pc23-range.test

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=239224&r1=239223&r2=239224&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp Sat Jun  6 12:26:18 2015
@@ -24,11 +24,31 @@ enum class CrossJumpMode {
   ToMicro    // cross isa jump to microMips symbol
 };
 
+typedef std::function<std::error_code(int64_t, bool)> OverflowChecker;
+
+static std::error_code dummyCheck(int64_t, bool) {
+  return std::error_code();
+}
+
+template <int BITS> static std::error_code signedCheck(int64_t res, bool) {
+  if (llvm::isInt<BITS>(res))
+    return std::error_code();
+  return make_out_of_range_reloc_error();
+}
+
+template <int BITS>
+static std::error_code gpDispCheck(int64_t res, bool isGpDisp) {
+  if (!isGpDisp || llvm::isInt<BITS>(res))
+    return std::error_code();
+  return make_out_of_range_reloc_error();
+}
+
 struct MipsRelocationParams {
   uint8_t _size;  // Relocations's size in bytes
   uint64_t _mask; // Read/write mask of relocation
   uint8_t _shift; // Relocation's addendum left shift size
   bool _shuffle;  // Relocation's addendum/result needs to be shuffled
+  OverflowChecker _overflow; // Check the relocation result
 };
 
 template <class ELFT> class RelocationHandler : public TargetRelocationHandler {
@@ -50,34 +70,35 @@ private:
 static MipsRelocationParams getRelocationParams(uint32_t rType) {
   switch (rType) {
   case R_MIPS_NONE:
-    return {4, 0x0, 0, false};
+    return {4, 0x0, 0, false, dummyCheck};
   case R_MIPS_64:
   case R_MIPS_SUB:
-    return {8, 0xffffffffffffffffull, 0, false};
+    return {8, 0xffffffffffffffffull, 0, false, dummyCheck};
   case R_MIPS_32:
   case R_MIPS_GPREL32:
   case R_MIPS_REL32:
   case R_MIPS_PC32:
   case R_MIPS_EH:
-    return {4, 0xffffffff, 0, false};
+    return {4, 0xffffffff, 0, false, dummyCheck};
   case LLD_R_MIPS_32_HI16:
-    return {4, 0xffff0000, 0, false};
+    return {4, 0xffff0000, 0, false, dummyCheck};
   case LLD_R_MIPS_64_HI16:
-    return {8, 0xffffffffffff0000ull, 0, false};
+    return {8, 0xffffffffffff0000ull, 0, false, dummyCheck};
   case R_MIPS_26:
   case LLD_R_MIPS_GLOBAL_26:
-    return {4, 0x3ffffff, 2, false};
+    return {4, 0x3ffffff, 2, false, dummyCheck};
   case R_MIPS_PC18_S3:
-    return {4, 0x3ffff, 3, false};
+    return {4, 0x3ffff, 3, false, signedCheck<21>};
   case R_MIPS_PC19_S2:
-    return {4, 0x7ffff, 2, false};
+    return {4, 0x7ffff, 2, false, signedCheck<21>};
   case R_MIPS_PC21_S2:
-    return {4, 0x1fffff, 2, false};
+    return {4, 0x1fffff, 2, false, signedCheck<23>};
   case R_MIPS_PC26_S2:
-    return {4, 0x3ffffff, 2, false};
+    return {4, 0x3ffffff, 2, false, signedCheck<28>};
   case R_MIPS_HI16:
+    return {4, 0xffff, 0, false, gpDispCheck<16>};
   case R_MIPS_LO16:
-    return {4, 0xffff, 0, false};
+    return {4, 0xffff, 0, false, dummyCheck};
   case R_MIPS_PCHI16:
   case R_MIPS_PCLO16:
   case R_MIPS_GOT16:
@@ -89,7 +110,7 @@ static MipsRelocationParams getRelocatio
   case R_MIPS_TLS_GD:
   case R_MIPS_TLS_LDM:
   case R_MIPS_TLS_GOTTPREL:
-    return {4, 0xffff, 0, false};
+    return {4, 0xffff, 0, false, signedCheck<16>};
   case R_MIPS_GOT_HI16:
   case R_MIPS_GOT_LO16:
   case R_MIPS_CALL_HI16:
@@ -100,7 +121,7 @@ static MipsRelocationParams getRelocatio
   case R_MIPS_TLS_TPREL_LO16:
   case LLD_R_MIPS_HI16:
   case LLD_R_MIPS_LO16:
-    return {4, 0xffff, 0, false};
+    return {4, 0xffff, 0, false, dummyCheck};
   case R_MICROMIPS_GOT_HI16:
   case R_MICROMIPS_GOT_LO16:
   case R_MICROMIPS_CALL_HI16:
@@ -109,30 +130,31 @@ static MipsRelocationParams getRelocatio
   case R_MICROMIPS_TLS_DTPREL_LO16:
   case R_MICROMIPS_TLS_TPREL_HI16:
   case R_MICROMIPS_TLS_TPREL_LO16:
-    return {4, 0xffff, 0, true};
+    return {4, 0xffff, 0, true, dummyCheck};
   case R_MICROMIPS_26_S1:
   case LLD_R_MICROMIPS_GLOBAL_26_S1:
-    return {4, 0x3ffffff, 1, true};
+    return {4, 0x3ffffff, 1, true, dummyCheck};
   case R_MICROMIPS_HI16:
+    return {4, 0xffff, 0, true, gpDispCheck<16>};
   case R_MICROMIPS_LO16:
-  case R_MICROMIPS_GOT16:
-    return {4, 0xffff, 0, true};
+    return {4, 0xffff, 0, true, dummyCheck};
   case R_MICROMIPS_PC16_S1:
-    return {4, 0xffff, 1, true};
+    return {4, 0xffff, 1, true, signedCheck<17>};
   case R_MICROMIPS_PC7_S1:
-    return {4, 0x7f, 1, false};
+    return {4, 0x7f, 1, false, signedCheck<8>};
   case R_MICROMIPS_PC10_S1:
-    return {4, 0x3ff, 1, false};
+    return {4, 0x3ff, 1, false, signedCheck<11>};
   case R_MICROMIPS_PC23_S2:
-    return {4, 0x7fffff, 2, true};
+    return {4, 0x7fffff, 2, true, signedCheck<25>};
   case R_MICROMIPS_PC18_S3:
-    return {4, 0x3ffff, 3, true};
+    return {4, 0x3ffff, 3, true, signedCheck<21>};
   case R_MICROMIPS_PC19_S2:
-    return {4, 0x7ffff, 2, true};
+    return {4, 0x7ffff, 2, true, signedCheck<21>};
   case R_MICROMIPS_PC21_S2:
-    return {4, 0x1fffff, 2, true};
+    return {4, 0x1fffff, 2, true, signedCheck<23>};
   case R_MICROMIPS_PC26_S2:
-    return {4, 0x3ffffff, 2, true};
+    return {4, 0x3ffffff, 2, true, signedCheck<28>};
+  case R_MICROMIPS_GOT16:
   case R_MICROMIPS_CALL16:
   case R_MICROMIPS_TLS_GD:
   case R_MICROMIPS_TLS_LDM:
@@ -140,26 +162,26 @@ static MipsRelocationParams getRelocatio
   case R_MICROMIPS_GOT_DISP:
   case R_MICROMIPS_GOT_PAGE:
   case R_MICROMIPS_GOT_OFST:
-    return {4, 0xffff, 0, true};
+    return {4, 0xffff, 0, true, signedCheck<16>};
   case R_MIPS_JALR:
-    return {4, 0x0, 0, false};
+    return {4, 0x0, 0, false, dummyCheck};
   case R_MICROMIPS_JALR:
-    return {4, 0x0, 0, true};
+    return {4, 0x0, 0, true, dummyCheck};
   case R_MIPS_JUMP_SLOT:
   case R_MIPS_COPY:
   case R_MIPS_TLS_DTPMOD32:
   case R_MIPS_TLS_DTPREL32:
   case R_MIPS_TLS_TPREL32:
     // Ignore runtime relocations.
-    return {4, 0x0, 0, false};
+    return {4, 0x0, 0, false, dummyCheck};
   case R_MIPS_TLS_DTPMOD64:
   case R_MIPS_TLS_DTPREL64:
   case R_MIPS_TLS_TPREL64:
-    return {8, 0x0, 0, false};
+    return {8, 0x0, 0, false, dummyCheck};
   case LLD_R_MIPS_GLOBAL_GOT:
   case LLD_R_MIPS_STO_PLT:
     // Do nothing.
-    return {4, 0x0, 0, false};
+    return {4, 0x0, 0, false, dummyCheck};
   default:
     llvm_unreachable("Unknown relocation");
   }
@@ -203,7 +225,7 @@ static int32_t reloc26ext(uint64_t S, in
 /// _gp_disp      : hi16 (AHL + GP - P) - (short)(AHL + GP - P) (verify)
 static int32_t relocHi16(uint64_t P, uint64_t S, int64_t AHL, bool isGPDisp) {
   int32_t result = isGPDisp ? AHL + S - P : AHL + S;
-  return (result + 0x8000) >> 16;
+  return ((result + 0x8000) >> 16) & 0xffff;
 }
 
 /// \brief R_MIPS_PCHI16
@@ -262,7 +284,7 @@ static int32_t relocGOTOfst(uint64_t S,
 /// external: sign-extend(A) + S - GP
 static int64_t relocGPRel16(uint64_t S, int64_t A, uint64_t GP) {
   // We added GP0 to addendum for a local symbol during a Relocation pass.
-  return llvm::SignExtend32<16>(A) + S - GP;
+  return A + S - GP;
 }
 
 /// \brief R_MIPS_GPREL32
@@ -326,13 +348,7 @@ static int32_t relocPc16(uint64_t P, uin
 /// \brief R_MICROMIPS_PC23_S2
 static uint32_t relocPc23(uint64_t P, uint64_t S, int64_t A) {
   A = llvm::SignExtend32<25>(A);
-  int32_t result = S + A - P;
-
-  // Check addiupc 16MB range.
-  if (result + 0x1000000 >= 0x2000000)
-    llvm::errs() << "The addiupc instruction immediate "
-                 << llvm::format_hex(result, 10) << " is out of range.\n";
-  return result;
+  return S + A - P;
 }
 
 /// \brief LLD_R_MIPS_32_HI16, LLD_R_MIPS_64_HI16
@@ -406,10 +422,6 @@ static ErrorOr<int64_t> calculateRelocat
                                             uint64_t tgtAddr, uint64_t relAddr,
                                             uint64_t gpAddr, bool isGP,
                                             bool isCrossJump) {
-  if (!tgtAddr) {
-    isGP = false;
-    isCrossJump = false;
-  }
   switch (kind) {
   case R_MIPS_NONE:
     return 0;
@@ -575,11 +587,15 @@ static void relocWrite(uint64_t data, co
 static uint32_t getRelKind(const Reference &ref, size_t num) {
   if (num == 0)
     return ref.kindValue();
+  if (num > 2)
+    return R_MIPS_NONE;
   return (ref.tag() >> (8 * (num - 1))) & 0xff;
 }
 
-static uint8_t getRelShift(Reference::KindValue kind, bool isCrossJump) {
-  uint8_t shift = getRelocationParams(kind)._shift;
+static uint8_t getRelShift(Reference::KindValue kind,
+                           const MipsRelocationParams &params,
+                           bool isCrossJump) {
+  uint8_t shift = params._shift;
   if (isCrossJump &&
       (kind == R_MICROMIPS_26_S1 || kind == LLD_R_MICROMIPS_GLOBAL_26_S1))
     return 2;
@@ -616,13 +632,21 @@ std::error_code RelocationHandler<ELFT>:
     Reference::KindValue kind = getRelKind(ref, relNum);
     if (kind == R_MIPS_NONE)
       break;
+    auto params = getRelocationParams(kind);
     res = calculateRelocation(kind, *res, sym, relAddr, gpAddr, isGpDisp,
                               isCrossJump);
     if (auto ec = res.getError())
       return ec;
-    res = *res >> getRelShift(kind, isCrossJump);
+    // Check result for the last relocation only.
+    if (getRelKind(ref, relNum + 1) == R_MIPS_NONE) {
+      if (auto ec = params._overflow(*res, isGpDisp))
+        return ec;
+    }
+    res = *res >> getRelShift(kind, params, isCrossJump);
     // FIXME (simon): Handle r_ssym value.
     sym = 0;
+    isGpDisp = false;
+    isCrossJump = false;
     lastRel = kind;
   }
 
@@ -658,7 +682,15 @@ Reference::Addend readMipsRelocAddend(Re
                                       const uint8_t *content) {
   auto params = getRelocationParams(kind);
   uint64_t ins = relocRead(params, content);
-  return (ins & params._mask) << params._shift;
+  int64_t res = (ins & params._mask) << params._shift;
+  switch (kind) {
+  case R_MIPS_GPREL16:
+    return llvm::SignExtend32<16>(res);
+  default:
+    // Nothing to do
+    break;
+  }
+  return res;
 }
 
 } // elf

Added: lld/trunk/test/elf/Mips/hilo16-3-overflow.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/hilo16-3-overflow.test?rev=239224&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/hilo16-3-overflow.test (added)
+++ lld/trunk/test/elf/Mips/hilo16-3-overflow.test Sat Jun  6 12:26:18 2015
@@ -0,0 +1,44 @@
+# Check R_MIPS_HI16 relocation overflow handling.
+
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: not lld -flavor gnu -target mipsel -shared -o %t.so %t.o 2>&1 \
+# RUN:       | FileCheck %s
+
+# CHECK: Relocation out of range in file {{.*}} reference from T0+0 to _gp_disp+2147483648 of type 5 (R_MIPS_HI16)
+
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Content:      "0080000000000000"
+#                ^ %hi(gp+0x80000000)
+#                        ^ %lo(gp+0x80000000)
+  AddressAlign: 16
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+
+- Name:         .rel.text
+  Type:         SHT_REL
+  Info:         .text
+  AddressAlign: 4
+  Relocations:
+    - Offset: 0x0
+      Symbol: _gp_disp
+      Type:   R_MIPS_HI16
+    - Offset: 0x4
+      Symbol: _gp_disp
+      Type:   R_MIPS_LO16
+
+Symbols:
+  Global:
+    - Name:    T0
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    8
+    - Name:    _gp_disp

Modified: lld/trunk/test/elf/Mips/pc23-range.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/pc23-range.test?rev=239224&r1=239223&r2=239224&view=diff
==============================================================================
--- lld/trunk/test/elf/Mips/pc23-range.test (original)
+++ lld/trunk/test/elf/Mips/pc23-range.test Sat Jun  6 12:26:18 2015
@@ -1,18 +1,16 @@
 # Check that LLD shows an error if ADDIUPC immediate is out of range.
 
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor gnu -target mipsel -o %t-exe %t-obj 2>&1 | FileCheck %s
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: not lld -flavor gnu -target mipsel -o %t.exe %t.o 2>&1 | FileCheck %s
 
-# CHECK: The addiupc instruction immediate 0x02000008 is out of range
+# CHECK: Relocation out of range in file {{.*}}: reference from __start+4 to T0+4 of type 173 (R_MICROMIPS_PC23_S2)
 
-!ELF
-FileHeader: !FileHeader
+FileHeader:
   Class:   ELFCLASS32
   Data:    ELFDATA2LSB
   Type:    ET_REL
   Machine: EM_MIPS
-  Flags:   [ EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2,
-             EF_MIPS_MICROMIPS ]
+  Flags:   [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, EF_MIPS_MICROMIPS]
 
 Sections:
 - Name:         .text

Added: lld/trunk/test/elf/Mips/rel-gprel16-overflow.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/rel-gprel16-overflow.test?rev=239224&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/rel-gprel16-overflow.test (added)
+++ lld/trunk/test/elf/Mips/rel-gprel16-overflow.test Sat Jun  6 12:26:18 2015
@@ -0,0 +1,48 @@
+# Check R_MIPS_GPREL16 relocation overflow handling.
+#
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: not lld -flavor gnu -target mipsel -shared -o %t.so %t.o 2>&1 \
+# RUN:       | FileCheck %s
+
+# CHECK: Relocation out of range in file {{.*}} reference from +0 to T1+-32768 of type 7 (R_MIPS_GPREL16)
+
+FileHeader:
+  Class:    ELFCLASS32
+  Data:     ELFDATA2LSB
+  Type:     ET_REL
+  Machine:  EM_MIPS
+  Flags:    [EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
+             EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
+
+Sections:
+- Type:         SHT_PROGBITS
+  Name:         .text
+  Type:         SHT_PROGBITS
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+  AddressAlign: 4
+  Size:         4
+
+- Type:         SHT_PROGBITS
+  Name:         .rodata
+  Type:         SHT_PROGBITS
+  Flags:        [ SHF_ALLOC ]
+  AddressAlign: 4
+  Content:      00800000
+
+- Type:         SHT_REL
+  Name:         .rel.rodata
+  Type:         SHT_REL
+  Link:         .symtab
+  Info:         .rodata
+  AddressAlign: 4
+  Relocations:
+    - Offset:      0
+      Symbol:      T1
+      Type:        R_MIPS_GPREL16
+
+Symbols:
+  Global:
+    - Name:     T1
+      Section:  .text
+      Value:    0
+      Size:     4

Added: lld/trunk/test/elf/Mips/rel-pc21-s2-overflow.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Mips/rel-pc21-s2-overflow.test?rev=239224&view=auto
==============================================================================
--- lld/trunk/test/elf/Mips/rel-pc21-s2-overflow.test (added)
+++ lld/trunk/test/elf/Mips/rel-pc21-s2-overflow.test Sat Jun  6 12:26:18 2015
@@ -0,0 +1,45 @@
+# Check R_MIPS_PC21_S2 relocation overflow handling.
+
+# RUN: yaml2obj -format=elf %s > %t.o
+# RUN: not lld -flavor gnu -target mipsel -shared -o %t.exe %t.o 2>&1 \
+# RUN:       | FileCheck %s
+
+# CHECK: Relocation out of range in file {{.*}} reference from T0+0 to T1+4194300 of type 60 (R_MIPS_PC21_S2)
+
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_MIPS
+  Flags:   [EF_MIPS_PIC, EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R6]
+
+Sections:
+- Name:         .text
+  Type:         SHT_PROGBITS
+  Content:      "ffff0f000000000000000000"
+#                                ^ T1
+#                ^ T0 A := 0xfffff
+  AddressAlign: 16
+  Flags:        [ SHF_ALLOC, SHF_EXECINSTR ]
+
+- Name:         .rel.text
+  Type:         SHT_REL
+  Info:         .text
+  AddressAlign: 4
+  Relocations:
+    - Offset: 0
+      Symbol: T1
+      Type:   R_MIPS_PC21_S2
+
+Symbols:
+  Global:
+    - Name:    T0
+      Section: .text
+      Type:    STT_FUNC
+      Value:   0
+      Size:    8
+    - Name:    T1
+      Section: .text
+      Type:    STT_FUNC
+      Value:   8
+      Size:    4





More information about the llvm-commits mailing list