1//===- CodeViewYAMLSymbols.cpp - CodeView YAMLIO Symbol 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 CodeView
10// Debug Info.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
15#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/StringRef.h"
17#include "llvm/DebugInfo/CodeView/CodeView.h"
18#include "llvm/DebugInfo/CodeView/CodeViewError.h"
19#include "llvm/DebugInfo/CodeView/EnumTables.h"
20#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
21#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
22#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
23#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
24#include "llvm/DebugInfo/CodeView/TypeIndex.h"
25#include "llvm/ObjectYAML/YAML.h"
26#include "llvm/Support/Allocator.h"
27#include "llvm/Support/Error.h"
28#include "llvm/Support/ScopedPrinter.h"
29#include "llvm/Support/YAMLTraits.h"
30#include <algorithm>
31#include <cstdint>
32#include <cstring>
33#include <optional>
34#include <string>
35#include <vector>
36
37using namespace llvm;
38using namespace llvm::codeview;
39using namespace llvm::CodeViewYAML;
40using namespace llvm::CodeViewYAML::detail;
41using namespace llvm::yaml;
42
43LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)
44LLVM_YAML_IS_SEQUENCE_VECTOR(LocalVariableAddrGap)
45
46// We only need to declare these, the definitions are in CodeViewYAMLTypes.cpp
47LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, QuotingType::None)
48LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, QuotingType::None)
49
50LLVM_YAML_DECLARE_ENUM_TRAITS(SymbolKind)
51LLVM_YAML_DECLARE_ENUM_TRAITS(FrameCookieKind)
52
53LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym2Flags)
54LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym3Flags)
55LLVM_YAML_DECLARE_BITSET_TRAITS(ExportFlags)
56LLVM_YAML_DECLARE_BITSET_TRAITS(PublicSymFlags)
57LLVM_YAML_DECLARE_BITSET_TRAITS(LocalSymFlags)
58LLVM_YAML_DECLARE_BITSET_TRAITS(ProcSymFlags)
59LLVM_YAML_DECLARE_BITSET_TRAITS(FrameProcedureOptions)
60LLVM_YAML_DECLARE_ENUM_TRAITS(CPUType)
61LLVM_YAML_DECLARE_ENUM_TRAITS(RegisterId)
62LLVM_YAML_DECLARE_ENUM_TRAITS(TrampolineType)
63LLVM_YAML_DECLARE_ENUM_TRAITS(ThunkOrdinal)
64LLVM_YAML_DECLARE_ENUM_TRAITS(JumpTableEntrySize)
65
66LLVM_YAML_STRONG_TYPEDEF(StringRef, TypeName)
67
68LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeName, QuotingType::Single)
69
70StringRef ScalarTraits<TypeName>::input(StringRef S, void *V, TypeName &T) {
71 return ScalarTraits<StringRef>::input(S, V, T.value);
72}
73
74void ScalarTraits<TypeName>::output(const TypeName &T, void *V,
75 raw_ostream &R) {
76 ScalarTraits<StringRef>::output(T.value, V, R);
77}
78
79void ScalarEnumerationTraits<SymbolKind>::enumeration(IO &io,
80 SymbolKind &Value) {
81 auto SymbolNames = getSymbolTypeNames();
82 for (const auto &E : SymbolNames)
83 io.enumCase(Val&: Value, Str: E.Name, ConstVal: E.Value);
84}
85
86void ScalarBitSetTraits<CompileSym2Flags>::bitset(IO &io,
87 CompileSym2Flags &Flags) {
88 auto FlagNames = getCompileSym2FlagNames();
89 for (const auto &E : FlagNames) {
90 io.bitSetCase(Val&: Flags, Str: E.Name, ConstVal: static_cast<CompileSym2Flags>(E.Value));
91 }
92}
93
94void ScalarBitSetTraits<CompileSym3Flags>::bitset(IO &io,
95 CompileSym3Flags &Flags) {
96 auto FlagNames = getCompileSym3FlagNames();
97 for (const auto &E : FlagNames) {
98 io.bitSetCase(Val&: Flags, Str: E.Name, ConstVal: static_cast<CompileSym3Flags>(E.Value));
99 }
100}
101
102void ScalarBitSetTraits<ExportFlags>::bitset(IO &io, ExportFlags &Flags) {
103 auto FlagNames = getExportSymFlagNames();
104 for (const auto &E : FlagNames) {
105 io.bitSetCase(Val&: Flags, Str: E.Name, ConstVal: static_cast<ExportFlags>(E.Value));
106 }
107}
108
109void ScalarBitSetTraits<PublicSymFlags>::bitset(IO &io, PublicSymFlags &Flags) {
110 auto FlagNames = getPublicSymFlagNames();
111 for (const auto &E : FlagNames) {
112 io.bitSetCase(Val&: Flags, Str: E.Name, ConstVal: static_cast<PublicSymFlags>(E.Value));
113 }
114}
115
116void ScalarBitSetTraits<LocalSymFlags>::bitset(IO &io, LocalSymFlags &Flags) {
117 auto FlagNames = getLocalFlagNames();
118 for (const auto &E : FlagNames) {
119 io.bitSetCase(Val&: Flags, Str: E.Name, ConstVal: static_cast<LocalSymFlags>(E.Value));
120 }
121}
122
123void ScalarBitSetTraits<ProcSymFlags>::bitset(IO &io, ProcSymFlags &Flags) {
124 auto FlagNames = getProcSymFlagNames();
125 for (const auto &E : FlagNames) {
126 io.bitSetCase(Val&: Flags, Str: E.Name, ConstVal: static_cast<ProcSymFlags>(E.Value));
127 }
128}
129
130void ScalarBitSetTraits<FrameProcedureOptions>::bitset(
131 IO &io, FrameProcedureOptions &Flags) {
132 auto FlagNames = getFrameProcSymFlagNames();
133 for (const auto &E : FlagNames) {
134 io.bitSetCase(Val&: Flags, Str: E.Name, ConstVal: static_cast<FrameProcedureOptions>(E.Value));
135 }
136}
137
138void ScalarEnumerationTraits<CPUType>::enumeration(IO &io, CPUType &Cpu) {
139 auto CpuNames = getCPUTypeNames();
140 for (const auto &E : CpuNames) {
141 io.enumCase(Val&: Cpu, Str: E.Name, ConstVal: static_cast<CPUType>(E.Value));
142 }
143}
144
145void ScalarEnumerationTraits<RegisterId>::enumeration(IO &io, RegisterId &Reg) {
146 const auto *Header = static_cast<COFF::header *>(io.getContext());
147 assert(Header && "The IO context is not initialized");
148
149 std::optional<CPUType> CpuType;
150 ArrayRef<EnumEntry<uint16_t>> RegNames;
151
152 switch (Header->Machine) {
153 case COFF::IMAGE_FILE_MACHINE_I386:
154 CpuType = CPUType::Pentium3;
155 break;
156 case COFF::IMAGE_FILE_MACHINE_AMD64:
157 CpuType = CPUType::X64;
158 break;
159 case COFF::IMAGE_FILE_MACHINE_ARMNT:
160 CpuType = CPUType::ARMNT;
161 break;
162 case COFF::IMAGE_FILE_MACHINE_ARM64:
163 case COFF::IMAGE_FILE_MACHINE_ARM64EC:
164 case COFF::IMAGE_FILE_MACHINE_ARM64X:
165 CpuType = CPUType::ARM64;
166 break;
167 }
168
169 if (CpuType)
170 RegNames = getRegisterNames(Cpu: *CpuType);
171
172 for (const auto &E : RegNames) {
173 io.enumCase(Val&: Reg, Str: E.Name, ConstVal: static_cast<RegisterId>(E.Value));
174 }
175 io.enumFallback<Hex16>(Val&: Reg);
176}
177
178void ScalarEnumerationTraits<TrampolineType>::enumeration(
179 IO &io, TrampolineType &Tramp) {
180 auto TrampNames = getTrampolineNames();
181 for (const auto &E : TrampNames) {
182 io.enumCase(Val&: Tramp, Str: E.Name, ConstVal: static_cast<TrampolineType>(E.Value));
183 }
184}
185
186void ScalarEnumerationTraits<ThunkOrdinal>::enumeration(IO &io,
187 ThunkOrdinal &Ord) {
188 auto ThunkNames = getThunkOrdinalNames();
189 for (const auto &E : ThunkNames) {
190 io.enumCase(Val&: Ord, Str: E.Name, ConstVal: static_cast<ThunkOrdinal>(E.Value));
191 }
192}
193
194void ScalarEnumerationTraits<FrameCookieKind>::enumeration(
195 IO &io, FrameCookieKind &FC) {
196 auto ThunkNames = getFrameCookieKindNames();
197 for (const auto &E : ThunkNames) {
198 io.enumCase(Val&: FC, Str: E.Name, ConstVal: static_cast<FrameCookieKind>(E.Value));
199 }
200}
201
202void ScalarEnumerationTraits<JumpTableEntrySize>::enumeration(
203 IO &io, JumpTableEntrySize &FC) {
204 auto ThunkNames = getJumpTableEntrySizeNames();
205 for (const auto &E : ThunkNames) {
206 io.enumCase(Val&: FC, Str: E.Name, ConstVal: static_cast<JumpTableEntrySize>(E.Value));
207 }
208}
209
210namespace llvm {
211namespace yaml {
212template <> struct MappingTraits<LocalVariableAddrRange> {
213 static void mapping(IO &io, LocalVariableAddrRange &Range) {
214 io.mapRequired(Key: "OffsetStart", Val&: Range.OffsetStart);
215 io.mapRequired(Key: "ISectStart", Val&: Range.ISectStart);
216 io.mapRequired(Key: "Range", Val&: Range.Range);
217 }
218};
219template <> struct MappingTraits<LocalVariableAddrGap> {
220 static void mapping(IO &io, LocalVariableAddrGap &Gap) {
221 io.mapRequired(Key: "GapStartOffset", Val&: Gap.GapStartOffset);
222 io.mapRequired(Key: "Range", Val&: Gap.Range);
223 }
224};
225} // namespace yaml
226} // namespace llvm
227
228namespace llvm {
229namespace CodeViewYAML {
230namespace detail {
231
232struct SymbolRecordBase {
233 codeview::SymbolKind Kind;
234
235 explicit SymbolRecordBase(codeview::SymbolKind K) : Kind(K) {}
236 virtual ~SymbolRecordBase() = default;
237
238 virtual void map(yaml::IO &io) = 0;
239 virtual codeview::CVSymbol
240 toCodeViewSymbol(BumpPtrAllocator &Allocator,
241 CodeViewContainer Container) const = 0;
242 virtual Error fromCodeViewSymbol(codeview::CVSymbol Type) = 0;
243};
244
245template <typename T> struct SymbolRecordImpl : public SymbolRecordBase {
246 explicit SymbolRecordImpl(codeview::SymbolKind K)
247 : SymbolRecordBase(K), Symbol(static_cast<SymbolRecordKind>(K)) {}
248
249 void map(yaml::IO &io) override;
250
251 codeview::CVSymbol
252 toCodeViewSymbol(BumpPtrAllocator &Allocator,
253 CodeViewContainer Container) const override {
254 return SymbolSerializer::writeOneSymbol(Symbol, Allocator, Container);
255 }
256
257 Error fromCodeViewSymbol(codeview::CVSymbol CVS) override {
258 return SymbolDeserializer::deserializeAs<T>(CVS, Symbol);
259 }
260
261 mutable T Symbol;
262};
263
264struct UnknownSymbolRecord : public SymbolRecordBase {
265 explicit UnknownSymbolRecord(codeview::SymbolKind K) : SymbolRecordBase(K) {}
266
267 void map(yaml::IO &io) override;
268
269 CVSymbol toCodeViewSymbol(BumpPtrAllocator &Allocator,
270 CodeViewContainer Container) const override {
271 RecordPrefix Prefix;
272 uint32_t TotalLen = sizeof(RecordPrefix) + Data.size();
273 Prefix.RecordKind = Kind;
274 Prefix.RecordLen = TotalLen - 2;
275 uint8_t *Buffer = Allocator.Allocate<uint8_t>(Num: TotalLen);
276 ::memcpy(dest: Buffer, src: &Prefix, n: sizeof(RecordPrefix));
277 ::memcpy(dest: Buffer + sizeof(RecordPrefix), src: Data.data(), n: Data.size());
278 return CVSymbol(ArrayRef<uint8_t>(Buffer, TotalLen));
279 }
280
281 Error fromCodeViewSymbol(CVSymbol CVS) override {
282 this->Kind = CVS.kind();
283 Data = CVS.RecordData.drop_front(N: sizeof(RecordPrefix));
284 return Error::success();
285 }
286
287 std::vector<uint8_t> Data;
288};
289
290template <> void SymbolRecordImpl<ScopeEndSym>::map(IO &IO) {}
291
292void UnknownSymbolRecord::map(yaml::IO &io) {
293 yaml::BinaryRef Binary;
294 if (io.outputting())
295 Binary = yaml::BinaryRef(Data);
296 io.mapRequired(Key: "Data", Val&: Binary);
297 if (!io.outputting()) {
298 std::string Str;
299 raw_string_ostream OS(Str);
300 Binary.writeAsBinary(OS);
301 Data.assign(first: Str.begin(), last: Str.end());
302 }
303}
304
305template <> void SymbolRecordImpl<Thunk32Sym>::map(IO &IO) {
306 IO.mapRequired(Key: "Parent", Val&: Symbol.Parent);
307 IO.mapRequired(Key: "End", Val&: Symbol.End);
308 IO.mapRequired(Key: "Next", Val&: Symbol.Next);
309 IO.mapRequired(Key: "Off", Val&: Symbol.Offset);
310 IO.mapRequired(Key: "Seg", Val&: Symbol.Segment);
311 IO.mapRequired(Key: "Len", Val&: Symbol.Length);
312 IO.mapRequired(Key: "Ordinal", Val&: Symbol.Thunk);
313}
314
315template <> void SymbolRecordImpl<TrampolineSym>::map(IO &IO) {
316 IO.mapRequired(Key: "Type", Val&: Symbol.Type);
317 IO.mapRequired(Key: "Size", Val&: Symbol.Size);
318 IO.mapRequired(Key: "ThunkOff", Val&: Symbol.ThunkOffset);
319 IO.mapRequired(Key: "TargetOff", Val&: Symbol.TargetOffset);
320 IO.mapRequired(Key: "ThunkSection", Val&: Symbol.ThunkSection);
321 IO.mapRequired(Key: "TargetSection", Val&: Symbol.TargetSection);
322}
323
324template <> void SymbolRecordImpl<SectionSym>::map(IO &IO) {
325 IO.mapRequired(Key: "SectionNumber", Val&: Symbol.SectionNumber);
326 IO.mapRequired(Key: "Alignment", Val&: Symbol.Alignment);
327 IO.mapRequired(Key: "Rva", Val&: Symbol.Rva);
328 IO.mapRequired(Key: "Length", Val&: Symbol.Length);
329 IO.mapRequired(Key: "Characteristics", Val&: Symbol.Characteristics);
330 IO.mapRequired(Key: "Name", Val&: Symbol.Name);
331}
332
333template <> void SymbolRecordImpl<CoffGroupSym>::map(IO &IO) {
334 IO.mapRequired(Key: "Size", Val&: Symbol.Size);
335 IO.mapRequired(Key: "Characteristics", Val&: Symbol.Characteristics);
336 IO.mapRequired(Key: "Offset", Val&: Symbol.Offset);
337 IO.mapRequired(Key: "Segment", Val&: Symbol.Segment);
338 IO.mapRequired(Key: "Name", Val&: Symbol.Name);
339}
340
341template <> void SymbolRecordImpl<ExportSym>::map(IO &IO) {
342 IO.mapRequired(Key: "Ordinal", Val&: Symbol.Ordinal);
343 IO.mapRequired(Key: "Flags", Val&: Symbol.Flags);
344 IO.mapRequired(Key: "Name", Val&: Symbol.Name);
345}
346
347template <> void SymbolRecordImpl<ProcSym>::map(IO &IO) {
348 IO.mapOptional(Key: "PtrParent", Val&: Symbol.Parent, Default: 0U);
349 IO.mapOptional(Key: "PtrEnd", Val&: Symbol.End, Default: 0U);
350 IO.mapOptional(Key: "PtrNext", Val&: Symbol.Next, Default: 0U);
351 IO.mapRequired(Key: "CodeSize", Val&: Symbol.CodeSize);
352 IO.mapRequired(Key: "DbgStart", Val&: Symbol.DbgStart);
353 IO.mapRequired(Key: "DbgEnd", Val&: Symbol.DbgEnd);
354 IO.mapRequired(Key: "FunctionType", Val&: Symbol.FunctionType);
355 IO.mapOptional(Key: "Offset", Val&: Symbol.CodeOffset, Default: 0U);
356 IO.mapOptional(Key: "Segment", Val&: Symbol.Segment, Default: uint16_t(0));
357 IO.mapRequired(Key: "Flags", Val&: Symbol.Flags);
358 IO.mapRequired(Key: "DisplayName", Val&: Symbol.Name);
359}
360
361template <> void SymbolRecordImpl<RegisterSym>::map(IO &IO) {
362 IO.mapRequired(Key: "Type", Val&: Symbol.Index);
363 IO.mapRequired(Key: "Seg", Val&: Symbol.Register);
364 IO.mapRequired(Key: "Name", Val&: Symbol.Name);
365}
366
367template <> void SymbolRecordImpl<PublicSym32>::map(IO &IO) {
368 IO.mapRequired(Key: "Flags", Val&: Symbol.Flags);
369 IO.mapOptional(Key: "Offset", Val&: Symbol.Offset, Default: 0U);
370 IO.mapOptional(Key: "Segment", Val&: Symbol.Segment, Default: uint16_t(0));
371 IO.mapRequired(Key: "Name", Val&: Symbol.Name);
372}
373
374template <> void SymbolRecordImpl<ProcRefSym>::map(IO &IO) {
375 IO.mapRequired(Key: "SumName", Val&: Symbol.SumName);
376 IO.mapRequired(Key: "SymOffset", Val&: Symbol.SymOffset);
377 IO.mapRequired(Key: "Mod", Val&: Symbol.Module);
378 IO.mapRequired(Key: "Name", Val&: Symbol.Name);
379}
380
381template <> void SymbolRecordImpl<EnvBlockSym>::map(IO &IO) {
382 IO.mapRequired(Key: "Entries", Val&: Symbol.Fields);
383}
384
385template <> void SymbolRecordImpl<InlineSiteSym>::map(IO &IO) {
386 IO.mapOptional(Key: "PtrParent", Val&: Symbol.Parent, Default: 0U);
387 IO.mapOptional(Key: "PtrEnd", Val&: Symbol.End, Default: 0U);
388 IO.mapRequired(Key: "Inlinee", Val&: Symbol.Inlinee);
389 IO.mapOptional(Key: "AnnotationData", Val&: Symbol.AnnotationData);
390}
391
392template <> void SymbolRecordImpl<LocalSym>::map(IO &IO) {
393 IO.mapRequired(Key: "Type", Val&: Symbol.Type);
394 IO.mapRequired(Key: "Flags", Val&: Symbol.Flags);
395
396 IO.mapRequired(Key: "VarName", Val&: Symbol.Name);
397}
398
399template <> void SymbolRecordImpl<DefRangeSym>::map(IO &IO) {
400 IO.mapRequired(Key: "Program", Val&: Symbol.Program);
401 IO.mapRequired(Key: "Range", Val&: Symbol.Range);
402 IO.mapRequired(Key: "Gaps", Val&: Symbol.Gaps);
403}
404
405template <> void SymbolRecordImpl<DefRangeSubfieldSym>::map(IO &IO) {
406 IO.mapRequired(Key: "Program", Val&: Symbol.Program);
407 IO.mapRequired(Key: "OffsetInParent", Val&: Symbol.OffsetInParent);
408 IO.mapRequired(Key: "Range", Val&: Symbol.Range);
409 IO.mapRequired(Key: "Gaps", Val&: Symbol.Gaps);
410}
411
412template <> void SymbolRecordImpl<DefRangeRegisterSym>::map(IO &IO) {
413 IO.mapRequired(Key: "Register", Val&: Symbol.Hdr.Register);
414 IO.mapRequired(Key: "MayHaveNoName", Val&: Symbol.Hdr.MayHaveNoName);
415 IO.mapRequired(Key: "Range", Val&: Symbol.Range);
416 IO.mapRequired(Key: "Gaps", Val&: Symbol.Gaps);
417}
418
419template <> void SymbolRecordImpl<DefRangeFramePointerRelSym>::map(IO &IO) {
420 IO.mapRequired(Key: "Offset", Val&: Symbol.Hdr.Offset);
421 IO.mapRequired(Key: "Range", Val&: Symbol.Range);
422 IO.mapRequired(Key: "Gaps", Val&: Symbol.Gaps);
423}
424
425template <> void SymbolRecordImpl<DefRangeSubfieldRegisterSym>::map(IO &IO) {
426 IO.mapRequired(Key: "Register", Val&: Symbol.Hdr.Register);
427 IO.mapRequired(Key: "MayHaveNoName", Val&: Symbol.Hdr.MayHaveNoName);
428 IO.mapRequired(Key: "OffsetInParent", Val&: Symbol.Hdr.OffsetInParent);
429 IO.mapRequired(Key: "Range", Val&: Symbol.Range);
430 IO.mapRequired(Key: "Gaps", Val&: Symbol.Gaps);
431}
432
433template <>
434void SymbolRecordImpl<DefRangeFramePointerRelFullScopeSym>::map(IO &IO) {
435 IO.mapRequired(Key: "Register", Val&: Symbol.Offset);
436}
437
438template <> void SymbolRecordImpl<DefRangeRegisterRelSym>::map(IO &IO) {
439 IO.mapRequired(Key: "Register", Val&: Symbol.Hdr.Register);
440 IO.mapRequired(Key: "Flags", Val&: Symbol.Hdr.Flags);
441 IO.mapRequired(Key: "BasePointerOffset", Val&: Symbol.Hdr.BasePointerOffset);
442 IO.mapRequired(Key: "Range", Val&: Symbol.Range);
443 IO.mapRequired(Key: "Gaps", Val&: Symbol.Gaps);
444}
445
446template <> void SymbolRecordImpl<BlockSym>::map(IO &IO) {
447 IO.mapOptional(Key: "PtrParent", Val&: Symbol.Parent, Default: 0U);
448 IO.mapOptional(Key: "PtrEnd", Val&: Symbol.End, Default: 0U);
449 IO.mapRequired(Key: "CodeSize", Val&: Symbol.CodeSize);
450 IO.mapOptional(Key: "Offset", Val&: Symbol.CodeOffset, Default: 0U);
451 IO.mapOptional(Key: "Segment", Val&: Symbol.Segment, Default: uint16_t(0));
452 IO.mapRequired(Key: "BlockName", Val&: Symbol.Name);
453}
454
455template <> void SymbolRecordImpl<LabelSym>::map(IO &IO) {
456 IO.mapOptional(Key: "Offset", Val&: Symbol.CodeOffset, Default: 0U);
457 IO.mapOptional(Key: "Segment", Val&: Symbol.Segment, Default: uint16_t(0));
458 IO.mapRequired(Key: "Flags", Val&: Symbol.Flags);
459 IO.mapRequired(Key: "DisplayName", Val&: Symbol.Name);
460}
461
462template <> void SymbolRecordImpl<ObjNameSym>::map(IO &IO) {
463 IO.mapRequired(Key: "Signature", Val&: Symbol.Signature);
464 IO.mapRequired(Key: "ObjectName", Val&: Symbol.Name);
465}
466
467template <> void SymbolRecordImpl<Compile2Sym>::map(IO &IO) {
468 IO.mapRequired(Key: "Flags", Val&: Symbol.Flags);
469 IO.mapRequired(Key: "Machine", Val&: Symbol.Machine);
470 IO.mapRequired(Key: "FrontendMajor", Val&: Symbol.VersionFrontendMajor);
471 IO.mapRequired(Key: "FrontendMinor", Val&: Symbol.VersionFrontendMinor);
472 IO.mapRequired(Key: "FrontendBuild", Val&: Symbol.VersionFrontendBuild);
473 IO.mapRequired(Key: "BackendMajor", Val&: Symbol.VersionBackendMajor);
474 IO.mapRequired(Key: "BackendMinor", Val&: Symbol.VersionBackendMinor);
475 IO.mapRequired(Key: "BackendBuild", Val&: Symbol.VersionBackendBuild);
476 IO.mapRequired(Key: "Version", Val&: Symbol.Version);
477}
478
479template <> void SymbolRecordImpl<Compile3Sym>::map(IO &IO) {
480 IO.mapRequired(Key: "Flags", Val&: Symbol.Flags);
481 IO.mapRequired(Key: "Machine", Val&: Symbol.Machine);
482 IO.mapRequired(Key: "FrontendMajor", Val&: Symbol.VersionFrontendMajor);
483 IO.mapRequired(Key: "FrontendMinor", Val&: Symbol.VersionFrontendMinor);
484 IO.mapRequired(Key: "FrontendBuild", Val&: Symbol.VersionFrontendBuild);
485 IO.mapRequired(Key: "FrontendQFE", Val&: Symbol.VersionFrontendQFE);
486 IO.mapRequired(Key: "BackendMajor", Val&: Symbol.VersionBackendMajor);
487 IO.mapRequired(Key: "BackendMinor", Val&: Symbol.VersionBackendMinor);
488 IO.mapRequired(Key: "BackendBuild", Val&: Symbol.VersionBackendBuild);
489 IO.mapRequired(Key: "BackendQFE", Val&: Symbol.VersionBackendQFE);
490 IO.mapRequired(Key: "Version", Val&: Symbol.Version);
491}
492
493template <> void SymbolRecordImpl<FrameProcSym>::map(IO &IO) {
494 IO.mapRequired(Key: "TotalFrameBytes", Val&: Symbol.TotalFrameBytes);
495 IO.mapRequired(Key: "PaddingFrameBytes", Val&: Symbol.PaddingFrameBytes);
496 IO.mapRequired(Key: "OffsetToPadding", Val&: Symbol.OffsetToPadding);
497 IO.mapRequired(Key: "BytesOfCalleeSavedRegisters",
498 Val&: Symbol.BytesOfCalleeSavedRegisters);
499 IO.mapRequired(Key: "OffsetOfExceptionHandler", Val&: Symbol.OffsetOfExceptionHandler);
500 IO.mapRequired(Key: "SectionIdOfExceptionHandler",
501 Val&: Symbol.SectionIdOfExceptionHandler);
502 IO.mapRequired(Key: "Flags", Val&: Symbol.Flags);
503}
504
505template <> void SymbolRecordImpl<CallSiteInfoSym>::map(IO &IO) {
506 IO.mapOptional(Key: "Offset", Val&: Symbol.CodeOffset, Default: 0U);
507 IO.mapOptional(Key: "Segment", Val&: Symbol.Segment, Default: uint16_t(0));
508 IO.mapRequired(Key: "Type", Val&: Symbol.Type);
509}
510
511template <> void SymbolRecordImpl<FileStaticSym>::map(IO &IO) {
512 IO.mapRequired(Key: "Index", Val&: Symbol.Index);
513 IO.mapRequired(Key: "ModFilenameOffset", Val&: Symbol.ModFilenameOffset);
514 IO.mapRequired(Key: "Flags", Val&: Symbol.Flags);
515 IO.mapRequired(Key: "Name", Val&: Symbol.Name);
516}
517
518template <> void SymbolRecordImpl<HeapAllocationSiteSym>::map(IO &IO) {
519 IO.mapOptional(Key: "Offset", Val&: Symbol.CodeOffset, Default: 0U);
520 IO.mapOptional(Key: "Segment", Val&: Symbol.Segment, Default: uint16_t(0));
521 IO.mapRequired(Key: "CallInstructionSize", Val&: Symbol.CallInstructionSize);
522 IO.mapRequired(Key: "Type", Val&: Symbol.Type);
523}
524
525template <> void SymbolRecordImpl<FrameCookieSym>::map(IO &IO) {
526 IO.mapRequired(Key: "Register", Val&: Symbol.Register);
527 IO.mapRequired(Key: "CookieKind", Val&: Symbol.CookieKind);
528 IO.mapRequired(Key: "Flags", Val&: Symbol.Flags);
529}
530
531template <> void SymbolRecordImpl<CallerSym>::map(IO &IO) {
532 IO.mapRequired(Key: "FuncID", Val&: Symbol.Indices);
533}
534
535template <> void SymbolRecordImpl<UDTSym>::map(IO &IO) {
536 IO.mapRequired(Key: "Type", Val&: Symbol.Type);
537 IO.mapRequired(Key: "UDTName", Val&: Symbol.Name);
538}
539
540template <> void SymbolRecordImpl<BuildInfoSym>::map(IO &IO) {
541 IO.mapRequired(Key: "BuildId", Val&: Symbol.BuildId);
542}
543
544template <> void SymbolRecordImpl<BPRelativeSym>::map(IO &IO) {
545 IO.mapRequired(Key: "Offset", Val&: Symbol.Offset);
546 IO.mapRequired(Key: "Type", Val&: Symbol.Type);
547 IO.mapRequired(Key: "VarName", Val&: Symbol.Name);
548}
549
550template <> void SymbolRecordImpl<RegRelativeSym>::map(IO &IO) {
551 IO.mapRequired(Key: "Offset", Val&: Symbol.Offset);
552 IO.mapRequired(Key: "Type", Val&: Symbol.Type);
553 IO.mapRequired(Key: "Register", Val&: Symbol.Register);
554 IO.mapRequired(Key: "VarName", Val&: Symbol.Name);
555}
556
557template <> void SymbolRecordImpl<ConstantSym>::map(IO &IO) {
558 IO.mapRequired(Key: "Type", Val&: Symbol.Type);
559 IO.mapRequired(Key: "Value", Val&: Symbol.Value);
560 IO.mapRequired(Key: "Name", Val&: Symbol.Name);
561}
562
563template <> void SymbolRecordImpl<DataSym>::map(IO &IO) {
564 IO.mapRequired(Key: "Type", Val&: Symbol.Type);
565 IO.mapOptional(Key: "Offset", Val&: Symbol.DataOffset, Default: 0U);
566 IO.mapOptional(Key: "Segment", Val&: Symbol.Segment, Default: uint16_t(0));
567 IO.mapRequired(Key: "DisplayName", Val&: Symbol.Name);
568}
569
570template <> void SymbolRecordImpl<ThreadLocalDataSym>::map(IO &IO) {
571 IO.mapRequired(Key: "Type", Val&: Symbol.Type);
572 IO.mapOptional(Key: "Offset", Val&: Symbol.DataOffset, Default: 0U);
573 IO.mapOptional(Key: "Segment", Val&: Symbol.Segment, Default: uint16_t(0));
574 IO.mapRequired(Key: "DisplayName", Val&: Symbol.Name);
575}
576
577template <> void SymbolRecordImpl<UsingNamespaceSym>::map(IO &IO) {
578 IO.mapRequired(Key: "Namespace", Val&: Symbol.Name);
579}
580
581template <> void SymbolRecordImpl<AnnotationSym>::map(IO &IO) {
582 IO.mapOptional(Key: "Offset", Val&: Symbol.CodeOffset, Default: 0U);
583 IO.mapOptional(Key: "Segment", Val&: Symbol.Segment, Default: uint16_t(0));
584 IO.mapRequired(Key: "Strings", Val&: Symbol.Strings);
585}
586
587template <> void SymbolRecordImpl<JumpTableSym>::map(IO &IO) {
588 IO.mapRequired(Key: "BaseOffset", Val&: Symbol.BaseOffset);
589 IO.mapRequired(Key: "BaseSegment", Val&: Symbol.BaseSegment);
590 IO.mapRequired(Key: "SwitchType", Val&: Symbol.SwitchType);
591 IO.mapRequired(Key: "BranchOffset", Val&: Symbol.BranchOffset);
592 IO.mapRequired(Key: "TableOffset", Val&: Symbol.TableOffset);
593 IO.mapRequired(Key: "BranchSegment", Val&: Symbol.BranchSegment);
594 IO.mapRequired(Key: "TableSegment", Val&: Symbol.TableSegment);
595 IO.mapRequired(Key: "EntriesCount", Val&: Symbol.EntriesCount);
596}
597
598template <> void SymbolRecordImpl<HotPatchFuncSym>::map(IO &IO) {
599 IO.mapRequired(Key: "Function", Val&: Symbol.Function);
600 IO.mapRequired(Key: "Name", Val&: Symbol.Name);
601}
602
603} // end namespace detail
604} // end namespace CodeViewYAML
605} // end namespace llvm
606
607CVSymbol CodeViewYAML::SymbolRecord::toCodeViewSymbol(
608 BumpPtrAllocator &Allocator, CodeViewContainer Container) const {
609 return Symbol->toCodeViewSymbol(Allocator, Container);
610}
611
612namespace llvm {
613namespace yaml {
614
615template <> struct MappingTraits<SymbolRecordBase> {
616 static void mapping(IO &io, SymbolRecordBase &Record) { Record.map(io); }
617};
618
619} // end namespace yaml
620} // end namespace llvm
621
622template <typename SymbolType>
623static inline Expected<CodeViewYAML::SymbolRecord>
624fromCodeViewSymbolImpl(CVSymbol Symbol) {
625 CodeViewYAML::SymbolRecord Result;
626
627 auto Impl = std::make_shared<SymbolType>(Symbol.kind());
628 if (auto EC = Impl->fromCodeViewSymbol(Symbol))
629 return std::move(EC);
630 Result.Symbol = std::move(Impl);
631 return Result;
632}
633
634Expected<CodeViewYAML::SymbolRecord>
635CodeViewYAML::SymbolRecord::fromCodeViewSymbol(CVSymbol Symbol) {
636#define SYMBOL_RECORD(EnumName, EnumVal, ClassName) \
637 case EnumName: \
638 return fromCodeViewSymbolImpl<SymbolRecordImpl<ClassName>>(Symbol);
639#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
640 SYMBOL_RECORD(EnumName, EnumVal, ClassName)
641 switch (Symbol.kind()) {
642#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
643 default:
644 return fromCodeViewSymbolImpl<UnknownSymbolRecord>(Symbol);
645 }
646 return make_error<CodeViewError>(Args: cv_error_code::corrupt_record);
647}
648
649template <typename ConcreteType>
650static void mapSymbolRecordImpl(IO &IO, const char *Class, SymbolKind Kind,
651 CodeViewYAML::SymbolRecord &Obj) {
652 if (!IO.outputting())
653 Obj.Symbol = std::make_shared<ConcreteType>(Kind);
654
655 IO.mapRequired(Key: Class, Val&: *Obj.Symbol);
656}
657
658void MappingTraits<CodeViewYAML::SymbolRecord>::mapping(
659 IO &IO, CodeViewYAML::SymbolRecord &Obj) {
660 SymbolKind Kind;
661 if (IO.outputting())
662 Kind = Obj.Symbol->Kind;
663 IO.mapRequired(Key: "Kind", Val&: Kind);
664
665#define SYMBOL_RECORD(EnumName, EnumVal, ClassName) \
666 case EnumName: \
667 mapSymbolRecordImpl<SymbolRecordImpl<ClassName>>(IO, #ClassName, Kind, \
668 Obj); \
669 break;
670#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
671 SYMBOL_RECORD(EnumName, EnumVal, ClassName)
672 switch (Kind) {
673#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
674 default:
675 mapSymbolRecordImpl<UnknownSymbolRecord>(IO, Class: "UnknownSym", Kind, Obj);
676 }
677}
678