//===- DwarfStreamer.h ------------------------------------------*- C++ -*-===//
 
//
 
// 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
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_DWARFLINKER_DWARFSTREAMER_H
 
#define LLVM_DWARFLINKER_DWARFSTREAMER_H
 
 
 
#include "llvm/BinaryFormat/Swift.h"
 
#include "llvm/CodeGen/AsmPrinter.h"
 
#include "llvm/DWARFLinker/DWARFLinker.h"
 
#include "llvm/MC/MCAsmInfo.h"
 
#include "llvm/MC/MCContext.h"
 
#include "llvm/MC/MCInstrInfo.h"
 
#include "llvm/MC/MCObjectFileInfo.h"
 
#include "llvm/MC/MCRegisterInfo.h"
 
#include "llvm/MC/MCSubtargetInfo.h"
 
#include "llvm/Target/TargetMachine.h"
 
 
 
namespace llvm {
 
template <typename DataT> class AccelTable;
 
 
 
enum class OutputFileType {
 
  Object,
 
  Assembly,
 
};
 
 
 
///   User of DwarfStreamer should call initialization code
 
///   for AsmPrinter:
 
///
 
///   InitializeAllTargetInfos();
 
///   InitializeAllTargetMCs();
 
///   InitializeAllTargets();
 
///   InitializeAllAsmPrinters();
 
 
 
class MCCodeEmitter;
 
class DWARFDebugMacro;
 
 
 
/// The Dwarf streaming logic.
 
///
 
/// All interactions with the MC layer that is used to build the debug
 
/// information binary representation are handled in this class.
 
class DwarfStreamer : public DwarfEmitter {
 
public:
 
  DwarfStreamer(OutputFileType OutFileType, raw_pwrite_stream &OutFile,
 
                std::function<StringRef(StringRef Input)> Translator,
 
                messageHandler Error, messageHandler Warning)
 
      : OutFile(OutFile), OutFileType(OutFileType), Translator(Translator),
 
        ErrorHandler(Error), WarningHandler(Warning) {}
 
 
 
  bool init(Triple TheTriple, StringRef Swift5ReflectionSegmentName);
 
 
 
  /// Dump the file to the disk.
 
  void finish();
 
 
 
  AsmPrinter &getAsmPrinter() const { return *Asm; }
 
 
 
  /// Set the current output section to debug_info and change
 
  /// the MC Dwarf version to \p DwarfVersion.
 
  void switchToDebugInfoSection(unsigned DwarfVersion);
 
 
 
  /// Emit the compilation unit header for \p Unit in the
 
  /// debug_info section.
 
  ///
 
  /// As a side effect, this also switches the current Dwarf version
 
  /// of the MC layer to the one of U.getOrigUnit().
 
  void emitCompileUnitHeader(CompileUnit &Unit, unsigned DwarfVersion) override;
 
 
 
  /// Recursively emit the DIE tree rooted at \p Die.
 
  void emitDIE(DIE &Die) override;
 
 
 
  /// Emit the abbreviation table \p Abbrevs to the debug_abbrev section.
 
  void emitAbbrevs(const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
 
                   unsigned DwarfVersion) override;
 
 
 
  /// Emit DIE containing warnings.
 
  void emitPaperTrailWarningsDie(DIE &Die) override;
 
 
 
  /// Emit contents of section SecName From Obj.
 
  void emitSectionContents(StringRef SecData, StringRef SecName) override;
 
 
 
  /// Emit the string table described by \p Pool.
 
  void emitStrings(const NonRelocatableStringpool &Pool) override;
 
 
 
  /// Emit the swift_ast section stored in \p Buffer.
 
  void emitSwiftAST(StringRef Buffer);
 
 
 
  /// Emit the swift reflection section stored in \p Buffer.
 
  void emitSwiftReflectionSection(
 
      llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
 
      StringRef Buffer, uint32_t Alignment, uint32_t Size);
 
 
 
  /// Emit piece of .debug_ranges for \p Ranges.
 
  virtual void
 
  emitDwarfDebugRangesTableFragment(const CompileUnit &Unit,
 
                                    const AddressRanges &LinkedRanges) override;
 
 
 
  /// Emit debug_aranges entries for \p Unit and if \p DoRangesSection is true,
 
  /// also emit the debug_ranges entries for the DW_TAG_compile_unit's
 
  /// DW_AT_ranges attribute.
 
  void emitUnitRangesEntries(CompileUnit &Unit, bool DoRangesSection) override;
 
 
 
  uint64_t getRangesSectionSize() const override { return RangesSectionSize; }
 
 
 
  /// Emit the debug_loc contribution for \p Unit by copying the entries from
 
  /// \p Dwarf and offsetting them. Update the location attributes to point to
 
  /// the new entries.
 
  void emitLocationsForUnit(
 
      const CompileUnit &Unit, DWARFContext &Dwarf,
 
      std::function<void(StringRef, SmallVectorImpl<uint8_t> &)> ProcessExpr)
 
      override;
 
 
 
  /// Emit the line table described in \p Rows into the debug_line section.
 
  void emitLineTableForUnit(MCDwarfLineTableParams Params,
 
                            StringRef PrologueBytes, unsigned MinInstLength,
 
                            std::vector<DWARFDebugLine::Row> &Rows,
 
                            unsigned AdddressSize) override;
 
 
 
