1//===- CodeViewYAMLTypes.cpp - CodeView YAMLIO types 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/CodeViewYAMLTypes.h"
15#include "llvm/ADT/APSInt.h"
16#include "llvm/ADT/ArrayRef.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/BinaryFormat/COFF.h"
19#include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"
20#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
21#include "llvm/DebugInfo/CodeView/CodeView.h"
22#include "llvm/DebugInfo/CodeView/CodeViewError.h"
23#include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"
24#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
25#include "llvm/DebugInfo/CodeView/TypeIndex.h"
26#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
27#include "llvm/Support/Allocator.h"
28#include "llvm/Support/BinaryStreamReader.h"
29#include "llvm/Support/BinaryStreamWriter.h"
30#include "llvm/Support/Endian.h"
31#include "llvm/Support/Error.h"
32#include "llvm/Support/ErrorHandling.h"
33#include "llvm/Support/YAMLTraits.h"
34#include "llvm/Support/raw_ostream.h"
35#include <algorithm>
36#include <cassert>
37#include <cstdint>
38#include <vector>
39
40using namespace llvm;
41using namespace llvm::codeview;
42using namespace llvm::CodeViewYAML;
43using namespace llvm::CodeViewYAML::detail;
44using namespace llvm::yaml;
45
46LLVM_YAML_IS_SEQUENCE_VECTOR(OneMethodRecord)
47LLVM_YAML_IS_SEQUENCE_VECTOR(VFTableSlotKind)
48LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)
49
50LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, QuotingType::None)
51LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, QuotingType::None)
52
53LLVM_YAML_DECLARE_ENUM_TRAITS(TypeLeafKind)
54LLVM_YAML_DECLARE_ENUM_TRAITS(PointerToMemberRepresentation)
55LLVM_YAML_DECLARE_ENUM_TRAITS(VFTableSlotKind)
56LLVM_YAML_DECLARE_ENUM_TRAITS(CallingConvention)
57LLVM_YAML_DECLARE_ENUM_TRAITS(PointerKind)
58LLVM_YAML_DECLARE_ENUM_TRAITS(PointerMode)
59LLVM_YAML_DECLARE_ENUM_TRAITS(HfaKind)
60LLVM_YAML_DECLARE_ENUM_TRAITS(MemberAccess)
61LLVM_YAML_DECLARE_ENUM_TRAITS(MethodKind)
62LLVM_YAML_DECLARE_ENUM_TRAITS(WindowsRTClassKind)
63LLVM_YAML_DECLARE_ENUM_TRAITS(LabelType)
64
65LLVM_YAML_DECLARE_BITSET_TRAITS(PointerOptions)
66LLVM_YAML_DECLARE_BITSET_TRAITS(ModifierOptions)
67LLVM_YAML_DECLARE_BITSET_TRAITS(FunctionOptions)
68LLVM_YAML_DECLARE_BITSET_TRAITS(ClassOptions)
69LLVM_YAML_DECLARE_BITSET_TRAITS(MethodOptions)
70
71LLVM_YAML_DECLARE_MAPPING_TRAITS(OneMethodRecord)
72LLVM_YAML_DECLARE_MAPPING_TRAITS(MemberPointerInfo)
73
74namespace llvm {
75namespace CodeViewYAML {
76namespace detail {
77
78struct LeafRecordBase {
79  TypeLeafKind Kind;
80
81  explicit LeafRecordBase(TypeLeafKind K) : Kind(K) {}
82  virtual ~LeafRecordBase() = default;
83
84  virtual void map(yaml::IO &io) = 0;
85  virtual CVType toCodeViewRecord(AppendingTypeTableBuilder &TS) const = 0;
86  virtual Error fromCodeViewRecord(CVType Type) = 0;
87};
88
89template <typename T> struct LeafRecordImpl : public LeafRecordBase {
90  explicit LeafRecordImpl(TypeLeafKind K)
91      : LeafRecordBase(K), Record(static_cast<TypeRecordKind>(K)) {}
92
93  void map(yaml::IO &io) override;
94
95  Error fromCodeViewRecord(CVType Type) override {
96    return TypeDeserializer::deserializeAs<T>(Type, Record);
97  }
98
99  CVType toCodeViewRecord(AppendingTypeTableBuilder &TS) const override {
100    TS.writeLeafType(Record);
101    return CVType(TS.records().back());
102  }
103
104  mutable T Record;
105};
106
107template <> struct LeafRecordImpl<FieldListRecord> : public LeafRecordBase {
108  explicit LeafRecordImpl(TypeLeafKind K) : LeafRecordBase(K) {}
109
110  void map(yaml::IO &io) override;
111  CVType toCodeViewRecord(AppendingTypeTableBuilder &TS) const override;
112  Error fromCodeViewRecord(CVType Type) override;
113
114  std::vector<MemberRecord> Members;
115};
116
117struct MemberRecordBase {
118  TypeLeafKind Kind;
119
120  explicit MemberRecordBase(TypeLeafKind K) : Kind(K) {}
121  virtual ~MemberRecordBase() = default;
122
123  virtual void map(yaml::IO &io) = 0;
124  virtual void writeTo(ContinuationRecordBuilder &CRB) = 0;
125};
126
127template <typename T> struct MemberRecordImpl : public MemberRecordBase {
128  explicit MemberRecordImpl(TypeLeafKind K)
129      : MemberRecordBase(K), Record(static_cast<TypeRecordKind>(K)) {}
130
131  void map(yaml::IO &io) override;
132
133  void writeTo(ContinuationRecordBuilder &CRB) override {
134    CRB.writeMemberType(Record);
135  }
136
137  mutable T Record;
138};
139
140} // end namespace detail
141} // end namespace CodeViewYAML
142} // end namespace llvm
143
144void ScalarTraits<GUID>::output(const GUID &G, void *, llvm::raw_ostream &OS) {
145  OS << G;
146}
147
148StringRef ScalarTraits<GUID>::input(StringRef Scalar, void *Ctx, GUID &S) {
149  if (Scalar.size() != 38)
150    return "GUID strings are 38 characters long";
151  if (Scalar.front() != '{' || Scalar.back() != '}')
152    return "GUID is not enclosed in {}";
153  Scalar = Scalar.substr(1, Scalar.size() - 2);
154  SmallVector<StringRef, 6> A;
155  Scalar.split(A, '-', 5);
156  if (A.size() != 5 || Scalar[8] != '-' || Scalar[13] != '-' ||
157      Scalar[18] != '-' || Scalar[23] != '-')
158    return "GUID sections are not properly delineated with dashes";
159  struct MSGuid {
160    support::ulittle32_t Data1;
161    support::ulittle16_t Data2;
162    support::ulittle16_t Data3;
163    support::ubig64_t Data4;
164  };
165  MSGuid G = {};
166  uint64_t D41{}, D42{};
167  if (!to_integer(A[0], G.Data1, 16) || !to_integer(A[1], G.Data2, 16) ||
168      !to_integer(A[2], G.Data3, 16) || !to_integer(A[3], D41, 16) ||
169      !to_integer(A[4], D42, 16))
170    return "GUID contains non hex digits";
171  G.Data4 = (D41 << 48) | D42;
172  ::memcpy(&S, &G, sizeof(GUID));
173  return "";
174}
175
176void ScalarTraits<TypeIndex>::output(const TypeIndex &S, void *,
177                                     raw_ostream &OS) {
178  OS << S.getIndex();
179}
180
181StringRef ScalarTraits<TypeIndex>::input(StringRef Scalar, void *Ctx,
182                                         TypeIndex &S) {
183  uint32_t I;
184  StringRef Result = ScalarTraits<uint32_t>::input(Scalar, Ctx, I);
185  S.setIndex(I);
186  return Result;
187}
188
189void ScalarTraits<APSInt>::output(const APSInt &S, void *, raw_ostream &OS) {
190  S.print(OS, S.isSigned());
191}
192
193StringRef ScalarTraits<APSInt>::input(StringRef Scalar, void *Ctx, APSInt &S) {
194  S = APSInt(Scalar);
195  return "";
196}
197
198void ScalarEnumerationTraits<TypeLeafKind>::enumeration(IO &io,
199                                                        TypeLeafKind &Value) {
200#define CV_TYPE(name, val) io.enumCase(Value, #name, name);
201#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
202#undef CV_TYPE
203}
204
205void ScalarEnumerationTraits<PointerToMemberRepresentation>::enumeration(
206    IO &IO, PointerToMemberRepresentation &Value) {
207  IO.enumCase(Value, "Unknown", PointerToMemberRepresentation::Unknown);
208  IO.enumCase(Value, "SingleInheritanceData",
209              PointerToMemberRepresentation::SingleInheritanceData);
210  IO.enumCase(Value, "MultipleInheritanceData",
211              PointerToMemberRepresentation::MultipleInheritanceData);
212  IO.enumCase(Value, "VirtualInheritanceData",
213              PointerToMemberRepresentation::VirtualInheritanceData);
214  IO.enumCase(Value, "GeneralData", PointerToMemberRepresentation::GeneralData);
215  IO.enumCase(Value, "SingleInheritanceFunction",
216              PointerToMemberRepresentation::SingleInheritanceFunction);
217  IO.enumCase(Value, "MultipleInheritanceFunction",
218              PointerToMemberRepresentation::MultipleInheritanceFunction);
219  IO.enumCase(Value, "VirtualInheritanceFunction",
220              PointerToMemberRepresentation::VirtualInheritanceFunction);
221  IO.enumCase(Value, "GeneralFunction",
222              PointerToMemberRepresentation::GeneralFunction);
223}
224
225void ScalarEnumerationTraits<VFTableSlotKind>::enumeration(
226    IO &IO, VFTableSlotKind &Kind) {
227  IO.enumCase(Kind, "Near16", VFTableSlotKind::Near16);
228  IO.enumCase(Kind, "Far16", VFTableSlotKind::Far16);
229  IO.enumCase(Kind, "This", VFTableSlotKind::This);
230  IO.enumCase(Kind, "Outer", VFTableSlotKind::Outer);
231  IO.enumCase(Kind, "Meta", VFTableSlotKind::Meta);
232  IO.enumCase(Kind, "Near", VFTableSlotKind::Near);
233  IO.enumCase(Kind, "Far", VFTableSlotKind::Far);
234}
235
236void ScalarEnumerationTraits<CallingConvention>::enumeration(
237    IO &IO, CallingConvention &Value) {
238  IO.enumCase(Value, "NearC", CallingConvention::NearC);
239  IO.enumCase(Value, "FarC", CallingConvention::FarC);
240  IO.enumCase(Value, "NearPascal", CallingConvention::NearPascal);
241  IO.enumCase(Value, "FarPascal", CallingConvention::FarPascal);
242  IO.enumCase(Value, "NearFast", CallingConvention::NearFast);
243  IO.enumCase(Value, "FarFast", CallingConvention::FarFast);
244  IO.enumCase(Value, "NearStdCall", CallingConvention::NearStdCall);
245  IO.enumCase(Value, "FarStdCall", CallingConvention::FarStdCall);
246  IO.enumCase(Value, "NearSysCall", CallingConvention::NearSysCall);
247  IO.enumCase(Value, "FarSysCall", CallingConvention::FarSysCall);
248  IO.enumCase(Value, "ThisCall", CallingConvention::ThisCall);
249  IO.enumCase(Value, "MipsCall", CallingConvention::MipsCall);
250  IO.enumCase(Value, "Generic", CallingConvention::Generic);
251  IO.enumCase(Value, "AlphaCall", CallingConvention::AlphaCall);
252  IO.enumCase(Value, "PpcCall", CallingConvention::PpcCall);
253  IO.enumCase(Value, "SHCall", CallingConvention::SHCall);
254  IO.enumCase(Value, "ArmCall", CallingConvention::ArmCall);
255  IO.enumCase(Value, "AM33Call", CallingConvention::AM33Call);
256  IO.enumCase(Value, "TriCall", CallingConvention::TriCall);
257  IO.enumCase(Value, "SH5Call", CallingConvention::SH5Call);
258  IO.enumCase(Value, "M32RCall", CallingConvention::M32RCall);
259  IO.enumCase(Value, "ClrCall", CallingConvention::ClrCall);
260  IO.enumCase(Value, "Inline", CallingConvention::Inline);
261  IO.enumCase(Value, "NearVector", CallingConvention::NearVector);
262}
263
264void ScalarEnumerationTraits<PointerKind>::enumeration(IO &IO,
265                                                       PointerKind &Kind) {
266  IO.enumCase(Kind, "Near16", PointerKind::Near16);
267  IO.enumCase(Kind, "Far16", PointerKind::Far16);
268  IO.enumCase(Kind, "Huge16", PointerKind::Huge16);
269  IO.enumCase(Kind, "BasedOnSegment", PointerKind::BasedOnSegment);
270  IO.enumCase(Kind, "BasedOnValue", PointerKind::BasedOnValue);
271  IO.enumCase(Kind, "BasedOnSegmentValue", PointerKind::BasedOnSegmentValue);
272  IO.enumCase(Kind, "BasedOnAddress", PointerKind::BasedOnAddress);
273  IO.enumCase(Kind, "BasedOnSegmentAddress",
274              PointerKind::BasedOnSegmentAddress);
275  IO.enumCase(Kind, "BasedOnType", PointerKind::BasedOnType);
276  IO.enumCase(Kind, "BasedOnSelf", PointerKind::BasedOnSelf);
277  IO.enumCase(Kind, "Near32", PointerKind::Near32);
278  IO.enumCase(Kind, "Far32", PointerKind::Far32);
279  IO.enumCase(Kind, "Near64", PointerKind::Near64);
280}
281
282void ScalarEnumerationTraits<PointerMode>::enumeration(IO &IO,
283                                                       PointerMode &Mode) {
284  IO.enumCase(Mode, "Pointer", PointerMode::Pointer);
285  IO.enumCase(Mode, "LValueReference", PointerMode::LValueReference);
286  IO.enumCase(Mode, "PointerToDataMember", PointerMode::PointerToDataMember);
287  IO.enumCase(Mode, "PointerToMemberFunction",
288              PointerMode::PointerToMemberFunction);
289  IO.enumCase(Mode, "RValueReference", PointerMode::RValueReference);
290}
291
292void ScalarEnumerationTraits<HfaKind>::enumeration(IO &IO, HfaKind &Value) {
293  IO.enumCase(Value, "None", HfaKind::None);
294  IO.enumCase(Value, "Float", HfaKind::Float);
295  IO.enumCase(Value, "Double", HfaKind::Double);
296  IO.enumCase(Value, "Other", HfaKind::Other);
297}
298
299void ScalarEnumerationTraits<MemberAccess>::enumeration(IO &IO,
300                                                        MemberAccess &Access) {
301  IO.enumCase(Access, "None", MemberAccess::None);
302  IO.enumCase(Access, "Private", MemberAccess::Private);
303  IO.enumCase(Access, "Protected", MemberAccess::Protected);
304  IO.enumCase(Access, "Public", MemberAccess::Public);
305}
306
307void ScalarEnumerationTraits<MethodKind>::enumeration(IO &IO,
308                                                      MethodKind &Kind) {
309  IO.enumCase(Kind, "Vanilla", MethodKind::Vanilla);
310  IO.enumCase(Kind, "Virtual", MethodKind::Virtual);
311  IO.enumCase(Kind, "Static", MethodKind::Static);
312  IO.enumCase(Kind, "Friend", MethodKind::Friend);
313  IO.enumCase(Kind, "IntroducingVirtual", MethodKind::IntroducingVirtual);
314  IO.enumCase(Kind, "PureVirtual", MethodKind::PureVirtual);
315  IO.enumCase(Kind, "PureIntroducingVirtual",
316              MethodKind::PureIntroducingVirtual);
317}
318
319void ScalarEnumerationTraits<WindowsRTClassKind>::enumeration(
320    IO &IO, WindowsRTClassKind &Value) {
321  IO.enumCase(Value, "None", WindowsRTClassKind::None);
322  IO.enumCase(Value, "Ref", WindowsRTClassKind::RefClass);
323  IO.enumCase(Value, "Value", WindowsRTClassKind::ValueClass);
324  IO.enumCase(Value, "Interface", WindowsRTClassKind::Interface);
325}
326
327void ScalarEnumerationTraits<LabelType>::enumeration(IO &IO, LabelType &Value) {
328  IO.enumCase(Value, "Near", LabelType::Near);
329  IO.enumCase(Value, "Far", LabelType::Far);
330}
331
332void ScalarBitSetTraits<PointerOptions>::bitset(IO &IO,
333                                                PointerOptions &Options) {
334  IO.bitSetCase(Options, "None", PointerOptions::None);
335  IO.bitSetCase(Options, "Flat32", PointerOptions::Flat32);
336  IO.bitSetCase(Options, "Volatile", PointerOptions::Volatile);
337  IO.bitSetCase(Options, "Const", PointerOptions::Const);
338  IO.bitSetCase(Options, "Unaligned", PointerOptions::Unaligned);
339  IO.bitSetCase(Options, "Restrict", PointerOptions::Restrict);
340  IO.bitSetCase(Options, "WinRTSmartPointer",
341                PointerOptions::WinRTSmartPointer);
342}
343
344void ScalarBitSetTraits<ModifierOptions>::bitset(IO &IO,
345                                                 ModifierOptions &Options) {
346  IO.bitSetCase(Options, "None", ModifierOptions::None);
347  IO.bitSetCase(Options, "Const", ModifierOptions::Const);
348  IO.bitSetCase(Options, "Volatile", ModifierOptions::Volatile);
349  IO.bitSetCase(Options, "Unaligned", ModifierOptions::Unaligned);
350}
351
352void ScalarBitSetTraits<FunctionOptions>::bitset(IO &IO,
353                                                 FunctionOptions &Options) {
354  IO.bitSetCase(Options, "None", FunctionOptions::None);
355  IO.bitSetCase(Options, "CxxReturnUdt", FunctionOptions::CxxReturnUdt);
356  IO.bitSetCase(Options, "Constructor", FunctionOptions::Constructor);
357  IO.bitSetCase(Options, "ConstructorWithVirtualBases",
358                FunctionOptions::ConstructorWithVirtualBases);
359}
360
361void ScalarBitSetTraits<ClassOptions>::bitset(IO &IO, ClassOptions &Options) {
362  IO.bitSetCase(Options, "None", ClassOptions::None);
363  IO.bitSetCase(Options, "HasConstructorOrDestructor",
364                ClassOptions::HasConstructorOrDestructor);
365  IO.bitSetCase(Options, "HasOverloadedOperator",
366                ClassOptions::HasOverloadedOperator);
367  IO.bitSetCase(Options, "Nested", ClassOptions::Nested);
368  IO.bitSetCase(Options, "ContainsNestedClass",
369                ClassOptions::ContainsNestedClass);
370  IO.bitSetCase(Options, "HasOverloadedAssignmentOperator",
371                ClassOptions::HasOverloadedAssignmentOperator);
372  IO.bitSetCase(Options, "HasConversionOperator",
373                ClassOptions::HasConversionOperator);
374  IO.bitSetCase(Options, "ForwardReference", ClassOptions::ForwardReference);
375  IO.bitSetCase(Options, "Scoped", ClassOptions::Scoped);
376  IO.bitSetCase(Options, "HasUniqueName", ClassOptions::HasUniqueName);
377  IO.bitSetCase(Options, "Sealed", ClassOptions::Sealed);
378  IO.bitSetCase(Options, "Intrinsic", ClassOptions::Intrinsic);
379}
380
381void ScalarBitSetTraits<MethodOptions>::bitset(IO &IO, MethodOptions &Options) {
382  IO.bitSetCase(Options, "None", MethodOptions::None);
383  IO.bitSetCase(Options, "Pseudo", MethodOptions::Pseudo);
384  IO.bitSetCase(Options, "NoInherit", MethodOptions::NoInherit);
385  IO.bitSetCase(Options, "NoConstruct", MethodOptions::NoConstruct);
386  IO.bitSetCase(Options, "CompilerGenerated", MethodOptions::CompilerGenerated);
387  IO.bitSetCase(Options, "Sealed", MethodOptions::Sealed);
388}
389
390void MappingTraits<MemberPointerInfo>::mapping(IO &IO, MemberPointerInfo &MPI) {
391  IO.mapRequired("ContainingType", MPI.ContainingType);
392  IO.mapRequired("Representation", MPI.Representation);
393}
394
395namespace llvm {
396namespace CodeViewYAML {
397namespace detail {
398
399template <> void LeafRecordImpl<ModifierRecord>::map(IO &IO) {
400  IO.mapRequired("ModifiedType", Record.ModifiedType);
401  IO.mapRequired("Modifiers", Record.Modifiers);
402}
403
404template <> void LeafRecordImpl<ProcedureRecord>::map(IO &IO) {
405  IO.mapRequired("ReturnType", Record.ReturnType);
406  IO.mapRequired("CallConv", Record.CallConv);
407  IO.mapRequired("Options", Record.Options);
408  IO.mapRequired("ParameterCount", Record.ParameterCount);
409  IO.mapRequired("ArgumentList", Record.ArgumentList);
410}
411
412template <> void LeafRecordImpl<MemberFunctionRecord>::map(IO &IO) {
413  IO.mapRequired("ReturnType", Record.ReturnType);
414  IO.mapRequired("ClassType", Record.ClassType);
415  IO.mapRequired("ThisType", Record.ThisType);
416  IO.mapRequired("CallConv", Record.CallConv);
417  IO.mapRequired("Options", Record.Options);
418  IO.mapRequired("ParameterCount", Record.ParameterCount);
419  IO.mapRequired("ArgumentList", Record.ArgumentList);
420  IO.mapRequired("ThisPointerAdjustment", Record.ThisPointerAdjustment);
421}
422
423template <> void LeafRecordImpl<LabelRecord>::map(IO &IO) {
424  IO.mapRequired("Mode", Record.Mode);
425}
426
427template <> void LeafRecordImpl<MemberFuncIdRecord>::map(IO &IO) {
428  IO.mapRequired("ClassType", Record.ClassType);
429  IO.mapRequired("FunctionType", Record.FunctionType);
430  IO.mapRequired("Name", Record.Name);
431}
432
433template <> void LeafRecordImpl<ArgListRecord>::map(IO &IO) {
434  IO.mapRequired("ArgIndices", Record.ArgIndices);
435}
436
437template <> void LeafRecordImpl<StringListRecord>::map(IO &IO) {
438  IO.mapRequired("StringIndices", Record.StringIndices);
439}
440
441template <> void LeafRecordImpl<PointerRecord>::map(IO &IO) {
442  IO.mapRequired("ReferentType", Record.ReferentType);
443  IO.mapRequired("Attrs", Record.Attrs);
444  IO.mapOptional("MemberInfo", Record.MemberInfo);
445}
446
447template <> void LeafRecordImpl<ArrayRecord>::map(IO &IO) {
448  IO.mapRequired("ElementType", Record.ElementType);
449  IO.mapRequired("IndexType", Record.IndexType);
450  IO.mapRequired("Size", Record.Size);
451  IO.mapRequired("Name", Record.Name);
452}
453
454void LeafRecordImpl<FieldListRecord>::map(IO &IO) {
455  IO.mapRequired("FieldList", Members);
456}
457
458} // end namespace detail
459} // end namespace CodeViewYAML
460} // end namespace llvm
461
462namespace {
463
464class MemberRecordConversionVisitor : public TypeVisitorCallbacks {
465public:
466  explicit MemberRecordConversionVisitor(std::vector<MemberRecord> &Records)
467      : Records(Records) {}
468
469#define TYPE_RECORD(EnumName, EnumVal, Name)
470#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
471  Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
472    return visitKnownMemberImpl(Record);                                       \
473  }
474#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
475#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
476#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
477private:
478  template <typename T> Error visitKnownMemberImpl(T &Record) {
479    TypeLeafKind K = static_cast<TypeLeafKind>(Record.getKind());
480    auto Impl = std::make_shared<MemberRecordImpl<T>>(K);
481    Impl->Record = Record;
482    Records.push_back(MemberRecord{Impl});
483    return Error::success();
484  }
485
486  std::vector<MemberRecord> &Records;
487};
488
489} // end anonymous namespace
490
491Error LeafRecordImpl<FieldListRecord>::fromCodeViewRecord(CVType Type) {
492  MemberRecordConversionVisitor V(Members);
493  return visitMemberRecordStream(Type.content(), V);
494}
495
496CVType LeafRecordImpl<FieldListRecord>::toCodeViewRecord(
497    AppendingTypeTableBuilder &TS) const {
498  ContinuationRecordBuilder CRB;
499  CRB.begin(ContinuationRecordKind::FieldList);
500  for (const auto &Member : Members) {
501    Member.Member->writeTo(CRB);
502  }
503  TS.insertRecord(CRB);
504  return CVType(TS.records().back());
505}
506
507void MappingTraits<OneMethodRecord>::mapping(IO &io, OneMethodRecord &Record) {
508  io.mapRequired("Type", Record.Type);
509  io.mapRequired("Attrs", Record.Attrs.Attrs);
510  io.mapRequired("VFTableOffset", Record.VFTableOffset);
511  io.mapRequired("Name", Record.Name);
512}
513
514namespace llvm {
515namespace CodeViewYAML {
516namespace detail {
517
518template <> void LeafRecordImpl<ClassRecord>::map(IO &IO) {
519  IO.mapRequired("MemberCount", Record.MemberCount);
520  IO.mapRequired("Options", Record.Options);
521  IO.mapRequired("FieldList", Record.FieldList);
522  IO.mapRequired("Name", Record.Name);
523  IO.mapRequired("UniqueName", Record.UniqueName);
524  IO.mapRequired("DerivationList", Record.DerivationList);
525  IO.mapRequired("VTableShape", Record.VTableShape);
526  IO.mapRequired("Size", Record.Size);
527}
528
529template <> void LeafRecordImpl<UnionRecord>::map(IO &IO) {
530  IO.mapRequired("MemberCount", Record.MemberCount);
531  IO.mapRequired("Options", Record.Options);
532  IO.mapRequired("FieldList", Record.FieldList);
533  IO.mapRequired("Name", Record.Name);
534  IO.mapRequired("UniqueName", Record.UniqueName);
535  IO.mapRequired("Size", Record.Size);
536}
537
538template <> void LeafRecordImpl<EnumRecord>::map(IO &IO) {
539  IO.mapRequired("NumEnumerators", Record.MemberCount);
540  IO.mapRequired("Options", Record.Options);
541  IO.mapRequired("FieldList", Record.FieldList);
542  IO.mapRequired("Name", Record.Name);
543  IO.mapRequired("UniqueName", Record.UniqueName);
544  IO.mapRequired("UnderlyingType", Record.UnderlyingType);
545}
546
547template <> void LeafRecordImpl<BitFieldRecord>::map(IO &IO) {
548  IO.mapRequired("Type", Record.Type);
549  IO.mapRequired("BitSize", Record.BitSize);
550  IO.mapRequired("BitOffset", Record.BitOffset);
551}
552
553template <> void LeafRecordImpl<VFTableShapeRecord>::map(IO &IO) {
554  IO.mapRequired("Slots", Record.Slots);
555}
556
557template <> void LeafRecordImpl<TypeServer2Record>::map(IO &IO) {
558  IO.mapRequired("Guid", Record.Guid);
559  IO.mapRequired("Age", Record.Age);
560  IO.mapRequired("Name", Record.Name);
561}
562
563template <> void LeafRecordImpl<StringIdRecord>::map(IO &IO) {
564  IO.mapRequired("Id", Record.Id);
565  IO.mapRequired("String", Record.String);
566}
567
568template <> void LeafRecordImpl<FuncIdRecord>::map(IO &IO) {
569  IO.mapRequired("ParentScope", Record.ParentScope);
570  IO.mapRequired("FunctionType", Record.FunctionType);
571  IO.mapRequired("Name", Record.Name);
572}
573
574template <> void LeafRecordImpl<UdtSourceLineRecord>::map(IO &IO) {
575  IO.mapRequired("UDT", Record.UDT);
576  IO.mapRequired("SourceFile", Record.SourceFile);
577  IO.mapRequired("LineNumber", Record.LineNumber);
578}
579
580template <> void LeafRecordImpl<UdtModSourceLineRecord>::map(IO &IO) {
581  IO.mapRequired("UDT", Record.UDT);
582  IO.mapRequired("SourceFile", Record.SourceFile);
583  IO.mapRequired("LineNumber", Record.LineNumber);
584  IO.mapRequired("Module", Record.Module);
585}
586
587template <> void LeafRecordImpl<BuildInfoRecord>::map(IO &IO) {
588  IO.mapRequired("ArgIndices", Record.ArgIndices);
589}
590
591template <> void LeafRecordImpl<VFTableRecord>::map(IO &IO) {
592  IO.mapRequired("CompleteClass", Record.CompleteClass);
593  IO.mapRequired("OverriddenVFTable", Record.OverriddenVFTable);
594  IO.mapRequired("VFPtrOffset", Record.VFPtrOffset);
595  IO.mapRequired("MethodNames", Record.MethodNames);
596}
597
598template <> void LeafRecordImpl<MethodOverloadListRecord>::map(IO &IO) {
599  IO.mapRequired("Methods", Record.Methods);
600}
601
602template <> void LeafRecordImpl<PrecompRecord>::map(IO &IO) {
603  IO.mapRequired("StartTypeIndex", Record.StartTypeIndex);
604  IO.mapRequired("TypesCount", Record.TypesCount);
605  IO.mapRequired("Signature", Record.Signature);
606  IO.mapRequired("PrecompFilePath", Record.PrecompFilePath);
607}
608
609template <> void LeafRecordImpl<EndPrecompRecord>::map(IO &IO) {
610  IO.mapRequired("Signature", Record.Signature);
611}
612
613template <> void MemberRecordImpl<OneMethodRecord>::map(IO &IO) {
614  MappingTraits<OneMethodRecord>::mapping(IO, Record);
615}
616
617template <> void MemberRecordImpl<OverloadedMethodRecord>::map(IO &IO) {
618  IO.mapRequired("NumOverloads", Record.NumOverloads);
619  IO.mapRequired("MethodList", Record.MethodList);
620  IO.mapRequired("Name", Record.Name);
621}
622
623template <> void MemberRecordImpl<NestedTypeRecord>::map(IO &IO) {
624  IO.mapRequired("Type", Record.Type);
625  IO.mapRequired("Name", Record.Name);
626}
627
628template <> void MemberRecordImpl<DataMemberRecord>::map(IO &IO) {
629  IO.mapRequired("Attrs", Record.Attrs.Attrs);
630  IO.mapRequired("Type", Record.Type);
631  IO.mapRequired("FieldOffset", Record.FieldOffset);
632  IO.mapRequired("Name", Record.Name);
633}
634
635template <> void MemberRecordImpl<StaticDataMemberRecord>::map(IO &IO) {
636  IO.mapRequired("Attrs", Record.Attrs.Attrs);
637  IO.mapRequired("Type", Record.Type);
638  IO.mapRequired("Name", Record.Name);
639}
640
641template <> void MemberRecordImpl<EnumeratorRecord>::map(IO &IO) {
642  IO.mapRequired("Attrs", Record.Attrs.Attrs);
643  IO.mapRequired("Value", Record.Value);
644  IO.mapRequired("Name", Record.Name);
645}
646
647template <> void MemberRecordImpl<VFPtrRecord>::map(IO &IO) {
648  IO.mapRequired("Type", Record.Type);
649}
650
651template <> void MemberRecordImpl<BaseClassRecord>::map(IO &IO) {
652  IO.mapRequired("Attrs", Record.Attrs.Attrs);
653  IO.mapRequired("Type", Record.Type);
654  IO.mapRequired("Offset", Record.Offset);
655}
656
657template <> void MemberRecordImpl<VirtualBaseClassRecord>::map(IO &IO) {
658  IO.mapRequired("Attrs", Record.Attrs.Attrs);
659  IO.mapRequired("BaseType", Record.BaseType);
660  IO.mapRequired("VBPtrType", Record.VBPtrType);
661  IO.mapRequired("VBPtrOffset", Record.VBPtrOffset);
662  IO.mapRequired("VTableIndex", Record.VTableIndex);
663}
664
665template <> void MemberRecordImpl<ListContinuationRecord>::map(IO &IO) {
666  IO.mapRequired("ContinuationIndex", Record.ContinuationIndex);
667}
668
669} // end namespace detail
670} // end namespace CodeViewYAML
671} // end namespace llvm
672
673template <typename T>
674static inline Expected<LeafRecord> fromCodeViewRecordImpl(CVType Type) {
675  LeafRecord Result;
676
677  auto Impl = std::make_shared<LeafRecordImpl<T>>(Type.kind());
678  if (auto EC = Impl->fromCodeViewRecord(Type))
679    return std::move(EC);
680  Result.Leaf = Impl;
681  return Result;
682}
683
684Expected<LeafRecord> LeafRecord::fromCodeViewRecord(CVType Type) {
685#define TYPE_RECORD(EnumName, EnumVal, ClassName)                              \
686  case EnumName:                                                               \
687    return fromCodeViewRecordImpl<ClassName##Record>(Type);
688#define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)             \
689  TYPE_RECORD(EnumName, EnumVal, ClassName)
690#define MEMBER_RECORD(EnumName, EnumVal, ClassName)
691#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
692  switch (Type.kind()) {
693#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
694  default:
695      llvm_unreachable("Unknown leaf kind!");
696  }
697  return make_error<CodeViewError>(cv_error_code::corrupt_record);
698}
699
700CVType
701LeafRecord::toCodeViewRecord(AppendingTypeTableBuilder &Serializer) const {
702  return Leaf->toCodeViewRecord(Serializer);
703}
704
705namespace llvm {
706namespace yaml {
707
708template <> struct MappingTraits<LeafRecordBase> {
709  static void mapping(IO &io, LeafRecordBase &Record) { Record.map(io); }
710};
711
712template <> struct MappingTraits<MemberRecordBase> {
713  static void mapping(IO &io, MemberRecordBase &Record) { Record.map(io); }
714};
715
716} // end namespace yaml
717} // end namespace llvm
718
719template <typename ConcreteType>
720static void mapLeafRecordImpl(IO &IO, const char *Class, TypeLeafKind Kind,
721                              LeafRecord &Obj) {
722  if (!IO.outputting())
723    Obj.Leaf = std::make_shared<LeafRecordImpl<ConcreteType>>(Kind);
724
725  if (Kind == LF_FIELDLIST)
726    Obj.Leaf->map(IO);
727  else
728    IO.mapRequired(Class, *Obj.Leaf);
729}
730
731void MappingTraits<LeafRecord>::mapping(IO &IO, LeafRecord &Obj) {
732  TypeLeafKind Kind;
733  if (IO.outputting())
734    Kind = Obj.Leaf->Kind;
735  IO.mapRequired("Kind", Kind);
736
737#define TYPE_RECORD(EnumName, EnumVal, ClassName)                              \
738  case EnumName:                                                               \
739    mapLeafRecordImpl<ClassName##Record>(IO, #ClassName, Kind, Obj);           \
740    break;
741#define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)             \
742  TYPE_RECORD(EnumName, EnumVal, ClassName)
743#define MEMBER_RECORD(EnumName, EnumVal, ClassName)
744#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
745  switch (Kind) {
746#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
747  default: { llvm_unreachable("Unknown leaf kind!"); }
748  }
749}
750
751template <typename ConcreteType>
752static void mapMemberRecordImpl(IO &IO, const char *Class, TypeLeafKind Kind,
753                                MemberRecord &Obj) {
754  if (!IO.outputting())
755    Obj.Member = std::make_shared<MemberRecordImpl<ConcreteType>>(Kind);
756
757  IO.mapRequired(Class, *Obj.Member);
758}
759
760void MappingTraits<MemberRecord>::mapping(IO &IO, MemberRecord &Obj) {
761  TypeLeafKind Kind;
762  if (IO.outputting())
763    Kind = Obj.Member->Kind;
764  IO.mapRequired("Kind", Kind);
765
766#define MEMBER_RECORD(EnumName, EnumVal, ClassName)                            \
767  case EnumName:                                                               \
768    mapMemberRecordImpl<ClassName##Record>(IO, #ClassName, Kind, Obj);         \
769    break;
770#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)           \
771  MEMBER_RECORD(EnumName, EnumVal, ClassName)
772#define TYPE_RECORD(EnumName, EnumVal, ClassName)
773#define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
774  switch (Kind) {
775#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
776  default: { llvm_unreachable("Unknown member kind!"); }
777  }
778}
779
780std::vector<LeafRecord>
781llvm::CodeViewYAML::fromDebugT(ArrayRef<uint8_t> DebugTorP,
782                               StringRef SectionName) {
783  ExitOnError Err("Invalid " + std::string(SectionName) + " section!");
784  BinaryStreamReader Reader(DebugTorP, support::little);
785  CVTypeArray Types;
786  uint32_t Magic;
787
788  Err(Reader.readInteger(Magic));
789  assert(Magic == COFF::DEBUG_SECTION_MAGIC &&
790         "Invalid .debug$T or .debug$P section!");
791
792  std::vector<LeafRecord> Result;
793  Err(Reader.readArray(Types, Reader.bytesRemaining()));
794  for (const auto &T : Types) {
795    auto CVT = Err(LeafRecord::fromCodeViewRecord(T));
796    Result.push_back(CVT);
797  }
798  return Result;
799}
800
801ArrayRef<uint8_t> llvm::CodeViewYAML::toDebugT(ArrayRef<LeafRecord> Leafs,
802                                               BumpPtrAllocator &Alloc,
803                                               StringRef SectionName) {
804  AppendingTypeTableBuilder TS(Alloc);
805  uint32_t Size = sizeof(uint32_t);
806  for (const auto &Leaf : Leafs) {
807    CVType T = Leaf.Leaf->toCodeViewRecord(TS);
808    Size += T.length();
809    assert(T.length() % 4 == 0 && "Improper type record alignment!");
810  }
811  uint8_t *ResultBuffer = Alloc.Allocate<uint8_t>(Size);
812  MutableArrayRef<uint8_t> Output(ResultBuffer, Size);
813  BinaryStreamWriter Writer(Output, support::little);
814  ExitOnError Err("Error writing type record to " + std::string(SectionName) +
815                  " section");
816  Err(Writer.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC));
817  for (const auto &R : TS.records()) {
818    Err(Writer.writeBytes(R));
819  }
820  assert(Writer.bytesRemaining() == 0 && "Didn't write all type record bytes!");
821  return Output;
822}
823