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