brintos

brintos / llvm-project-archived public Read only

0
0
Text · 21.1 KiB · 6f1935a Raw
647 lines · cpp
1//===--- unittests/DebugInfo/DWARF/DwarfGenerator.cpp -----------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "DwarfGenerator.h"10#include "../lib/CodeGen/AsmPrinter/DwarfStringPool.h"11#include "llvm/BinaryFormat/Dwarf.h"12#include "llvm/CodeGen/AsmPrinter.h"13#include "llvm/CodeGen/DIE.h"14#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"15#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"16#include "llvm/MC/MCAsmBackend.h"17#include "llvm/MC/MCAsmInfo.h"18#include "llvm/MC/MCCodeEmitter.h"19#include "llvm/MC/MCContext.h"20#include "llvm/MC/MCDwarf.h"21#include "llvm/MC/MCInstrInfo.h"22#include "llvm/MC/MCObjectFileInfo.h"23#include "llvm/MC/MCObjectWriter.h"24#include "llvm/MC/MCRegisterInfo.h"25#include "llvm/MC/MCStreamer.h"26#include "llvm/MC/MCSubtargetInfo.h"27#include "llvm/MC/MCTargetOptionsCommandFlags.h"28#include "llvm/MC/TargetRegistry.h"29#include "llvm/Pass.h"30#include "llvm/Support/FileSystem.h"31#include "llvm/Support/LEB128.h"32#include "llvm/Support/raw_ostream.h"33#include "llvm/Target/TargetLoweringObjectFile.h"34#include "llvm/Target/TargetMachine.h"35#include "llvm/Target/TargetOptions.h"36#include "llvm/TargetParser/Triple.h"37 38using namespace llvm;39using namespace dwarf;40 41mc::RegisterMCTargetOptionsFlags MOF;42 43namespace {} // end anonymous namespace44 45//===----------------------------------------------------------------------===//46/// dwarfgen::DIE implementation.47//===----------------------------------------------------------------------===//48unsigned dwarfgen::DIE::computeSizeAndOffsets(unsigned Offset) {49  auto &DG = CU->getGenerator();50  return Die->computeOffsetsAndAbbrevs(DG.getAsmPrinter()->getDwarfFormParams(),51                                       DG.getAbbrevSet(), Offset);52}53 54void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form, uint64_t U) {55  auto &DG = CU->getGenerator();56  switch (Form) {57  case DW_FORM_addrx:58  case DW_FORM_addrx1:59  case DW_FORM_addrx2:60  case DW_FORM_addrx3:61  case DW_FORM_addrx4:62    U = DG.getAddressPool().getIndex(U);63    break;64  default:65    break;66  }67  Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,68                DIEInteger(U));69}70 71void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form, const MCExpr &Expr) {72  auto &DG = CU->getGenerator();73  Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,74                DIEExpr(&Expr));75}76 77void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,78                                 StringRef String) {79  auto &DG = CU->getGenerator();80  switch (Form) {81  case DW_FORM_string:82    Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,83                  new (DG.getAllocator())84                      DIEInlineString(String, DG.getAllocator()));85    break;86 87  case DW_FORM_strp:88    Die->addValue(89        DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,90        DIEString(DG.getStringPool().getEntry(*DG.getAsmPrinter(), String)));91    break;92 93  case DW_FORM_GNU_str_index:94  case DW_FORM_strx:95  case DW_FORM_strx1:96  case DW_FORM_strx2:97  case DW_FORM_strx3:98  case DW_FORM_strx4:99    Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,100                  DIEString(DG.getStringPool().getIndexedEntry(101                      *DG.getAsmPrinter(), String)));102    break;103 104  default:105    llvm_unreachable("Unhandled form!");106  }107}108 109void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,110                                 dwarfgen::DIE &RefDie) {111  auto &DG = CU->getGenerator();112  Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,113                DIEEntry(*RefDie.Die));114}115 116void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form, const void *P,117                                 size_t S) {118  auto &DG = CU->getGenerator();119  DIEBlock *Block = new (DG.getAllocator()) DIEBlock;120  for (size_t I = 0; I < S; ++I)121    Block->addValue(122        DG.getAllocator(), (dwarf::Attribute)0, dwarf::DW_FORM_data1,123        DIEInteger(124            (const_cast<uint8_t *>(static_cast<const uint8_t *>(P)))[I]));125 126  Block->computeSize(DG.getAsmPrinter()->getDwarfFormParams());127  Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,128                Block);129}130 131void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form) {132  auto &DG = CU->getGenerator();133  assert(Form == DW_FORM_flag_present);134  Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,135                DIEInteger(1));136}137 138void dwarfgen::DIE::addStrOffsetsBaseAttribute() {139  auto &DG = CU->getGenerator();140  auto &MC = *DG.getMCContext();141  AsmPrinter *Asm = DG.getAsmPrinter();142 143  const MCSymbol *SectionStart =144      Asm->getObjFileLowering().getDwarfStrOffSection()->getBeginSymbol();145 146  const MCExpr *Expr =147      MCSymbolRefExpr::create(DG.getStringOffsetsStartSym(), MC);148 149  if (!Asm->MAI->doesDwarfUseRelocationsAcrossSections())150    Expr = MCBinaryExpr::createSub(151        Expr, MCSymbolRefExpr::create(SectionStart, MC), MC);152 153  addAttribute(dwarf::DW_AT_str_offsets_base, DW_FORM_sec_offset, *Expr);154}155 156// This is currently fixed to be the first address entry after the header.157void dwarfgen::DIE::addAddrBaseAttribute() {158  auto &DG = CU->getGenerator();159  auto &MC = *DG.getMCContext();160  AsmPrinter *Asm = DG.getAsmPrinter();161 162  const MCSymbol *SectionStart =163      Asm->getObjFileLowering().getDwarfAddrSection()->getBeginSymbol();164 165  const MCExpr *Expr = MCSymbolRefExpr::create(DG.getAddrTableStartSym(), MC);166 167  if (!Asm->MAI->doesDwarfUseRelocationsAcrossSections())168    Expr = MCBinaryExpr::createSub(169        Expr, MCSymbolRefExpr::create(SectionStart, MC), MC);170 171  addAttribute(dwarf::DW_AT_addr_base, DW_FORM_sec_offset, *Expr);172}173 174dwarfgen::DIE dwarfgen::DIE::addChild(dwarf::Tag Tag) {175  auto &DG = CU->getGenerator();176  return dwarfgen::DIE(CU,177                       &Die->addChild(llvm::DIE::get(DG.getAllocator(), Tag)));178}179 180dwarfgen::DIE dwarfgen::CompileUnit::getUnitDIE() {181  return dwarfgen::DIE(this, &DU.getUnitDie());182}183 184//===----------------------------------------------------------------------===//185/// dwarfgen::LineTable implementation.186//===----------------------------------------------------------------------===//187DWARFDebugLine::Prologue dwarfgen::LineTable::createBasicPrologue() const {188  DWARFDebugLine::Prologue P;189  switch (Version) {190  case 2:191  case 3:192    P.TotalLength = 41;193    P.PrologueLength = 35;194    break;195  case 4:196    P.TotalLength = 42;197    P.PrologueLength = 36;198    break;199  case 5:200    P.TotalLength = 50;201    P.PrologueLength = 42;202    P.FormParams.AddrSize = AddrSize;203    break;204  default:205    llvm_unreachable("unsupported version");206  }207  if (Format == DWARF64) {208    P.TotalLength += 4;209    P.FormParams.Format = DWARF64;210  }211  P.TotalLength += getContentsSize();212  P.FormParams.Version = Version;213  P.MinInstLength = 1;214  P.MaxOpsPerInst = 1;215  P.DefaultIsStmt = 1;216  P.LineBase = -5;217  P.LineRange = 14;218  P.OpcodeBase = 13;219  P.StandardOpcodeLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1};220  P.IncludeDirectories.push_back(221      DWARFFormValue::createFromPValue(DW_FORM_string, "a dir"));222  P.FileNames.push_back(DWARFDebugLine::FileNameEntry());223  P.FileNames.back().Name =224      DWARFFormValue::createFromPValue(DW_FORM_string, "a file");225  return P;226}227 228void dwarfgen::LineTable::setPrologue(DWARFDebugLine::Prologue NewPrologue) {229  Prologue = NewPrologue;230  CustomPrologue.clear();231}232 233void dwarfgen::LineTable::setCustomPrologue(234    ArrayRef<ValueAndLength> NewPrologue) {235  Prologue.reset();236  CustomPrologue = NewPrologue;237}238 239void dwarfgen::LineTable::addByte(uint8_t Value) {240  Contents.push_back({Value, Byte});241}242 243void dwarfgen::LineTable::addStandardOpcode(uint8_t Opcode,244                                            ArrayRef<ValueAndLength> Operands) {245  Contents.push_back({Opcode, Byte});246  llvm::append_range(Contents, Operands);247}248 249void dwarfgen::LineTable::addExtendedOpcode(uint64_t Length, uint8_t Opcode,250                                            ArrayRef<ValueAndLength> Operands) {251  Contents.push_back({0, Byte});252  Contents.push_back({Length, ULEB});253  Contents.push_back({Opcode, Byte});254  llvm::append_range(Contents, Operands);255}256 257void dwarfgen::LineTable::generate(MCContext &MC, AsmPrinter &Asm) const {258  MC.setDwarfVersion(Version);259 260  MCSymbol *EndSymbol = nullptr;261  if (!CustomPrologue.empty()) {262    writeData(CustomPrologue, Asm);263  } else if (!Prologue) {264    EndSymbol = writeDefaultPrologue(Asm);265  } else {266    writePrologue(Asm);267  }268 269  writeData(Contents, Asm);270  if (EndSymbol != nullptr)271    Asm.OutStreamer->emitLabel(EndSymbol);272}273 274void dwarfgen::LineTable::writeData(ArrayRef<ValueAndLength> Data,275                                    AsmPrinter &Asm) const {276  for (auto Entry : Data) {277    switch (Entry.Length) {278    case Byte:279    case Half:280    case Long:281    case Quad:282      Asm.OutStreamer->emitIntValue(Entry.Value, Entry.Length);283      continue;284    case ULEB:285      Asm.emitULEB128(Entry.Value);286      continue;287    case SLEB:288      Asm.emitSLEB128(Entry.Value);289      continue;290    }291    llvm_unreachable("unsupported ValueAndLength Length value");292  }293}294 295size_t dwarfgen::LineTable::getContentsSize() const {296  size_t Size = 0;297  for (auto Entry : Contents) {298    switch (Entry.Length) {299    case ULEB:300      Size += getULEB128Size(Entry.Value);301      break;302    case SLEB:303      Size += getSLEB128Size(Entry.Value);304      break;305    default:306      Size += Entry.Length;307      break;308    }309  }310  return Size;311}312 313MCSymbol *dwarfgen::LineTable::writeDefaultPrologue(AsmPrinter &Asm) const {314  MCSymbol *UnitStart = Asm.createTempSymbol("line_unit_start");315  MCSymbol *UnitEnd = Asm.createTempSymbol("line_unit_end");316  if (Format == DwarfFormat::DWARF64) {317    Asm.emitInt32((int)dwarf::DW_LENGTH_DWARF64);318    Asm.emitLabelDifference(UnitEnd, UnitStart, 8);319  } else {320    Asm.emitLabelDifference(UnitEnd, UnitStart, 4);321  }322  Asm.OutStreamer->emitLabel(UnitStart);323  Asm.emitInt16(Version);324  if (Version == 5) {325    Asm.emitInt8(AddrSize);326    Asm.emitInt8(SegSize);327  }328 329  MCSymbol *PrologueStart = Asm.createTempSymbol("line_prologue_start");330  MCSymbol *PrologueEnd = Asm.createTempSymbol("line_prologue_end");331  Asm.emitLabelDifference(PrologueEnd, PrologueStart,332                          Format == DwarfFormat::DWARF64 ? 8 : 4);333  Asm.OutStreamer->emitLabel(PrologueStart);334 335  DWARFDebugLine::Prologue DefaultPrologue = createBasicPrologue();336  writeProloguePayload(DefaultPrologue, Asm);337  Asm.OutStreamer->emitLabel(PrologueEnd);338  return UnitEnd;339}340 341void dwarfgen::LineTable::writePrologue(AsmPrinter &Asm) const {342  if (Format == DwarfFormat::DWARF64) {343    Asm.emitInt32((int)dwarf::DW_LENGTH_DWARF64);344    Asm.emitInt64(Prologue->TotalLength);345  } else {346    Asm.emitInt32(Prologue->TotalLength);347  }348  Asm.emitInt16(Prologue->getVersion());349  if (Version == 5) {350    Asm.emitInt8(Prologue->getAddressSize());351    Asm.emitInt8(Prologue->SegSelectorSize);352  }353  if (Format == DwarfFormat::DWARF64)354    Asm.emitInt64(Prologue->PrologueLength);355  else356    Asm.emitInt32(Prologue->PrologueLength);357 358  writeProloguePayload(*Prologue, Asm);359}360 361static void writeCString(StringRef Str, AsmPrinter &Asm) {362  Asm.OutStreamer->emitBytes(Str);363  Asm.emitInt8(0);364}365 366static void writeV2IncludeAndFileTable(const DWARFDebugLine::Prologue &Prologue,367                                       AsmPrinter &Asm) {368  for (auto Include : Prologue.IncludeDirectories)369    writeCString(*toString(Include), Asm);370 371  Asm.emitInt8(0);372 373  for (auto File : Prologue.FileNames) {374    writeCString(*toString(File.Name), Asm);375    Asm.emitULEB128(File.DirIdx);376    Asm.emitULEB128(File.ModTime);377    Asm.emitULEB128(File.Length);378  }379  Asm.emitInt8(0);380}381 382static void writeV5IncludeAndFileTable(const DWARFDebugLine::Prologue &Prologue,383                                       AsmPrinter &Asm) {384  Asm.emitInt8(1); // directory_entry_format_count.385  // TODO: Add support for other content descriptions - we currently only386  // support a single DW_LNCT_path/DW_FORM_string.387  Asm.emitULEB128(DW_LNCT_path);388  Asm.emitULEB128(DW_FORM_string);389  Asm.emitULEB128(Prologue.IncludeDirectories.size());390  for (auto Include : Prologue.IncludeDirectories)391    writeCString(*toString(Include), Asm);392 393  Asm.emitInt8(2); // file_name_entry_format_count.394  Asm.emitULEB128(DW_LNCT_path);395  Asm.emitULEB128(DW_FORM_string);396  Asm.emitULEB128(DW_LNCT_directory_index);397  Asm.emitULEB128(DW_FORM_data1);398  Asm.emitULEB128(Prologue.FileNames.size());399  for (auto File : Prologue.FileNames) {400    writeCString(*toString(File.Name), Asm);401    Asm.emitInt8(File.DirIdx);402  }403}404 405void dwarfgen::LineTable::writeProloguePayload(406    const DWARFDebugLine::Prologue &Prologue, AsmPrinter &Asm) const {407  Asm.emitInt8(Prologue.MinInstLength);408  if (Version >= 4)409    Asm.emitInt8(Prologue.MaxOpsPerInst);410  Asm.emitInt8(Prologue.DefaultIsStmt);411  Asm.emitInt8(Prologue.LineBase);412  Asm.emitInt8(Prologue.LineRange);413  Asm.emitInt8(Prologue.OpcodeBase);414  for (auto Length : Prologue.StandardOpcodeLengths) {415    Asm.emitInt8(Length);416  }417 418  if (Version < 5)419    writeV2IncludeAndFileTable(Prologue, Asm);420  else421    writeV5IncludeAndFileTable(Prologue, Asm);422}423 424//===----------------------------------------------------------------------===//425/// dwarfgen::Generator implementation.426//===----------------------------------------------------------------------===//427 428dwarfgen::Generator::Generator()429    : MAB(nullptr), MCE(nullptr), MS(nullptr), TLOF(nullptr),430      StringPool(nullptr), Abbreviations(Allocator),431      StringOffsetsStartSym(nullptr), Version(0) {}432dwarfgen::Generator::~Generator() = default;433 434llvm::Expected<std::unique_ptr<dwarfgen::Generator>>435dwarfgen::Generator::create(Triple TheTriple, uint16_t DwarfVersion) {436  std::unique_ptr<dwarfgen::Generator> GenUP(new dwarfgen::Generator());437  llvm::Error error = GenUP->init(TheTriple, DwarfVersion);438  if (error)439    return Expected<std::unique_ptr<dwarfgen::Generator>>(std::move(error));440  return Expected<std::unique_ptr<dwarfgen::Generator>>(std::move(GenUP));441}442 443llvm::Error dwarfgen::Generator::init(Triple TheTriple, uint16_t V) {444  Version = V;445  std::string ErrorStr;446  std::string TripleName;447 448  // Get the target.449  const Target *TheTarget =450      TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);451  if (!TheTarget)452    return make_error<StringError>(ErrorStr, inconvertibleErrorCode());453 454  TripleName = TheTriple.getTriple();455 456  // Create all the MC Objects.457  MRI.reset(TheTarget->createMCRegInfo(TheTriple));458  if (!MRI)459    return make_error<StringError>(Twine("no register info for target ") +460                                       TripleName,461                                   inconvertibleErrorCode());462 463  MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();464  MAI.reset(TheTarget->createMCAsmInfo(*MRI, TheTriple, MCOptions));465  if (!MAI)466    return make_error<StringError>("no asm info for target " + TripleName,467                                   inconvertibleErrorCode());468 469  MSTI.reset(TheTarget->createMCSubtargetInfo(TheTriple, "", ""));470  if (!MSTI)471    return make_error<StringError>("no subtarget info for target " + TripleName,472                                   inconvertibleErrorCode());473 474  MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);475  if (!MAB)476    return make_error<StringError>("no asm backend for target " + TripleName,477                                   inconvertibleErrorCode());478 479  MII.reset(TheTarget->createMCInstrInfo());480  if (!MII)481    return make_error<StringError>("no instr info info for target " +482                                       TripleName,483                                   inconvertibleErrorCode());484 485  TM.reset(TheTarget->createTargetMachine(TheTriple, "", "", TargetOptions(),486                                          std::nullopt));487  if (!TM)488    return make_error<StringError>("no target machine for target " + TripleName,489                                   inconvertibleErrorCode());490 491  MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get()));492  TLOF = TM->getObjFileLowering();493  TLOF->Initialize(*MC, *TM);494  MC->setObjectFileInfo(TLOF);495 496  MCE = TheTarget->createMCCodeEmitter(*MII, *MC);497  if (!MCE)498    return make_error<StringError>("no code emitter for target " + TripleName,499                                   inconvertibleErrorCode());500 501  Stream = std::make_unique<raw_svector_ostream>(FileBytes);502 503  MS = TheTarget->createMCObjectStreamer(504      TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),505      MAB->createObjectWriter(*Stream), std::unique_ptr<MCCodeEmitter>(MCE),506      *MSTI);507  if (!MS)508    return make_error<StringError>("no object streamer for target " +509                                       TripleName,510                                   inconvertibleErrorCode());511 512 513  // Finally create the AsmPrinter we'll use to emit the DIEs.514  Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));515  if (!Asm)516    return make_error<StringError>("no asm printer for target " + TripleName,517                                   inconvertibleErrorCode());518 519  // Set the DWARF version correctly on all classes that we use.520  MC->setDwarfVersion(Version);521  Asm->setDwarfVersion(Version);522 523  StringPool = std::make_unique<DwarfStringPool>(Allocator, *Asm, StringRef());524  StringOffsetsStartSym = Asm->createTempSymbol("str_offsets_base");525 526  AddrTableStartSym = Asm->createTempSymbol("addr_table_base");527 528  return Error::success();529}530 531unsigned dwarfgen::Generator::DummyAddressPool::getIndex(uint64_t Address) {532  AddressValues.push_back(Address);533  return static_cast<unsigned>(AddressValues.size() - 1);534}535 536void dwarfgen::Generator::DummyAddressPool::emit(AsmPrinter &Asm,537                                                 MCSection *AddrSection,538                                                 MCSymbol *StartSym) {539  const uint8_t AddrSize = Asm.getPointerSize();540 541  // Switch to .debug_addr section542  Asm.OutStreamer->switchSection(AddrSection);543 544  if (Asm.getDwarfVersion() >= 5) {545    // Emit header546    Asm.emitDwarfUnitLength(AddrSize * AddressValues.size() + 4,547                            "Length of contribution");548    Asm.emitInt16(Asm.getDwarfVersion());549    Asm.emitInt8(AddrSize);550    Asm.emitInt8(0);551  }552 553  if (StartSym)554    Asm.OutStreamer->emitLabel(StartSym);555 556  // Emit addresses557  for (uint64_t Addr : AddressValues)558    Asm.OutStreamer->emitIntValue(Addr, AddrSize);559}560 561StringRef dwarfgen::Generator::generate() {562  // Offset from the first CU in the debug info section is 0 initially.563  uint64_t SecOffset = 0;564 565  // Iterate over each compile unit and set the size and offsets for each566  // DIE within each compile unit. All offsets are CU relative.567  for (auto &CU : CompileUnits) {568    // Set the absolute .debug_info offset for this compile unit.569    CU->setOffset(SecOffset);570    // The DIEs contain compile unit relative offsets and the offset depends571    // on the Dwarf version.572    unsigned CUOffset = 4 + // Length573                        2 + // Version574                        4 + // Abbreviation offset575                        1;  // Address size576    if (Asm->getDwarfVersion() >= 5)577      CUOffset += 1; // DW_UT_compile tag.578 579    CUOffset = CU->getUnitDIE().computeSizeAndOffsets(CUOffset);580    // Update our absolute .debug_info offset.581    SecOffset += CUOffset;582    unsigned CUOffsetUnitLength = 4;583    CU->setLength(CUOffset - CUOffsetUnitLength);584  }585  Abbreviations.Emit(Asm.get(), TLOF->getDwarfAbbrevSection());586 587  StringPool->emitStringOffsetsTableHeader(*Asm, TLOF->getDwarfStrOffSection(),588                                           StringOffsetsStartSym);589  StringPool->emit(*Asm, TLOF->getDwarfStrSection(),590                   TLOF->getDwarfStrOffSection());591 592  if (Asm->getDwarfVersion() >= 5)593    AddressPool.emit(*Asm, TLOF->getDwarfAddrSection(), AddrTableStartSym);594 595  MS->switchSection(TLOF->getDwarfInfoSection());596  for (auto &CU : CompileUnits) {597    uint16_t Version = CU->getVersion();598    auto Length = CU->getLength();599    MC->setDwarfVersion(Version);600    assert(Length != -1U);601    Asm->emitInt32(Length);602    Asm->emitInt16(Version);603    if (Version <= 4) {604      Asm->emitInt32(0);605      Asm->emitInt8(CU->getAddressSize());606    } else {607      Asm->emitInt8(dwarf::DW_UT_compile);608      Asm->emitInt8(CU->getAddressSize());609      Asm->emitInt32(0);610    }611    Asm->emitDwarfDIE(*CU->getUnitDIE().Die);612  }613 614  MS->switchSection(TLOF->getDwarfLineSection());615  for (auto &LT : LineTables)616    LT->generate(*MC, *Asm);617 618  MS->finish();619  if (FileBytes.empty())620    return StringRef();621  return StringRef(FileBytes.data(), FileBytes.size());622}623 624bool dwarfgen::Generator::saveFile(StringRef Path) {625  if (FileBytes.empty())626    return false;627  std::error_code EC;628  raw_fd_ostream Strm(Path, EC, sys::fs::OF_None);629  if (EC)630    return false;631  Strm.write(FileBytes.data(), FileBytes.size());632  Strm.close();633  return true;634}635 636dwarfgen::CompileUnit &dwarfgen::Generator::addCompileUnit() {637  CompileUnits.push_back(638      std::make_unique<CompileUnit>(*this, Version, Asm->getPointerSize()));639  return *CompileUnits.back();640}641 642dwarfgen::LineTable &dwarfgen::Generator::addLineTable(DwarfFormat Format) {643  LineTables.push_back(644      std::make_unique<LineTable>(Version, Format, Asm->getPointerSize()));645  return *LineTables.back();646}647