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