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