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
35using namespace llvm;
36using namespace llvm::codeview;
37using namespace llvm::CodeViewYAML;
38using namespace llvm::CodeViewYAML::detail;
39using namespace llvm::yaml;
40
41LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)
42LLVM_YAML_IS_SEQUENCE_VECTOR(LocalVariableAddrGap)
43
44// We only need to declare these, the definitions are in CodeViewYAMLTypes.cpp
45LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, QuotingType::None)
46LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, QuotingType::None)
47
48LLVM_YAML_DECLARE_ENUM_TRAITS(SymbolKind)
49LLVM_YAML_DECLARE_ENUM_TRAITS(FrameCookieKind)
50
51LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym2Flags)
52LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym3Flags)
53LLVM_YAML_DECLARE_BITSET_TRAITS(ExportFlags)
54LLVM_YAML_DECLARE_BITSET_TRAITS(PublicSymFlags)
55LLVM_YAML_DECLARE_BITSET_TRAITS(LocalSymFlags)
56LLVM_YAML_DECLARE_BITSET_TRAITS(ProcSymFlags)
57LLVM_YAML_DECLARE_BITSET_TRAITS(FrameProcedureOptions)
58LLVM_YAML_DECLARE_ENUM_TRAITS(CPUType)
59LLVM_YAML_DECLARE_ENUM_TRAITS(RegisterId)
60LLVM_YAML_DECLARE_ENUM_TRAITS(TrampolineType)
61LLVM_YAML_DECLARE_ENUM_TRAITS(ThunkOrdinal)
62
63LLVM_YAML_STRONG_TYPEDEF(StringRef, TypeName)
64
65LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeName, QuotingType::Single)
66
67StringRef ScalarTraits<TypeName>::input(StringRef S, void *V, TypeName &T) {
68  return ScalarTraits<StringRef>::input(S, V, T.value);
69}
70
71void ScalarTraits<TypeName>::output(const TypeName &T, void *V,
72                                    raw_ostream &R) {
73  ScalarTraits<StringRef>::output(T.value, V, R);
74}
75
76void 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
83void 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
92void 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
101void 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
109void 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
117void 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
125void 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
133void 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
142void 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
149void 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
180void 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
189void 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
197void 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
206namespace llvm {
207namespace yaml {
208template <> 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};
215template <> 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
224namespace llvm {
225namespace CodeViewYAML {
226namespace detail {
227
228struct 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
241template <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
260struct 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
286template <> void SymbolRecordImpl<ScopeEndSym>::map(IO &IO) {}
287
288void 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
302template <> 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
312template <> 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
321template <> 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
330template <> 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
338template <> 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
344template <> 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
358template <> 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
364template <> 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
371template <> 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
378template <> void SymbolRecordImpl<EnvBlockSym>::map(IO &IO) {
379  IO.mapRequired("Entries", Symbol.Fields);
380}
381
382template <> 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
389template <> 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
396template <> 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
402template <> 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
409template <> 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
416template <> 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
422template <> 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
430template <>
431void SymbolRecordImpl<DefRangeFramePointerRelFullScopeSym>::map(IO &IO) {
432  IO.mapRequired("Register", Symbol.Offset);
433}
434
435template <> 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
443template <> 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
452template <> 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
460template <> void SymbolRecordImpl<ObjNameSym>::map(IO &IO) {
461  IO.mapRequired("Signature", Symbol.Signature);
462  IO.mapRequired("ObjectName", Symbol.Name);
463}
464
465template <> 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
477template <> 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
491template <> 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
503template <> 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
509template <> 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
516template <> 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
523template <> 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
529template <> void SymbolRecordImpl<CallerSym>::map(IO &IO) {
530  IO.mapRequired("FuncID", Symbol.Indices);
531}
532
533template <> void SymbolRecordImpl<UDTSym>::map(IO &IO) {
534  IO.mapRequired("Type", Symbol.Type);
535  IO.mapRequired("UDTName", Symbol.Name);
536}
537
538template <> void SymbolRecordImpl<BuildInfoSym>::map(IO &IO) {
539  IO.mapRequired("BuildId", Symbol.BuildId);
540}
541
542template <> 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
548template <> 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
555template <> 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
561template <> 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
568template <> 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
575template <> void SymbolRecordImpl<UsingNamespaceSym>::map(IO &IO) {
576  IO.mapRequired("Namespace", Symbol.Name);
577}
578
579template <> 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
589CVSymbol CodeViewYAML::SymbolRecord::toCodeViewSymbol(
590    BumpPtrAllocator &Allocator, CodeViewContainer Container) const {
591  return Symbol->toCodeViewSymbol(Allocator, Container);
592}
593
594namespace llvm {
595namespace yaml {
596
597template <> 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
604template <typename SymbolType>
605static inline Expected<CodeViewYAML::SymbolRecord>
606fromCodeViewSymbolImpl(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
616Expected<CodeViewYAML::SymbolRecord>
617CodeViewYAML::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
631template <typename ConcreteType>
632static 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
640void 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