[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / lib / DebugInfo / DWARF / DWARFDebugMacro.cpp
blob80ffd81b34034f19959eed41589acd19905b6b26
1 //===- DWARFDebugMacro.cpp ------------------------------------------------===//
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 //===----------------------------------------------------------------------===//
9 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
10 #include "llvm/BinaryFormat/Dwarf.h"
11 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
12 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
13 #include "llvm/Support/WithColor.h"
14 #include "llvm/Support/raw_ostream.h"
15 #include <cstdint>
17 using namespace llvm;
18 using namespace dwarf;
20 DwarfFormat DWARFDebugMacro::MacroHeader::getDwarfFormat() const {
21 return Flags & MACRO_OFFSET_SIZE ? DWARF64 : DWARF32;
24 uint8_t DWARFDebugMacro::MacroHeader::getOffsetByteSize() const {
25 return getDwarfOffsetByteSize(getDwarfFormat());
28 void DWARFDebugMacro::MacroHeader::dumpMacroHeader(raw_ostream &OS) const {
29 // FIXME: Add support for dumping opcode_operands_table
30 OS << format("macro header: version = 0x%04" PRIx16, Version)
31 << format(", flags = 0x%02" PRIx8, Flags)
32 << ", format = " << FormatString(getDwarfFormat());
33 if (Flags & MACRO_DEBUG_LINE_OFFSET)
34 OS << format(", debug_line_offset = 0x%0*" PRIx64, 2 * getOffsetByteSize(),
35 DebugLineOffset);
36 OS << "\n";
39 void DWARFDebugMacro::dump(raw_ostream &OS) const {
40 unsigned IndLevel = 0;
41 for (const auto &Macros : MacroLists) {
42 OS << format("0x%08" PRIx64 ":\n", Macros.Offset);
43 if (Macros.IsDebugMacro)
44 Macros.Header.dumpMacroHeader(OS);
45 for (const Entry &E : Macros.Macros) {
46 // There should not be DW_MACINFO_end_file when IndLevel is Zero. However,
47 // this check handles the case of corrupted ".debug_macinfo" section.
48 if (IndLevel > 0)
49 IndLevel -= (E.Type == DW_MACINFO_end_file);
50 // Print indentation.
51 for (unsigned I = 0; I < IndLevel; I++)
52 OS << " ";
53 IndLevel += (E.Type == DW_MACINFO_start_file);
54 // Based on which version we are handling choose appropriate macro forms.
55 if (Macros.IsDebugMacro)
56 WithColor(OS, HighlightColor::Macro).get()
57 << (Macros.Header.Version < 5 ? GnuMacroString(E.Type)
58 : MacroString(E.Type));
59 else
60 WithColor(OS, HighlightColor::Macro).get() << MacinfoString(E.Type);
61 switch (E.Type) {
62 default:
63 // Got a corrupted ".debug_macinfo/.debug_macro" section (invalid
64 // macinfo type).
65 break;
66 // debug_macro and debug_macinfo share some common encodings.
67 // DW_MACRO_define == DW_MACINFO_define
68 // DW_MACRO_undef == DW_MACINFO_undef
69 // DW_MACRO_start_file == DW_MACINFO_start_file
70 // DW_MACRO_end_file == DW_MACINFO_end_file
71 // For readability/uniformity we are using DW_MACRO_*.
73 // The GNU .debug_macro extension's entries have the same encoding
74 // as DWARF 5's DW_MACRO_* entries, so we only use the latter here.
75 case DW_MACRO_define:
76 case DW_MACRO_undef:
77 case DW_MACRO_define_strp:
78 case DW_MACRO_undef_strp:
79 case DW_MACRO_define_strx:
80 case DW_MACRO_undef_strx:
81 OS << " - lineno: " << E.Line;
82 OS << " macro: " << E.MacroStr;
83 break;
84 case DW_MACRO_start_file:
85 OS << " - lineno: " << E.Line;
86 OS << " filenum: " << E.File;
87 break;
88 case DW_MACRO_import:
89 OS << format(" - import offset: 0x%0*" PRIx64,
90 2 * Macros.Header.getOffsetByteSize(), E.ImportOffset);
91 break;
92 case DW_MACRO_end_file:
93 break;
94 case DW_MACINFO_vendor_ext:
95 OS << " - constant: " << E.ExtConstant;
96 OS << " string: " << E.ExtStr;
97 break;
99 OS << "\n";
104 Error DWARFDebugMacro::parseImpl(
105 Optional<DWARFUnitVector::compile_unit_range> Units,
106 Optional<DataExtractor> StringExtractor, DWARFDataExtractor Data,
107 bool IsMacro) {
108 uint64_t Offset = 0;
109 MacroList *M = nullptr;
110 using MacroToUnitsMap = DenseMap<uint64_t, DWARFUnit *>;
111 MacroToUnitsMap MacroToUnits;
112 if (IsMacro && Data.isValidOffset(Offset)) {
113 // Keep a mapping from Macro contribution to CUs, this will
114 // be needed while retrieving macro from DW_MACRO_define_strx form.
115 for (const auto &U : Units.getValue())
116 if (auto CUDIE = U->getUnitDIE())
117 // Skip units which does not contibutes to macro section.
118 if (auto MacroOffset = toSectionOffset(CUDIE.find(DW_AT_macros)))
119 MacroToUnits.try_emplace(*MacroOffset, U.get());
121 while (Data.isValidOffset(Offset)) {
122 if (!M) {
123 MacroLists.emplace_back();
124 M = &MacroLists.back();
125 M->Offset = Offset;
126 M->IsDebugMacro = IsMacro;
127 if (IsMacro) {
128 auto Err = M->Header.parseMacroHeader(Data, &Offset);
129 if (Err)
130 return Err;
133 // A macro list entry consists of:
134 M->Macros.emplace_back();
135 Entry &E = M->Macros.back();
136 // 1. Macinfo type
137 E.Type = Data.getULEB128(&Offset);
139 if (E.Type == 0) {
140 // Reached end of a ".debug_macinfo/debug_macro" section contribution.
141 M = nullptr;
142 continue;
145 switch (E.Type) {
146 default:
147 // Got a corrupted ".debug_macinfo" section (invalid macinfo type).
148 // Push the corrupted entry to the list and halt parsing.
149 E.Type = DW_MACINFO_invalid;
150 return Error::success();
151 // debug_macro and debug_macinfo share some common encodings.
152 // DW_MACRO_define == DW_MACINFO_define
153 // DW_MACRO_undef == DW_MACINFO_undef
154 // DW_MACRO_start_file == DW_MACINFO_start_file
155 // DW_MACRO_end_file == DW_MACINFO_end_file
156 // For readibility/uniformity we are using DW_MACRO_*.
157 case DW_MACRO_define:
158 case DW_MACRO_undef:
159 // 2. Source line
160 E.Line = Data.getULEB128(&Offset);
161 // 3. Macro string
162 E.MacroStr = Data.getCStr(&Offset);
163 break;
164 case DW_MACRO_define_strp:
165 case DW_MACRO_undef_strp: {
166 if (!IsMacro) {
167 // DW_MACRO_define_strp is a new form introduced in DWARFv5, it is
168 // not supported in debug_macinfo[.dwo] sections. Assume it as an
169 // invalid entry, push it and halt parsing.
170 E.Type = DW_MACINFO_invalid;
171 return Error::success();
173 uint64_t StrOffset = 0;
174 // 2. Source line
175 E.Line = Data.getULEB128(&Offset);
176 // 3. Macro string
177 StrOffset =
178 Data.getRelocatedValue(M->Header.getOffsetByteSize(), &Offset);
179 assert(StringExtractor && "String Extractor not found");
180 E.MacroStr = StringExtractor->getCStr(&StrOffset);
181 break;
183 case DW_MACRO_define_strx:
184 case DW_MACRO_undef_strx: {
185 if (!IsMacro) {
186 // DW_MACRO_define_strx is a new form introduced in DWARFv5, it is
187 // not supported in debug_macinfo[.dwo] sections. Assume it as an
188 // invalid entry, push it and halt parsing.
189 E.Type = DW_MACINFO_invalid;
190 return Error::success();
192 E.Line = Data.getULEB128(&Offset);
193 auto MacroContributionOffset = MacroToUnits.find(M->Offset);
194 if (MacroContributionOffset == MacroToUnits.end())
195 return createStringError(errc::invalid_argument,
196 "Macro contribution of the unit not found");
197 Optional<uint64_t> StrOffset =
198 MacroContributionOffset->second->getStringOffsetSectionItem(
199 Data.getULEB128(&Offset));
200 if (!StrOffset)
201 return createStringError(
202 errc::invalid_argument,
203 "String offsets contribution of the unit not found");
204 E.MacroStr =
205 MacroContributionOffset->second->getStringExtractor().getCStr(
206 &*StrOffset);
207 break;
209 case DW_MACRO_start_file:
210 // 2. Source line
211 E.Line = Data.getULEB128(&Offset);
212 // 3. Source file id
213 E.File = Data.getULEB128(&Offset);
214 break;
215 case DW_MACRO_end_file:
216 break;
217 case DW_MACRO_import:
218 E.ImportOffset =
219 Data.getRelocatedValue(M->Header.getOffsetByteSize(), &Offset);
220 break;
221 case DW_MACINFO_vendor_ext:
222 // 2. Vendor extension constant
223 E.ExtConstant = Data.getULEB128(&Offset);
224 // 3. Vendor extension string
225 E.ExtStr = Data.getCStr(&Offset);
226 break;
229 return Error::success();
232 Error DWARFDebugMacro::MacroHeader::parseMacroHeader(DWARFDataExtractor Data,
233 uint64_t *Offset) {
234 Version = Data.getU16(Offset);
235 uint8_t FlagData = Data.getU8(Offset);
237 // FIXME: Add support for parsing opcode_operands_table
238 if (FlagData & MACRO_OPCODE_OPERANDS_TABLE)
239 return createStringError(errc::not_supported,
240 "opcode_operands_table is not supported");
241 Flags = FlagData;
242 if (Flags & MACRO_DEBUG_LINE_OFFSET)
243 DebugLineOffset = Data.getUnsigned(Offset, getOffsetByteSize());
244 return Error::success();