1 //===- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework -----------------===//
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
7 //===----------------------------------------------------------------------===//
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"
22 DwarfFile::DwarfFile(AsmPrinter
*AP
, StringRef Pref
, BumpPtrAllocator
&DA
)
23 : Asm(AP
), Abbrevs(AbbrevAllocator
), StrPool(DA
, *Asm
, Pref
) {}
25 void DwarfFile::addUnit(std::unique_ptr
<DwarfCompileUnit
> U
) {
26 CUs
.push_back(std::move(U
));
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
);
36 void DwarfFile::emitUnit(DwarfUnit
*TheU
, bool UseOffsets
) {
37 if (TheU
->getCUNode()->isDebugDirectivesOnly())
40 MCSection
*S
= TheU
->getSection();
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()))
50 Asm
->OutStreamer
->SwitchSection(S
);
51 TheU
->emitHeader(UseOffsets
);
52 Asm
->emitDwarfDIE(TheU
->getUnitDie());
54 if (MCSymbol
*EndLabel
= TheU
->getEndLabel())
55 Asm
->OutStreamer
->emitLabel(EndLabel
);
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;
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())
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()))
74 TheU
->setDebugSectionOffset(SecOffset
);
75 SecOffset
+= computeSizeAndOffsetsForUnit(TheU
.get());
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.");
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
87 // The return value here is CU-relative, after laying out
89 return computeSizeAndOffset(TheU
->getUnitDie(), Offset
);
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
->getDwarfFormParams(), Abbrevs
,
99 void DwarfFile::emitAbbrevs(MCSection
*Section
) { Abbrevs
.Emit(Asm
, Section
); }
101 // Emit strings into a string section.
102 void DwarfFile::emitStrings(MCSection
*StrSection
, MCSection
*OffsetSection
,
103 bool UseRelativeOffsets
) {
104 StrPool
.emit(*Asm
, StrSection
, OffsetSection
, UseRelativeOffsets
);
107 bool DwarfFile::addScopeVariable(LexicalScope
*LS
, DbgVariable
*Var
) {
108 auto &ScopeVars
= ScopeVariables
[LS
];
109 const DILocalVariable
*DV
= Var
->getVariable();
110 if (unsigned ArgNum
= DV
->getArg()) {
111 auto Cached
= ScopeVars
.Args
.find(ArgNum
);
112 if (Cached
== ScopeVars
.Args
.end())
113 ScopeVars
.Args
[ArgNum
] = Var
;
115 Cached
->second
->addMMIEntry(*Var
);
119 ScopeVars
.Locals
.push_back(Var
);
124 void DwarfFile::addScopeLabel(LexicalScope
*LS
, DbgLabel
*Label
) {
125 SmallVectorImpl
<DbgLabel
*> &Labels
= ScopeLabels
[LS
];
126 Labels
.push_back(Label
);
129 std::pair
<uint32_t, RangeSpanList
*>
130 DwarfFile::addRange(const DwarfCompileUnit
&CU
, SmallVector
<RangeSpan
, 2> R
) {
131 CURangeLists
.push_back(
132 RangeSpanList
{Asm
->createTempSymbol("debug_ranges"), &CU
, std::move(R
)});
133 return std::make_pair(CURangeLists
.size() - 1, &CURangeLists
.back());