From 94921e9f8ad04793638e02a6104f63e06ae62b9e Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 11 Sep 2020 09:31:37 -0700 Subject: [PATCH] [ELF] Define a reportRangeError() overload for thunks and tidy up recent PPC64 thunk range errors Prefer `errorOrWarn` to `fatal` for recoverable errors and graceful degradation when --noinhibit-exec is specified. Mention the destination symbol, otherwise the diagnostic is not really actionable. Two errors are not tested but the patch does not intend to add the coverage. Reviewed By: grimar Differential Revision: https://reviews.llvm.org/D87486 --- lld/ELF/Relocations.cpp | 11 +++++++++++ lld/ELF/Target.h | 2 ++ lld/ELF/Thunks.cpp | 7 ++++--- lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s | 5 ++++- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 3080d53c332..1ff47244c99 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -113,6 +113,17 @@ void elf::reportRangeError(uint8_t *loc, const Relocation &rel, const Twine &v, ", " + 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 index e53ac4d0662..9399ecf526f 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -229,6 +229,8 @@ template bool isMipsPIC(const Defined *sym); 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 index 6a8ea4dc0e4..684ff5154a3 100644 --- a/lld/ELF/Thunks.cpp +++ b/lld/ELF/Thunks.cpp @@ -896,7 +896,7 @@ void PPC64R2SaveStub::writeTo(uint8_t *buf) { 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 PPC64R2SaveStub::addSymbols(ThunkSection &isec) { 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 PPC64R12SetupStub::addSymbols(ThunkSection &isec) { 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 index a6e99db8c5c..4175ba31310 100644 --- 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: -- 2.11.0