#include "bolt/Rewrite/DWARFRewriter.h"
#include "bolt/Core/BinaryContext.h"
#include "bolt/Core/BinaryFunction.h"
#include "bolt/Core/DIEBuilder.h"
#include "bolt/Core/DebugData.h"
#include "bolt/Core/DynoStats.h"
#include "bolt/Core/ParallelUtilities.h"
#include "bolt/Rewrite/RewriteInstance.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/DWARFLinker/Classic/DWARFStreamer.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstdint>
#include <functional>
#include <iterator>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#undef DEBUG_TYPE
#define DEBUG_TYPE …
static mc::RegisterMCTargetOptionsFlags MOF;
static void printDie(const DWARFDie &DIE) { … }
LLVM_ATTRIBUTE_UNUSED
static void printDie(DWARFUnit &DU, uint64_t DIEOffset) { … }
usingnamespacebolt;
static DebugAddressRangesVector
translateInputToOutputRanges(const BinaryFunction &BF,
const DWARFAddressRangesVector &InputRanges) { … }
static DebugLocationsVector
translateInputToOutputLocationList(const BinaryFunction &BF,
const DebugLocationsVector &InputLL) { … }
usingnamespacedwarf_linker;
usingnamespacedwarf_linker::classic;
namespace llvm {
namespace bolt {
class DIEStreamer : public DwarfStreamer { … };
std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,
std::vector<dwarf::Attribute> Attrs) { … }
}
}
usingnamespacellvm;
usingnamespacellvm::support::endian;
usingnamespaceobject;
usingnamespacebolt;
namespace opts {
extern cl::OptionCategory BoltCategory;
extern cl::opt<unsigned> Verbosity;
extern cl::opt<std::string> OutputFilename;
static cl::opt<bool> KeepARanges(
"keep-aranges",
cl::desc(
"keep or generate .debug_aranges section if .gdb_index is written"),
cl::Hidden, cl::cat(BoltCategory));
static cl::opt<unsigned>
DebugThreadCount("debug-thread-count",
cl::desc("specifies thread count for the multithreading "
"for updating DWO debug info"),
cl::init(1), cl::cat(BoltCategory));
static cl::opt<std::string> DwarfOutputPath(
"dwarf-output-path",
cl::desc("Path to where .dwo files will be written out to."), cl::init(""),
cl::cat(BoltCategory));
static cl::opt<bool> CreateDebugNames(
"create-debug-names-section",
cl::desc("Creates .debug_names section, if the input binary doesn't have "
"it already, for DWARF5 CU/TUs."),
cl::init(false), cl::cat(BoltCategory));
static cl::opt<bool>
DebugSkeletonCu("debug-skeleton-cu",
cl::desc("prints out offsets for abbrev and debug_info of "
"Skeleton CUs that get patched."),
cl::ZeroOrMore, cl::Hidden, cl::init(false),
cl::cat(BoltCategory));
static cl::opt<unsigned> BatchSize(
"cu-processing-batch-size",
cl::desc(
"Specifies the size of batches for processing CUs. Higher number has "
"better performance, but more memory usage. Default value is 1."),
cl::Hidden, cl::init(1), cl::cat(BoltCategory));
static cl::opt<bool> AlwaysConvertToRanges(
"always-convert-to-ranges",
cl::desc("This option is for testing purposes only. It forces BOLT to "
"convert low_pc/high_pc to ranges always."),
cl::ReallyHidden, cl::init(false), cl::cat(BoltCategory));
extern cl::opt<std::string> CompDirOverride;
}
static bool getLowPC(const DIE &Die, const DWARFUnit &DU, uint64_t &LowPC,
uint64_t &SectionIndex) { … }
static bool getHighPC(const DIE &Die, const uint64_t LowPC, uint64_t &HighPC) { … }
static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU,
uint64_t &LowPC, uint64_t &HighPC,
uint64_t &SectionIndex) { … }
static Expected<llvm::DWARFAddressRangesVector>
getDIEAddressRanges(const DIE &Die, DWARFUnit &DU) { … }
static std::optional<uint64_t> getAsAddress(const DWARFUnit &DU,
const DIEValue &AttrVal) { … }
static std::unique_ptr<DIEStreamer>
createDIEStreamer(const Triple &TheTriple, raw_pwrite_stream &OutFile,
StringRef Swift5ReflectionSegmentName, DIEBuilder &DIEBldr,
GDBIndex &GDBIndexSection) { … }
static void emitUnit(DIEBuilder &DIEBldr, DIEStreamer &Streamer,
DWARFUnit &Unit) { … }
static void emitDWOBuilder(const std::string &DWOName,
DIEBuilder &DWODIEBuilder, DWARFRewriter &Rewriter,
DWARFUnit &SplitCU, DWARFUnit &CU,
DebugLocWriter &LocWriter,
DebugStrOffsetsWriter &StrOffstsWriter,
DebugStrWriter &StrWriter, GDBIndex &GDBIndexSection,
DebugRangesSectionWriter &TempRangesSectionWriter) { … }
DWARFUnitVec;
CUPartitionVector;
static CUPartitionVector partitionCUs(DWARFContext &DwCtx) { … }
void DWARFRewriter::updateDebugInfo() { … }
void DWARFRewriter::updateUnitDebugInfo(
DWARFUnit &Unit, DIEBuilder &DIEBldr, DebugLocWriter &DebugLocWriter,
DebugRangesSectionWriter &RangesSectionWriter,
DebugAddrWriter &AddressWriter, std::optional<uint64_t> RangesBase) { … }
void DWARFRewriter::updateDWARFObjectAddressRanges(
DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die, uint64_t DebugRangesOffset,
std::optional<uint64_t> RangesBase) { … }
void DWARFRewriter::updateLineTableOffsets(const MCAssembler &Asm) { … }
CUOffsetMap DWARFRewriter::finalizeTypeSections(DIEBuilder &DIEBlder,
DIEStreamer &Streamer,
GDBIndex &GDBIndexSection) { … }
void DWARFRewriter::finalizeDebugSections(
DIEBuilder &DIEBlder, DWARF5AcceleratorTable &DebugNamesTable,
DIEStreamer &Streamer, raw_svector_ostream &ObjOS, CUOffsetMap &CUMap,
DebugAddrWriter &FinalAddrWriter) { … }
void DWARFRewriter::finalizeCompileUnits(DIEBuilder &DIEBlder,
DIEStreamer &Streamer,
CUOffsetMap &CUMap,
const std::list<DWARFUnit *> &CUs,
DebugAddrWriter &FinalAddrWriter) { … }
namespace {
std::unique_ptr<BinaryContext>
createDwarfOnlyBC(const object::ObjectFile &File) { … }
StringMap<DWARFRewriter::KnownSectionsEntry>
createKnownSectionsMap(const MCObjectFileInfo &MCOFI) { … }
StringRef getSectionName(const SectionRef &Section) { … }
std::optional<StringRef> updateDebugData(
DWARFContext &DWCtx, StringRef SectionName, StringRef SectionContents,
const StringMap<DWARFRewriter::KnownSectionsEntry> &KnownSections,
MCStreamer &Streamer, DWARFRewriter &Writer,
const DWARFUnitIndex::Entry *CUDWOEntry, uint64_t DWOId,
std::unique_ptr<DebugBufferVector> &OutputBuffer,
DebugRangeListsSectionWriter *RangeListsWriter, DebugLocWriter &LocWriter,
DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter,
const llvm::bolt::DWARFRewriter::OverriddenSectionsMap &OverridenSections) { … }
}
void DWARFRewriter::writeDWOFiles(
DWARFUnit &CU, const OverriddenSectionsMap &OverridenSections,
const std::string &DWOName, DebugLocWriter &LocWriter,
DebugStrOffsetsWriter &StrOffstsWriter, DebugStrWriter &StrWriter,
DebugRangesSectionWriter &TempRangesSectionWriter) { … }
std::unique_ptr<DebugBufferVector>
DWARFRewriter::makeFinalLocListsSection(DWARFVersion Version) { … }
void DWARFRewriter::convertToRangesPatchDebugInfo(
DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die,
uint64_t RangesSectionOffset, DIEValue &LowPCAttrInfo,
DIEValue &HighPCAttrInfo, std::optional<uint64_t> RangesBase) { … }