1//===- DWARFYAML.cpp - DWARF YAMLIO implementation ------------------------===//
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//
9// This file defines classes for handling the YAML representation of DWARF Debug
10// Info.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/ObjectYAML/DWARFYAML.h"
15#include "llvm/BinaryFormat/Dwarf.h"
16#include "llvm/Support/Errc.h"
17#include "llvm/Support/Error.h"
18
19namespace llvm {
20
21bool DWARFYAML::Data::isEmpty() const {
22 return getNonEmptySectionNames().empty();
23}
24
25SetVector<StringRef> DWARFYAML::Data::getNonEmptySectionNames() const {
26 SetVector<StringRef> SecNames;
27 if (DebugStrings)
28 SecNames.insert(X: "debug_str");
29 if (DebugAranges)
30 SecNames.insert(X: "debug_aranges");
31 if (DebugRanges)
32 SecNames.insert(X: "debug_ranges");
33 if (!DebugLines.empty())
34 SecNames.insert(X: "debug_line");
35 if (DebugAddr)
36 SecNames.insert(X: "debug_addr");
37 if (!DebugAbbrev.empty())
38 SecNames.insert(X: "debug_abbrev");
39 if (!CompileUnits.empty())
40 SecNames.insert(X: "debug_info");
41 if (PubNames)
42 SecNames.insert(X: "debug_pubnames");
43 if (PubTypes)
44 SecNames.insert(X: "debug_pubtypes");
45 if (GNUPubNames)
46 SecNames.insert(X: "debug_gnu_pubnames");
47 if (GNUPubTypes)
48 SecNames.insert(X: "debug_gnu_pubtypes");
49 if (DebugStrOffsets)
50 SecNames.insert(X: "debug_str_offsets");
51 if (DebugRnglists)
52 SecNames.insert(X: "debug_rnglists");
53 if (DebugLoclists)
54 SecNames.insert(X: "debug_loclists");
55 if (DebugNames)
56 SecNames.insert(X: "debug_names");
57 return SecNames;
58}
59
60Expected<DWARFYAML::Data::AbbrevTableInfo>
61DWARFYAML::Data::getAbbrevTableInfoByID(uint64_t ID) const {
62 if (AbbrevTableInfoMap.empty()) {
63 uint64_t AbbrevTableOffset = 0;
64 for (const auto &[Index, AbbrevTable] : enumerate(First: DebugAbbrev)) {
65 // If the abbrev table's ID isn't specified, we use the index as its ID.
66 uint64_t AbbrevTableID = AbbrevTable.ID.value_or(u&: Index);
67 auto It = AbbrevTableInfoMap.insert(
68 x: {AbbrevTableID, AbbrevTableInfo{/*Index=*/Index,
69 /*Offset=*/AbbrevTableOffset}});
70 if (!It.second)
71 return createStringError(
72 EC: errc::invalid_argument,
73 Fmt: "the ID (%" PRIu64 ") of abbrev table with index %zu has been used "
74 "by abbrev table with index %" PRIu64,
75 Vals: AbbrevTableID, Vals: Index, Vals: It.first->second.Index);
76
77 AbbrevTableOffset += getAbbrevTableContentByIndex(Index).size();
78 }
79 }
80
81 auto It = AbbrevTableInfoMap.find(x: ID);
82 if (It == AbbrevTableInfoMap.end())
83 return createStringError(EC: errc::invalid_argument,
84 Fmt: "cannot find abbrev table whose ID is %" PRIu64,
85 Vals: ID);
86 return It->second;
87}
88
89namespace yaml {
90
91void MappingTraits<DWARFYAML::Data>::mapping(IO &IO, DWARFYAML::Data &DWARF) {
92 void *OldContext = IO.getContext();
93 DWARFYAML::DWARFContext DWARFCtx;
94 IO.setContext(&DWARFCtx);
95 IO.mapOptional(Key: "debug_str", Val&: DWARF.DebugStrings);
96 IO.mapOptional(Key: "debug_abbrev", Val&: DWARF.DebugAbbrev);
97 IO.mapOptional(Key: "debug_aranges", Val&: DWARF.DebugAranges);
98 IO.mapOptional(Key: "debug_ranges", Val&: DWARF.DebugRanges);
99 IO.mapOptional(Key: "debug_pubnames", Val&: DWARF.PubNames);
100 IO.mapOptional(Key: "debug_pubtypes", Val&: DWARF.PubTypes);
101 DWARFCtx.IsGNUPubSec = true;
102 IO.mapOptional(Key: "debug_gnu_pubnames", Val&: DWARF.GNUPubNames);
103 IO.mapOptional(Key: "debug_gnu_pubtypes", Val&: DWARF.GNUPubTypes);
104 IO.mapOptional(Key: "debug_info", Val&: DWARF.CompileUnits);
105 IO.mapOptional(Key: "debug_line", Val&: DWARF.DebugLines);
106 IO.mapOptional(Key: "debug_addr", Val&: DWARF.DebugAddr);
107 IO.mapOptional(Key: "debug_str_offsets", Val&: DWARF.DebugStrOffsets);
108 IO.mapOptional(Key: "debug_rnglists", Val&: DWARF.DebugRnglists);
109 IO.mapOptional(Key: "debug_loclists", Val&: DWARF.DebugLoclists);
110 IO.mapOptional(Key: "debug_names", Val&: DWARF.DebugNames);
111 IO.setContext(OldContext);
112}
113
114void MappingTraits<DWARFYAML::AbbrevTable>::mapping(
115 IO &IO, DWARFYAML::AbbrevTable &AbbrevTable) {
116 IO.mapOptional(Key: "ID", Val&: AbbrevTable.ID);
117 IO.mapOptional(Key: "Table", Val&: AbbrevTable.Table);
118}
119
120void MappingTraits<DWARFYAML::Abbrev>::mapping(IO &IO,
121 DWARFYAML::Abbrev &Abbrev) {
122 IO.mapOptional(Key: "Code", Val&: Abbrev.Code);
123 IO.mapRequired(Key: "Tag", Val&: Abbrev.Tag);
124 IO.mapRequired(Key: "Children", Val&: Abbrev.Children);
125 IO.mapOptional(Key: "Attributes", Val&: Abbrev.Attributes);
126}
127
128void MappingTraits<DWARFYAML::IdxForm>::mapping(IO &IO,
129 DWARFYAML::IdxForm &IdxForm) {
130 IO.mapRequired(Key: "Idx", Val&: IdxForm.Idx);
131 IO.mapRequired(Key: "Form", Val&: IdxForm.Form);
132}
133
134void MappingTraits<DWARFYAML::DebugNameAbbreviation>::mapping(
135 IO &IO, DWARFYAML::DebugNameAbbreviation &DebugNameAbbreviation) {
136 IO.mapRequired(Key: "Code", Val&: DebugNameAbbreviation.Code);
137 IO.mapRequired(Key: "Tag", Val&: DebugNameAbbreviation.Tag);
138 IO.mapRequired(Key: "Indices", Val&: DebugNameAbbreviation.Indices);
139}
140
141void MappingTraits<DWARFYAML::DebugNameEntry>::mapping(
142 IO &IO, DWARFYAML::DebugNameEntry &DebugNameEntry) {
143 IO.mapRequired(Key: "Name", Val&: DebugNameEntry.NameStrp);
144 IO.mapRequired(Key: "Code", Val&: DebugNameEntry.Code);
145 IO.mapOptional(Key: "Values", Val&: DebugNameEntry.Values);
146}
147
148void MappingTraits<DWARFYAML::DebugNamesSection>::mapping(
149 IO &IO, DWARFYAML::DebugNamesSection &DebugNames) {
150 IO.mapRequired(Key: "Abbreviations", Val&: DebugNames.Abbrevs);
151 IO.mapRequired(Key: "Entries", Val&: DebugNames.Entries);
152}
153
154void MappingTraits<DWARFYAML::AttributeAbbrev>::mapping(
155 IO &IO, DWARFYAML::AttributeAbbrev &AttAbbrev) {
156 IO.mapRequired(Key: "Attribute", Val&: AttAbbrev.Attribute);
157 IO.mapRequired(Key: "Form", Val&: AttAbbrev.Form);
158 if(AttAbbrev.Form == dwarf::DW_FORM_implicit_const)
159 IO.mapRequired(Key: "Value", Val&: AttAbbrev.Value);
160}
161
162void MappingTraits<DWARFYAML::ARangeDescriptor>::mapping(
163 IO &IO, DWARFYAML::ARangeDescriptor &Descriptor) {
164 IO.mapRequired(Key: "Address", Val&: Descriptor.Address);
165 IO.mapRequired(Key: "Length", Val&: Descriptor.Length);
166}
167
168void MappingTraits<DWARFYAML::ARange>::mapping(IO &IO,
169 DWARFYAML::ARange &ARange) {
170 IO.mapOptional(Key: "Format", Val&: ARange.Format, Default: dwarf::DWARF32);
171 IO.mapOptional(Key: "Length", Val&: ARange.Length);
172 IO.mapRequired(Key: "Version", Val&: ARange.Version);
173 IO.mapRequired(Key: "CuOffset", Val&: ARange.CuOffset);
174 IO.mapOptional(Key: "AddressSize", Val&: ARange.AddrSize);
175 IO.mapOptional(Key: "SegmentSelectorSize", Val&: ARange.SegSize, Default: 0);
176 IO.mapOptional(Key: "Descriptors", Val&: ARange.Descriptors);
177}
178
179void MappingTraits<DWARFYAML::RangeEntry>::mapping(
180 IO &IO, DWARFYAML::RangeEntry &Descriptor) {
181 IO.mapRequired(Key: "LowOffset", Val&: Descriptor.LowOffset);
182 IO.mapRequired(Key: "HighOffset", Val&: Descriptor.HighOffset);
183}
184
185void MappingTraits<DWARFYAML::Ranges>::mapping(IO &IO,
186 DWARFYAML::Ranges &DebugRanges) {
187 IO.mapOptional(Key: "Offset", Val&: DebugRanges.Offset);
188 IO.mapOptional(Key: "AddrSize", Val&: DebugRanges.AddrSize);
189 IO.mapRequired(Key: "Entries", Val&: DebugRanges.Entries);
190}
191
192void MappingTraits<DWARFYAML::PubEntry>::mapping(IO &IO,
193 DWARFYAML::PubEntry &Entry) {
194 IO.mapRequired(Key: "DieOffset", Val&: Entry.DieOffset);
195 if (static_cast<DWARFYAML::DWARFContext *>(IO.getContext())->IsGNUPubSec)
196 IO.mapRequired(Key: "Descriptor", Val&: Entry.Descriptor);
197 IO.mapRequired(Key: "Name", Val&: Entry.Name);
198}
199
200void MappingTraits<DWARFYAML::PubSection>::mapping(
201 IO &IO, DWARFYAML::PubSection &Section) {
202 IO.mapOptional(Key: "Format", Val&: Section.Format, Default: dwarf::DWARF32);
203 IO.mapRequired(Key: "Length", Val&: Section.Length);
204 IO.mapRequired(Key: "Version", Val&: Section.Version);
205 IO.mapRequired(Key: "UnitOffset", Val&: Section.UnitOffset);
206 IO.mapRequired(Key: "UnitSize", Val&: Section.UnitSize);
207 IO.mapRequired(Key: "Entries", Val&: Section.Entries);
208}
209
210void MappingTraits<DWARFYAML::Unit>::mapping(IO &IO, DWARFYAML::Unit &Unit) {
211 IO.mapOptional(Key: "Format", Val&: Unit.Format, Default: dwarf::DWARF32);
212 IO.mapOptional(Key: "Length", Val&: Unit.Length);
213 IO.mapRequired(Key: "Version", Val&: Unit.Version);
214 if (Unit.Version >= 5)
215 IO.mapRequired(Key: "UnitType", Val&: Unit.Type);
216 IO.mapOptional(Key: "AbbrevTableID", Val&: Unit.AbbrevTableID);
217 IO.mapOptional(Key: "AbbrOffset", Val&: Unit.AbbrOffset);
218 IO.mapOptional(Key: "AddrSize", Val&: Unit.AddrSize);
219 IO.mapOptional(Key: "Entries", Val&: Unit.Entries);
220}
221
222void MappingTraits<DWARFYAML::Entry>::mapping(IO &IO, DWARFYAML::Entry &Entry) {
223 IO.mapRequired(Key: "AbbrCode", Val&: Entry.AbbrCode);
224 IO.mapOptional(Key: "Values", Val&: Entry.Values);
225}
226
227void MappingTraits<DWARFYAML::FormValue>::mapping(
228 IO &IO, DWARFYAML::FormValue &FormValue) {
229 IO.mapOptional(Key: "Value", Val&: FormValue.Value);
230 if (!FormValue.CStr.empty() || !IO.outputting())
231 IO.mapOptional(Key: "CStr", Val&: FormValue.CStr);
232 if (!FormValue.BlockData.empty() || !IO.outputting())
233 IO.mapOptional(Key: "BlockData", Val&: FormValue.BlockData);
234}
235
236void MappingTraits<DWARFYAML::File>::mapping(IO &IO, DWARFYAML::File &File) {
237 IO.mapRequired(Key: "Name", Val&: File.Name);
238 IO.mapRequired(Key: "DirIdx", Val&: File.DirIdx);
239 IO.mapRequired(Key: "ModTime", Val&: File.ModTime);
240 IO.mapRequired(Key: "Length", Val&: File.Length);
241}
242
243void MappingTraits<DWARFYAML::LineTableOpcode>::mapping(
244 IO &IO, DWARFYAML::LineTableOpcode &LineTableOpcode) {
245 IO.mapRequired(Key: "Opcode", Val&: LineTableOpcode.Opcode);
246 if (LineTableOpcode.Opcode == dwarf::DW_LNS_extended_op) {
247 IO.mapOptional(Key: "ExtLen", Val&: LineTableOpcode.ExtLen);
248 IO.mapRequired(Key: "SubOpcode", Val&: LineTableOpcode.SubOpcode);
249 }
250
251 if (!LineTableOpcode.UnknownOpcodeData.empty() || !IO.outputting())
252 IO.mapOptional(Key: "UnknownOpcodeData", Val&: LineTableOpcode.UnknownOpcodeData);
253 if (!LineTableOpcode.UnknownOpcodeData.empty() || !IO.outputting())
254 IO.mapOptional(Key: "StandardOpcodeData", Val&: LineTableOpcode.StandardOpcodeData);
255 if (!LineTableOpcode.FileEntry.Name.empty() || !IO.outputting())
256 IO.mapOptional(Key: "FileEntry", Val&: LineTableOpcode.FileEntry);
257 if (LineTableOpcode.Opcode == dwarf::DW_LNS_advance_line || !IO.outputting())
258 IO.mapOptional(Key: "SData", Val&: LineTableOpcode.SData);
259 IO.mapOptional(Key: "Data", Val&: LineTableOpcode.Data);
260}
261
262void MappingTraits<DWARFYAML::LineTable>::mapping(
263 IO &IO, DWARFYAML::LineTable &LineTable) {
264 IO.mapOptional(Key: "Format", Val&: LineTable.Format, Default: dwarf::DWARF32);
265 IO.mapOptional(Key: "Length", Val&: LineTable.Length);
266 IO.mapRequired(Key: "Version", Val&: LineTable.Version);
267 IO.mapOptional(Key: "PrologueLength", Val&: LineTable.PrologueLength);
268 IO.mapRequired(Key: "MinInstLength", Val&: LineTable.MinInstLength);
269 if(LineTable.Version >= 4)
270 IO.mapRequired(Key: "MaxOpsPerInst", Val&: LineTable.MaxOpsPerInst);
271 IO.mapRequired(Key: "DefaultIsStmt", Val&: LineTable.DefaultIsStmt);
272 IO.mapRequired(Key: "LineBase", Val&: LineTable.LineBase);
273 IO.mapRequired(Key: "LineRange", Val&: LineTable.LineRange);
274 IO.mapOptional(Key: "OpcodeBase", Val&: LineTable.OpcodeBase);
275 IO.mapOptional(Key: "StandardOpcodeLengths", Val&: LineTable.StandardOpcodeLengths);
276 IO.mapOptional(Key: "IncludeDirs", Val&: LineTable.IncludeDirs);
277 IO.mapOptional(Key: "Files", Val&: LineTable.Files);
278 IO.mapOptional(Key: "Opcodes", Val&: LineTable.Opcodes);
279}
280
281void MappingTraits<DWARFYAML::SegAddrPair>::mapping(
282 IO &IO, DWARFYAML::SegAddrPair &SegAddrPair) {
283 IO.mapOptional(Key: "Segment", Val&: SegAddrPair.Segment, Default: 0);
284 IO.mapOptional(Key: "Address", Val&: SegAddrPair.Address, Default: 0);
285}
286
287void MappingTraits<DWARFYAML::AddrTableEntry>::mapping(
288 IO &IO, DWARFYAML::AddrTableEntry &AddrTable) {
289 IO.mapOptional(Key: "Format", Val&: AddrTable.Format, Default: dwarf::DWARF32);
290 IO.mapOptional(Key: "Length", Val&: AddrTable.Length);
291 IO.mapRequired(Key: "Version", Val&: AddrTable.Version);
292 IO.mapOptional(Key: "AddressSize", Val&: AddrTable.AddrSize);
293 IO.mapOptional(Key: "SegmentSelectorSize", Val&: AddrTable.SegSelectorSize, Default: 0);
294 IO.mapOptional(Key: "Entries", Val&: AddrTable.SegAddrPairs);
295}
296
297void MappingTraits<DWARFYAML::StringOffsetsTable>::mapping(
298 IO &IO, DWARFYAML::StringOffsetsTable &StrOffsetsTable) {
299 IO.mapOptional(Key: "Format", Val&: StrOffsetsTable.Format, Default: dwarf::DWARF32);
300 IO.mapOptional(Key: "Length", Val&: StrOffsetsTable.Length);
301 IO.mapOptional(Key: "Version", Val&: StrOffsetsTable.Version, Default: 5);
302 IO.mapOptional(Key: "Padding", Val&: StrOffsetsTable.Padding, Default: 0);
303 IO.mapOptional(Key: "Offsets", Val&: StrOffsetsTable.Offsets);
304}
305
306void MappingTraits<DWARFYAML::DWARFOperation>::mapping(
307 IO &IO, DWARFYAML::DWARFOperation &DWARFOperation) {
308 IO.mapRequired(Key: "Operator", Val&: DWARFOperation.Operator);
309 IO.mapOptional(Key: "Values", Val&: DWARFOperation.Values);
310}
311
312void MappingTraits<DWARFYAML::RnglistEntry>::mapping(
313 IO &IO, DWARFYAML::RnglistEntry &RnglistEntry) {
314 IO.mapRequired(Key: "Operator", Val&: RnglistEntry.Operator);
315 IO.mapOptional(Key: "Values", Val&: RnglistEntry.Values);
316}
317
318void MappingTraits<DWARFYAML::LoclistEntry>::mapping(
319 IO &IO, DWARFYAML::LoclistEntry &LoclistEntry) {
320 IO.mapRequired(Key: "Operator", Val&: LoclistEntry.Operator);
321 IO.mapOptional(Key: "Values", Val&: LoclistEntry.Values);
322 IO.mapOptional(Key: "DescriptionsLength", Val&: LoclistEntry.DescriptionsLength);
323 IO.mapOptional(Key: "Descriptions", Val&: LoclistEntry.Descriptions);
324}
325
326template <typename EntryType>
327void MappingTraits<DWARFYAML::ListEntries<EntryType>>::mapping(
328 IO &IO, DWARFYAML::ListEntries<EntryType> &ListEntries) {
329 IO.mapOptional("Entries", ListEntries.Entries);
330 IO.mapOptional("Content", ListEntries.Content);
331}
332
333template <typename EntryType>
334std::string MappingTraits<DWARFYAML::ListEntries<EntryType>>::validate(
335 IO &IO, DWARFYAML::ListEntries<EntryType> &ListEntries) {
336 if (ListEntries.Entries && ListEntries.Content)
337 return "Entries and Content can't be used together";
338 return "";
339}
340
341template <typename EntryType>
342void MappingTraits<DWARFYAML::ListTable<EntryType>>::mapping(
343 IO &IO, DWARFYAML::ListTable<EntryType> &ListTable) {
344 IO.mapOptional("Format", ListTable.Format, dwarf::DWARF32);
345 IO.mapOptional("Length", ListTable.Length);
346 IO.mapOptional("Version", ListTable.Version, 5);
347 IO.mapOptional("AddressSize", ListTable.AddrSize);
348 IO.mapOptional("SegmentSelectorSize", ListTable.SegSelectorSize, 0);
349 IO.mapOptional("OffsetEntryCount", ListTable.OffsetEntryCount);
350 IO.mapOptional("Offsets", ListTable.Offsets);
351 IO.mapOptional("Lists", ListTable.Lists);
352}
353
354} // end namespace yaml
355
356} // end namespace llvm
357