1 //===- DWARFDebugMacro.cpp ------------------------------------------------===//
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 //===----------------------------------------------------------------------===//
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"
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(),
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.
49 IndLevel
-= (E
.Type
== DW_MACINFO_end_file
);
51 for (unsigned I
= 0; I
< IndLevel
; I
++)
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
));
60 WithColor(OS
, HighlightColor::Macro
).get() << MacinfoString(E
.Type
);
63 // Got a corrupted ".debug_macinfo/.debug_macro" section (invalid
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.
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
;
84 case DW_MACRO_start_file
:
85 OS
<< " - lineno: " << E
.Line
;
86 OS
<< " filenum: " << E
.File
;
89 OS
<< format(" - import offset: 0x%0*" PRIx64
,
90 2 * Macros
.Header
.getOffsetByteSize(), E
.ImportOffset
);
92 case DW_MACRO_end_file
:
94 case DW_MACINFO_vendor_ext
:
95 OS
<< " - constant: " << E
.ExtConstant
;
96 OS
<< " string: " << E
.ExtStr
;
104 Error
DWARFDebugMacro::parseImpl(
105 Optional
<DWARFUnitVector::compile_unit_range
> Units
,
106 Optional
<DataExtractor
> StringExtractor
, DWARFDataExtractor Data
,
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
)) {
123 MacroLists
.emplace_back();
124 M
= &MacroLists
.back();
126 M
->IsDebugMacro
= IsMacro
;
128 auto Err
= M
->Header
.parseMacroHeader(Data
, &Offset
);
133 // A macro list entry consists of:
134 M
->Macros
.emplace_back();
135 Entry
&E
= M
->Macros
.back();
137 E
.Type
= Data
.getULEB128(&Offset
);
140 // Reached end of a ".debug_macinfo/debug_macro" section contribution.
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
:
160 E
.Line
= Data
.getULEB128(&Offset
);
162 E
.MacroStr
= Data
.getCStr(&Offset
);
164 case DW_MACRO_define_strp
:
165 case DW_MACRO_undef_strp
: {
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;
175 E
.Line
= Data
.getULEB128(&Offset
);
178 Data
.getRelocatedValue(M
->Header
.getOffsetByteSize(), &Offset
);
179 assert(StringExtractor
&& "String Extractor not found");
180 E
.MacroStr
= StringExtractor
->getCStr(&StrOffset
);
183 case DW_MACRO_define_strx
:
184 case DW_MACRO_undef_strx
: {
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
));
201 return createStringError(
202 errc::invalid_argument
,
203 "String offsets contribution of the unit not found");
205 MacroContributionOffset
->second
->getStringExtractor().getCStr(
209 case DW_MACRO_start_file
:
211 E
.Line
= Data
.getULEB128(&Offset
);
213 E
.File
= Data
.getULEB128(&Offset
);
215 case DW_MACRO_end_file
:
217 case DW_MACRO_import
:
219 Data
.getRelocatedValue(M
->Header
.getOffsetByteSize(), &Offset
);
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
);
229 return Error::success();
232 Error
DWARFDebugMacro::MacroHeader::parseMacroHeader(DWARFDataExtractor Data
,
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");
242 if (Flags
& MACRO_DEBUG_LINE_OFFSET
)
243 DebugLineOffset
= Data
.getUnsigned(Offset
, getOffsetByteSize());
244 return Error::success();