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