diff options
| -rw-r--r-- | lld/ELF/Writer.cpp | 12 | ||||
| -rw-r--r-- | lld/test/elf2/Inputs/abs.s | 2 | ||||
| -rw-r--r-- | lld/test/elf2/relocation-errors.s | 10 |
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 |

