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