LLVM 20.0.0git
DWARFDebugMacro.cpp
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
8
10#include "llvm/ADT/DenseMap.h"
15#include "llvm/Support/Errc.h"
18#include <cstdint>
19
20using namespace llvm;
21using namespace dwarf;
22
23DwarfFormat DWARFDebugMacro::MacroHeader::getDwarfFormat() const {
24 return Flags & MACRO_OFFSET_SIZE ? DWARF64 : DWARF32;
25}
26
27uint8_t DWARFDebugMacro::MacroHeader::getOffsetByteSize() const {
28 return getDwarfOffsetByteSize(getDwarfFormat());
29}
30
31void DWARFDebugMacro::MacroHeader::dumpMacroHeader(raw_ostream &OS) const {
32 // FIXME: Add support for dumping opcode_operands_table
33 OS << format("macro header: version = 0x%04" PRIx16, Version)
34 << format(", flags = 0x%02" PRIx8, Flags)
35 << ", format = " << FormatString(getDwarfFormat());
36 if (Flags & MACRO_DEBUG_LINE_OFFSET)
37 OS << format(", debug_line_offset = 0x%0*" PRIx64, 2 * getOffsetByteSize(),
38 DebugLineOffset);
39 OS << "\n";
40}
41
43 unsigned IndLevel = 0;
44 for (const auto &Macros : MacroLists) {
45 OS << format("0x%08" PRIx64 ":\n", Macros.Offset);
46 if (Macros.IsDebugMacro)
47 Macros.Header.dumpMacroHeader(OS);
48 for (const Entry &E : Macros.Macros) {
49 // There should not be DW_MACINFO_end_file when IndLevel is Zero. However,
50 // this check handles the case of corrupted ".debug_macinfo" section.
51 if (IndLevel > 0)
52 IndLevel -= (E.Type == DW_MACINFO_end_file);
53 // Print indentation.
54 for (unsigned I = 0; I < IndLevel; I++)
55 OS << " ";
56 IndLevel += (E.Type == DW_MACINFO_start_file);
57 // Based on which version we are handling choose appropriate macro forms.
58 if (Macros.IsDebugMacro)
60 << (Macros.Header.Version < 5 ? GnuMacroString(E.Type)
61 : MacroString(E.Type));
62 else
64 switch (E.Type) {
65 default:
66 // Got a corrupted ".debug_macinfo/.debug_macro" section (invalid
67 // macinfo type).
68 break;
69 // debug_macro and debug_macinfo share some common encodings.
70 // DW_MACRO_define == DW_MACINFO_define
71 // DW_MACRO_undef == DW_MACINFO_undef
72 // DW_MACRO_start_file == DW_MACINFO_start_file
73 // DW_MACRO_end_file == DW_MACINFO_end_file
74 // For readability/uniformity we are using DW_MACRO_*.
75 //
76 // The GNU .debug_macro extension's entries have the same encoding
77 // as DWARF 5's DW_MACRO_* entries, so we only use the latter here.
78 case DW_MACRO_define:
79 case DW_MACRO_undef:
80 case DW_MACRO_define_strp:
81 case DW_MACRO_undef_strp:
82 case DW_MACRO_define_strx:
83 case DW_MACRO_undef_strx:
84 OS << " - lineno: " << E.Line;
85 OS << " macro: " << E.MacroStr;
86 break;
87 case DW_MACRO_start_file:
88 OS << " - lineno: " << E.Line;
89 OS << " filenum: " << E.File;
90 break;
91 case DW_MACRO_import:
92 OS << format(" - import offset: 0x%0*" PRIx64,
93 2 * Macros.Header.getOffsetByteSize(), E.ImportOffset);
94 break;
95 case DW_MACRO_end_file:
96 break;
98 OS << " - constant: " << E.ExtConstant;
99 OS << " string: " << E.ExtStr;
100 break;
101 }
102 OS << "\n";
103 }
104 }
105}
106
107Error DWARFDebugMacro::parseImpl(
108 std::optional<DWARFUnitVector::compile_unit_range> Units,
109 std::optional<DataExtractor> StringExtractor, DWARFDataExtractor Data,
110 bool IsMacro) {
111 uint64_t Offset = 0;
112 MacroList *M = nullptr;
113 using MacroToUnitsMap = DenseMap<uint64_t, DWARFUnit *>;
114 MacroToUnitsMap MacroToUnits;
115 if (IsMacro && Data.isValidOffset(Offset)) {
116 // Keep a mapping from Macro contribution to CUs, this will
117 // be needed while retrieving macro from DW_MACRO_define_strx form.
118 for (const auto &U : *Units)
119 if (auto CUDIE = U->getUnitDIE())
120 // Skip units which does not contibutes to macro section.
121 if (auto MacroOffset = toSectionOffset(CUDIE.find(DW_AT_macros)))
122 MacroToUnits.try_emplace(*MacroOffset, U.get());
123 }
124 while (Data.isValidOffset(Offset)) {
125 if (!M) {
126 MacroLists.emplace_back();
127 M = &MacroLists.back();
128 M->Offset = Offset;
129 M->IsDebugMacro = IsMacro;
130 if (IsMacro) {
131 auto Err = M->Header.parseMacroHeader(Data, &Offset);
132 if (Err)
133 return Err;
134 }
135 }
136 // A macro list entry consists of:
137 M->Macros.emplace_back();
138 Entry &E = M->Macros.back();
139 // 1. Macinfo type
140 E.Type = Data.getULEB128(&Offset);
141
142 if (E.Type == 0) {
143 // Reached end of a ".debug_macinfo/debug_macro" section contribution.
144 M = nullptr;
145 continue;
146 }
147
148 switch (E.Type) {
149 default:
150 // Got a corrupted ".debug_macinfo" section (invalid macinfo type).
151 // Push the corrupted entry to the list and halt parsing.
152 E.Type = DW_MACINFO_invalid;
153 return Error::success();
154 // debug_macro and debug_macinfo share some common encodings.
155 // DW_MACRO_define == DW_MACINFO_define
156 // DW_MACRO_undef == DW_MACINFO_undef
157 // DW_MACRO_start_file == DW_MACINFO_start_file
158 // DW_MACRO_end_file == DW_MACINFO_end_file
159 // For readibility/uniformity we are using DW_MACRO_*.
160 case DW_MACRO_define:
161 case DW_MACRO_undef:
162 // 2. Source line
163 E.Line = Data.getULEB128(&Offset);
164 // 3. Macro string
165 E.MacroStr = Data.getCStr(&Offset);
166 break;
167 case DW_MACRO_define_strp:
168 case DW_MACRO_undef_strp: {
169 if (!IsMacro) {
170 // DW_MACRO_define_strp is a new form introduced in DWARFv5, it is
171 // not supported in debug_macinfo[.dwo] sections. Assume it as an
172 // invalid entry, push it and halt parsing.
173 E.Type = DW_MACINFO_invalid;
174 return Error::success();
175 }
176 uint64_t StrOffset = 0;
177 // 2. Source line
178 E.Line = Data.getULEB128(&Offset);
179 // 3. Macro string
180 StrOffset =
181 Data.getRelocatedValue(M->Header.getOffsetByteSize(), &Offset);
182 assert(StringExtractor && "String Extractor not found");
183 E.MacroStr = StringExtractor->getCStr(&StrOffset);
184 break;
185 }
186 case DW_MACRO_define_strx:
187 case DW_MACRO_undef_strx: {
188 if (!IsMacro) {
189 // DW_MACRO_define_strx is a new form introduced in DWARFv5, it is
190 // not supported in debug_macinfo[.dwo] sections. Assume it as an
191 // invalid entry, push it and halt parsing.
192 E.Type = DW_MACINFO_invalid;
193 return Error::success();
194 }
195 E.Line = Data.getULEB128(&Offset);
196 auto MacroContributionOffset = MacroToUnits.find(M->Offset);
197 if (MacroContributionOffset == MacroToUnits.end())
199 "Macro contribution of the unit not found");
200 Expected<uint64_t> StrOffset =
201 MacroContributionOffset->second->getStringOffsetSectionItem(
202 Data.getULEB128(&Offset));
203 if (!StrOffset)
204 return StrOffset.takeError();
205 E.MacroStr =
206 MacroContributionOffset->second->getStringExtractor().getCStr(
207 &*StrOffset);
208 break;
209 }
210 case DW_MACRO_start_file:
211 // 2. Source line
212 E.Line = Data.getULEB128(&Offset);
213 // 3. Source file id
214 E.File = Data.getULEB128(&Offset);
215 break;
216 case DW_MACRO_end_file:
217 break;
218 case DW_MACRO_import:
219 E.ImportOffset =
220 Data.getRelocatedValue(M->Header.getOffsetByteSize(), &Offset);
221 break;
223 // 2. Vendor extension constant
224 E.ExtConstant = Data.getULEB128(&Offset);
225 // 3. Vendor extension string
226 E.ExtStr = Data.getCStr(&Offset);
227 break;
228 }
229 }
230 return Error::success();
231}
232
233Error DWARFDebugMacro::MacroHeader::parseMacroHeader(DWARFDataExtractor Data,
234 uint64_t *Offset) {
235 Version = Data.getU16(Offset);
236 uint8_t FlagData = Data.getU8(Offset);
237
238 // FIXME: Add support for parsing opcode_operands_table
239 if (FlagData & MACRO_OPCODE_OPERANDS_TABLE)
241 "opcode_operands_table is not supported");
242 Flags = FlagData;
243 if (Flags & MACRO_DEBUG_LINE_OFFSET)
244 DebugLineOffset = Data.getUnsigned(Offset, getOffsetByteSize());
245 return Error::success();
246}
This file defines the DenseMap class.
This file contains constants used for implementing Dwarf debug support.
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
A DataExtractor (typically for an in-memory copy of an object-file section) plus a relocation map for...
void dump(raw_ostream &OS) const
Print the macro list found within the debug_macinfo/debug_macro section.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition: DenseMap.h:226
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Tagged union holding either a T or a Error.
Definition: Error.h:481
Error takeError()
Take ownership of the stored error.
Definition: Error.h:608
An RAII object that temporarily switches an output stream to a specific color.
Definition: WithColor.h:54
raw_ostream & get()
Definition: WithColor.h:79
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
StringRef MacroString(unsigned Encoding)
Definition: Dwarf.cpp:563
StringRef FormatString(DwarfFormat Format)
Definition: Dwarf.cpp:868
StringRef GnuMacroString(unsigned Encoding)
Definition: Dwarf.cpp:574
StringRef MacinfoString(unsigned Encoding)
Definition: Dwarf.cpp:534
@ Entry
Definition: COFF.h:844
DwarfFormat
Constants that define the DWARF format as 32 or 64 bit.
Definition: Dwarf.h:91
@ DWARF64
Definition: Dwarf.h:91
@ DWARF32
Definition: Dwarf.h:91
@ DW_MACINFO_start_file
Definition: Dwarf.h:798
@ DW_MACINFO_end_file
Definition: Dwarf.h:799
@ DW_MACINFO_vendor_ext
Definition: Dwarf.h:800
std::optional< uint64_t > toSectionOffset(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an section offset.
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
Definition: Dwarf.h:1071
@ DW_MACINFO_invalid
Macinfo type for invalid results.
Definition: Dwarf.h:49
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1291
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125