  /// Copy the debug_line over to the updated binary while unobfuscating the
 
  /// file names and directories.
 
  void translateLineTable(DataExtractor LineData, uint64_t Offset) override;
 
 
 
  uint64_t getLineSectionSize() const override { return LineSectionSize; }
 
 
 
  /// Emit the .debug_pubnames contribution for \p Unit.
 
  void emitPubNamesForUnit(const CompileUnit &Unit) override;
 
 
 
  /// Emit the .debug_pubtypes contribution for \p Unit.
 
  void emitPubTypesForUnit(const CompileUnit &Unit) override;
 
 
 
  /// Emit a CIE.
 
  void emitCIE(StringRef CIEBytes) override;
 
 
 
  /// Emit an FDE with data \p Bytes.
 
  void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint64_t Address,
 
               StringRef Bytes) override;
 
 
 
  /// Emit DWARF debug names.
 
  void emitDebugNames(AccelTable<DWARF5AccelTableStaticData> &Table) override;
 
 
 
  /// Emit Apple namespaces accelerator table.
 
  void emitAppleNamespaces(
 
      AccelTable<AppleAccelTableStaticOffsetData> &Table) override;
 
 
 
  /// Emit Apple names accelerator table.
 
  void
 
  emitAppleNames(AccelTable<AppleAccelTableStaticOffsetData> &Table) override;
 
 
 
  /// Emit Apple Objective-C accelerator table.
 
  void
 
  emitAppleObjc(AccelTable<AppleAccelTableStaticOffsetData> &Table) override;
 
 
 
  /// Emit Apple type accelerator table.
 
  void
 
  emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> &Table) override;
 
 
 
  uint64_t getFrameSectionSize() const override { return FrameSectionSize; }
 
 
 
  uint64_t getDebugInfoSectionSize() const override {
 
    return DebugInfoSectionSize;
 
  }
 
 
 
  uint64_t getDebugMacInfoSectionSize() const override {
 
    return MacInfoSectionSize;
 
  }
 
 
 
  uint64_t getDebugMacroSectionSize() const override {
 
    return MacroSectionSize;
 
  }
 
 
 
  void emitMacroTables(DWARFContext *Context,
 
                       const Offset2UnitMap &UnitMacroMap,
 
                       OffsetsStringPool &StringPool) override;
 
 
 
private:
 
  inline void error(const Twine &Error, StringRef Context = "") {
 
    if (ErrorHandler)
 
      ErrorHandler(Error, Context, nullptr);
 
  }
 
 
 
  inline void warn(const Twine &Warning, StringRef Context = "") {
 
    if (WarningHandler)
 
      WarningHandler(Warning, Context, nullptr);
 
  }
 
 
 
  void emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
 
                          const Offset2UnitMap &UnitMacroMap,
 
                          OffsetsStringPool &StringPool, uint64_t &OutOffset);
 
  void emitDwarfDebugArangesTable(const CompileUnit &Unit,
 
                                  const AddressRanges &LinkedRanges);
 
 
 
  /// \defgroup MCObjects MC layer objects constructed by the streamer
 
  /// @{
 
  std::unique_ptr<MCRegisterInfo> MRI;
 
  std::unique_ptr<MCAsmInfo> MAI;
 
  std::unique_ptr<MCObjectFileInfo> MOFI;
 
  std::unique_ptr<MCContext> MC;
 
  MCAsmBackend *MAB; // Owned by MCStreamer
 
  std::unique_ptr<MCInstrInfo> MII;
 
  std::unique_ptr<MCSubtargetInfo> MSTI;
 
  MCInstPrinter *MIP; // Owned by AsmPrinter
 
  MCCodeEmitter *MCE; // Owned by MCStreamer
 
  MCStreamer *MS;     // Owned by AsmPrinter
 
  std::unique_ptr<TargetMachine> TM;
 
  std::unique_ptr<AsmPrinter> Asm;
 
  /// @}
 
 
 
  /// The output file we stream the linked Dwarf to.
 
  raw_pwrite_stream &OutFile;
 
  OutputFileType OutFileType = OutputFileType::Object;
 
  std::function<StringRef(StringRef Input)> Translator;
 
 
 
  uint64_t RangesSectionSize = 0;
 
  uint64_t LocSectionSize = 0;
 
  uint64_t LineSectionSize = 0;
 
  uint64_t FrameSectionSize = 0;
 
  uint64_t DebugInfoSectionSize = 0;
 
  uint64_t MacInfoSectionSize = 0;
 
  uint64_t MacroSectionSize = 0;
 
 
 
  /// Keep track of emitted CUs and their Unique ID.
 
  struct EmittedUnit {
 
    unsigned ID;
 
    MCSymbol *LabelBegin;
 
  };
 
  std::vector<EmittedUnit> EmittedUnits;
 
 
 
  /// Emit the pubnames or pubtypes section contribution for \p
 
  /// Unit into \p Sec. The data is provided in \p Names.
 
  void emitPubSectionForUnit(MCSection *Sec, StringRef Name,
 
                             const CompileUnit &Unit,
 
                             const std::vector<CompileUnit::AccelInfo> &Names);
 
 
 
  messageHandler ErrorHandler = nullptr;
 
  messageHandler WarningHandler = nullptr;
 
};
 
 
 
} // end namespace llvm
 
 
 
#endif // LLVM_DWARFLINKER_DWARFSTREAMER_H