[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 ¶ms,
+ 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