diff --git a/bolt/include/bolt/Core/BinaryContext.h b/bolt/include/bolt/Core/BinaryContext.h index f1db1fbded6a..5dc5fdb150be 100644 --- a/bolt/include/bolt/Core/BinaryContext.h +++ b/bolt/include/bolt/Core/BinaryContext.h @@ -145,6 +145,29 @@ public: } }; +/// BOLT-exclusive errors generated in core BOLT libraries, optionally holding a +/// string message and whether it is fatal or not. In case it is fatal and if +/// BOLT is running as a standalone process, the process might be killed as soon +/// as the error is checked. +class BOLTError : public ErrorInfo { +public: + static char ID; + + BOLTError(bool IsFatal, const Twine &S = Twine()); + void log(raw_ostream &OS) const override; + bool isFatal() const { return IsFatal; } + + const std::string &getMessage() const { return Msg; } + std::error_code convertToErrorCode() const override; + +private: + bool IsFatal; + std::string Msg; +}; + +Error createNonFatalBOLTError(const Twine &S); +Error createFatalBOLTError(const Twine &S); + class BinaryContext { BinaryContext() = delete; diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp index df835d287680..1c33544f40a1 100644 --- a/bolt/lib/Core/BinaryContext.cpp +++ b/bolt/lib/Core/BinaryContext.cpp @@ -83,6 +83,37 @@ cl::opt CompDirOverride( namespace llvm { namespace bolt { +char BOLTError::ID = 0; + +BOLTError::BOLTError(bool IsFatal, const Twine &S) + : IsFatal(IsFatal), Msg(S.str()) {} + +void BOLTError::log(raw_ostream &OS) const { + if (IsFatal) + OS << "FATAL "; + StringRef ErrMsg = StringRef(Msg); + // Prepend our error prefix if it is missing + if (ErrMsg.empty()) { + OS << "BOLT-ERROR\n"; + } else { + if (!ErrMsg.starts_with("BOLT-ERROR")) + OS << "BOLT-ERROR: "; + OS << ErrMsg << "\n"; + } +} + +std::error_code BOLTError::convertToErrorCode() const { + return inconvertibleErrorCode(); +} + +Error createNonFatalBOLTError(const Twine &S) { + return make_error(/*IsFatal*/ false, S); +} + +Error createFatalBOLTError(const Twine &S) { + return make_error(/*IsFatal*/ true, S); +} + BinaryContext::BinaryContext(std::unique_ptr Ctx, std::unique_ptr DwCtx, std::unique_ptr TheTriple, diff --git a/bolt/lib/Passes/ADRRelaxationPass.cpp b/bolt/lib/Passes/ADRRelaxationPass.cpp index 681b5ab688e0..aa715a3f3787 100644 --- a/bolt/lib/Passes/ADRRelaxationPass.cpp +++ b/bolt/lib/Passes/ADRRelaxationPass.cpp @@ -110,7 +110,7 @@ Error ADRRelaxationPass::runOnFunctions(BinaryContext &BC) { "ADRRelaxationPass"); if (PassFailed) - exit(1); + return createFatalBOLTError(""); return Error::success(); } diff --git a/bolt/lib/Passes/BinaryPasses.cpp b/bolt/lib/Passes/BinaryPasses.cpp index e90f01acf93b..281488b3fbae 100644 --- a/bolt/lib/Passes/BinaryPasses.cpp +++ b/bolt/lib/Passes/BinaryPasses.cpp @@ -528,12 +528,14 @@ Error FixupBranches::runOnFunctions(BinaryContext &BC) { } Error FinalizeFunctions::runOnFunctions(BinaryContext &BC) { + std::atomic HasFatal{false}; ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) { if (!BF.finalizeCFIState()) { if (BC.HasRelocations) { errs() << "BOLT-ERROR: unable to fix CFI state for function " << BF << ". Exiting.\n"; - exit(1); + HasFatal = true; + return; } BF.setSimple(false); return; @@ -552,6 +554,8 @@ Error FinalizeFunctions::runOnFunctions(BinaryContext &BC) { ParallelUtilities::runOnEachFunction( BC, ParallelUtilities::SchedulingPolicy::SP_CONSTANT, WorkFun, SkipPredicate, "FinalizeFunctions"); + if (HasFatal) + return createFatalBOLTError("finalize CFI state failure"); return Error::success(); } diff --git a/bolt/lib/Passes/Instrumentation.cpp b/bolt/lib/Passes/Instrumentation.cpp index b6dc7705bf61..26b4a67fec42 100644 --- a/bolt/lib/Passes/Instrumentation.cpp +++ b/bolt/lib/Passes/Instrumentation.cpp @@ -567,10 +567,9 @@ Error Instrumentation::runOnFunctions(BinaryContext &BC) { ErrorOr SetupSection = BC.getUniqueSectionByName("I__setup"); - if (!SetupSection) { - llvm::errs() << "Cannot find I__setup section\n"; - exit(1); - } + if (!SetupSection) + return createFatalBOLTError("Cannot find I__setup section\n"); + MCSymbol *Target = BC.registerNameAtAddress( "__bolt_instr_setup", SetupSection->getAddress(), 0, 0); MCInst NewInst; @@ -586,10 +585,9 @@ Error Instrumentation::runOnFunctions(BinaryContext &BC) { BinaryBasicBlock &BB = Ctor->front(); ErrorOr FiniSection = BC.getUniqueSectionByName("I__fini"); - if (!FiniSection) { - llvm::errs() << "Cannot find I__fini section\n"; - exit(1); - } + if (!FiniSection) + return createFatalBOLTError("Cannot find I__fini section"); + MCSymbol *Target = BC.registerNameAtAddress( "__bolt_instr_fini", FiniSection->getAddress(), 0, 0); auto IsLEA = [&BC](const MCInst &Inst) { return BC.MIB->isLEA64r(Inst); }; diff --git a/bolt/lib/Passes/PatchEntries.cpp b/bolt/lib/Passes/PatchEntries.cpp index ddef85409f02..0b0e15f1b5bd 100644 --- a/bolt/lib/Passes/PatchEntries.cpp +++ b/bolt/lib/Passes/PatchEntries.cpp @@ -103,7 +103,7 @@ Error PatchEntries::runOnFunctions(BinaryContext &BC) { if (opts::ForcePatch) { errs() << "BOLT-ERROR: unable to patch entries in " << Function << "\n"; - exit(1); + return createFatalBOLTError(""); } continue; diff --git a/bolt/lib/Passes/ReorderFunctions.cpp b/bolt/lib/Passes/ReorderFunctions.cpp index 86fc03d4e0f0..9cecd08e9dcf 100644 --- a/bolt/lib/Passes/ReorderFunctions.cpp +++ b/bolt/lib/Passes/ReorderFunctions.cpp @@ -444,7 +444,7 @@ Error ReorderFunctions::runOnFunctions(BinaryContext &BC) { if (!FuncsFile) { errs() << "BOLT-ERROR: ordered functions file " << opts::GenerateFunctionOrderFile << " cannot be opened\n"; - exit(1); + return createFatalBOLTError(""); } } @@ -455,7 +455,7 @@ Error ReorderFunctions::runOnFunctions(BinaryContext &BC) { if (!LinkSectionsFile) { errs() << "BOLT-ERROR: link sections file " << opts::LinkSectionsFile << " cannot be opened\n"; - exit(1); + return createFatalBOLTError(""); } } diff --git a/bolt/lib/Passes/VeneerElimination.cpp b/bolt/lib/Passes/VeneerElimination.cpp index 06cfecc04ddb..d844a068184d 100644 --- a/bolt/lib/Passes/VeneerElimination.cpp +++ b/bolt/lib/Passes/VeneerElimination.cpp @@ -79,8 +79,8 @@ Error VeneerElimination::runOnFunctions(BinaryContext &BC) { VeneerCallers++; if (!BC.MIB->replaceBranchTarget( Instr, VeneerDestinations[TargetSymbol], BC.Ctx.get())) { - errs() << "BOLT-ERROR: updating veneer call destination failed\n"; - exit(1); + return createFatalBOLTError( + "BOLT-ERROR: updating veneer call destination failed\n"); } } }