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/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 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 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 71 void 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 77 void 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 109 void 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 116 void 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 131 void 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 138 void 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. 157 void 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 174 dwarfgen::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 180 dwarfgen::DIE dwarfgen::CompileUnit::getUnitDIE() { 181 return dwarfgen::DIE(this, &DU.getUnitDie()); 182 } 183 184 //===----------------------------------------------------------------------===// 185 /// dwarfgen::LineTable implementation. 186 //===----------------------------------------------------------------------===// 187 DWARFDebugLine::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 228 void dwarfgen::LineTable::setPrologue(DWARFDebugLine::Prologue NewPrologue) { 229 Prologue = NewPrologue; 230 CustomPrologue.clear(); 231 } 232 233 void dwarfgen::LineTable::setCustomPrologue( 234 ArrayRef<ValueAndLength> NewPrologue) { 235 Prologue.reset(); 236 CustomPrologue = NewPrologue; 237 } 238 239 void dwarfgen::LineTable::addByte(uint8_t Value) { 240 Contents.push_back({Value, Byte}); 241 } 242 243 void dwarfgen::LineTable::addStandardOpcode(uint8_t Opcode, 244 ArrayRef<ValueAndLength> Operands) { 245 Contents.push_back({Opcode, Byte}); 246 Contents.insert(Contents.end(), Operands.begin(), Operands.end()); 247 } 248 249 void 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 Contents.insert(Contents.end(), Operands.begin(), Operands.end()); 255 } 256 257 void 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 274 void 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 295 size_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 313 MCSymbol *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 341 void 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 else 356 Asm.emitInt32(Prologue->PrologueLength); 357 358 writeProloguePayload(*Prologue, Asm); 359 } 360 361 static void writeCString(StringRef Str, AsmPrinter &Asm) { 362 Asm.OutStreamer->emitBytes(Str); 363 Asm.emitInt8(0); 364 } 365 366 static 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 382 static 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 only 386 // 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 405 void 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 else 421 writeV5IncludeAndFileTable(Prologue, Asm); 422 } 423 424 //===----------------------------------------------------------------------===// 425 /// dwarfgen::Generator implementation. 426 //===----------------------------------------------------------------------===// 427 428 dwarfgen::Generator::Generator() 429 : MAB(nullptr), MCE(nullptr), MS(nullptr), TLOF(nullptr), 430 StringPool(nullptr), Abbreviations(Allocator), 431 StringOffsetsStartSym(nullptr), Version(0) {} 432 dwarfgen::Generator::~Generator() = default; 433 434 llvm::Expected<std::unique_ptr<dwarfgen::Generator>> 435 dwarfgen::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 443 llvm::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(TripleName)); 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, TripleName, MCOptions)); 465 if (!MAI) 466 return make_error<StringError>("no asm info for target " + TripleName, 467 inconvertibleErrorCode()); 468 469 MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", "")); 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(TripleName, "", "", 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 531 unsigned dwarfgen::Generator::DummyAddressPool::getIndex(uint64_t Address) { 532 AddressValues.push_back(Address); 533 return static_cast<unsigned>(AddressValues.size() - 1); 534 } 535 536 void 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 section 542 Asm.OutStreamer->switchSection(AddrSection); 543 544 if (Asm.getDwarfVersion() >= 5) { 545 // Emit header 546 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 addresses 557 for (uint64_t Addr : AddressValues) 558 Asm.OutStreamer->emitIntValue(Addr, AddrSize); 559 } 560 561 StringRef 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 each 566 // 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 depends 571 // on the Dwarf version. 572 unsigned CUOffset = 4 + // Length 573 2 + // Version 574 4 + // Abbreviation offset 575 1; // Address size 576 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 < : 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 624 bool 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 636 dwarfgen::CompileUnit &dwarfgen::Generator::addCompileUnit() { 637 CompileUnits.push_back( 638 std::make_unique<CompileUnit>(*this, Version, Asm->getPointerSize())); 639 return *CompileUnits.back(); 640 } 641 642 dwarfgen::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