summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Writer.cpp12
-rw-r--r--lld/test/elf2/Inputs/abs.s2
-rw-r--r--lld/test/elf2/relocation-errors.s10
3 files changed, 22 insertions, 2 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 9826203636a..ae996e197bd 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -14,6 +14,7 @@
#include "Symbols.h"
#include "SymbolTable.h"
+#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/StringTableBuilder.h"
@@ -499,9 +500,16 @@ template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
case llvm::ELF::R_X86_64_64:
support::endian::write64le(Location, SymVA + RI.r_addend);
break;
- case llvm::ELF::R_X86_64_32:
- support::endian::write32le(Location, SymVA + RI.r_addend);
+ case llvm::ELF::R_X86_64_32: {
+ APInt VA(64, SymVA);
+ APInt Addend(64, RI.r_addend, true);
+ APInt Result64 = VA + Addend;
+ APInt Result = Result64.trunc(32);
+ if (Result.zext(64) != Result64)
+ error("Relocation out of range");
+ support::endian::write32le(Location, Result.getZExtValue());
break;
+ }
default:
llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';
break;
diff --git a/lld/test/elf2/Inputs/abs.s b/lld/test/elf2/Inputs/abs.s
index 5e3f124c568..dc7f67a3c25 100644
--- a/lld/test/elf2/Inputs/abs.s
+++ b/lld/test/elf2/Inputs/abs.s
@@ -1,2 +1,4 @@
.global abs
abs = 0x42
+.global big
+big = 0x1000000000
diff --git a/lld/test/elf2/relocation-errors.s b/lld/test/elf2/relocation-errors.s
new file mode 100644
index 00000000000..485d5d03ade
--- /dev/null
+++ b/lld/test/elf2/relocation-errors.s
@@ -0,0 +1,10 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/abs.s -o %tabs
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: not lld -flavor gnu2 %tabs %t -o %t2 2>&1 | FileCheck %s
+// REQUIRES: x86
+
+.global _start
+_start:
+ movl $big, %edx
+
+#CHECK: Relocation out of range
OpenPOWER on IntegriCloud