1 //===- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework -----------------===// 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 "DwarfFile.h" 10 #include "DwarfCompileUnit.h" 11 #include "DwarfDebug.h" 12 #include "DwarfUnit.h" 13 #include "llvm/CodeGen/AsmPrinter.h" 14 #include "llvm/IR/DebugInfoMetadata.h" 15 #include "llvm/IR/Metadata.h" 16 #include "llvm/MC/MCStreamer.h" 17 #include <algorithm> 18 #include <cstdint> 19 20 using namespace llvm; 21 22 DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA) 23 : Asm(AP), Abbrevs(AbbrevAllocator), StrPool(DA, *Asm, Pref) {} 24 25 void DwarfFile::addUnit(std::unique_ptr<DwarfCompileUnit> U) { 26 CUs.push_back(std::move(U)); 27 } 28 29 // Emit the various dwarf units to the unit section USection with 30 // the abbreviations going into ASection. 31 void DwarfFile::emitUnits(bool UseOffsets) { 32 for (const auto &TheU : CUs) 33 emitUnit(TheU.get(), UseOffsets); 34 } 35 36 void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) { 37 if (TheU->getCUNode()->isDebugDirectivesOnly()) 38 return; 39 40 MCSection *S = TheU->getSection(); 41 42 if (!S) 43 return; 44 45 // Skip CUs that ended up not being needed (split CUs that were abandoned 46 // because they added no information beyond the non-split CU) 47 if (llvm::empty(TheU->getUnitDie().values())) 48 return; 49 50 Asm->OutStreamer->SwitchSection(S); 51 TheU->emitHeader(UseOffsets); 52 Asm->emitDwarfDIE(TheU->getUnitDie()); 53 54 if (MCSymbol *EndLabel = TheU->getEndLabel()) 55 Asm->OutStreamer->emitLabel(EndLabel); 56 } 57 58 // Compute the size and offset for each DIE. 59 void DwarfFile::computeSizeAndOffsets() { 60 // Offset from the first CU in the debug info section is 0 initially. 61 uint64_t SecOffset = 0; 62 63 // Iterate over each compile unit and set the size and offsets for each 64 // DIE within each compile unit. All offsets are CU relative. 65 for (const auto &TheU : CUs) { 66 if (TheU->getCUNode()->isDebugDirectivesOnly()) 67 continue; 68 69 // Skip CUs that ended up not being needed (split CUs that were abandoned 70 // because they added no information beyond the non-split CU) 71 if (llvm::empty(TheU->getUnitDie().values())) 72 return; 73 74 TheU->setDebugSectionOffset(SecOffset); 75 SecOffset += computeSizeAndOffsetsForUnit(TheU.get()); 76 } 77 if (SecOffset > UINT32_MAX && !Asm->isDwarf64()) 78 report_fatal_error("The generated debug information is too large " 79 "for the 32-bit DWARF format."); 80 } 81 82 unsigned DwarfFile::computeSizeAndOffsetsForUnit(DwarfUnit *TheU) { 83 // CU-relative offset is reset to 0 here. 84 unsigned Offset = Asm->getUnitLengthFieldByteSize() + // Length of Unit Info 85 TheU->getHeaderSize(); // Unit-specific headers 86 87 // The return value here is CU-relative, after laying out 88 // all of the CU DIE. 89 return computeSizeAndOffset(TheU->getUnitDie(), Offset); 90 } 91 92 // Compute the size and offset of a DIE. The offset is relative to start of the 93 // CU. It returns the offset after laying out the DIE. 94 unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) { 95 return Die.computeOffsetsAndAbbrevs(Asm, Abbrevs, Offset); 96 } 97 98 void DwarfFile::emitAbbrevs(MCSection *Section) { Abbrevs.Emit(Asm, Section); } 99 100 // Emit strings into a string section. 101 void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection, 102 bool UseRelativeOffsets) { 103 StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets); 104 } 105 106 bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) { 107 auto &ScopeVars = ScopeVariables[LS]; 108 const DILocalVariable *DV = Var->getVariable(); 109 if (unsigned ArgNum = DV->getArg()) { 110 auto Cached = ScopeVars.Args.find(ArgNum); 111 if (Cached == ScopeVars.Args.end()) 112 ScopeVars.Args[ArgNum] = Var; 113 else { 114 Cached->second->addMMIEntry(*Var); 115 return false; 116 } 117 } else { 118 ScopeVars.Locals.push_back(Var); 119 } 120 return true; 121 } 122 123 void DwarfFile::addScopeLabel(LexicalScope *LS, DbgLabel *Label) { 124 SmallVectorImpl<DbgLabel *> &Labels = ScopeLabels[LS]; 125 Labels.push_back(Label); 126 } 127 128 std::pair<uint32_t, RangeSpanList *> 129 DwarfFile::addRange(const DwarfCompileUnit &CU, SmallVector<RangeSpan, 2> R) { 130 CURangeLists.push_back( 131 RangeSpanList{Asm->createTempSymbol("debug_ranges"), &CU, std::move(R)}); 132 return std::make_pair(CURangeLists.size() - 1, &CURangeLists.back()); 133 } 134