diff options
Diffstat (limited to 'bolt/lib/Rewrite/RewriteInstance.cpp')
| -rw-r--r-- | bolt/lib/Rewrite/RewriteInstance.cpp | 571 |
1 files changed, 319 insertions, 252 deletions
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp index 9a242d94dd77..db093bfc2d8b 100644 --- a/bolt/lib/Rewrite/RewriteInstance.cpp +++ b/bolt/lib/Rewrite/RewriteInstance.cpp @@ -309,9 +309,11 @@ bool refersToReorderedSection(ErrorOr<BinarySection &> Section) { Expected<std::unique_ptr<RewriteInstance>> RewriteInstance::create(ELFObjectFileBase *File, const int Argc, - const char *const *Argv, StringRef ToolPath) { + const char *const *Argv, StringRef ToolPath, + raw_ostream &Stdout, raw_ostream &Stderr) { Error Err = Error::success(); - auto RI = std::make_unique<RewriteInstance>(File, Argc, Argv, ToolPath, Err); + auto RI = std::make_unique<RewriteInstance>(File, Argc, Argv, ToolPath, + Stdout, Stderr, Err); if (Err) return std::move(Err); return std::move(RI); @@ -319,6 +321,7 @@ RewriteInstance::create(ELFObjectFileBase *File, const int Argc, RewriteInstance::RewriteInstance(ELFObjectFileBase *File, const int Argc, const char *const *Argv, StringRef ToolPath, + raw_ostream &Stdout, raw_ostream &Stderr, Error &Err) : InputFile(File), Argc(Argc), Argv(Argv), ToolPath(ToolPath), SHStrTab(StringTableBuilder::ELF) { @@ -333,17 +336,23 @@ RewriteInstance::RewriteInstance(ELFObjectFileBase *File, const int Argc, bool IsPIC = false; const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile(); if (Obj.getHeader().e_type != ELF::ET_EXEC) { - outs() << "BOLT-INFO: shared object or position-independent executable " + Stdout << "BOLT-INFO: shared object or position-independent executable " "detected\n"; IsPIC = true; } + // Make sure we don't miss any output on core dumps. + Stdout.SetUnbuffered(); + Stderr.SetUnbuffered(); + LLVM_DEBUG(dbgs().SetUnbuffered()); + auto BCOrErr = BinaryContext::createBinaryContext( File, IsPIC, DWARFContext::create(*File, DWARFContext::ProcessDebugRelocations::Ignore, nullptr, opts::DWPPathName, WithColor::defaultErrorHandler, - WithColor::defaultWarningHandler)); + WithColor::defaultWarningHandler), + JournalingStreams{Stdout, Stderr}); if (Error E = BCOrErr.takeError()) { Err = std::move(E); return; @@ -457,22 +466,23 @@ void RewriteInstance::markGnuRelroSections() { bool VMAContains = checkVMA<ELFT>(Phdr, *Sec, VMAOverlap); if (ImageOverlap) { if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: GNU_RELRO segment has partial file offset " - << "overlap with section " << BinarySection->getName() << '\n'; + BC->errs() << "BOLT-WARNING: GNU_RELRO segment has partial file offset " + << "overlap with section " << BinarySection->getName() + << '\n'; return; } if (VMAOverlap) { if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: GNU_RELRO segment has partial VMA overlap " - << "with section " << BinarySection->getName() << '\n'; + BC->errs() << "BOLT-WARNING: GNU_RELRO segment has partial VMA overlap " + << "with section " << BinarySection->getName() << '\n'; return; } if (!ImageContains || !VMAContains) return; BinarySection->setRelro(); if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: marking " << BinarySection->getName() - << " as GNU_RELRO\n"; + BC->outs() << "BOLT-INFO: marking " << BinarySection->getName() + << " as GNU_RELRO\n"; }; for (const ELFT::Phdr &Phdr : cantFail(Obj.program_headers())) @@ -523,7 +533,7 @@ Error RewriteInstance::discoverStorage() { } if (BC->IsLinuxKernel) - outs() << "BOLT-INFO: Linux kernel binary detected\n"; + BC->outs() << "BOLT-INFO: Linux kernel binary detected\n"; for (const SectionRef &Section : InputFile->sections()) { Expected<StringRef> SectionNameOrErr = Section.getName(); @@ -555,8 +565,8 @@ Error RewriteInstance::discoverStorage() { return createStringError(errc::executable_format_error, "no PT_LOAD pheader seen"); - outs() << "BOLT-INFO: first alloc address is 0x" - << Twine::utohexstr(BC->FirstAllocAddress) << '\n'; + BC->outs() << "BOLT-INFO: first alloc address is 0x" + << Twine::utohexstr(BC->FirstAllocAddress) << '\n'; FirstNonAllocatableOffset = NextAvailableOffset; @@ -588,9 +598,9 @@ Error RewriteInstance::discoverStorage() { NextAvailableAddress - BC->FirstAllocAddress && "PHDR table address calculation error"); - outs() << "BOLT-INFO: creating new program header table at address 0x" - << Twine::utohexstr(NextAvailableAddress) << ", offset 0x" - << Twine::utohexstr(NextAvailableOffset) << '\n'; + BC->outs() << "BOLT-INFO: creating new program header table at address 0x" + << Twine::utohexstr(NextAvailableAddress) << ", offset 0x" + << Twine::utohexstr(NextAvailableOffset) << '\n'; PHDRTableAddress = NextAvailableAddress; PHDRTableOffset = NextAvailableOffset; @@ -685,7 +695,8 @@ void RewriteInstance::patchBuildID() { uint64_t FileOffset = getFileOffsetForAddress(BuildIDSection->getAddress()); if (!FileOffset) { - errs() << "BOLT-WARNING: Non-allocatable build-id will not be updated.\n"; + BC->errs() + << "BOLT-WARNING: Non-allocatable build-id will not be updated.\n"; return; } @@ -693,17 +704,17 @@ void RewriteInstance::patchBuildID() { LastIDByte ^= 1; OS.pwrite(&LastIDByte, 1, FileOffset + IDOffset + BuildID.size() - 1); - outs() << "BOLT-INFO: patched build-id (flipped last bit)\n"; + BC->outs() << "BOLT-INFO: patched build-id (flipped last bit)\n"; } Error RewriteInstance::run() { assert(BC && "failed to create a binary context"); - outs() << "BOLT-INFO: Target architecture: " - << Triple::getArchTypeName( - (llvm::Triple::ArchType)InputFile->getArch()) - << "\n"; - outs() << "BOLT-INFO: BOLT version: " << BoltRevision << "\n"; + BC->outs() << "BOLT-INFO: Target architecture: " + << Triple::getArchTypeName( + (llvm::Triple::ArchType)InputFile->getArch()) + << "\n"; + BC->outs() << "BOLT-INFO: BOLT version: " << BoltRevision << "\n"; if (Error E = discoverStorage()) return E; @@ -758,10 +769,10 @@ Error RewriteInstance::run() { updateRtFiniReloc(); if (opts::OutputFilename == "/dev/null") { - outs() << "BOLT-INFO: skipping writing final binary to disk\n"; + BC->outs() << "BOLT-INFO: skipping writing final binary to disk\n"; return Error::success(); } else if (BC->IsLinuxKernel) { - errs() << "BOLT-WARNING: Linux kernel support is experimental\n"; + BC->errs() << "BOLT-WARNING: Linux kernel support is experimental\n"; } // Rewrite allocatable contents and copy non-allocatable parts with mods. @@ -786,13 +797,15 @@ void RewriteInstance::discoverFileObjects() { for (const ELFSymbolRef &Symbol : InputFile->symbols()) { Expected<StringRef> NameOrError = Symbol.getName(); if (NameOrError && NameOrError->starts_with("__asan_init")) { - errs() << "BOLT-ERROR: input file was compiled or linked with sanitizer " - "support. Cannot optimize.\n"; + BC->errs() + << "BOLT-ERROR: input file was compiled or linked with sanitizer " + "support. Cannot optimize.\n"; exit(1); } if (NameOrError && NameOrError->starts_with("__llvm_coverage_mapping")) { - errs() << "BOLT-ERROR: input file was compiled or linked with coverage " - "support. Cannot optimize.\n"; + BC->errs() + << "BOLT-ERROR: input file was compiled or linked with coverage " + "support. Cannot optimize.\n"; exit(1); } @@ -924,7 +937,7 @@ void RewriteInstance::discoverFileObjects() { StringRef SymName = cantFail(Symbol.getName(), "cannot get symbol name"); if (SymbolAddress == 0) { if (opts::Verbosity >= 1 && SymbolType == SymbolRef::ST_Function) - errs() << "BOLT-WARNING: function with 0 address seen\n"; + BC->errs() << "BOLT-WARNING: function with 0 address seen\n"; continue; } @@ -965,13 +978,13 @@ void RewriteInstance::discoverFileObjects() { if (BD->getSize() == ELFSymbolRef(Symbol).getSize() && BD->getAddress() == SymbolAddress) { if (opts::Verbosity > 1) - errs() << "BOLT-WARNING: ignoring duplicate global symbol " << Name - << "\n"; + BC->errs() << "BOLT-WARNING: ignoring duplicate global symbol " + << Name << "\n"; // Ignore duplicate entry - possibly a bug in the linker continue; } - errs() << "BOLT-ERROR: bad input binary, global symbol \"" << Name - << "\" is not unique\n"; + BC->errs() << "BOLT-ERROR: bad input binary, global symbol \"" << Name + << "\" is not unique\n"; exit(1); } UniqueName = Name; @@ -1059,9 +1072,9 @@ void RewriteInstance::discoverFileObjects() { !SymbolSize) { LLVM_DEBUG(dbgs() << "BOLT-DEBUG: ignoring symbol as a marker\n"); } else if (opts::Verbosity > 1) { - errs() << "BOLT-WARNING: symbol " << UniqueName - << " seen in the middle of function " << *PreviousFunction - << ". Could be a new entry.\n"; + BC->errs() << "BOLT-WARNING: symbol " << UniqueName + << " seen in the middle of function " << *PreviousFunction + << ". Could be a new entry.\n"; } registerName(SymbolSize); continue; @@ -1077,12 +1090,14 @@ void RewriteInstance::discoverFileObjects() { PreviousFunction->getAddress() != SymbolAddress) { if (PreviousFunction->isSymbolValidInScope(Symbol, SymbolSize)) { if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: skipping possibly another entry for function " - << *PreviousFunction << " : " << UniqueName << '\n'; + BC->outs() + << "BOLT-INFO: skipping possibly another entry for function " + << *PreviousFunction << " : " << UniqueName << '\n'; registerName(SymbolSize); } else { - outs() << "BOLT-INFO: using " << UniqueName << " as another entry to " - << "function " << *PreviousFunction << '\n'; + BC->outs() << "BOLT-INFO: using " << UniqueName + << " as another entry to " + << "function " << *PreviousFunction << '\n'; registerName(0); @@ -1114,20 +1129,21 @@ void RewriteInstance::discoverFileObjects() { uint64_t PrevLength = PrevFDE.getAddressRange(); if (SymbolAddress > PrevStart && SymbolAddress < PrevStart + PrevLength) { - errs() << "BOLT-ERROR: function " << UniqueName - << " is in conflict with FDE [" - << Twine::utohexstr(PrevStart) << ", " - << Twine::utohexstr(PrevStart + PrevLength) - << "). Skipping.\n"; + BC->errs() << "BOLT-ERROR: function " << UniqueName + << " is in conflict with FDE [" + << Twine::utohexstr(PrevStart) << ", " + << Twine::utohexstr(PrevStart + PrevLength) + << "). Skipping.\n"; IsSimple = false; } } } else if (FDE.getAddressRange() != SymbolSize) { if (SymbolSize) { // Function addresses match but sizes differ. - errs() << "BOLT-WARNING: sizes differ for function " << UniqueName - << ". FDE : " << FDE.getAddressRange() - << "; symbol table : " << SymbolSize << ". Using max size.\n"; + BC->errs() << "BOLT-WARNING: sizes differ for function " << UniqueName + << ". FDE : " << FDE.getAddressRange() + << "; symbol table : " << SymbolSize + << ". Using max size.\n"; } SymbolSize = std::max(SymbolSize, FDE.getAddressRange()); if (BC->getBinaryDataAtAddress(SymbolAddress)) { @@ -1151,10 +1167,11 @@ void RewriteInstance::discoverFileObjects() { if (SymbolSize != BF->getSize()) { if (opts::Verbosity >= 1) { if (SymbolSize && BF->getSize()) - errs() << "BOLT-WARNING: size mismatch for duplicate entries " - << *BF << " and " << UniqueName << '\n'; - outs() << "BOLT-INFO: adjusting size of function " << *BF << " old " - << BF->getSize() << " new " << SymbolSize << "\n"; + BC->errs() << "BOLT-WARNING: size mismatch for duplicate entries " + << *BF << " and " << UniqueName << '\n'; + BC->outs() << "BOLT-INFO: adjusting size of function " << *BF + << " old " << BF->getSize() << " new " << SymbolSize + << "\n"; } BF->setSize(std::max(SymbolSize, BF->getSize())); BC->setBinaryDataSize(SymbolAddress, BF->getSize()); @@ -1165,9 +1182,9 @@ void RewriteInstance::discoverFileObjects() { BC->getSectionForAddress(SymbolAddress); // Skip symbols from invalid sections if (!Section) { - errs() << "BOLT-WARNING: " << UniqueName << " (0x" - << Twine::utohexstr(SymbolAddress) - << ") does not have any section\n"; + BC->errs() << "BOLT-WARNING: " << UniqueName << " (0x" + << Twine::utohexstr(SymbolAddress) + << ") does not have any section\n"; continue; } @@ -1186,12 +1203,12 @@ void RewriteInstance::discoverFileObjects() { static bool PrintedWarning = false; if (!PrintedWarning) { PrintedWarning = true; - errs() << "BOLT-WARNING: split function detected on input : " - << SymName; + BC->errs() << "BOLT-WARNING: split function detected on input : " + << SymName; if (BC->HasRelocations) - errs() << ". The support is limited in relocation mode\n"; + BC->errs() << ". The support is limited in relocation mode\n"; else - errs() << '\n'; + BC->errs() << '\n'; } BC->HasSplitFunctions = true; BF->IsFragment = true; @@ -1222,16 +1239,16 @@ void RewriteInstance::discoverFileObjects() { BF = BC->getBinaryFunctionContainingAddress(Address); if (BF) { - errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Address) << ", 0x" - << Twine::utohexstr(Address + FDE->getAddressRange()) - << ") conflicts with function " << *BF << '\n'; + BC->errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Address) + << ", 0x" << Twine::utohexstr(Address + FDE->getAddressRange()) + << ") conflicts with function " << *BF << '\n'; continue; } if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Address) << ", 0x" - << Twine::utohexstr(Address + FDE->getAddressRange()) - << ") has no corresponding symbol table entry\n"; + BC->errs() << "BOLT-WARNING: FDE [0x" << Twine::utohexstr(Address) + << ", 0x" << Twine::utohexstr(Address + FDE->getAddressRange()) + << ") has no corresponding symbol table entry\n"; ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address); assert(Section && "cannot get section for address from FDE"); @@ -1283,7 +1300,8 @@ void RewriteInstance::discoverFileObjects() { /*UseMaxSize*/ true); if (BF) { assert(Rel.isRelative() && "Expected relative relocation for island"); - BF->markIslandDynamicRelocationAtAddress(RelAddress); + BC->logBOLTErrorsAndQuitOnFatal( + BF->markIslandDynamicRelocationAtAddress(RelAddress)); } } } @@ -1395,23 +1413,24 @@ void RewriteInstance::registerFragments() { } if (!BD) { if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: parent function not found for " << Name << "\n"; + BC->outs() << "BOLT-INFO: parent function not found for " << Name + << "\n"; continue; } const uint64_t Address = BD->getAddress(); BinaryFunction *BF = BC->getBinaryFunctionAtAddress(Address); if (!BF) { if (opts::Verbosity >= 1) - outs() << formatv("BOLT-INFO: parent function not found at {0:x}\n", - Address); + BC->outs() << formatv( + "BOLT-INFO: parent function not found at {0:x}\n", Address); continue; } BC->registerFragment(Function, *BF); ++ParentsFound; } if (!ParentsFound) { - errs() << "BOLT-ERROR: parent function not found for " << Function - << '\n'; + BC->errs() << "BOLT-ERROR: parent function not found for " << Function + << '\n'; exit(1); } } @@ -1449,7 +1468,7 @@ void RewriteInstance::createPLTBinaryFunction(uint64_t TargetAddress, // IFUNC trampoline without symbol BinaryFunction *TargetBF = BC->getBinaryFunctionAtAddress(Rel->Addend); if (!TargetBF) { - errs() + BC->errs() << "BOLT-WARNING: Expected BF to be presented as IFUNC resolver at " << Twine::utohexstr(Rel->Addend) << ", skipping\n"; return; @@ -1483,8 +1502,9 @@ void RewriteInstance::disassemblePLTInstruction(const BinarySection &Section, if (!BC->DisAsm->getInstruction(Instruction, InstrSize, PLTData.slice(InstrOffset), InstrAddr, nulls())) { - errs() << "BOLT-ERROR: unable to disassemble instruction in PLT section " - << Section.getName() << formatv(" at offset {0:x}\n", InstrOffset); + BC->errs() + << "BOLT-ERROR: unable to disassemble instruction in PLT section " + << Section.getName() << formatv(" at offset {0:x}\n", InstrOffset); exit(1); } } @@ -1546,9 +1566,10 @@ void RewriteInstance::disassemblePLTSectionRISCV(BinarySection &Section) { if (!BC->DisAsm->getInstruction(Instruction, InstrSize, PLTData.slice(InstrOffset), InstrAddr, nulls())) { - errs() << "BOLT-ERROR: unable to disassemble instruction in PLT section " - << Section.getName() << " at offset 0x" - << Twine::utohexstr(InstrOffset) << '\n'; + BC->errs() + << "BOLT-ERROR: unable to disassemble instruction in PLT section " + << Section.getName() << " at offset 0x" + << Twine::utohexstr(InstrOffset) << '\n'; exit(1); } }; @@ -1606,8 +1627,8 @@ void RewriteInstance::disassemblePLTSectionX86(BinarySection &Section, if (!BC->MIB->evaluateMemOperandTarget(Instruction, TargetAddress, SectionAddress + InstrOffset, InstrSize)) { - errs() << "BOLT-ERROR: error evaluating PLT instruction at offset 0x" - << Twine::utohexstr(SectionAddress + InstrOffset) << '\n'; + BC->errs() << "BOLT-ERROR: error evaluating PLT instruction at offset 0x" + << Twine::utohexstr(SectionAddress + InstrOffset) << '\n'; exit(1); } @@ -1714,8 +1735,8 @@ void RewriteInstance::adjustFunctionBoundaries() { const uint64_t MaxSize = NextObjectAddress - Function.getAddress(); if (MaxSize < Function.getSize()) { - errs() << "BOLT-ERROR: symbol seen in the middle of the function " - << Function << ". Skipping.\n"; + BC->errs() << "BOLT-ERROR: symbol seen in the middle of the function " + << Function << ". Skipping.\n"; Function.setSimple(false); Function.setMaxSize(Function.getSize()); continue; @@ -1725,8 +1746,8 @@ void RewriteInstance::adjustFunctionBoundaries() { // Some assembly functions have their size set to 0, use the max // size as their real size. if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: setting size of function " << Function << " to " - << Function.getMaxSize() << " (was 0)\n"; + BC->outs() << "BOLT-INFO: setting size of function " << Function + << " to " << Function.getMaxSize() << " (was 0)\n"; Function.setSize(Function.getMaxSize()); } } @@ -1812,8 +1833,8 @@ Error RewriteInstance::readSpecialSections() { markGnuRelroSections(); if (HasDebugInfo && !opts::UpdateDebugSections && !opts::AggregateOnly) { - errs() << "BOLT-WARNING: debug info will be stripped from the binary. " - "Use -update-debug-sections to keep it.\n"; + BC->errs() << "BOLT-WARNING: debug info will be stripped from the binary. " + "Use -update-debug-sections to keep it.\n"; } HasTextRelocations = (bool)BC->getUniqueSectionByName(".rela.text"); @@ -1825,22 +1846,23 @@ Error RewriteInstance::readSpecialSections() { BC->getUniqueSectionByName(BoltAddressTranslation::SECTION_NAME)) { // Do not read BAT when plotting a heatmap if (!opts::HeatmapMode) { - if (std::error_code EC = BAT->parse(BATSec->getContents())) { - errs() << "BOLT-ERROR: failed to parse BOLT address translation " - "table.\n"; + if (std::error_code EC = BAT->parse(BC->outs(), BATSec->getContents())) { + BC->errs() << "BOLT-ERROR: failed to parse BOLT address translation " + "table.\n"; exit(1); } } } if (opts::PrintSections) { - outs() << "BOLT-INFO: Sections from original binary:\n"; - BC->printSections(outs()); + BC->outs() << "BOLT-INFO: Sections from original binary:\n"; + BC->printSections(BC->outs()); } if (opts::RelocationMode == cl::BOU_TRUE && !HasTextRelocations) { - errs() << "BOLT-ERROR: relocations against code are missing from the input " - "file. Cannot proceed in relocations mode (-relocs).\n"; + BC->errs() + << "BOLT-ERROR: relocations against code are missing from the input " + "file. Cannot proceed in relocations mode (-relocs).\n"; exit(1); } @@ -1848,15 +1870,16 @@ Error RewriteInstance::readSpecialSections() { HasTextRelocations && (opts::RelocationMode != cl::BOU_FALSE); if (BC->IsLinuxKernel && BC->HasRelocations) { - outs() << "BOLT-INFO: disabling relocation mode for Linux kernel\n"; + BC->outs() << "BOLT-INFO: disabling relocation mode for Linux kernel\n"; BC->HasRelocations = false; } BC->IsStripped = !HasSymbolTable; if (BC->IsStripped && !opts::AllowStripped) { - errs() << "BOLT-ERROR: stripped binaries are not supported. If you know " - "what you're doing, use --allow-stripped to proceed"; + BC->errs() + << "BOLT-ERROR: stripped binaries are not supported. If you know " + "what you're doing, use --allow-stripped to proceed"; exit(1); } @@ -1865,14 +1888,14 @@ Error RewriteInstance::readSpecialSections() { BC->HasRelocations = false; if (BC->HasRelocations) - outs() << "BOLT-INFO: enabling " << (opts::StrictMode ? "strict " : "") - << "relocation mode\n"; + BC->outs() << "BOLT-INFO: enabling " << (opts::StrictMode ? "strict " : "") + << "relocation mode\n"; // Read EH frame for function boundaries info. Expected<const DWARFDebugFrame *> EHFrameOrError = BC->DwCtx->getEHFrame(); if (!EHFrameOrError) report_error("expected valid eh_frame section", EHFrameOrError.takeError()); - CFIRdWrt.reset(new CFIReaderWriter(*EHFrameOrError.get())); + CFIRdWrt.reset(new CFIReaderWriter(*BC, *EHFrameOrError.get())); // Parse build-id parseBuildID(); @@ -1885,63 +1908,68 @@ Error RewriteInstance::readSpecialSections() { void RewriteInstance::adjustCommandLineOptions() { if (BC->isAArch64() && !BC->HasRelocations) - errs() << "BOLT-WARNING: non-relocation mode for AArch64 is not fully " - "supported\n"; + BC->errs() << "BOLT-WARNING: non-relocation mode for AArch64 is not fully " + "supported\n"; if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary()) RtLibrary->adjustCommandLineOptions(*BC); if (opts::AlignMacroOpFusion != MFT_NONE && !BC->isX86()) { - outs() << "BOLT-INFO: disabling -align-macro-fusion on non-x86 platform\n"; + BC->outs() + << "BOLT-INFO: disabling -align-macro-fusion on non-x86 platform\n"; opts::AlignMacroOpFusion = MFT_NONE; } if (BC->isX86() && BC->MAB->allowAutoPadding()) { if (!BC->HasRelocations) { - errs() << "BOLT-ERROR: cannot apply mitigations for Intel JCC erratum in " - "non-relocation mode\n"; + BC->errs() + << "BOLT-ERROR: cannot apply mitigations for Intel JCC erratum in " + "non-relocation mode\n"; exit(1); } - outs() << "BOLT-WARNING: using mitigation for Intel JCC erratum, layout " - "may take several minutes\n"; + BC->outs() + << "BOLT-WARNING: using mitigation for Intel JCC erratum, layout " + "may take several minutes\n"; opts::AlignMacroOpFusion = MFT_NONE; } if (opts::AlignMacroOpFusion != MFT_NONE && !BC->HasRelocations) { - outs() << "BOLT-INFO: disabling -align-macro-fusion in non-relocation " - "mode\n"; + BC->outs() << "BOLT-INFO: disabling -align-macro-fusion in non-relocation " + "mode\n"; opts::AlignMacroOpFusion = MFT_NONE; } if (opts::SplitEH && !BC->HasRelocations) { - errs() << "BOLT-WARNING: disabling -split-eh in non-relocation mode\n"; + BC->errs() << "BOLT-WARNING: disabling -split-eh in non-relocation mode\n"; opts::SplitEH = false; } if (opts::StrictMode && !BC->HasRelocations) { - errs() << "BOLT-WARNING: disabling strict mode (-strict) in non-relocation " - "mode\n"; + BC->errs() + << "BOLT-WARNING: disabling strict mode (-strict) in non-relocation " + "mode\n"; opts::StrictMode = false; } if (BC->HasRelocations && opts::AggregateOnly && !opts::StrictMode.getNumOccurrences()) { - outs() << "BOLT-INFO: enabling strict relocation mode for aggregation " - "purposes\n"; + BC->outs() << "BOLT-INFO: enabling strict relocation mode for aggregation " + "purposes\n"; opts::StrictMode = true; } if (BC->isX86() && BC->HasRelocations && opts::AlignMacroOpFusion == MFT_HOT && !ProfileReader) { - outs() << "BOLT-INFO: enabling -align-macro-fusion=all since no profile " - "was specified\n"; + BC->outs() + << "BOLT-INFO: enabling -align-macro-fusion=all since no profile " + "was specified\n"; opts::AlignMacroOpFusion = MFT_ALL; } if (!BC->HasRelocations && opts::ReorderFunctions != ReorderFunctions::RT_NONE) { - errs() << "BOLT-ERROR: function reordering only works when " - << "relocations are enabled\n"; + BC->errs() << "BOLT-ERROR: function reordering only works when " + << "relocations are enabled\n"; exit(1); } @@ -1950,7 +1978,7 @@ void RewriteInstance::adjustCommandLineOptions() { !opts::HotText.getNumOccurrences())) { opts::HotText = true; } else if (opts::HotText && !BC->HasRelocations) { - errs() << "BOLT-WARNING: hot text is disabled in non-relocation mode\n"; + BC->errs() << "BOLT-WARNING: hot text is disabled in non-relocation mode\n"; opts::HotText = false; } @@ -1961,12 +1989,13 @@ void RewriteInstance::adjustCommandLineOptions() { } if (opts::UseOldText && !BC->OldTextSectionAddress) { - errs() << "BOLT-WARNING: cannot use old .text as the section was not found" - "\n"; + BC->errs() + << "BOLT-WARNING: cannot use old .text as the section was not found" + "\n"; opts::UseOldText = false; } if (opts::UseOldText && !BC->HasRelocations) { - errs() << "BOLT-WARNING: cannot use old .text in non-relocation mode\n"; + BC->errs() << "BOLT-WARNING: cannot use old .text in non-relocation mode\n"; opts::UseOldText = false; } @@ -1981,23 +2010,25 @@ void RewriteInstance::adjustCommandLineOptions() { opts::Lite = true; if (opts::Lite && opts::UseOldText) { - errs() << "BOLT-WARNING: cannot combine -lite with -use-old-text. " - "Disabling -use-old-text.\n"; + BC->errs() << "BOLT-WARNING: cannot combine -lite with -use-old-text. " + "Disabling -use-old-text.\n"; opts::UseOldText = false; } if (opts::Lite && opts::StrictMode) { - errs() << "BOLT-ERROR: -strict and -lite cannot be used at the same time\n"; + BC->errs() + << "BOLT-ERROR: -strict and -lite cannot be used at the same time\n"; exit(1); } if (opts::Lite) - outs() << "BOLT-INFO: enabling lite mode\n"; + BC->outs() << "BOLT-INFO: enabling lite mode\n"; if (!opts::SaveProfile.empty() && BAT->enabledFor(InputFile)) { - errs() << "BOLT-ERROR: unable to save profile in YAML format for input " - "file processed by BOLT. Please remove -w option and use branch " - "profile.\n"; + BC->errs() + << "BOLT-ERROR: unable to save profile in YAML format for input " + "file processed by BOLT. Please remove -w option and use branch " + "profile.\n"; exit(1); } } @@ -2252,8 +2283,8 @@ void RewriteInstance::processRelocations() { } if (NumFailedRelocations) - errs() << "BOLT-WARNING: Failed to analyze " << NumFailedRelocations - << " relocations\n"; + BC->errs() << "BOLT-WARNING: Failed to analyze " << NumFailedRelocations + << " relocations\n"; } void RewriteInstance::readDynamicRelocations(const SectionRef &Section, @@ -2497,8 +2528,8 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection, assert(ContainingBF && "cannot find function for address in code"); if (!IsAArch64 && !ContainingBF->containsAddress(Rel.getOffset())) { if (opts::Verbosity >= 1) - outs() << formatv("BOLT-INFO: {0} has relocations in padding area\n", - *ContainingBF); + BC->outs() << formatv( + "BOLT-INFO: {0} has relocations in padding area\n", *ContainingBF); ContainingBF->setSize(ContainingBF->getMaxSize()); ContainingBF->setSimple(false); return; @@ -2593,12 +2624,13 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection, if (BF != ReferencedBF) { // It's possible we are referencing a function without referencing any // code, e.g. when taking a bitmask action on a function address. - errs() << "BOLT-WARNING: non-standard function reference (e.g. bitmask)" - << formatv(" detected against function {0} from ", *BF); + BC->errs() + << "BOLT-WARNING: non-standard function reference (e.g. bitmask)" + << formatv(" detected against function {0} from ", *BF); if (IsFromCode) - errs() << formatv("function {0}\n", *ContainingBF); + BC->errs() << formatv("function {0}\n", *ContainingBF); else - errs() << formatv("data section at {0:x}\n", Rel.getOffset()); + BC->errs() << formatv("data section at {0:x}\n", Rel.getOffset()); LLVM_DEBUG(printRelocationInfo(Rel, SymbolName, SymbolAddress, Addend, ExtractedValue)); ReferencedBF = BF; @@ -2628,10 +2660,11 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection, llvm::make_second_range(ContainingBF->Relocations), CheckReloc); if (Found) { - errs() << "BOLT-WARNING: detected possible compiler de-virtualization " - "bug: -1 addend used with non-pc-relative relocation against " - << formatv("function {0} in function {1}\n", *RogueBF, - *ContainingBF); + BC->errs() + << "BOLT-WARNING: detected possible compiler de-virtualization " + "bug: -1 addend used with non-pc-relative relocation against " + << formatv("function {0} in function {1}\n", *RogueBF, + *ContainingBF); return; } } @@ -2681,9 +2714,10 @@ void RewriteInstance::handleRelocation(const SectionRef &RelocatedSection, } if (opts::Verbosity > 1 && BinarySection(*BC, RelocatedSection).isWritable()) - errs() << "BOLT-WARNING: writable reference into the middle of the " - << formatv("function {0} detected at address {1:x}\n", - *ReferencedBF, Rel.getOffset()); + BC->errs() + << "BOLT-WARNING: writable reference into the middle of the " + << formatv("function {0} detected at address {1:x}\n", + *ReferencedBF, Rel.getOffset()); } SymbolAddress = Address; Addend = 0; @@ -2825,8 +2859,9 @@ void RewriteInstance::selectFunctionsToProcess() { if ((!opts::ForceFunctionNames.empty() || !opts::ForceFunctionNamesNR.empty()) && !opts::SkipFunctionNames.empty()) { - errs() << "BOLT-ERROR: cannot select functions to process and skip at the " - "same time. Please use only one type of selection.\n"; + BC->errs() + << "BOLT-ERROR: cannot select functions to process and skip at the " + "same time. Please use only one type of selection.\n"; exit(1); } @@ -2850,8 +2885,8 @@ void RewriteInstance::selectFunctionsToProcess() { if (Index) --Index; LiteThresholdExecCount = TopFunctions[Index]->getKnownExecutionCount(); - outs() << "BOLT-INFO: limiting processing to functions with at least " - << LiteThresholdExecCount << " invocations\n"; + BC->outs() << "BOLT-INFO: limiting processing to functions with at least " + << LiteThresholdExecCount << " invocations\n"; } LiteThresholdExecCount = std::max( LiteThresholdExecCount, static_cast<uint64_t>(opts::LiteThresholdCount)); @@ -2859,8 +2894,10 @@ void RewriteInstance::selectFunctionsToProcess() { StringSet<> ReorderFunctionsUserSet; StringSet<> ReorderFunctionsLTOCommonSet; if (opts::ReorderFunctions == ReorderFunctions::RT_USER) { - for (const std::string &Function : - ReorderFunctions::readFunctionOrderFile()) { + std::vector<std::string> FunctionNames; + BC->logBOLTErrorsAndQuitOnFatal( + ReorderFunctions::readFunctionOrderFile(FunctionNames)); + for (const std::string &Function : FunctionNames) { ReorderFunctionsUserSet.insert(Function); if (std::optional<StringRef> LTOCommonName = getLTOCommonName(Function)) ReorderFunctionsLTOCommonSet.insert(*LTOCommonName); @@ -2936,15 +2973,15 @@ void RewriteInstance::selectFunctionsToProcess() { if (!shouldProcess(Function)) { if (opts::Verbosity >= 1) { - outs() << "BOLT-INFO: skipping processing " << Function - << " per user request\n"; + BC->outs() << "BOLT-INFO: skipping processing " << Function + << " per user request\n"; } Function.setIgnored(); } else { ++NumFunctionsToProcess; if (opts::MaxFunctions.getNumOccurrences() && NumFunctionsToProcess == opts::MaxFunctions) - outs() << "BOLT-INFO: processing ending on " << Function << '\n'; + BC->outs() << "BOLT-INFO: processing ending on " << Function << '\n'; } } @@ -2963,8 +3000,8 @@ void RewriteInstance::selectFunctionsToProcess() { if (mustSkip(Function)) { for (BinaryFunction *Parent : Function.ParentFragments) { if (opts::Verbosity >= 1) { - outs() << "BOLT-INFO: skipping processing " << *Parent - << " together with fragment function\n"; + BC->outs() << "BOLT-INFO: skipping processing " << *Parent + << " together with fragment function\n"; } Parent->setIgnored(); --NumFunctionsToProcess; @@ -2979,18 +3016,18 @@ void RewriteInstance::selectFunctionsToProcess() { }); if (IgnoredParent) { if (opts::Verbosity >= 1) { - outs() << "BOLT-INFO: skipping processing " << Function - << " together with parent function\n"; + BC->outs() << "BOLT-INFO: skipping processing " << Function + << " together with parent function\n"; } Function.setIgnored(); } else { ++NumFunctionsToProcess; if (opts::Verbosity >= 1) { - outs() << "BOLT-INFO: processing " << Function - << " as a sibling of non-ignored function\n"; + BC->outs() << "BOLT-INFO: processing " << Function + << " as a sibling of non-ignored function\n"; } if (opts::MaxFunctions && NumFunctionsToProcess == opts::MaxFunctions) - outs() << "BOLT-INFO: processing ending on " << Function << '\n'; + BC->outs() << "BOLT-INFO: processing ending on " << Function << '\n'; } } } @@ -3011,12 +3048,12 @@ void RewriteInstance::preprocessProfileData() { NamedRegionTimer T("preprocessprofile", "pre-process profile data", TimerGroupName, TimerGroupDesc, opts::TimeRewrite); - outs() << "BOLT-INFO: pre-processing profile using " - << ProfileReader->getReaderName() << '\n'; + BC->outs() << "BOLT-INFO: pre-processing profile using " + << ProfileReader->getReaderName() << '\n'; if (BAT->enabledFor(InputFile)) { - outs() << "BOLT-INFO: profile collection done on a binary already " - "processed by BOLT\n"; + BC->outs() << "BOLT-INFO: profile collection done on a binary already " + "processed by BOLT\n"; ProfileReader->setBAT(&*BAT); } @@ -3024,10 +3061,11 @@ void RewriteInstance::preprocessProfileData() { report_error("cannot pre-process profile", std::move(E)); if (!BC->hasSymbolsWithFileName() && ProfileReader->hasLocalsWithFileName()) { - errs() << "BOLT-ERROR: input binary does not have local file symbols " - "but profile data includes function names with embedded file " - "names. It appears that the input binary was stripped while a " - "profiled binary was not\n"; + BC->errs() + << "BOLT-ERROR: input binary does not have local file symbols " + "but profile data includes function names with embedded file " + "names. It appears that the input binary was stripped while a " + "profiled binary was not\n"; exit(1); } } @@ -3080,7 +3118,7 @@ void RewriteInstance::processProfileData() { if (Function.empty()) continue; - Function.print(outs(), "after attaching profile"); + Function.print(BC->outs(), "after attaching profile"); } } @@ -3109,8 +3147,8 @@ void RewriteInstance::disassembleFunctions() { ErrorOr<ArrayRef<uint8_t>> FunctionData = Function.getData(); if (!FunctionData) { - errs() << "BOLT-ERROR: corresponding section is non-executable or " - << "empty for function " << Function << '\n'; + BC->errs() << "BOLT-ERROR: corresponding section is non-executable or " + << "empty for function " << Function << '\n'; exit(1); } @@ -3133,21 +3171,32 @@ void RewriteInstance::disassembleFunctions() { continue; } - if (!Function.disassemble()) { - if (opts::processAllFunctions()) - BC->exitWithBugReport("function cannot be properly disassembled. " - "Unable to continue in relocation mode.", - Function); + bool DisasmFailed{false}; + handleAllErrors(Function.disassemble(), [&](const BOLTError &E) { + DisasmFailed = true; + if (E.isFatal()) { + E.log(BC->errs()); + exit(1); + } + if (opts::processAllFunctions()) { + BC->errs() << BC->generateBugReportMessage( + "function cannot be properly disassembled. " + "Unable to continue in relocation mode.", + Function); + exit(1); + } if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: could not disassemble function " << Function - << ". Will ignore.\n"; + BC->outs() << "BOLT-INFO: could not disassemble function " << Function + << ". Will ignore.\n"; // Forcefully ignore the function. Function.setIgnored(); + }); + + if (DisasmFailed) continue; - } if (opts::PrintAll || opts::PrintDisasm) - Function.print(outs(), "after disassembly"); + Function.print(BC->outs(), "after disassembly"); } BC->processInterproceduralReferences(); @@ -3182,10 +3231,12 @@ void RewriteInstance::disassembleFunctions() { // Fill in CFI information for this function if (!Function.trapsOnEntry() && !CFIRdWrt->fillCFIInfoFor(Function)) { if (BC->HasRelocations) { - BC->exitWithBugReport("unable to fill CFI.", Function); + BC->errs() << BC->generateBugReportMessage("unable to fill CFI.", + Function); + exit(1); } else { - errs() << "BOLT-WARNING: unable to fill CFI for function " << Function - << ". Skipping.\n"; + BC->errs() << "BOLT-WARNING: unable to fill CFI for function " + << Function << ". Skipping.\n"; Function.setSimple(false); continue; } @@ -3199,7 +3250,8 @@ void RewriteInstance::disassembleFunctions() { check_error(LSDASection.getError(), "failed to get LSDA section"); ArrayRef<uint8_t> LSDAData = ArrayRef<uint8_t>( LSDASection->getData(), LSDASection->getContents().size()); - Function.parseLSDA(LSDAData, LSDASection->getAddress()); + BC->logBOLTErrorsAndQuitOnFatal( + Function.parseLSDA(LSDAData, LSDASection->getAddress())); } } } @@ -3214,12 +3266,21 @@ void RewriteInstance::buildFunctionsCFG() { ParallelUtilities::WorkFuncWithAllocTy WorkFun = [&](BinaryFunction &BF, MCPlusBuilder::AllocatorIdTy AllocId) { - if (!BF.buildCFG(AllocId)) + bool HadErrors{false}; + handleAllErrors(BF.buildCFG(AllocId), [&](const BOLTError &E) { + if (!E.getMessage().empty()) + E.log(BC->errs()); + if (E.isFatal()) + exit(1); + HadErrors = true; + }); + + if (HadErrors) return; if (opts::PrintAll) { auto L = BC->scopeLock(); - BF.print(outs(), "while building cfg"); + BF.print(BC->outs(), "while building cfg"); } }; @@ -3258,14 +3319,14 @@ void RewriteInstance::postProcessFunctions() { Function.postProcessCFG(); if (opts::PrintAll || opts::PrintCFG) - Function.print(outs(), "after building cfg"); + Function.print(BC->outs(), "after building cfg"); if (opts::DumpDotAll) Function.dumpGraphForPass("00_build-cfg"); if (opts::PrintLoopInfo) { Function.calculateLoopInfo(); - Function.printLoopInfo(outs()); + Function.printLoopInfo(BC->outs()); } BC->TotalScore += Function.getFunctionScore(); @@ -3273,15 +3334,15 @@ void RewriteInstance::postProcessFunctions() { } if (opts::PrintGlobals) { - outs() << "BOLT-INFO: Global symbols:\n"; - BC->printGlobalSymbols(outs()); + BC->outs() << "BOLT-INFO: Global symbols:\n"; + BC->printGlobalSymbols(BC->outs()); } } void RewriteInstance::runOptimizationPasses() { NamedRegionTimer T("runOptimizationPasses", "run optimization passes", TimerGroupName, TimerGroupDesc, opts::TimeRewrite); - BinaryFunctionPassManager::runAllPasses(*BC); + BC->logBOLTErrorsAndQuitOnFatal(BinaryFunctionPassManager::runAllPasses(*BC)); } void RewriteInstance::preregisterSections() { @@ -3331,7 +3392,7 @@ void RewriteInstance::emitAndLink() { Streamer->finish(); if (Streamer->getContext().hadError()) { - errs() << "BOLT-ERROR: Emission failed.\n"; + BC->errs() << "BOLT-ERROR: Emission failed.\n"; exit(1); } @@ -3342,9 +3403,10 @@ void RewriteInstance::emitAndLink() { raw_fd_ostream FOS(OutObjectPath, EC); check_error(EC, "cannot create output object file"); FOS << ObjectBuffer; - outs() << "BOLT-INFO: intermediary output object file saved for debugging " - "purposes: " - << OutObjectPath << "\n"; + BC->outs() + << "BOLT-INFO: intermediary output object file saved for debugging " + "purposes: " + << OutObjectPath << "\n"; } ErrorOr<BinarySection &> TextSection = @@ -3409,8 +3471,8 @@ void RewriteInstance::emitAndLink() { } if (opts::PrintCacheMetrics) { - outs() << "BOLT-INFO: cache metrics after emitting functions:\n"; - CacheMetrics::printAll(BC->getSortedFunctions()); + BC->outs() << "BOLT-INFO: cache metrics after emitting functions:\n"; + CacheMetrics::printAll(BC->outs(), BC->getSortedFunctions()); } } @@ -3576,14 +3638,15 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) { allocateAt(BC->OldTextSectionAddress) - BC->OldTextSectionAddress; if (CodeSize <= BC->OldTextSectionSize) { - outs() << "BOLT-INFO: using original .text for new code with 0x" - << Twine::utohexstr(opts::AlignText) << " alignment\n"; + BC->outs() << "BOLT-INFO: using original .text for new code with 0x" + << Twine::utohexstr(opts::AlignText) << " alignment\n"; AllocationDone = true; } else { - errs() << "BOLT-WARNING: original .text too small to fit the new code" - << " using 0x" << Twine::utohexstr(opts::AlignText) - << " alignment. " << CodeSize << " bytes needed, have " - << BC->OldTextSectionSize << " bytes available.\n"; + BC->errs() + << "BOLT-WARNING: original .text too small to fit the new code" + << " using 0x" << Twine::utohexstr(opts::AlignText) + << " alignment. " << CodeSize << " bytes needed, have " + << BC->OldTextSectionSize << " bytes available.\n"; opts::UseOldText = false; } } @@ -3604,9 +3667,9 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) { // Check if we need to insert a padding section for hot text. if (PaddingSize && !opts::UseOldText) - outs() << "BOLT-INFO: padding code to 0x" - << Twine::utohexstr(NextAvailableAddress) - << " to accommodate hot text\n"; + BC->outs() << "BOLT-INFO: padding code to 0x" + << Twine::utohexstr(NextAvailableAddress) + << " to accommodate hot text\n"; return; } @@ -3814,7 +3877,7 @@ void RewriteInstance::patchELFPHDRTable() { assert(!PHDRTableAddress && "unexpected address for program header table"); PHDRTableOffset = Obj.getHeader().e_phoff; if (NewWritableSegmentSize) { - errs() << "Unable to add writable segment with UseGnuStack option\n"; + BC->errs() << "Unable to add writable segment with UseGnuStack option\n"; exit(1); } } @@ -4114,7 +4177,8 @@ void RewriteInstance::encodeBATSection() { copyByteArray(BoltInfo), BoltInfo.size(), /*Alignment=*/1, /*IsReadOnly=*/true, ELF::SHT_NOTE); - outs() << "BOLT-INFO: BAT section size (bytes): " << BoltInfo.size() << '\n'; + BC->outs() << "BOLT-INFO: BAT section size (bytes): " << BoltInfo.size() + << '\n'; } template <typename ELFShdrTy> @@ -4175,14 +4239,14 @@ RewriteInstance::getOutputSections(ELFObjectFile<ELFT> *File, if (Section.hasSectionRef() || Section.isAnonymous()) { if (opts::Verbosity) - outs() << "BOLT-INFO: not writing section header for section " - << Section.getOutputName() << '\n'; + BC->outs() << "BOLT-INFO: not writing section header for section " + << Section.getOutputName() << '\n'; continue; } if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: writing section header for " - << Section.getOutputName() << '\n'; + BC->outs() << "BOLT-INFO: writing section header for " + << Section.getOutputName() << '\n'; ELFShdrTy NewSection; NewSection.sh_type = ELF::SHT_PROGBITS; NewSection.sh_addr = Section.getOutputAddress(); @@ -4216,8 +4280,8 @@ RewriteInstance::getOutputSections(ELFObjectFile<ELFT> *File, if (PrevSection && PrevSection->sh_offset + PrevSection->sh_size > Section.sh_offset) { if (opts::Verbosity > 1) { - outs() << "BOLT-INFO: adjusting size for section " - << PrevBinSec->getOutputName() << '\n'; + BC->outs() << "BOLT-INFO: adjusting size for section " + << PrevBinSec->getOutputName() << '\n'; } PrevSection->sh_size = Section.sh_offset - PrevSection->sh_offset; } @@ -4264,8 +4328,8 @@ RewriteInstance::getOutputSections(ELFObjectFile<ELFT> *File, continue; if (opts::Verbosity >= 1) - outs() << "BOLT-INFO: writing section header for " - << Section.getOutputName() << '\n'; + BC->outs() << "BOLT-INFO: writing section header for " + << Section.getOutputName() << '\n'; ELFShdrTy NewSection; NewSection.sh_type = Section.getELFType(); @@ -4663,8 +4727,8 @@ void RewriteInstance::updateELFSymbolTable( std::optional<uint64_t> Value = std::nullopt) { NewSymbol.st_value = Value ? *Value : getNewValueForSymbol(Name); NewSymbol.st_shndx = ELF::SHN_ABS; - outs() << "BOLT-INFO: setting " << Name << " to 0x" - << Twine::utohexstr(NewSymbol.st_value) << '\n'; + BC->outs() << "BOLT-INFO: setting " << Name << " to 0x" + << Twine::utohexstr(NewSymbol.st_value) << '\n'; }; if (opts::HotText && @@ -4739,8 +4803,8 @@ void RewriteInstance::updateELFSymbolTable( Symbol.st_other = 0; Symbol.setBindingAndType(ELF::STB_WEAK, ELF::STT_NOTYPE); - outs() << "BOLT-INFO: setting " << Name << " to 0x" - << Twine::utohexstr(Symbol.st_value) << '\n'; + BC->outs() << "BOLT-INFO: setting " << Name << " to 0x" + << Twine::utohexstr(Symbol.st_value) << '\n'; Symbols.emplace_back(Symbol); }; @@ -4836,7 +4900,7 @@ void RewriteInstance::patchELFSymTabs(ELFObjectFile<ELFT> *File) { } } if (!SymTabSection) { - errs() << "BOLT-WARNING: no symbol table found\n"; + BC->errs() << "BOLT-WARNING: no symbol table found\n"; return; } @@ -4939,7 +5003,7 @@ void RewriteInstance::patchELFAllocatableRelrSection( auto WriteRelr = [&](uint64_t Value) { if (RelrDynOffset + DynamicRelrEntrySize > RelrDynEndOffset) { - errs() << "BOLT-ERROR: Offset overflow for relr.dyn section\n"; + BC->errs() << "BOLT-ERROR: Offset overflow for relr.dyn section\n"; exit(1); } @@ -5051,12 +5115,12 @@ RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) { const uint64_t &EndOffset = IsJmpRel ? RelPltEndOffset : RelDynEndOffset; if (!Offset || !EndOffset) { - errs() << "BOLT-ERROR: Invalid offsets for dynamic relocation\n"; + BC->errs() << "BOLT-ERROR: Invalid offsets for dynamic relocation\n"; exit(1); } if (Offset + sizeof(NewRelA) > EndOffset) { - errs() << "BOLT-ERROR: Offset overflow for dynamic relocation\n"; + BC->errs() << "BOLT-ERROR: Offset overflow for dynamic relocation\n"; exit(1); } @@ -5105,7 +5169,7 @@ void RewriteInstance::patchELFGOT(ELFObjectFile<ELFT> *File) { } if (!GOTSection.getObject()) { if (!BC->IsStaticExecutable) - errs() << "BOLT-INFO: no .got section found\n"; + BC->errs() << "BOLT-INFO: no .got section found\n"; return; } @@ -5209,9 +5273,10 @@ void RewriteInstance::patchELFDynamic(ELFObjectFile<ELFT> *File) { } if (BC->RequiresZNow && !ZNowSet) { - errs() << "BOLT-ERROR: output binary requires immediate relocation " - "processing which depends on DT_FLAGS or DT_FLAGS_1 presence in " - ".dynamic. Please re-link the binary with -znow.\n"; + BC->errs() + << "BOLT-ERROR: output binary requires immediate relocation " + "processing which depends on DT_FLAGS or DT_FLAGS_1 presence in " + ".dynamic. Please re-link the binary with -znow.\n"; exit(1); } } @@ -5233,7 +5298,7 @@ Error RewriteInstance::readELFDynamic(ELFObjectFile<ELFT> *File) { } if (!DynamicPhdr) { - outs() << "BOLT-INFO: static input executable detected\n"; + BC->outs() << "BOLT-INFO: static input executable detected\n"; // TODO: static PIE executable might have dynamic header BC->IsStaticExecutable = true; return Error::success(); @@ -5307,12 +5372,12 @@ Error RewriteInstance::readELFDynamic(ELFObjectFile<ELFT> *File) { DynamicRelrAddress.reset(); DynamicRelrSize = 0; } else if (!DynamicRelrEntrySize) { - errs() << "BOLT-ERROR: expected DT_RELRENT to be presented " - << "in DYNAMIC section\n"; + BC->errs() << "BOLT-ERROR: expected DT_RELRENT to be presented " + << "in DYNAMIC section\n"; exit(1); } else if (DynamicRelrSize % DynamicRelrEntrySize) { - errs() << "BOLT-ERROR: expected RELR table size to be divisible " - << "by RELR entry size\n"; + BC->errs() << "BOLT-ERROR: expected RELR table size to be divisible " + << "by RELR entry size\n"; exit(1); } @@ -5368,11 +5433,11 @@ void RewriteInstance::rewriteFile() { if (Function->getImageSize() > Function->getMaxSize()) { if (opts::Verbosity >= 1) - errs() << "BOLT-WARNING: new function size (0x" - << Twine::utohexstr(Function->getImageSize()) - << ") is larger than maximum allowed size (0x" - << Twine::utohexstr(Function->getMaxSize()) << ") for function " - << *Function << '\n'; + BC->errs() << "BOLT-WARNING: new function size (0x" + << Twine::utohexstr(Function->getImageSize()) + << ") is larger than maximum allowed size (0x" + << Twine::utohexstr(Function->getMaxSize()) + << ") for function " << *Function << '\n'; // Remove jump table sections that this function owns in non-reloc mode // because we don't want to write them anymore. @@ -5408,7 +5473,7 @@ void RewriteInstance::rewriteFile() { // Overwrite function in the output file. if (opts::Verbosity >= 2) - outs() << "BOLT: rewriting function \"" << *Function << "\"\n"; + BC->outs() << "BOLT: rewriting function \"" << *Function << "\"\n"; OS.pwrite(reinterpret_cast<char *>(Function->getImageAddress()), Function->getImageSize(), Function->getFileOffset()); @@ -5428,8 +5493,8 @@ void RewriteInstance::rewriteFile() { // Write cold part if (opts::Verbosity >= 2) { - outs() << formatv("BOLT: rewriting function \"{0}\" (split parts)\n", - *Function); + BC->outs() << formatv("BOLT: rewriting function \"{0}\" (split parts)\n", + *Function); } for (const FunctionFragment &FF : @@ -5441,14 +5506,15 @@ void RewriteInstance::rewriteFile() { // Print function statistics for non-relocation mode. if (!BC->HasRelocations) { - outs() << "BOLT: " << CountOverwrittenFunctions << " out of " - << BC->getBinaryFunctions().size() - << " functions were overwritten.\n"; + BC->outs() << "BOLT: " << CountOverwrittenFunctions << " out of " + << BC->getBinaryFunctions().size() + << " functions were overwritten.\n"; if (BC->TotalScore != 0) { double Coverage = OverwrittenScore / (double)BC->TotalScore * 100.0; - outs() << format("BOLT-INFO: rewritten functions cover %.2lf", Coverage) - << "% of the execution count of simple functions of " - "this binary\n"; + BC->outs() << format("BOLT-INFO: rewritten functions cover %.2lf", + Coverage) + << "% of the execution count of simple functions of " + "this binary\n"; } } @@ -5476,10 +5542,11 @@ void RewriteInstance::rewriteFile() { continue; if (opts::Verbosity >= 1) - outs() << "BOLT: writing new section " << Section.getName() - << "\n data at 0x" << Twine::utohexstr(Section.getAllocAddress()) - << "\n of size " << Section.getOutputSize() << "\n at offset " - << Section.getOutputFileOffset() << '\n'; + BC->outs() << "BOLT: writing new section " << Section.getName() + << "\n data at 0x" + << Twine::utohexstr(Section.getAllocAddress()) << "\n of size " + << Section.getOutputSize() << "\n at offset " + << Section.getOutputFileOffset() << '\n'; OS.pwrite(reinterpret_cast<const char *>(Section.getOutputData()), Section.getOutputSize(), Section.getOutputFileOffset()); } @@ -5529,8 +5596,8 @@ void RewriteInstance::rewriteFile() { patchELFSectionHeaderTable(); if (opts::PrintSections) { - outs() << "BOLT-INFO: Sections after processing:\n"; - BC->printSections(outs()); + BC->outs() << "BOLT-INFO: Sections after processing:\n"; + BC->printSections(BC->outs()); } Out->keep(); |
