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