1 //===- CodeViewYAMLTypes.cpp - CodeView YAMLIO types implementation -------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines classes for handling the YAML representation of CodeView
12 //===----------------------------------------------------------------------===//
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"
41 using namespace llvm::codeview
;
42 using namespace llvm::CodeViewYAML
;
43 using namespace llvm::CodeViewYAML::detail
;
44 using namespace llvm::yaml
;
46 LLVM_YAML_IS_SEQUENCE_VECTOR(OneMethodRecord
)
47 LLVM_YAML_IS_SEQUENCE_VECTOR(VFTableSlotKind
)
48 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex
)
50 LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex
, QuotingType::None
)
51 LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt
, QuotingType::None
)
53 LLVM_YAML_DECLARE_ENUM_TRAITS(TypeLeafKind
)
54 LLVM_YAML_DECLARE_ENUM_TRAITS(PointerToMemberRepresentation
)
55 LLVM_YAML_DECLARE_ENUM_TRAITS(VFTableSlotKind
)
56 LLVM_YAML_DECLARE_ENUM_TRAITS(CallingConvention
)
57 LLVM_YAML_DECLARE_ENUM_TRAITS(PointerKind
)
58 LLVM_YAML_DECLARE_ENUM_TRAITS(PointerMode
)
59 LLVM_YAML_DECLARE_ENUM_TRAITS(HfaKind
)
60 LLVM_YAML_DECLARE_ENUM_TRAITS(MemberAccess
)
61 LLVM_YAML_DECLARE_ENUM_TRAITS(MethodKind
)
62 LLVM_YAML_DECLARE_ENUM_TRAITS(WindowsRTClassKind
)
63 LLVM_YAML_DECLARE_ENUM_TRAITS(LabelType
)
65 LLVM_YAML_DECLARE_BITSET_TRAITS(PointerOptions
)
66 LLVM_YAML_DECLARE_BITSET_TRAITS(ModifierOptions
)
67 LLVM_YAML_DECLARE_BITSET_TRAITS(FunctionOptions
)
68 LLVM_YAML_DECLARE_BITSET_TRAITS(ClassOptions
)
69 LLVM_YAML_DECLARE_BITSET_TRAITS(MethodOptions
)
71 LLVM_YAML_DECLARE_MAPPING_TRAITS(OneMethodRecord
)
72 LLVM_YAML_DECLARE_MAPPING_TRAITS(MemberPointerInfo
)
75 namespace CodeViewYAML
{
78 struct LeafRecordBase
{
81 explicit LeafRecordBase(TypeLeafKind K
) : Kind(K
) {}
82 virtual ~LeafRecordBase() = default;
84 virtual void map(yaml::IO
&io
) = 0;
85 virtual CVType
toCodeViewRecord(AppendingTypeTableBuilder
&TS
) const = 0;
86 virtual Error
fromCodeViewRecord(CVType Type
) = 0;
89 template <typename T
> struct LeafRecordImpl
: public LeafRecordBase
{
90 explicit LeafRecordImpl(TypeLeafKind K
)
91 : LeafRecordBase(K
), Record(static_cast<TypeRecordKind
>(K
)) {}
93 void map(yaml::IO
&io
) override
;
95 Error
fromCodeViewRecord(CVType Type
) override
{
96 return TypeDeserializer::deserializeAs
<T
>(Type
, Record
);
99 CVType
toCodeViewRecord(AppendingTypeTableBuilder
&TS
) const override
{
100 TS
.writeLeafType(Record
);
101 return CVType(TS
.records().back());
107 template <> struct LeafRecordImpl
<FieldListRecord
> : public LeafRecordBase
{
108 explicit LeafRecordImpl(TypeLeafKind K
) : LeafRecordBase(K
) {}
110 void map(yaml::IO
&io
) override
;
111 CVType
toCodeViewRecord(AppendingTypeTableBuilder
&TS
) const override
;
112 Error
fromCodeViewRecord(CVType Type
) override
;
114 std::vector
<MemberRecord
> Members
;
117 struct MemberRecordBase
{
120 explicit MemberRecordBase(TypeLeafKind K
) : Kind(K
) {}
121 virtual ~MemberRecordBase() = default;
123 virtual void map(yaml::IO
&io
) = 0;
124 virtual void writeTo(ContinuationRecordBuilder
&CRB
) = 0;
127 template <typename T
> struct MemberRecordImpl
: public MemberRecordBase
{
128 explicit MemberRecordImpl(TypeLeafKind K
)
129 : MemberRecordBase(K
), Record(static_cast<TypeRecordKind
>(K
)) {}
131 void map(yaml::IO
&io
) override
;
133 void writeTo(ContinuationRecordBuilder
&CRB
) override
{
134 CRB
.writeMemberType(Record
);
140 } // end namespace detail
141 } // end namespace CodeViewYAML
142 } // end namespace llvm
144 void ScalarTraits
<GUID
>::output(const GUID
&G
, void *, llvm::raw_ostream
&OS
) {
148 StringRef 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
[0] != '{' || Scalar
[37] != '}')
152 return "GUID is not enclosed in {}";
153 if (Scalar
[9] != '-' || Scalar
[14] != '-' || Scalar
[19] != '-' ||
155 return "GUID sections are not properly delineated with dashes";
157 uint8_t *OutBuffer
= S
.Guid
;
158 for (auto Iter
= Scalar
.begin(); Iter
!= Scalar
.end();) {
159 if (*Iter
== '-' || *Iter
== '{' || *Iter
== '}') {
163 uint8_t Value
= (llvm::hexDigitValue(*Iter
++) << 4);
164 Value
|= llvm::hexDigitValue(*Iter
++);
165 *OutBuffer
++ = Value
;
171 void ScalarTraits
<TypeIndex
>::output(const TypeIndex
&S
, void *,
176 StringRef ScalarTraits
<TypeIndex
>::input(StringRef Scalar
, void *Ctx
,
179 StringRef Result
= ScalarTraits
<uint32_t>::input(Scalar
, Ctx
, I
);
184 void ScalarTraits
<APSInt
>::output(const APSInt
&S
, void *, raw_ostream
&OS
) {
185 S
.print(OS
, S
.isSigned());
188 StringRef ScalarTraits
<APSInt
>::input(StringRef Scalar
, void *Ctx
, APSInt
&S
) {
193 void ScalarEnumerationTraits
<TypeLeafKind
>::enumeration(IO
&io
,
194 TypeLeafKind
&Value
) {
195 #define CV_TYPE(name, val) io.enumCase(Value, #name, name);
196 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
200 void ScalarEnumerationTraits
<PointerToMemberRepresentation
>::enumeration(
201 IO
&IO
, PointerToMemberRepresentation
&Value
) {
202 IO
.enumCase(Value
, "Unknown", PointerToMemberRepresentation::Unknown
);
203 IO
.enumCase(Value
, "SingleInheritanceData",
204 PointerToMemberRepresentation::SingleInheritanceData
);
205 IO
.enumCase(Value
, "MultipleInheritanceData",
206 PointerToMemberRepresentation::MultipleInheritanceData
);
207 IO
.enumCase(Value
, "VirtualInheritanceData",
208 PointerToMemberRepresentation::VirtualInheritanceData
);
209 IO
.enumCase(Value
, "GeneralData", PointerToMemberRepresentation::GeneralData
);
210 IO
.enumCase(Value
, "SingleInheritanceFunction",
211 PointerToMemberRepresentation::SingleInheritanceFunction
);
212 IO
.enumCase(Value
, "MultipleInheritanceFunction",
213 PointerToMemberRepresentation::MultipleInheritanceFunction
);
214 IO
.enumCase(Value
, "VirtualInheritanceFunction",
215 PointerToMemberRepresentation::VirtualInheritanceFunction
);
216 IO
.enumCase(Value
, "GeneralFunction",
217 PointerToMemberRepresentation::GeneralFunction
);
220 void ScalarEnumerationTraits
<VFTableSlotKind
>::enumeration(
221 IO
&IO
, VFTableSlotKind
&Kind
) {
222 IO
.enumCase(Kind
, "Near16", VFTableSlotKind::Near16
);
223 IO
.enumCase(Kind
, "Far16", VFTableSlotKind::Far16
);
224 IO
.enumCase(Kind
, "This", VFTableSlotKind::This
);
225 IO
.enumCase(Kind
, "Outer", VFTableSlotKind::Outer
);
226 IO
.enumCase(Kind
, "Meta", VFTableSlotKind::Meta
);
227 IO
.enumCase(Kind
, "Near", VFTableSlotKind::Near
);
228 IO
.enumCase(Kind
, "Far", VFTableSlotKind::Far
);
231 void ScalarEnumerationTraits
<CallingConvention
>::enumeration(
232 IO
&IO
, CallingConvention
&Value
) {
233 IO
.enumCase(Value
, "NearC", CallingConvention::NearC
);
234 IO
.enumCase(Value
, "FarC", CallingConvention::FarC
);
235 IO
.enumCase(Value
, "NearPascal", CallingConvention::NearPascal
);
236 IO
.enumCase(Value
, "FarPascal", CallingConvention::FarPascal
);
237 IO
.enumCase(Value
, "NearFast", CallingConvention::NearFast
);
238 IO
.enumCase(Value
, "FarFast", CallingConvention::FarFast
);
239 IO
.enumCase(Value
, "NearStdCall", CallingConvention::NearStdCall
);
240 IO
.enumCase(Value
, "FarStdCall", CallingConvention::FarStdCall
);
241 IO
.enumCase(Value
, "NearSysCall", CallingConvention::NearSysCall
);
242 IO
.enumCase(Value
, "FarSysCall", CallingConvention::FarSysCall
);
243 IO
.enumCase(Value
, "ThisCall", CallingConvention::ThisCall
);
244 IO
.enumCase(Value
, "MipsCall", CallingConvention::MipsCall
);
245 IO
.enumCase(Value
, "Generic", CallingConvention::Generic
);
246 IO
.enumCase(Value
, "AlphaCall", CallingConvention::AlphaCall
);
247 IO
.enumCase(Value
, "PpcCall", CallingConvention::PpcCall
);
248 IO
.enumCase(Value
, "SHCall", CallingConvention::SHCall
);
249 IO
.enumCase(Value
, "ArmCall", CallingConvention::ArmCall
);
250 IO
.enumCase(Value
, "AM33Call", CallingConvention::AM33Call
);
251 IO
.enumCase(Value
, "TriCall", CallingConvention::TriCall
);
252 IO
.enumCase(Value
, "SH5Call", CallingConvention::SH5Call
);
253 IO
.enumCase(Value
, "M32RCall", CallingConvention::M32RCall
);
254 IO
.enumCase(Value
, "ClrCall", CallingConvention::ClrCall
);
255 IO
.enumCase(Value
, "Inline", CallingConvention::Inline
);
256 IO
.enumCase(Value
, "NearVector", CallingConvention::NearVector
);
259 void ScalarEnumerationTraits
<PointerKind
>::enumeration(IO
&IO
,
261 IO
.enumCase(Kind
, "Near16", PointerKind::Near16
);
262 IO
.enumCase(Kind
, "Far16", PointerKind::Far16
);
263 IO
.enumCase(Kind
, "Huge16", PointerKind::Huge16
);
264 IO
.enumCase(Kind
, "BasedOnSegment", PointerKind::BasedOnSegment
);
265 IO
.enumCase(Kind
, "BasedOnValue", PointerKind::BasedOnValue
);
266 IO
.enumCase(Kind
, "BasedOnSegmentValue", PointerKind::BasedOnSegmentValue
);
267 IO
.enumCase(Kind
, "BasedOnAddress", PointerKind::BasedOnAddress
);
268 IO
.enumCase(Kind
, "BasedOnSegmentAddress",
269 PointerKind::BasedOnSegmentAddress
);
270 IO
.enumCase(Kind
, "BasedOnType", PointerKind::BasedOnType
);
271 IO
.enumCase(Kind
, "BasedOnSelf", PointerKind::BasedOnSelf
);
272 IO
.enumCase(Kind
, "Near32", PointerKind::Near32
);
273 IO
.enumCase(Kind
, "Far32", PointerKind::Far32
);
274 IO
.enumCase(Kind
, "Near64", PointerKind::Near64
);
277 void ScalarEnumerationTraits
<PointerMode
>::enumeration(IO
&IO
,
279 IO
.enumCase(Mode
, "Pointer", PointerMode::Pointer
);
280 IO
.enumCase(Mode
, "LValueReference", PointerMode::LValueReference
);
281 IO
.enumCase(Mode
, "PointerToDataMember", PointerMode::PointerToDataMember
);
282 IO
.enumCase(Mode
, "PointerToMemberFunction",
283 PointerMode::PointerToMemberFunction
);
284 IO
.enumCase(Mode
, "RValueReference", PointerMode::RValueReference
);
287 void ScalarEnumerationTraits
<HfaKind
>::enumeration(IO
&IO
, HfaKind
&Value
) {
288 IO
.enumCase(Value
, "None", HfaKind::None
);
289 IO
.enumCase(Value
, "Float", HfaKind::Float
);
290 IO
.enumCase(Value
, "Double", HfaKind::Double
);
291 IO
.enumCase(Value
, "Other", HfaKind::Other
);
294 void ScalarEnumerationTraits
<MemberAccess
>::enumeration(IO
&IO
,
295 MemberAccess
&Access
) {
296 IO
.enumCase(Access
, "None", MemberAccess::None
);
297 IO
.enumCase(Access
, "Private", MemberAccess::Private
);
298 IO
.enumCase(Access
, "Protected", MemberAccess::Protected
);
299 IO
.enumCase(Access
, "Public", MemberAccess::Public
);
302 void ScalarEnumerationTraits
<MethodKind
>::enumeration(IO
&IO
,
304 IO
.enumCase(Kind
, "Vanilla", MethodKind::Vanilla
);
305 IO
.enumCase(Kind
, "Virtual", MethodKind::Virtual
);
306 IO
.enumCase(Kind
, "Static", MethodKind::Static
);
307 IO
.enumCase(Kind
, "Friend", MethodKind::Friend
);
308 IO
.enumCase(Kind
, "IntroducingVirtual", MethodKind::IntroducingVirtual
);
309 IO
.enumCase(Kind
, "PureVirtual", MethodKind::PureVirtual
);
310 IO
.enumCase(Kind
, "PureIntroducingVirtual",
311 MethodKind::PureIntroducingVirtual
);
314 void ScalarEnumerationTraits
<WindowsRTClassKind
>::enumeration(
315 IO
&IO
, WindowsRTClassKind
&Value
) {
316 IO
.enumCase(Value
, "None", WindowsRTClassKind::None
);
317 IO
.enumCase(Value
, "Ref", WindowsRTClassKind::RefClass
);
318 IO
.enumCase(Value
, "Value", WindowsRTClassKind::ValueClass
);
319 IO
.enumCase(Value
, "Interface", WindowsRTClassKind::Interface
);
322 void ScalarEnumerationTraits
<LabelType
>::enumeration(IO
&IO
, LabelType
&Value
) {
323 IO
.enumCase(Value
, "Near", LabelType::Near
);
324 IO
.enumCase(Value
, "Far", LabelType::Far
);
327 void ScalarBitSetTraits
<PointerOptions
>::bitset(IO
&IO
,
328 PointerOptions
&Options
) {
329 IO
.bitSetCase(Options
, "None", PointerOptions::None
);
330 IO
.bitSetCase(Options
, "Flat32", PointerOptions::Flat32
);
331 IO
.bitSetCase(Options
, "Volatile", PointerOptions::Volatile
);
332 IO
.bitSetCase(Options
, "Const", PointerOptions::Const
);
333 IO
.bitSetCase(Options
, "Unaligned", PointerOptions::Unaligned
);
334 IO
.bitSetCase(Options
, "Restrict", PointerOptions::Restrict
);
335 IO
.bitSetCase(Options
, "WinRTSmartPointer",
336 PointerOptions::WinRTSmartPointer
);
339 void ScalarBitSetTraits
<ModifierOptions
>::bitset(IO
&IO
,
340 ModifierOptions
&Options
) {
341 IO
.bitSetCase(Options
, "None", ModifierOptions::None
);
342 IO
.bitSetCase(Options
, "Const", ModifierOptions::Const
);
343 IO
.bitSetCase(Options
, "Volatile", ModifierOptions::Volatile
);
344 IO
.bitSetCase(Options
, "Unaligned", ModifierOptions::Unaligned
);
347 void ScalarBitSetTraits
<FunctionOptions
>::bitset(IO
&IO
,
348 FunctionOptions
&Options
) {
349 IO
.bitSetCase(Options
, "None", FunctionOptions::None
);
350 IO
.bitSetCase(Options
, "CxxReturnUdt", FunctionOptions::CxxReturnUdt
);
351 IO
.bitSetCase(Options
, "Constructor", FunctionOptions::Constructor
);
352 IO
.bitSetCase(Options
, "ConstructorWithVirtualBases",
353 FunctionOptions::ConstructorWithVirtualBases
);
356 void ScalarBitSetTraits
<ClassOptions
>::bitset(IO
&IO
, ClassOptions
&Options
) {
357 IO
.bitSetCase(Options
, "None", ClassOptions::None
);
358 IO
.bitSetCase(Options
, "HasConstructorOrDestructor",
359 ClassOptions::HasConstructorOrDestructor
);
360 IO
.bitSetCase(Options
, "HasOverloadedOperator",
361 ClassOptions::HasOverloadedOperator
);
362 IO
.bitSetCase(Options
, "Nested", ClassOptions::Nested
);
363 IO
.bitSetCase(Options
, "ContainsNestedClass",
364 ClassOptions::ContainsNestedClass
);
365 IO
.bitSetCase(Options
, "HasOverloadedAssignmentOperator",
366 ClassOptions::HasOverloadedAssignmentOperator
);
367 IO
.bitSetCase(Options
, "HasConversionOperator",
368 ClassOptions::HasConversionOperator
);
369 IO
.bitSetCase(Options
, "ForwardReference", ClassOptions::ForwardReference
);
370 IO
.bitSetCase(Options
, "Scoped", ClassOptions::Scoped
);
371 IO
.bitSetCase(Options
, "HasUniqueName", ClassOptions::HasUniqueName
);
372 IO
.bitSetCase(Options
, "Sealed", ClassOptions::Sealed
);
373 IO
.bitSetCase(Options
, "Intrinsic", ClassOptions::Intrinsic
);
376 void ScalarBitSetTraits
<MethodOptions
>::bitset(IO
&IO
, MethodOptions
&Options
) {
377 IO
.bitSetCase(Options
, "None", MethodOptions::None
);
378 IO
.bitSetCase(Options
, "Pseudo", MethodOptions::Pseudo
);
379 IO
.bitSetCase(Options
, "NoInherit", MethodOptions::NoInherit
);
380 IO
.bitSetCase(Options
, "NoConstruct", MethodOptions::NoConstruct
);
381 IO
.bitSetCase(Options
, "CompilerGenerated", MethodOptions::CompilerGenerated
);
382 IO
.bitSetCase(Options
, "Sealed", MethodOptions::Sealed
);
385 void MappingTraits
<MemberPointerInfo
>::mapping(IO
&IO
, MemberPointerInfo
&MPI
) {
386 IO
.mapRequired("ContainingType", MPI
.ContainingType
);
387 IO
.mapRequired("Representation", MPI
.Representation
);
391 namespace CodeViewYAML
{
394 template <> void LeafRecordImpl
<ModifierRecord
>::map(IO
&IO
) {
395 IO
.mapRequired("ModifiedType", Record
.ModifiedType
);
396 IO
.mapRequired("Modifiers", Record
.Modifiers
);
399 template <> void LeafRecordImpl
<ProcedureRecord
>::map(IO
&IO
) {
400 IO
.mapRequired("ReturnType", Record
.ReturnType
);
401 IO
.mapRequired("CallConv", Record
.CallConv
);
402 IO
.mapRequired("Options", Record
.Options
);
403 IO
.mapRequired("ParameterCount", Record
.ParameterCount
);
404 IO
.mapRequired("ArgumentList", Record
.ArgumentList
);
407 template <> void LeafRecordImpl
<MemberFunctionRecord
>::map(IO
&IO
) {
408 IO
.mapRequired("ReturnType", Record
.ReturnType
);
409 IO
.mapRequired("ClassType", Record
.ClassType
);
410 IO
.mapRequired("ThisType", Record
.ThisType
);
411 IO
.mapRequired("CallConv", Record
.CallConv
);
412 IO
.mapRequired("Options", Record
.Options
);
413 IO
.mapRequired("ParameterCount", Record
.ParameterCount
);
414 IO
.mapRequired("ArgumentList", Record
.ArgumentList
);
415 IO
.mapRequired("ThisPointerAdjustment", Record
.ThisPointerAdjustment
);
418 template <> void LeafRecordImpl
<LabelRecord
>::map(IO
&IO
) {
419 IO
.mapRequired("Mode", Record
.Mode
);
422 template <> void LeafRecordImpl
<MemberFuncIdRecord
>::map(IO
&IO
) {
423 IO
.mapRequired("ClassType", Record
.ClassType
);
424 IO
.mapRequired("FunctionType", Record
.FunctionType
);
425 IO
.mapRequired("Name", Record
.Name
);
428 template <> void LeafRecordImpl
<ArgListRecord
>::map(IO
&IO
) {
429 IO
.mapRequired("ArgIndices", Record
.ArgIndices
);
432 template <> void LeafRecordImpl
<StringListRecord
>::map(IO
&IO
) {
433 IO
.mapRequired("StringIndices", Record
.StringIndices
);
436 template <> void LeafRecordImpl
<PointerRecord
>::map(IO
&IO
) {
437 IO
.mapRequired("ReferentType", Record
.ReferentType
);
438 IO
.mapRequired("Attrs", Record
.Attrs
);
439 IO
.mapOptional("MemberInfo", Record
.MemberInfo
);
442 template <> void LeafRecordImpl
<ArrayRecord
>::map(IO
&IO
) {
443 IO
.mapRequired("ElementType", Record
.ElementType
);
444 IO
.mapRequired("IndexType", Record
.IndexType
);
445 IO
.mapRequired("Size", Record
.Size
);
446 IO
.mapRequired("Name", Record
.Name
);
449 void LeafRecordImpl
<FieldListRecord
>::map(IO
&IO
) {
450 IO
.mapRequired("FieldList", Members
);
453 } // end namespace detail
454 } // end namespace CodeViewYAML
455 } // end namespace llvm
459 class MemberRecordConversionVisitor
: public TypeVisitorCallbacks
{
461 explicit MemberRecordConversionVisitor(std::vector
<MemberRecord
> &Records
)
462 : Records(Records
) {}
464 #define TYPE_RECORD(EnumName, EnumVal, Name)
465 #define MEMBER_RECORD(EnumName, EnumVal, Name) \
466 Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
467 return visitKnownMemberImpl(Record); \
469 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
470 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
471 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
473 template <typename T
> Error
visitKnownMemberImpl(T
&Record
) {
474 TypeLeafKind K
= static_cast<TypeLeafKind
>(Record
.getKind());
475 auto Impl
= std::make_shared
<MemberRecordImpl
<T
>>(K
);
476 Impl
->Record
= Record
;
477 Records
.push_back(MemberRecord
{Impl
});
478 return Error::success();
481 std::vector
<MemberRecord
> &Records
;
484 } // end anonymous namespace
486 Error LeafRecordImpl
<FieldListRecord
>::fromCodeViewRecord(CVType Type
) {
487 MemberRecordConversionVisitor
V(Members
);
488 return visitMemberRecordStream(Type
.content(), V
);
491 CVType LeafRecordImpl
<FieldListRecord
>::toCodeViewRecord(
492 AppendingTypeTableBuilder
&TS
) const {
493 ContinuationRecordBuilder CRB
;
494 CRB
.begin(ContinuationRecordKind::FieldList
);
495 for (const auto &Member
: Members
) {
496 Member
.Member
->writeTo(CRB
);
498 TS
.insertRecord(CRB
);
499 return CVType(TS
.records().back());
502 void MappingTraits
<OneMethodRecord
>::mapping(IO
&io
, OneMethodRecord
&Record
) {
503 io
.mapRequired("Type", Record
.Type
);
504 io
.mapRequired("Attrs", Record
.Attrs
.Attrs
);
505 io
.mapRequired("VFTableOffset", Record
.VFTableOffset
);
506 io
.mapRequired("Name", Record
.Name
);
510 namespace CodeViewYAML
{
513 template <> void LeafRecordImpl
<ClassRecord
>::map(IO
&IO
) {
514 IO
.mapRequired("MemberCount", Record
.MemberCount
);
515 IO
.mapRequired("Options", Record
.Options
);
516 IO
.mapRequired("FieldList", Record
.FieldList
);
517 IO
.mapRequired("Name", Record
.Name
);
518 IO
.mapRequired("UniqueName", Record
.UniqueName
);
519 IO
.mapRequired("DerivationList", Record
.DerivationList
);
520 IO
.mapRequired("VTableShape", Record
.VTableShape
);
521 IO
.mapRequired("Size", Record
.Size
);
524 template <> void LeafRecordImpl
<UnionRecord
>::map(IO
&IO
) {
525 IO
.mapRequired("MemberCount", Record
.MemberCount
);
526 IO
.mapRequired("Options", Record
.Options
);
527 IO
.mapRequired("FieldList", Record
.FieldList
);
528 IO
.mapRequired("Name", Record
.Name
);
529 IO
.mapRequired("UniqueName", Record
.UniqueName
);
530 IO
.mapRequired("Size", Record
.Size
);
533 template <> void LeafRecordImpl
<EnumRecord
>::map(IO
&IO
) {
534 IO
.mapRequired("NumEnumerators", Record
.MemberCount
);
535 IO
.mapRequired("Options", Record
.Options
);
536 IO
.mapRequired("FieldList", Record
.FieldList
);
537 IO
.mapRequired("Name", Record
.Name
);
538 IO
.mapRequired("UniqueName", Record
.UniqueName
);
539 IO
.mapRequired("UnderlyingType", Record
.UnderlyingType
);
542 template <> void LeafRecordImpl
<BitFieldRecord
>::map(IO
&IO
) {
543 IO
.mapRequired("Type", Record
.Type
);
544 IO
.mapRequired("BitSize", Record
.BitSize
);
545 IO
.mapRequired("BitOffset", Record
.BitOffset
);
548 template <> void LeafRecordImpl
<VFTableShapeRecord
>::map(IO
&IO
) {
549 IO
.mapRequired("Slots", Record
.Slots
);
552 template <> void LeafRecordImpl
<TypeServer2Record
>::map(IO
&IO
) {
553 IO
.mapRequired("Guid", Record
.Guid
);
554 IO
.mapRequired("Age", Record
.Age
);
555 IO
.mapRequired("Name", Record
.Name
);
558 template <> void LeafRecordImpl
<StringIdRecord
>::map(IO
&IO
) {
559 IO
.mapRequired("Id", Record
.Id
);
560 IO
.mapRequired("String", Record
.String
);
563 template <> void LeafRecordImpl
<FuncIdRecord
>::map(IO
&IO
) {
564 IO
.mapRequired("ParentScope", Record
.ParentScope
);
565 IO
.mapRequired("FunctionType", Record
.FunctionType
);
566 IO
.mapRequired("Name", Record
.Name
);
569 template <> void LeafRecordImpl
<UdtSourceLineRecord
>::map(IO
&IO
) {
570 IO
.mapRequired("UDT", Record
.UDT
);
571 IO
.mapRequired("SourceFile", Record
.SourceFile
);
572 IO
.mapRequired("LineNumber", Record
.LineNumber
);
575 template <> void LeafRecordImpl
<UdtModSourceLineRecord
>::map(IO
&IO
) {
576 IO
.mapRequired("UDT", Record
.UDT
);
577 IO
.mapRequired("SourceFile", Record
.SourceFile
);
578 IO
.mapRequired("LineNumber", Record
.LineNumber
);
579 IO
.mapRequired("Module", Record
.Module
);
582 template <> void LeafRecordImpl
<BuildInfoRecord
>::map(IO
&IO
) {
583 IO
.mapRequired("ArgIndices", Record
.ArgIndices
);
586 template <> void LeafRecordImpl
<VFTableRecord
>::map(IO
&IO
) {
587 IO
.mapRequired("CompleteClass", Record
.CompleteClass
);
588 IO
.mapRequired("OverriddenVFTable", Record
.OverriddenVFTable
);
589 IO
.mapRequired("VFPtrOffset", Record
.VFPtrOffset
);
590 IO
.mapRequired("MethodNames", Record
.MethodNames
);
593 template <> void LeafRecordImpl
<MethodOverloadListRecord
>::map(IO
&IO
) {
594 IO
.mapRequired("Methods", Record
.Methods
);
597 template <> void LeafRecordImpl
<PrecompRecord
>::map(IO
&IO
) {
598 IO
.mapRequired("StartTypeIndex", Record
.StartTypeIndex
);
599 IO
.mapRequired("TypesCount", Record
.TypesCount
);
600 IO
.mapRequired("Signature", Record
.Signature
);
601 IO
.mapRequired("PrecompFilePath", Record
.PrecompFilePath
);
604 template <> void LeafRecordImpl
<EndPrecompRecord
>::map(IO
&IO
) {
605 IO
.mapRequired("Signature", Record
.Signature
);
608 template <> void MemberRecordImpl
<OneMethodRecord
>::map(IO
&IO
) {
609 MappingTraits
<OneMethodRecord
>::mapping(IO
, Record
);
612 template <> void MemberRecordImpl
<OverloadedMethodRecord
>::map(IO
&IO
) {
613 IO
.mapRequired("NumOverloads", Record
.NumOverloads
);
614 IO
.mapRequired("MethodList", Record
.MethodList
);
615 IO
.mapRequired("Name", Record
.Name
);
618 template <> void MemberRecordImpl
<NestedTypeRecord
>::map(IO
&IO
) {
619 IO
.mapRequired("Type", Record
.Type
);
620 IO
.mapRequired("Name", Record
.Name
);
623 template <> void MemberRecordImpl
<DataMemberRecord
>::map(IO
&IO
) {
624 IO
.mapRequired("Attrs", Record
.Attrs
.Attrs
);
625 IO
.mapRequired("Type", Record
.Type
);
626 IO
.mapRequired("FieldOffset", Record
.FieldOffset
);
627 IO
.mapRequired("Name", Record
.Name
);
630 template <> void MemberRecordImpl
<StaticDataMemberRecord
>::map(IO
&IO
) {
631 IO
.mapRequired("Attrs", Record
.Attrs
.Attrs
);
632 IO
.mapRequired("Type", Record
.Type
);
633 IO
.mapRequired("Name", Record
.Name
);
636 template <> void MemberRecordImpl
<EnumeratorRecord
>::map(IO
&IO
) {
637 IO
.mapRequired("Attrs", Record
.Attrs
.Attrs
);
638 IO
.mapRequired("Value", Record
.Value
);
639 IO
.mapRequired("Name", Record
.Name
);
642 template <> void MemberRecordImpl
<VFPtrRecord
>::map(IO
&IO
) {
643 IO
.mapRequired("Type", Record
.Type
);
646 template <> void MemberRecordImpl
<BaseClassRecord
>::map(IO
&IO
) {
647 IO
.mapRequired("Attrs", Record
.Attrs
.Attrs
);
648 IO
.mapRequired("Type", Record
.Type
);
649 IO
.mapRequired("Offset", Record
.Offset
);
652 template <> void MemberRecordImpl
<VirtualBaseClassRecord
>::map(IO
&IO
) {
653 IO
.mapRequired("Attrs", Record
.Attrs
.Attrs
);
654 IO
.mapRequired("BaseType", Record
.BaseType
);
655 IO
.mapRequired("VBPtrType", Record
.VBPtrType
);
656 IO
.mapRequired("VBPtrOffset", Record
.VBPtrOffset
);
657 IO
.mapRequired("VTableIndex", Record
.VTableIndex
);
660 template <> void MemberRecordImpl
<ListContinuationRecord
>::map(IO
&IO
) {
661 IO
.mapRequired("ContinuationIndex", Record
.ContinuationIndex
);
664 } // end namespace detail
665 } // end namespace CodeViewYAML
666 } // end namespace llvm
668 template <typename T
>
669 static inline Expected
<LeafRecord
> fromCodeViewRecordImpl(CVType Type
) {
672 auto Impl
= std::make_shared
<LeafRecordImpl
<T
>>(Type
.kind());
673 if (auto EC
= Impl
->fromCodeViewRecord(Type
))
674 return std::move(EC
);
679 Expected
<LeafRecord
> LeafRecord::fromCodeViewRecord(CVType Type
) {
680 #define TYPE_RECORD(EnumName, EnumVal, ClassName) \
682 return fromCodeViewRecordImpl<ClassName##Record>(Type);
683 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
684 TYPE_RECORD(EnumName, EnumVal, ClassName)
685 #define MEMBER_RECORD(EnumName, EnumVal, ClassName)
686 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
687 switch (Type
.kind()) {
688 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
690 llvm_unreachable("Unknown leaf kind!");
692 return make_error
<CodeViewError
>(cv_error_code::corrupt_record
);
696 LeafRecord::toCodeViewRecord(AppendingTypeTableBuilder
&Serializer
) const {
697 return Leaf
->toCodeViewRecord(Serializer
);
703 template <> struct MappingTraits
<LeafRecordBase
> {
704 static void mapping(IO
&io
, LeafRecordBase
&Record
) { Record
.map(io
); }
707 template <> struct MappingTraits
<MemberRecordBase
> {
708 static void mapping(IO
&io
, MemberRecordBase
&Record
) { Record
.map(io
); }
711 } // end namespace yaml
712 } // end namespace llvm
714 template <typename ConcreteType
>
715 static void mapLeafRecordImpl(IO
&IO
, const char *Class
, TypeLeafKind Kind
,
717 if (!IO
.outputting())
718 Obj
.Leaf
= std::make_shared
<LeafRecordImpl
<ConcreteType
>>(Kind
);
720 if (Kind
== LF_FIELDLIST
)
723 IO
.mapRequired(Class
, *Obj
.Leaf
);
726 void MappingTraits
<LeafRecord
>::mapping(IO
&IO
, LeafRecord
&Obj
) {
729 Kind
= Obj
.Leaf
->Kind
;
730 IO
.mapRequired("Kind", Kind
);
732 #define TYPE_RECORD(EnumName, EnumVal, ClassName) \
734 mapLeafRecordImpl<ClassName##Record>(IO, #ClassName, Kind, Obj); \
736 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
737 TYPE_RECORD(EnumName, EnumVal, ClassName)
738 #define MEMBER_RECORD(EnumName, EnumVal, ClassName)
739 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
741 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
742 default: { llvm_unreachable("Unknown leaf kind!"); }
746 template <typename ConcreteType
>
747 static void mapMemberRecordImpl(IO
&IO
, const char *Class
, TypeLeafKind Kind
,
749 if (!IO
.outputting())
750 Obj
.Member
= std::make_shared
<MemberRecordImpl
<ConcreteType
>>(Kind
);
752 IO
.mapRequired(Class
, *Obj
.Member
);
755 void MappingTraits
<MemberRecord
>::mapping(IO
&IO
, MemberRecord
&Obj
) {
758 Kind
= Obj
.Member
->Kind
;
759 IO
.mapRequired("Kind", Kind
);
761 #define MEMBER_RECORD(EnumName, EnumVal, ClassName) \
763 mapMemberRecordImpl<ClassName##Record>(IO, #ClassName, Kind, Obj); \
765 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
766 MEMBER_RECORD(EnumName, EnumVal, ClassName)
767 #define TYPE_RECORD(EnumName, EnumVal, ClassName)
768 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
770 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
771 default: { llvm_unreachable("Unknown member kind!"); }
775 std::vector
<LeafRecord
>
776 llvm::CodeViewYAML::fromDebugT(ArrayRef
<uint8_t> DebugTorP
,
777 StringRef SectionName
) {
778 ExitOnError
Err("Invalid " + std::string(SectionName
) + " section!");
779 BinaryStreamReader
Reader(DebugTorP
, support::little
);
783 Err(Reader
.readInteger(Magic
));
784 assert(Magic
== COFF::DEBUG_SECTION_MAGIC
&&
785 "Invalid .debug$T or .debug$P section!");
787 std::vector
<LeafRecord
> Result
;
788 Err(Reader
.readArray(Types
, Reader
.bytesRemaining()));
789 for (const auto &T
: Types
) {
790 auto CVT
= Err(LeafRecord::fromCodeViewRecord(T
));
791 Result
.push_back(CVT
);
796 ArrayRef
<uint8_t> llvm::CodeViewYAML::toDebugT(ArrayRef
<LeafRecord
> Leafs
,
797 BumpPtrAllocator
&Alloc
,
798 StringRef SectionName
) {
799 AppendingTypeTableBuilder
TS(Alloc
);
800 uint32_t Size
= sizeof(uint32_t);
801 for (const auto &Leaf
: Leafs
) {
802 CVType T
= Leaf
.Leaf
->toCodeViewRecord(TS
);
804 assert(T
.length() % 4 == 0 && "Improper type record alignment!");
806 uint8_t *ResultBuffer
= Alloc
.Allocate
<uint8_t>(Size
);
807 MutableArrayRef
<uint8_t> Output(ResultBuffer
, Size
);
808 BinaryStreamWriter
Writer(Output
, support::little
);
809 ExitOnError
Err("Error writing type record to " + std::string(SectionName
) +
811 Err(Writer
.writeInteger
<uint32_t>(COFF::DEBUG_SECTION_MAGIC
));
812 for (const auto &R
: TS
.records()) {
813 Err(Writer
.writeBytes(R
));
815 assert(Writer
.bytesRemaining() == 0 && "Didn't write all type record bytes!");