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