OSDN Git Service

[ELF] Define a reportRangeError() overload for thunks and tidy up recent PPC64 thunk...
authorFangrui Song <i@maskray.me>
Fri, 11 Sep 2020 16:31:37 +0000 (09:31 -0700)
committerFangrui Song <i@maskray.me>
Mon, 14 Sep 2020 16:55:59 +0000 (09:55 -0700)
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
lld/ELF/Target.h
lld/ELF/Thunks.cpp
lld/test/ELF/ppc64-toc-call-to-pcrel-long-jump.s

index 3080d53..1ff4724 100644 (file)
@@ -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.
 //
index e53ac4d..9399ecf 100644 (file)
@@ -229,6 +229,8 @@ template <class ELFT> 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) {
index 6a8ea4d..684ff51 100644 (file)
@@ -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    <offset>
 }
@@ -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);
 
index a6e99db..4175ba3 100644 (file)
 # 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: