summaryrefslogtreecommitdiff
path: root/bolt/lib/Core/BinaryContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'bolt/lib/Core/BinaryContext.cpp')
-rw-r--r--bolt/lib/Core/BinaryContext.cpp220
1 files changed, 135 insertions, 85 deletions
diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp
index df835d287680..d544ece13a83 100644
--- a/bolt/lib/Core/BinaryContext.cpp
+++ b/bolt/lib/Core/BinaryContext.cpp
@@ -83,6 +83,46 @@ 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);
+}
+
+void BinaryContext::logBOLTErrorsAndQuitOnFatal(Error E) {
+ handleAllErrors(Error(std::move(E)), [&](const BOLTError &E) {
+ if (!E.getMessage().empty())
+ E.log(this->errs());
+ if (E.isFatal())
+ exit(1);
+ });
+}
+
BinaryContext::BinaryContext(std::unique_ptr<MCContext> Ctx,
std::unique_ptr<DWARFContext> DwCtx,
std::unique_ptr<Triple> TheTriple,
@@ -96,13 +136,15 @@ BinaryContext::BinaryContext(std::unique_ptr<MCContext> Ctx,
std::unique_ptr<const MCInstrAnalysis> MIA,
std::unique_ptr<MCPlusBuilder> MIB,
std::unique_ptr<const MCRegisterInfo> MRI,
- std::unique_ptr<MCDisassembler> DisAsm)
+ std::unique_ptr<MCDisassembler> DisAsm,
+ JournalingStreams Logger)
: Ctx(std::move(Ctx)), DwCtx(std::move(DwCtx)),
TheTriple(std::move(TheTriple)), TheTarget(TheTarget),
TripleName(TripleName), MCE(std::move(MCE)), MOFI(std::move(MOFI)),
AsmInfo(std::move(AsmInfo)), MII(std::move(MII)), STI(std::move(STI)),
InstPrinter(std::move(InstPrinter)), MIA(std::move(MIA)),
- MIB(std::move(MIB)), MRI(std::move(MRI)), DisAsm(std::move(DisAsm)) {
+ MIB(std::move(MIB)), MRI(std::move(MRI)), DisAsm(std::move(DisAsm)),
+ Logger(Logger) {
Relocation::Arch = this->TheTriple->getArch();
RegularPageSize = isAArch64() ? RegularPageSizeAArch64 : RegularPageSizeX86;
PageAlign = opts::NoHugePages ? RegularPageSize : HugePageSize;
@@ -122,7 +164,8 @@ BinaryContext::~BinaryContext() {
/// triple \p TripleName.
Expected<std::unique_ptr<BinaryContext>>
BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC,
- std::unique_ptr<DWARFContext> DwCtx) {
+ std::unique_ptr<DWARFContext> DwCtx,
+ JournalingStreams Logger) {
StringRef ArchName = "";
std::string FeaturesStr = "";
switch (File->getArch()) {
@@ -241,17 +284,12 @@ BinaryContext::createBinaryContext(const ObjectFile *File, bool IsPIC,
std::unique_ptr<MCCodeEmitter> MCE(
TheTarget->createMCCodeEmitter(*MII, *Ctx));
- // Make sure we don't miss any output on core dumps.
- outs().SetUnbuffered();
- errs().SetUnbuffered();
- dbgs().SetUnbuffered();
-
auto BC = std::make_unique<BinaryContext>(
std::move(Ctx), std::move(DwCtx), std::move(TheTriple), TheTarget,
std::string(TripleName), std::move(MCE), std::move(MOFI),
std::move(AsmInfo), std::move(MII), std::move(STI),
std::move(InstructionPrinter), std::move(MIA), nullptr, std::move(MRI),
- std::move(DisAsm));
+ std::move(DisAsm), Logger);
BC->LSDAEncoding = LSDAEncoding;
@@ -304,9 +342,9 @@ bool BinaryContext::validateObjectNesting() const {
Itr->second->containsRange(Next->second->getAddress(),
Next->second->getSize())) {
if (Next->second->Parent != Itr->second) {
- errs() << "BOLT-WARNING: object nesting incorrect for:\n"
- << "BOLT-WARNING: " << *Itr->second << "\n"
- << "BOLT-WARNING: " << *Next->second << "\n";
+ this->errs() << "BOLT-WARNING: object nesting incorrect for:\n"
+ << "BOLT-WARNING: " << *Itr->second << "\n"
+ << "BOLT-WARNING: " << *Next->second << "\n";
Valid = false;
}
++Next;
@@ -323,14 +361,16 @@ bool BinaryContext::validateHoles() const {
uint64_t RelAddr = Rel.Offset + Section.getAddress();
const BinaryData *BD = getBinaryDataContainingAddress(RelAddr);
if (!BD) {
- errs() << "BOLT-WARNING: no BinaryData found for relocation at address"
- << " 0x" << Twine::utohexstr(RelAddr) << " in "
- << Section.getName() << "\n";
+ this->errs()
+ << "BOLT-WARNING: no BinaryData found for relocation at address"
+ << " 0x" << Twine::utohexstr(RelAddr) << " in " << Section.getName()
+ << "\n";
Valid = false;
} else if (!BD->getAtomicRoot()) {
- errs() << "BOLT-WARNING: no atomic BinaryData found for relocation at "
- << "address 0x" << Twine::utohexstr(RelAddr) << " in "
- << Section.getName() << "\n";
+ this->errs()
+ << "BOLT-WARNING: no atomic BinaryData found for relocation at "
+ << "address 0x" << Twine::utohexstr(RelAddr) << " in "
+ << Section.getName() << "\n";
Valid = false;
}
}
@@ -438,8 +478,9 @@ BinaryContext::handleAddressRef(uint64_t Address, BinaryFunction &BF,
// The address could potentially escape. Mark it as another entry
// point into the function.
if (opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: potentially escaped address 0x"
- << Twine::utohexstr(Address) << " in function " << BF << '\n';
+ this->outs() << "BOLT-INFO: potentially escaped address 0x"
+ << Twine::utohexstr(Address) << " in function " << BF
+ << '\n';
}
BF.HasInternalLabelReference = true;
return std::make_pair(
@@ -482,9 +523,9 @@ MemoryContentsType BinaryContext::analyzeMemoryAt(uint64_t Address,
// internal function addresses to escape the function scope - we
// consider it a tail call.
if (opts::Verbosity > 1) {
- errs() << "BOLT-WARNING: no section for address 0x"
- << Twine::utohexstr(Address) << " referenced from function " << BF
- << '\n';
+ this->errs() << "BOLT-WARNING: no section for address 0x"
+ << Twine::utohexstr(Address) << " referenced from function "
+ << BF << '\n';
}
return MemoryContentsType::UNKNOWN;
}
@@ -730,7 +771,7 @@ void BinaryContext::skipMarkedFragments() {
assert(FragmentsToSkip.count(BF) &&
"internal error in traversing function fragments");
if (opts::Verbosity >= 1)
- errs() << "BOLT-WARNING: Ignoring " << BF->getPrintName() << '\n';
+ this->errs() << "BOLT-WARNING: Ignoring " << BF->getPrintName() << '\n';
BF->setSimple(false);
BF->setHasIndirectTargetToSplitFragment(true);
@@ -738,9 +779,9 @@ void BinaryContext::skipMarkedFragments() {
llvm::for_each(BF->ParentFragments, addToWorklist);
}
if (!FragmentsToSkip.empty())
- errs() << "BOLT-WARNING: skipped " << FragmentsToSkip.size() << " function"
- << (FragmentsToSkip.size() == 1 ? "" : "s")
- << " due to cold fragments\n";
+ this->errs() << "BOLT-WARNING: skipped " << FragmentsToSkip.size()
+ << " function" << (FragmentsToSkip.size() == 1 ? "" : "s")
+ << " due to cold fragments\n";
}
MCSymbol *BinaryContext::getOrCreateGlobalSymbol(uint64_t Address, Twine Prefix,
@@ -791,10 +832,10 @@ BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address,
// Duplicate the entry for the parent function for easy access
JT->Parents.push_back(&Function);
if (opts::Verbosity > 2) {
- outs() << "BOLT-INFO: Multiple fragments access same jump table: "
- << JT->Parents[0]->getPrintName() << "; "
- << Function.getPrintName() << "\n";
- JT->print(outs());
+ this->outs() << "BOLT-INFO: Multiple fragments access same jump table: "
+ << JT->Parents[0]->getPrintName() << "; "
+ << Function.getPrintName() << "\n";
+ JT->print(this->outs());
}
Function.JumpTables.emplace(Address, JT);
JT->Parents[0]->setHasIndirectTargetToSplitFragment(true);
@@ -832,7 +873,7 @@ BinaryContext::getOrCreateJumpTable(BinaryFunction &Function, uint64_t Address,
*getSectionForAddress(Address));
JT->Parents.push_back(&Function);
if (opts::Verbosity > 2)
- JT->print(outs());
+ JT->print(this->outs());
JumpTables.emplace(Address, JT);
// Duplicate the entry for the parent function for easy access.
@@ -961,12 +1002,13 @@ bool BinaryContext::hasValidCodePadding(const BinaryFunction &BF) {
return true;
if (opts::Verbosity >= 1) {
- errs() << "BOLT-WARNING: bad padding at address 0x"
- << Twine::utohexstr(BF.getAddress() + BF.getSize())
- << " starting at offset " << (Offset - BF.getSize())
- << " in function " << BF << '\n'
- << FunctionData->slice(BF.getSize(), BF.getMaxSize() - BF.getSize())
- << '\n';
+ this->errs() << "BOLT-WARNING: bad padding at address 0x"
+ << Twine::utohexstr(BF.getAddress() + BF.getSize())
+ << " starting at offset " << (Offset - BF.getSize())
+ << " in function " << BF << '\n'
+ << FunctionData->slice(BF.getSize(),
+ BF.getMaxSize() - BF.getSize())
+ << '\n';
}
return false;
@@ -981,8 +1023,8 @@ void BinaryContext::adjustCodePadding() {
if (!hasValidCodePadding(BF)) {
if (HasRelocations) {
if (opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: function " << BF
- << " has invalid padding. Ignoring the function.\n";
+ this->outs() << "BOLT-INFO: function " << BF
+ << " has invalid padding. Ignoring the function.\n";
}
BF.setIgnored();
} else {
@@ -1130,8 +1172,8 @@ void BinaryContext::generateSymbolHashes() {
// (i.e. all zeros or a "hole")
if (!isPadding(BD)) {
if (opts::Verbosity) {
- errs() << "BOLT-WARNING: collision detected when hashing " << BD
- << " with new name (" << NewName << "), skipping.\n";
+ this->errs() << "BOLT-WARNING: collision detected when hashing " << BD
+ << " with new name (" << NewName << "), skipping.\n";
}
++NumCollisions;
}
@@ -1141,11 +1183,11 @@ void BinaryContext::generateSymbolHashes() {
GlobalSymbols[NewName] = &BD;
}
if (NumCollisions) {
- errs() << "BOLT-WARNING: " << NumCollisions
- << " collisions detected while hashing binary objects";
+ this->errs() << "BOLT-WARNING: " << NumCollisions
+ << " collisions detected while hashing binary objects";
if (!opts::Verbosity)
- errs() << ". Use -v=1 to see the list.";
- errs() << '\n';
+ this->errs() << ". Use -v=1 to see the list.";
+ this->errs() << '\n';
}
}
@@ -1161,8 +1203,8 @@ bool BinaryContext::registerFragment(BinaryFunction &TargetFunction,
Function.setSimple(false);
}
if (opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: marking " << TargetFunction << " as a fragment of "
- << Function << '\n';
+ this->outs() << "BOLT-INFO: marking " << TargetFunction
+ << " as a fragment of " << Function << '\n';
}
return true;
}
@@ -1276,10 +1318,11 @@ void BinaryContext::processInterproceduralReferences() {
if (TargetFunction) {
if (TargetFunction->isFragment() &&
!TargetFunction->isChildOf(Function)) {
- errs() << "BOLT-WARNING: interprocedural reference between unrelated "
- "fragments: "
- << Function.getPrintName() << " and "
- << TargetFunction->getPrintName() << '\n';
+ this->errs()
+ << "BOLT-WARNING: interprocedural reference between unrelated "
+ "fragments: "
+ << Function.getPrintName() << " and "
+ << TargetFunction->getPrintName() << '\n';
}
if (uint64_t Offset = Address - TargetFunction->getAddress())
TargetFunction->addEntryPointAtOffset(Offset);
@@ -1305,9 +1348,10 @@ void BinaryContext::processInterproceduralReferences() {
continue;
if (opts::processAllFunctions()) {
- errs() << "BOLT-ERROR: cannot process binaries with unmarked "
- << "object in code at address 0x" << Twine::utohexstr(Address)
- << " belonging to section " << SectionName << " in current mode\n";
+ this->errs() << "BOLT-ERROR: cannot process binaries with unmarked "
+ << "object in code at address 0x"
+ << Twine::utohexstr(Address) << " belonging to section "
+ << SectionName << " in current mode\n";
exit(1);
}
@@ -1317,9 +1361,10 @@ void BinaryContext::processInterproceduralReferences() {
// We are not going to overwrite non-simple functions, but for simple
// ones - adjust the padding size.
if (TargetFunction && TargetFunction->isSimple()) {
- errs() << "BOLT-WARNING: function " << *TargetFunction
- << " has an object detected in a padding region at address 0x"
- << Twine::utohexstr(Address) << '\n';
+ this->errs()
+ << "BOLT-WARNING: function " << *TargetFunction
+ << " has an object detected in a padding region at address 0x"
+ << Twine::utohexstr(Address) << '\n';
TargetFunction->setMaxSize(TargetFunction->getSize());
}
}
@@ -1336,7 +1381,8 @@ void BinaryContext::postProcessSymbolTable() {
BD->getName().starts_with("DATAat")) &&
!BD->getParent() && !BD->getSize() && !BD->isAbsolute() &&
BD->getSection()) {
- errs() << "BOLT-WARNING: zero-sized top level symbol: " << *BD << "\n";
+ this->errs() << "BOLT-WARNING: zero-sized top level symbol: " << *BD
+ << "\n";
Valid = false;
}
}
@@ -1592,17 +1638,18 @@ void BinaryContext::preprocessDWODebugInfo() {
DWARFUnit *DWOCU =
DwarfUnit->getNonSkeletonUnitDIE(false, AbsolutePath).getDwarfUnit();
if (!DWOCU->isDWOUnit()) {
- outs() << "BOLT-WARNING: Debug Fission: DWO debug information for "
- << DWOName
- << " was not retrieved and won't be updated. Please check "
- "relative path.\n";
+ this->outs()
+ << "BOLT-WARNING: Debug Fission: DWO debug information for "
+ << DWOName
+ << " was not retrieved and won't be updated. Please check "
+ "relative path.\n";
continue;
}
DWOCUs[*DWOId] = DWOCU;
}
}
if (!DWOCUs.empty())
- outs() << "BOLT-INFO: processing split DWARF\n";
+ this->outs() << "BOLT-INFO: processing split DWARF\n";
}
void BinaryContext::preprocessDebugInfo() {
@@ -1663,8 +1710,8 @@ void BinaryContext::preprocessDebugInfo() {
}
if (opts::Verbosity >= 1) {
- outs() << "BOLT-INFO: " << ProcessedCUs.size() << " out of "
- << DwCtx->getNumCompileUnits() << " CUs will be updated\n";
+ this->outs() << "BOLT-INFO: " << ProcessedCUs.size() << " out of "
+ << DwCtx->getNumCompileUnits() << " CUs will be updated\n";
}
preprocessDWODebugInfo();
@@ -2245,23 +2292,26 @@ BinaryFunction *BinaryContext::getFunctionForSymbol(const MCSymbol *Symbol,
return BF;
}
-void BinaryContext::exitWithBugReport(StringRef Message,
- const BinaryFunction &Function) const {
- errs() << "=======================================\n";
- errs() << "BOLT is unable to proceed because it couldn't properly understand "
- "this function.\n";
- errs() << "If you are running the most recent version of BOLT, you may "
- "want to "
- "report this and paste this dump.\nPlease check that there is no "
- "sensitive contents being shared in this dump.\n";
- errs() << "\nOffending function: " << Function.getPrintName() << "\n\n";
- ScopedPrinter SP(errs());
+std::string
+BinaryContext::generateBugReportMessage(StringRef Message,
+ const BinaryFunction &Function) const {
+ std::string Msg;
+ raw_string_ostream SS(Msg);
+ SS << "=======================================\n";
+ SS << "BOLT is unable to proceed because it couldn't properly understand "
+ "this function.\n";
+ SS << "If you are running the most recent version of BOLT, you may "
+ "want to "
+ "report this and paste this dump.\nPlease check that there is no "
+ "sensitive contents being shared in this dump.\n";
+ SS << "\nOffending function: " << Function.getPrintName() << "\n\n";
+ ScopedPrinter SP(SS);
SP.printBinaryBlock("Function contents", *Function.getData());
- errs() << "\n";
- Function.dump();
- errs() << "ERROR: " << Message;
- errs() << "\n=======================================\n";
- exit(1);
+ SS << "\n";
+ const_cast<BinaryFunction &>(Function).print(SS, "");
+ SS << "ERROR: " << Message;
+ SS << "\n=======================================\n";
+ return Msg;
}
BinaryFunction *
@@ -2399,9 +2449,9 @@ bool BinaryContext::validateInstructionEncoding(
auto OutputSequence = ArrayRef<uint8_t>((uint8_t *)Code.data(), Code.size());
if (InputSequence != OutputSequence) {
if (opts::Verbosity > 1) {
- errs() << "BOLT-WARNING: mismatched encoding detected\n"
- << " input: " << InputSequence << '\n'
- << " output: " << OutputSequence << '\n';
+ this->errs() << "BOLT-WARNING: mismatched encoding detected\n"
+ << " input: " << InputSequence << '\n'
+ << " output: " << OutputSequence << '\n';
}
return false;
}