[BOLT][NFC] Add BOLTError and return it from passes (1/2) (#81522)

As part of the effort to refactor old error handling code that
would directly call exit(1), in this patch we add a new class
BOLTError and auxiliary functions `createFatalBOLTError()` and
`createNonFatalBOLTError()` that allow BOLT code to bubble up the
problem to the caller by using the Error class as a return
type (or Expected). Also changes passes to use these.

Co-authored-by: Rafael Auler <rafaelauler@fb.com>

Test Plan: NFC
This commit is contained in:
Amir Ayupov
2024-02-12 14:39:59 -08:00
committed by GitHub
parent a5f3d1a803
commit fa7dd4919a
8 changed files with 71 additions and 15 deletions

View File

@@ -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<BOLTError> {
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;

View File

@@ -83,6 +83,37 @@ cl::opt<std::string> 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<BOLTError>(/*IsFatal*/ false, S);
}
Error createFatalBOLTError(const Twine &S) {
return make_error<BOLTError>(/*IsFatal*/ true, S);
}
BinaryContext::BinaryContext(std::unique_ptr<MCContext> Ctx,
std::unique_ptr<DWARFContext> DwCtx,
std::unique_ptr<Triple> TheTriple,

View File

@@ -110,7 +110,7 @@ Error ADRRelaxationPass::runOnFunctions(BinaryContext &BC) {
"ADRRelaxationPass");
if (PassFailed)
exit(1);
return createFatalBOLTError("");
return Error::success();
}

View File

@@ -528,12 +528,14 @@ Error FixupBranches::runOnFunctions(BinaryContext &BC) {
}
Error FinalizeFunctions::runOnFunctions(BinaryContext &BC) {
std::atomic<bool> 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();
}

View File

@@ -567,10 +567,9 @@ Error Instrumentation::runOnFunctions(BinaryContext &BC) {
ErrorOr<BinarySection &> 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<BinarySection &> 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); };

View File

@@ -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;

View File

@@ -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("");
}
}

View File

@@ -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");
}
}
}