16e07bfd0SEugene Zelenko //===- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework -----------------===//
285f80d71SDavid Blaikie //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
685f80d71SDavid Blaikie //
785f80d71SDavid Blaikie //===----------------------------------------------------------------------===//
885f80d71SDavid Blaikie
985f80d71SDavid Blaikie #include "DwarfFile.h"
107c384cceSPeter Collingbourne #include "DwarfCompileUnit.h"
1185f80d71SDavid Blaikie #include "DwarfDebug.h"
1285f80d71SDavid Blaikie #include "DwarfUnit.h"
136e07bfd0SEugene Zelenko #include "llvm/CodeGen/AsmPrinter.h"
146e07bfd0SEugene Zelenko #include "llvm/IR/DebugInfoMetadata.h"
1585f80d71SDavid Blaikie #include "llvm/MC/MCStreamer.h"
166e07bfd0SEugene Zelenko #include <cstdint>
1785f80d71SDavid Blaikie
186e07bfd0SEugene Zelenko using namespace llvm;
196e07bfd0SEugene Zelenko
DwarfFile(AsmPrinter * AP,StringRef Pref,BumpPtrAllocator & DA)209412d63fSFrederic Riss DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA)
213462a420SGreg Clayton : Asm(AP), Abbrevs(AbbrevAllocator), StrPool(DA, *Asm, Pref) {}
2285f80d71SDavid Blaikie
addUnit(std::unique_ptr<DwarfCompileUnit> U)237c384cceSPeter Collingbourne void DwarfFile::addUnit(std::unique_ptr<DwarfCompileUnit> U) {
2485f80d71SDavid Blaikie CUs.push_back(std::move(U));
2585f80d71SDavid Blaikie }
2685f80d71SDavid Blaikie
2785f80d71SDavid Blaikie // Emit the various dwarf units to the unit section USection with
2885f80d71SDavid Blaikie // the abbreviations going into ASection.
emitUnits(bool UseOffsets)29063d725fSRafael Espindola void DwarfFile::emitUnits(bool UseOffsets) {
307c384cceSPeter Collingbourne for (const auto &TheU : CUs)
317c384cceSPeter Collingbourne emitUnit(TheU.get(), UseOffsets);
327c384cceSPeter Collingbourne }
337c384cceSPeter Collingbourne
emitUnit(DwarfUnit * TheU,bool UseOffsets)347c384cceSPeter Collingbourne void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) {
35d4dd7215SAlexey Bataev if (TheU->getCUNode()->isDebugDirectivesOnly())
36d4dd7215SAlexey Bataev return;
37d4dd7215SAlexey Bataev
38560ff355SDavid Blaikie MCSection *S = TheU->getSection();
3985f80d71SDavid Blaikie
40560ff355SDavid Blaikie if (!S)
41560ff355SDavid Blaikie return;
42560ff355SDavid Blaikie
43104dcb34SDavid Blaikie // Skip CUs that ended up not being needed (split CUs that were abandoned
44104dcb34SDavid Blaikie // because they added no information beyond the non-split CU)
45104dcb34SDavid Blaikie if (llvm::empty(TheU->getUnitDie().values()))
46104dcb34SDavid Blaikie return;
47104dcb34SDavid Blaikie
48*adf4142fSFangrui Song Asm->OutStreamer->switchSection(S);
49063d725fSRafael Espindola TheU->emitHeader(UseOffsets);
50560ff355SDavid Blaikie Asm->emitDwarfDIE(TheU->getUnitDie());
51c4e08febSDavid Blaikie
52c4e08febSDavid Blaikie if (MCSymbol *EndLabel = TheU->getEndLabel())
536d2d589bSFangrui Song Asm->OutStreamer->emitLabel(EndLabel);
5485f80d71SDavid Blaikie }
55f299947bSDavid Blaikie
5685f80d71SDavid Blaikie // Compute the size and offset for each DIE.
computeSizeAndOffsets()5785f80d71SDavid Blaikie void DwarfFile::computeSizeAndOffsets() {
5885f80d71SDavid Blaikie // Offset from the first CU in the debug info section is 0 initially.
59a845ebd6SIgor Kudrin uint64_t SecOffset = 0;
6085f80d71SDavid Blaikie
6185f80d71SDavid Blaikie // Iterate over each compile unit and set the size and offsets for each
6285f80d71SDavid Blaikie // DIE within each compile unit. All offsets are CU relative.
6385f80d71SDavid Blaikie for (const auto &TheU : CUs) {
64d4dd7215SAlexey Bataev if (TheU->getCUNode()->isDebugDirectivesOnly())
65d4dd7215SAlexey Bataev continue;
66d4dd7215SAlexey Bataev
67104dcb34SDavid Blaikie // Skip CUs that ended up not being needed (split CUs that were abandoned
68104dcb34SDavid Blaikie // because they added no information beyond the non-split CU)
69104dcb34SDavid Blaikie if (llvm::empty(TheU->getUnitDie().values()))
70104dcb34SDavid Blaikie return;
71104dcb34SDavid Blaikie
7235630c33SGreg Clayton TheU->setDebugSectionOffset(SecOffset);
737c384cceSPeter Collingbourne SecOffset += computeSizeAndOffsetsForUnit(TheU.get());
747c384cceSPeter Collingbourne }
75a845ebd6SIgor Kudrin if (SecOffset > UINT32_MAX && !Asm->isDwarf64())
76a845ebd6SIgor Kudrin report_fatal_error("The generated debug information is too large "
77a845ebd6SIgor Kudrin "for the 32-bit DWARF format.");
787c384cceSPeter Collingbourne }
7985f80d71SDavid Blaikie
computeSizeAndOffsetsForUnit(DwarfUnit * TheU)807c384cceSPeter Collingbourne unsigned DwarfFile::computeSizeAndOffsetsForUnit(DwarfUnit *TheU) {
8185f80d71SDavid Blaikie // CU-relative offset is reset to 0 here.
825dd1c591SIgor Kudrin unsigned Offset = Asm->getUnitLengthFieldByteSize() + // Length of Unit Info
8385f80d71SDavid Blaikie TheU->getHeaderSize(); // Unit-specific headers
8485f80d71SDavid Blaikie
857c384cceSPeter Collingbourne // The return value here is CU-relative, after laying out
8685f80d71SDavid Blaikie // all of the CU DIE.
877c384cceSPeter Collingbourne return computeSizeAndOffset(TheU->getUnitDie(), Offset);
8885f80d71SDavid Blaikie }
897c384cceSPeter Collingbourne
9085f80d71SDavid Blaikie // Compute the size and offset of a DIE. The offset is relative to start of the
9185f80d71SDavid Blaikie // CU. It returns the offset after laying out the DIE.
computeSizeAndOffset(DIE & Die,unsigned Offset)9285f80d71SDavid Blaikie unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
9339385d4cSAlexey Lapshin return Die.computeOffsetsAndAbbrevs(Asm->getDwarfFormParams(), Abbrevs,
9439385d4cSAlexey Lapshin Offset);
9585f80d71SDavid Blaikie }
9685f80d71SDavid Blaikie
emitAbbrevs(MCSection * Section)973462a420SGreg Clayton void DwarfFile::emitAbbrevs(MCSection *Section) { Abbrevs.Emit(Asm, Section); }
9885f80d71SDavid Blaikie
9985f80d71SDavid Blaikie // Emit strings into a string section.
emitStrings(MCSection * StrSection,MCSection * OffsetSection,bool UseRelativeOffsets)100456b555fSWolfgang Pieb void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection,
101456b555fSWolfgang Pieb bool UseRelativeOffsets) {
102456b555fSWolfgang Pieb StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets);
10385f80d71SDavid Blaikie }
104f299947bSDavid Blaikie
addScopeVariable(LexicalScope * LS,DbgVariable * Var)105ca7e4702SAdrian Prantl bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
106c929f7adSAdrian Prantl auto &ScopeVars = ScopeVariables[LS];
107a9308c49SDuncan P. N. Exon Smith const DILocalVariable *DV = Var->getVariable();
1087348ddaaSDuncan P. N. Exon Smith if (unsigned ArgNum = DV->getArg()) {
109c929f7adSAdrian Prantl auto Cached = ScopeVars.Args.find(ArgNum);
110c929f7adSAdrian Prantl if (Cached == ScopeVars.Args.end())
111c929f7adSAdrian Prantl ScopeVars.Args[ArgNum] = Var;
112c929f7adSAdrian Prantl else {
113c929f7adSAdrian Prantl Cached->second->addMMIEntry(*Var);
114ca7e4702SAdrian Prantl return false;
115ca7e4702SAdrian Prantl }
116c929f7adSAdrian Prantl } else {
117c929f7adSAdrian Prantl ScopeVars.Locals.push_back(Var);
1183b5c8400SDavid Blaikie }
119ca7e4702SAdrian Prantl return true;
1203b5c8400SDavid Blaikie }
1212532ac88SHsiangkai Wang
addScopeLabel(LexicalScope * LS,DbgLabel * Label)1222532ac88SHsiangkai Wang void DwarfFile::addScopeLabel(LexicalScope *LS, DbgLabel *Label) {
1232532ac88SHsiangkai Wang SmallVectorImpl<DbgLabel *> &Labels = ScopeLabels[LS];
1242532ac88SHsiangkai Wang Labels.push_back(Label);
1252532ac88SHsiangkai Wang }
126c4af8bf2SDavid Blaikie
127c4af8bf2SDavid Blaikie std::pair<uint32_t, RangeSpanList *>
addRange(const DwarfCompileUnit & CU,SmallVector<RangeSpan,2> R)128c8f7e6c1SDavid Blaikie DwarfFile::addRange(const DwarfCompileUnit &CU, SmallVector<RangeSpan, 2> R) {
129c8f7e6c1SDavid Blaikie CURangeLists.push_back(
13064fa76efSDavid Blaikie RangeSpanList{Asm->createTempSymbol("debug_ranges"), &CU, std::move(R)});
131c4af8bf2SDavid Blaikie return std::make_pair(CURangeLists.size() - 1, &CURangeLists.back());
132c4af8bf2SDavid Blaikie }
133