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