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