llvm/bolt/lib/Rewrite/DWARFRewriter.cpp

//===- bolt/Rewrite/DWARFRewriter.cpp -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#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) {}

/// Lazily parse DWARF DIE and print it out.
LLVM_ATTRIBUTE_UNUSED
static void printDie(DWARFUnit &DU, uint64_t DIEOffset) {}

usingnamespacebolt;

/// Take a set of DWARF address ranges corresponding to the input binary and
/// translate them to a set of address ranges in the output binary.
static DebugAddressRangesVector
translateInputToOutputRanges(const BinaryFunction &BF,
                             const DWARFAddressRangesVector &InputRanges) {}

/// Similar to translateInputToOutputRanges() but operates on location lists.
static DebugLocationsVector
translateInputToOutputLocationList(const BinaryFunction &BF,
                                   const DebugLocationsVector &InputLL) {}

usingnamespacedwarf_linker;
usingnamespacedwarf_linker::classic;

namespace llvm {
namespace bolt {
/// Emits debug information into .debug_info or .debug_types section.
class DIEStreamer : public DwarfStreamer {};

/// Finds attributes FormValue and Offset.
///
/// \param DIE die to look up in.
/// \param Attrs finds the first attribute that matches and extracts it.
/// \return an optional AttrInfo with DWARFFormValue and Offset.
std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,
                                          std::vector<dwarf::Attribute> Attrs) {}

} // namespace bolt
} // namespace llvm

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;
} // namespace opts

/// If DW_AT_low_pc exists sets LowPC and returns true.
static bool getLowPC(const DIE &Die, const DWARFUnit &DU, uint64_t &LowPC,
                     uint64_t &SectionIndex) {}

/// If DW_AT_high_pc exists sets HighPC and returns true.
static bool getHighPC(const DIE &Die, const uint64_t LowPC, uint64_t &HighPC) {}

/// If DW_AT_low_pc and DW_AT_high_pc exist sets LowPC and HighPC and returns
/// true.
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;
/// Partitions CUs in to buckets. Bucket size is controlled by
/// cu-processing-batch-size. All the CUs that have cross CU reference reference
/// as a source are put in to the same initial bucket.
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) {}

// Creates all the data structures necessary for creating MCStreamer.
// They are passed by reference because they need to be kept around.
// Also creates known debug sections. These are sections handled by
// handleDebugDataPatching.
namespace {

std::unique_ptr<BinaryContext>
createDwarfOnlyBC(const object::ObjectFile &File) {}

StringMap<DWARFRewriter::KnownSectionsEntry>
createKnownSectionsMap(const MCObjectFileInfo &MCOFI) {}

StringRef getSectionName(const SectionRef &Section) {}

// Exctracts an appropriate slice if input is DWP.
// Applies patches or overwrites the 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) {}

} // namespace

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) {}