diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -113,6 +113,17 @@ ", " + Twine(max).str() + "]" + hint); } +void elf::reportRangeError(uint8_t *loc, int64_t v, int n, const Symbol &sym, + const Twine &msg) { + ErrorPlace errPlace = getErrorPlace(loc); + std::string hint; + if (!sym.getName().empty()) + hint = "; references " + lld::toString(sym) + getDefinedLocation(sym); + errorOrWarn(errPlace.loc + msg + " is out of range: " + Twine(v) + + " is not in [" + Twine(llvm::minIntN(n)) + ", " + + Twine(llvm::maxIntN(n)) + "]" + hint); +} + namespace { // Build a bitmask with one bit set for each RelExpr. // diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -229,6 +229,8 @@ void reportRangeError(uint8_t *loc, const Relocation &rel, const Twine &v, int64_t min, uint64_t max); +void reportRangeError(uint8_t *loc, int64_t v, int n, const Symbol &sym, + const Twine &msg); // Make sure that V can be represented as an N bit signed integer. inline void checkInt(uint8_t *loc, int64_t v, int n, const Relocation &rel) { diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp --- a/lld/ELF/Thunks.cpp +++ b/lld/ELF/Thunks.cpp @@ -896,7 +896,7 @@ int64_t offset = destination.getVA() - (getThunkTargetSym()->getVA() + 4); // The branch offset needs to fit in 26 bits. if (!isInt<26>(offset)) - fatal("R2 save stub branch offset is too large: " + Twine(offset)); + reportRangeError(buf, offset, 26, destination, "R2 save stub offset"); write32(buf + 0, 0xf8410018); // std r2,24(r1) write32(buf + 4, 0x48000000 | (offset & 0x03fffffc)); // b } @@ -910,7 +910,7 @@ void PPC64R12SetupStub::writeTo(uint8_t *buf) { int64_t offset = destination.getVA() - getThunkTargetSym()->getVA(); if (!isInt<34>(offset)) - fatal("offset must fit in 34 bits to encode in the instruction"); + reportRangeError(buf, offset, 34, destination, "R12 setup stub offset"); uint64_t paddi = PADDI_R12_NO_DISP | (((offset >> 16) & 0x3ffff) << 32) | (offset & 0xffff); @@ -927,7 +927,8 @@ void PPC64PCRelPLTStub::writeTo(uint8_t *buf) { int64_t offset = destination.getGotPltVA() - getThunkTargetSym()->getVA(); if (!isInt<34>(offset)) - fatal("offset must fit in 34 bits to encode in the instruction"); + reportRangeError(buf, offset, 34, destination, + "PC-relative PLT stub offset"); uint64_t pld = PLD_R12_NO_DISP | (((offset >> 16) & 0x3ffff) << 32) | (offset & 0xffff); diff --git a/lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s b/lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s --- a/lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s +++ b/lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s @@ -10,7 +10,10 @@ # RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t.o # RUN: not ld.lld -T %t.script %t.o -o /dev/null 2>&1 | FileCheck %s -# CHECK: error: R2 save stub branch offset is too large: -268501028 +# CHECK: error: R2 save stub offset is out of range: -268501028 is not in [-33554432, 33554431]; references callee +# CHECK-NEXT: >>> defined in {{.*}}.o + +# RUN: ld.lld -T %t.script %t.o -o /dev/null --noinhibit-exec .section .text_callee, "ax", %progbits callee: