diff --git a/bolt/include/bolt/Core/BinaryFunction.h b/bolt/include/bolt/Core/BinaryFunction.h index 51b139a15e1a0..aea418034709f 100644 --- a/bolt/include/bolt/Core/BinaryFunction.h +++ b/bolt/include/bolt/Core/BinaryFunction.h @@ -650,7 +650,8 @@ class BinaryFunction { /// /// Prefer to use BinaryContext::getFunctionForSymbol(EntrySymbol, &ID) /// instead of calling this function directly. - uint64_t getEntryIDForSymbol(const MCSymbol *EntrySymbol) const; + std::optional + getEntryIDForSymbol(const MCSymbol *EntrySymbol) const; /// If the function represents a secondary split function fragment, set its /// parent fragment to \p BF. diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index 72c72bbaf4a65..9630f7d4a8872 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -2374,8 +2374,15 @@ BinaryFunction *BinaryContext::getFunctionForSymbol(const MCSymbol *Symbol, return nullptr; BinaryFunction *BF = BFI->second; - if (EntryDesc) - *EntryDesc = BF->getEntryIDForSymbol(Symbol); + if (EntryDesc) { + const uint64_t Address = BF->getAddress() + Symbol->getOffset(); + if (BF->isInConstantIsland(Address)) { + this->outs() << "BOLT-WARNING: symbol " << Symbol->getName() + << " is in data region of function " << BF->getOneName() + << "(0x" << Twine::utohexstr(BF->getAddress()) << ").\n"; + } + *EntryDesc = BF->getEntryIDForSymbol(Symbol).value_or(0); + } return BF; } diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp index 578a87dc6c09d..07d0d23dfc9f0 100644 --- a/bolt/lib/Core/BinaryFunction.cpp +++ b/bolt/lib/Core/BinaryFunction.cpp @@ -3855,7 +3855,8 @@ MCSymbol *BinaryFunction::getSymbolForEntryID(uint64_t EntryID) { return nullptr; } -uint64_t BinaryFunction::getEntryIDForSymbol(const MCSymbol *Symbol) const { +std::optional +BinaryFunction::getEntryIDForSymbol(const MCSymbol *Symbol) const { if (!isMultiEntry()) return 0; @@ -3882,8 +3883,7 @@ uint64_t BinaryFunction::getEntryIDForSymbol(const MCSymbol *Symbol) const { return NumEntries; ++NumEntries; } - - llvm_unreachable("symbol not found"); + return std::nullopt; } bool BinaryFunction::forEachEntryPoint(EntryPointCallbackTy Callback) const { diff --git a/bolt/test/AArch64/check-symbol-area.s b/bolt/test/AArch64/check-symbol-area.s new file mode 100644 index 0000000000000..abab547dd7558 --- /dev/null +++ b/bolt/test/AArch64/check-symbol-area.s @@ -0,0 +1,36 @@ +// This test checks that when looking for a function corresponding to a +// symbol, BOLT is not looking through a data area (constant island). + +# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o +# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q +# RUN: llvm-bolt %t.exe -o %t.bolt 2>&1 | FileCheck %s + +// Before adding a check for constant islands, BOLT would exit with an error +// of the form: "symbol not found" and throw an LLVM UNREACHABLE error. +# CHECK-NOT: symbol not found +# CHECK-NOT: UNREACHABLE + +// Now BOLT throws a warning and does not crash. +# CHECK: BOLT-WARNING: symbol third_block/1 is in data region of function first_block(0x{{[0-9a-f]+}}). + +.text +.global main +main: + add x0, x1, x1 + bl first_block + ret + +.global first_block +$d: +first_block: + add x0, x1, x1 + bl second_block + ret +second_block: + add x0, x1, x1 + bl third_block + ret +$x: +third_block: + add x0, x1, x1 + ret