LLVM 23.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"
20#include <cstdint>
21
22using namespace llvm;
23using namespace dwarf;
24
25DwarfFormat DWARFDebugMacro::MacroHeader::getDwarfFormat() const {
26 return Flags & MACRO_OFFSET_SIZE ? DWARF64 : DWARF32;
27}
28
29uint8_t DWARFDebugMacro::MacroHeader::getOffsetByteSize() const {
30 return getDwarfOffsetByteSize(getDwarfFormat());
31}
32
33void DWARFDebugMacro::MacroHeader::dumpMacroHeader(raw_ostream &OS) const {
34 // FIXME: Add support for dumping opcode_operands_table
35 OS << formatv("macro header: version = {0:x4}", Version)
36 << formatv(", flags = {0:x2}", Flags)
37 << ", format = " << FormatString(getDwarfFormat());
38 if (Flags & MACRO_DEBUG_LINE_OFFSET)
39 OS << formatv(", debug_line_offset = 0x{0:x-}",
40 fmt_align(DebugLineOffset, AlignStyle::Right,
41 2 * getOffsetByteSize(), '0'));
42 OS << "\n";
43}
44
46 unsigned IndLevel = 0;
47 for (const auto &Macros : MacroLists) {
48 OS << formatv("{0:x8}:\n", Macros.Offset);
49 if (Macros.IsDebugMacro)
50 Macros.Header.dumpMacroHeader(OS);
51 for (const Entry &E : Macros.Macros) {
52 // There should not be DW_MACINFO_end_file when IndLevel is Zero. However,
53 // this check handles the case of corrupted ".debug_macinfo" section.
54 if (IndLevel > 0)
55 IndLevel -= (E.Type == DW_MACINFO_end_file);
56 // Print indentation.
57 for (unsigned I = 0; I < IndLevel; I++)
58 OS << " ";
59 IndLevel += (E.Type == DW_MACINFO_start_file);
60 // Based on which version we are handling choose appropriate macro forms.
61 if (Macros.IsDebugMacro)
63 << (Macros.Header.Version < 5 ? GnuMacroString(E.Type)
64 : MacroString(E.Type));
65 else
67 switch (E.Type) {
68 default:
69 // Got a corrupted ".debug_macinfo/.debug_macro" section (invalid
70 // macinfo type).
71 break;
72 // debug_macro and debug_macinfo share some common encodings.
73 // DW_MACRO_define == DW_MACINFO_define
74 // DW_MACRO_undef == DW_MACINFO_undef
75 // DW_MACRO_start_file == DW_MACINFO_start_file
76 // DW_MACRO_end_file == DW_MACINFO_end_file
77 // For readability/uniformity we are using DW_MACRO_*.
78 //
79 // The GNU .debug_macro extension's entries have the same encoding
80 // as DWARF 5's DW_MACRO_* entries, so we only use the latter here.
81 case DW_MACRO_define:
82 case DW_MACRO_undef:
83 case DW_MACRO_define_strp:
84 case DW_MACRO_undef_strp:
85 case DW_MACRO_define_strx:
86 case DW_MACRO_undef_strx:
87 OS << " - lineno: " << E.Line;
88 OS << " macro: " << E.MacroStr;
89 break;
90 case DW_MACRO_start_file:
91 OS << " - lineno: " << E.Line;
92 OS << " filenum: " << E.File;
93 break;
94 case DW_MACRO_import:
95 OS << formatv(" - import offset: 0x{0:x-}",
96 fmt_align(E.ImportOffset, AlignStyle::Right,
97 2 * Macros.Header.getOffsetByteSize(), '0'));
98 break;
99 case DW_MACRO_end_file:
100 break;
102 OS << " - constant: " << E.ExtConstant;
103 OS << " string: " << E.ExtStr;
104 break;
105 }
106 OS << "\n";
107 }
108 }
109}
110
111Error DWARFDebugMacro::parseImpl(
112 std::optional<DWARFUnitVector::compile_unit_range> Units,
113 std::optional<DataExtractor> StringExtractor, DWARFDataExtractor Data,
114 bool IsMacro) {
115 uint64_t Offset = 0;
116 MacroList *M = nullptr;
117 using MacroToUnitsMap = DenseMap<uint64_t, DWARFUnit *>;
118 MacroToUnitsMap MacroToUnits;
119 if (IsMacro && Data.isValidOffset(Offset)) {
120 // Keep a mapping from Macro contribution to CUs, this will
121 // be needed while retrieving macro from DW_MACRO_define_strx form.
122 for (const auto &U : *Units)
123 if (auto CUDIE = U->getUnitDIE())
124 // Skip units which does not contibutes to macro section.
125 if (auto MacroOffset = toSectionOffset(CUDIE.find(DW_AT_macros)))
126 MacroToUnits.try_emplace(*MacroOffset, U.get());
127 }
128 while (Data.isValidOffset(Offset)) {
129 if (!M) {
130 MacroLists.emplace_back();
131 M = &MacroLists.back();
132 M->Offset = Offset;
133 M->IsDebugMacro = IsMacro;
134 if (IsMacro) {
135 auto Err = M->Header.parseMacroHeader(Data, &Offset);
136 if (Err)
137 return Err;
138 }
139 }
140 // A macro list entry consists of:
141 M->Macros.emplace_back();
142 Entry &E = M->Macros.back();
143 // 1. Macinfo type
144 E.Type = Data.getULEB128(&Offset);
145
146 if (E.Type == 0) {
147 // Reached end of a ".debug_macinfo/debug_macro" section contribution.
148 M = nullptr;
149 continue;
150 }
151
152 switch (E.Type) {
153 default:
154 // Got a corrupted ".debug_macinfo" section (invalid macinfo type).
155 // Push the corrupted entry to the list and halt parsing.
156 E.Type = DW_MACINFO_invalid;
157 return Error::success();
158 // debug_macro and debug_macinfo share some common encodings.
159 // DW_MACRO_define == DW_MACINFO_define
160 // DW_MACRO_undef == DW_MACINFO_undef
161 // DW_MACRO_start_file == DW_MACINFO_start_file
162 // DW_MACRO_end_file == DW_MACINFO_end_file
163 // For readibility/uniformity we are using DW_MACRO_*.
164 case DW_MACRO_define:
165 case DW_MACRO_undef:
166 // 2. Source line
167 E.Line = Data.getULEB128(&Offset);
168 // 3. Macro string
169 E.MacroStr = Data.getCStr(&Offset);
170 break;
171 case DW_MACRO_define_strp:
172 case DW_MACRO_undef_strp: {
173 if (!IsMacro) {
174 // DW_MACRO_define_strp is a new form introduced in DWARFv5, it is
175 // not supported in debug_macinfo[.dwo] sections. Assume it as an
176 // invalid entry, push it and halt parsing.
177 E.Type = DW_MACINFO_invalid;
178 return Error::success();
179 }
180 uint64_t StrOffset = 0;
181 // 2. Source line
182 E.Line = Data.getULEB128(&Offset);
183 // 3. Macro string
184 StrOffset =
185 Data.getRelocatedValue(M->Header.getOffsetByteSize(), &Offset);
186 assert(StringExtractor && "String Extractor not found");
187 E.MacroStr = StringExtractor->getCStr(&StrOffset);
188 break;
189 }
190 case DW_MACRO_define_strx:
191 case DW_MACRO_undef_strx: {
192 if (!IsMacro) {
193 // DW_MACRO_define_strx is a new form introduced in DWARFv5, it is
194 // not supported in debug_macinfo[.dwo] sections. Assume it as an
195 // invalid entry, push it and halt parsing.
196 E.Type = DW_MACINFO_invalid;
197 return Error::success();
198 }
199 E.Line = Data.getULEB128(&Offset);
200 auto MacroContributionOffset = MacroToUnits.find(M->Offset);
201 if (MacroContributionOffset == MacroToUnits.end())
203 "Macro contribution of the unit not found");
204 Expected<uint64_t> StrOffset =
205 MacroContributionOffset->second->getStringOffsetSectionItem(
206 Data.getULEB128(&Offset));
207 if (!StrOffset)
208 return StrOffset.takeError();
209 E.MacroStr =
210 MacroContributionOffset->second->getStringExtractor().getCStr(
211 &*StrOffset);
212 break;
213 }
214 case DW_MACRO_start_file:
215 // 2. Source line
216 E.Line = Data.getULEB128(&Offset);
217 // 3. Source file id
218 E.File = Data.getULEB128(&Offset);
219 break;
220 case DW_MACRO_end_file:
221 break;
222 case DW_MACRO_import:
223 E.ImportOffset =
224 Data.getRelocatedValue(M->Header.getOffsetByteSize(), &Offset);
225 break;
227 // 2. Vendor extension constant
228 E.ExtConstant = Data.getULEB128(&Offset);
229 // 3. Vendor extension string
230 E.ExtStr = Data.getCStr(&Offset);
231 break;
232 }
233 }
234 return Error::success();
235}
236
237Error DWARFDebugMacro::MacroHeader::parseMacroHeader(DWARFDataExtractor Data,
238 uint64_t *Offset) {
239 Version = Data.getU16(Offset);
240 uint8_t FlagData = Data.getU8(Offset);
241
242 // FIXME: Add support for parsing opcode_operands_table
243 if (FlagData & MACRO_OPCODE_OPERANDS_TABLE)
245 "opcode_operands_table is not supported");
246 Flags = FlagData;
247 if (Flags & MACRO_DEBUG_LINE_OFFSET)
248 DebugLineOffset = Data.getUnsigned(Offset, getOffsetByteSize());
249 return Error::success();
250}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
This file contains constants used for implementing Dwarf debug support.
#define I(x, y, z)
Definition MD5.cpp:57
A DWARFDataExtractor (typically for an in-memory copy of an object-file section) plus a relocation ma...
void dump(raw_ostream &OS) const
Print the macro list found within the debug_macinfo/debug_macro section.
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
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:53
LLVM_ABI StringRef MacroString(unsigned Encoding)
Definition Dwarf.cpp:714
LLVM_ABI StringRef FormatString(DwarfFormat Format)
Definition Dwarf.cpp:1023
LLVM_ABI StringRef GnuMacroString(unsigned Encoding)
Definition Dwarf.cpp:725
LLVM_ABI StringRef MacinfoString(unsigned Encoding)
Definition Dwarf.cpp:685
Calculates the starting offsets for various sections within the .debug_names section.
Definition Dwarf.h:35
DwarfFormat
Constants that define the DWARF format as 32 or 64 bit.
Definition Dwarf.h:93
@ DWARF64
Definition Dwarf.h:93
@ DWARF32
Definition Dwarf.h:93
@ DW_MACINFO_start_file
Definition Dwarf.h:819
@ DW_MACINFO_end_file
Definition Dwarf.h:820
@ DW_MACINFO_vendor_ext
Definition Dwarf.h:821
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:1097
@ DW_MACINFO_invalid
Macinfo type for invalid results.
Definition Dwarf.h:50
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
@ not_supported
Definition Errc.h:69
@ invalid_argument
Definition Errc.h:56
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
FunctionAddr VTableAddr uintptr_t uintptr_t Version
Definition InstrProf.h:334
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:221
support::detail::AlignAdapter< T > fmt_align(T &&Item, AlignStyle Where, size_t Amount, char Fill=' ')