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