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
.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";
160 support::ulittle32_t Data1
;
161 support::ulittle16_t Data2
;
162 support::ulittle16_t Data3
;
163 support::ubig64_t Data4
;
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
));
176 void ScalarTraits
<TypeIndex
>::output(const TypeIndex
&S
, void *,
181 StringRef ScalarTraits
<TypeIndex
>::input(StringRef Scalar
, void *Ctx
,
184 StringRef Result
= ScalarTraits
<uint32_t>::input(Scalar
, Ctx
, I
);
189 void ScalarTraits
<APSInt
>::output(const APSInt
&S
, void *, raw_ostream
&OS
) {
190 S
.print(OS
, S
.isSigned());
193 StringRef ScalarTraits
<APSInt
>::input(StringRef Scalar
, void *Ctx
, APSInt
&S
) {
198 void 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"
205 void 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
);
225 void 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
);
236 void 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 IO
.enumCase(Value
, "Swift", CallingConvention::Swift
);
265 void ScalarEnumerationTraits
<PointerKind
>::enumeration(IO
&IO
,
267 IO
.enumCase(Kind
, "Near16", PointerKind::Near16
);
268 IO
.enumCase(Kind
, "Far16", PointerKind::Far16
);
269 IO
.enumCase(Kind
, "Huge16", PointerKind::Huge16
);
270 IO
.enumCase(Kind
, "BasedOnSegment", PointerKind::BasedOnSegment
);
271 IO
.enumCase(Kind
, "BasedOnValue", PointerKind::BasedOnValue
);
272 IO
.enumCase(Kind
, "BasedOnSegmentValue", PointerKind::BasedOnSegmentValue
);
273 IO
.enumCase(Kind
, "BasedOnAddress", PointerKind::BasedOnAddress
);
274 IO
.enumCase(Kind
, "BasedOnSegmentAddress",
275 PointerKind::BasedOnSegmentAddress
);
276 IO
.enumCase(Kind
, "BasedOnType", PointerKind::BasedOnType
);
277 IO
.enumCase(Kind
, "BasedOnSelf", PointerKind::BasedOnSelf
);
278 IO
.enumCase(Kind
, "Near32", PointerKind::Near32
);
279 IO
.enumCase(Kind
, "Far32", PointerKind::Far32
);
280 IO
.enumCase(Kind
, "Near64", PointerKind::Near64
);
283 void ScalarEnumerationTraits
<PointerMode
>::enumeration(IO
&IO
,
285 IO
.enumCase(Mode
, "Pointer", PointerMode::Pointer
);
286 IO
.enumCase(Mode
, "LValueReference", PointerMode::LValueReference
);
287 IO
.enumCase(Mode
, "PointerToDataMember", PointerMode::PointerToDataMember
);
288 IO
.enumCase(Mode
, "PointerToMemberFunction",
289 PointerMode::PointerToMemberFunction
);
290 IO
.enumCase(Mode
, "RValueReference", PointerMode::RValueReference
);
293 void ScalarEnumerationTraits
<HfaKind
>::enumeration(IO
&IO
, HfaKind
&Value
) {
294 IO
.enumCase(Value
, "None", HfaKind::None
);
295 IO
.enumCase(Value
, "Float", HfaKind::Float
);
296 IO
.enumCase(Value
, "Double", HfaKind::Double
);
297 IO
.enumCase(Value
, "Other", HfaKind::Other
);
300 void ScalarEnumerationTraits
<MemberAccess
>::enumeration(IO
&IO
,
301 MemberAccess
&Access
) {
302 IO
.enumCase(Access
, "None", MemberAccess::None
);
303 IO
.enumCase(Access
, "Private", MemberAccess::Private
);
304 IO
.enumCase(Access
, "Protected", MemberAccess::Protected
);
305 IO
.enumCase(Access
, "Public", MemberAccess::Public
);
308 void ScalarEnumerationTraits
<MethodKind
>::enumeration(IO
&IO
,
310 IO
.enumCase(Kind
, "Vanilla", MethodKind::Vanilla
);
311 IO
.enumCase(Kind
, "Virtual", MethodKind::Virtual
);
312 IO
.enumCase(Kind
, "Static", MethodKind::Static
);
313 IO
.enumCase(Kind
, "Friend", MethodKind::Friend
);
314 IO
.enumCase(Kind
, "IntroducingVirtual", MethodKind::IntroducingVirtual
);
315 IO
.enumCase(Kind
, "PureVirtual", MethodKind::PureVirtual
);
316 IO
.enumCase(Kind
, "PureIntroducingVirtual",
317 MethodKind::PureIntroducingVirtual
);
320 void ScalarEnumerationTraits
<WindowsRTClassKind
>::enumeration(
321 IO
&IO
, WindowsRTClassKind
&Value
) {
322 IO
.enumCase(Value
, "None", WindowsRTClassKind::None
);
323 IO
.enumCase(Value
, "Ref", WindowsRTClassKind::RefClass
);
324 IO
.enumCase(Value
, "Value", WindowsRTClassKind::ValueClass
);
325 IO
.enumCase(Value
, "Interface", WindowsRTClassKind::Interface
);
328 void ScalarEnumerationTraits
<LabelType
>::enumeration(IO
&IO
, LabelType
&Value
) {
329 IO
.enumCase(Value
, "Near", LabelType::Near
);
330 IO
.enumCase(Value
, "Far", LabelType::Far
);
333 void ScalarBitSetTraits
<PointerOptions
>::bitset(IO
&IO
,
334 PointerOptions
&Options
) {
335 IO
.bitSetCase(Options
, "None", PointerOptions::None
);
336 IO
.bitSetCase(Options
, "Flat32", PointerOptions::Flat32
);
337 IO
.bitSetCase(Options
, "Volatile", PointerOptions::Volatile
);
338 IO
.bitSetCase(Options
, "Const", PointerOptions::Const
);
339 IO
.bitSetCase(Options
, "Unaligned", PointerOptions::Unaligned
);
340 IO
.bitSetCase(Options
, "Restrict", PointerOptions::Restrict
);
341 IO
.bitSetCase(Options
, "WinRTSmartPointer",
342 PointerOptions::WinRTSmartPointer
);
345 void ScalarBitSetTraits
<ModifierOptions
>::bitset(IO
&IO
,
346 ModifierOptions
&Options
) {
347 IO
.bitSetCase(Options
, "None", ModifierOptions::None
);
348 IO
.bitSetCase(Options
, "Const", ModifierOptions::Const
);
349 IO
.bitSetCase(Options
, "Volatile", ModifierOptions::Volatile
);
350 IO
.bitSetCase(Options
, "Unaligned", ModifierOptions::Unaligned
);
353 void ScalarBitSetTraits
<FunctionOptions
>::bitset(IO
&IO
,
354 FunctionOptions
&Options
) {
355 IO
.bitSetCase(Options
, "None", FunctionOptions::None
);
356 IO
.bitSetCase(Options
, "CxxReturnUdt", FunctionOptions::CxxReturnUdt
);
357 IO
.bitSetCase(Options
, "Constructor", FunctionOptions::Constructor
);
358 IO
.bitSetCase(Options
, "ConstructorWithVirtualBases",
359 FunctionOptions::ConstructorWithVirtualBases
);
362 void ScalarBitSetTraits
<ClassOptions
>::bitset(IO
&IO
, ClassOptions
&Options
) {
363 IO
.bitSetCase(Options
, "None", ClassOptions::None
);
364 IO
.bitSetCase(Options
, "HasConstructorOrDestructor",
365 ClassOptions::HasConstructorOrDestructor
);
366 IO
.bitSetCase(Options
, "HasOverloadedOperator",
367 ClassOptions::HasOverloadedOperator
);
368 IO
.bitSetCase(Options
, "Nested", ClassOptions::Nested
);
369 IO
.bitSetCase(Options
, "ContainsNestedClass",
370 ClassOptions::ContainsNestedClass
);
371 IO
.bitSetCase(Options
, "HasOverloadedAssignmentOperator",
372 ClassOptions::HasOverloadedAssignmentOperator
);
373 IO
.bitSetCase(Options
, "HasConversionOperator",
374 ClassOptions::HasConversionOperator
);
375 IO
.bitSetCase(Options
, "ForwardReference", ClassOptions::ForwardReference
);
376 IO
.bitSetCase(Options
, "Scoped", ClassOptions::Scoped
);
377 IO
.bitSetCase(Options
, "HasUniqueName", ClassOptions::HasUniqueName
);
378 IO
.bitSetCase(Options
, "Sealed", ClassOptions::Sealed
);
379 IO
.bitSetCase(Options
, "Intrinsic", ClassOptions::Intrinsic
);
382 void ScalarBitSetTraits
<MethodOptions
>::bitset(IO
&IO
, MethodOptions
&Options
) {
383 IO
.bitSetCase(Options
, "None", MethodOptions::None
);
384 IO
.bitSetCase(Options
, "Pseudo", MethodOptions::Pseudo
);
385 IO
.bitSetCase(Options
, "NoInherit", MethodOptions::NoInherit
);
386 IO
.bitSetCase(Options
, "NoConstruct", MethodOptions::NoConstruct
);
387 IO
.bitSetCase(Options
, "CompilerGenerated", MethodOptions::CompilerGenerated
);
388 IO
.bitSetCase(Options
, "Sealed", MethodOptions::Sealed
);
391 void MappingTraits
<MemberPointerInfo
>::mapping(IO
&IO
, MemberPointerInfo
&MPI
) {
392 IO
.mapRequired("ContainingType", MPI
.ContainingType
);
393 IO
.mapRequired("Representation", MPI
.Representation
);
397 namespace CodeViewYAML
{
400 template <> void LeafRecordImpl
<ModifierRecord
>::map(IO
&IO
) {
401 IO
.mapRequired("ModifiedType", Record
.ModifiedType
);
402 IO
.mapRequired("Modifiers", Record
.Modifiers
);
405 template <> void LeafRecordImpl
<ProcedureRecord
>::map(IO
&IO
) {
406 IO
.mapRequired("ReturnType", Record
.ReturnType
);
407 IO
.mapRequired("CallConv", Record
.CallConv
);
408 IO
.mapRequired("Options", Record
.Options
);
409 IO
.mapRequired("ParameterCount", Record
.ParameterCount
);
410 IO
.mapRequired("ArgumentList", Record
.ArgumentList
);
413 template <> void LeafRecordImpl
<MemberFunctionRecord
>::map(IO
&IO
) {
414 IO
.mapRequired("ReturnType", Record
.ReturnType
);
415 IO
.mapRequired("ClassType", Record
.ClassType
);
416 IO
.mapRequired("ThisType", Record
.ThisType
);
417 IO
.mapRequired("CallConv", Record
.CallConv
);
418 IO
.mapRequired("Options", Record
.Options
);
419 IO
.mapRequired("ParameterCount", Record
.ParameterCount
);
420 IO
.mapRequired("ArgumentList", Record
.ArgumentList
);
421 IO
.mapRequired("ThisPointerAdjustment", Record
.ThisPointerAdjustment
);
424 template <> void LeafRecordImpl
<LabelRecord
>::map(IO
&IO
) {
425 IO
.mapRequired("Mode", Record
.Mode
);
428 template <> void LeafRecordImpl
<MemberFuncIdRecord
>::map(IO
&IO
) {
429 IO
.mapRequired("ClassType", Record
.ClassType
);
430 IO
.mapRequired("FunctionType", Record
.FunctionType
);
431 IO
.mapRequired("Name", Record
.Name
);
434 template <> void LeafRecordImpl
<ArgListRecord
>::map(IO
&IO
) {
435 IO
.mapRequired("ArgIndices", Record
.ArgIndices
);
438 template <> void LeafRecordImpl
<StringListRecord
>::map(IO
&IO
) {
439 IO
.mapRequired("StringIndices", Record
.StringIndices
);
442 template <> void LeafRecordImpl
<PointerRecord
>::map(IO
&IO
) {
443 IO
.mapRequired("ReferentType", Record
.ReferentType
);
444 IO
.mapRequired("Attrs", Record
.Attrs
);
445 IO
.mapOptional("MemberInfo", Record
.MemberInfo
);
448 template <> void LeafRecordImpl
<ArrayRecord
>::map(IO
&IO
) {
449 IO
.mapRequired("ElementType", Record
.ElementType
);
450 IO
.mapRequired("IndexType", Record
.IndexType
);
451 IO
.mapRequired("Size", Record
.Size
);
452 IO
.mapRequired("Name", Record
.Name
);
455 void LeafRecordImpl
<FieldListRecord
>::map(IO
&IO
) {
456 IO
.mapRequired("FieldList", Members
);
459 } // end namespace detail
460 } // end namespace CodeViewYAML
461 } // end namespace llvm
465 class MemberRecordConversionVisitor
: public TypeVisitorCallbacks
{
467 explicit MemberRecordConversionVisitor(std::vector
<MemberRecord
> &Records
)
468 : Records(Records
) {}
470 #define TYPE_RECORD(EnumName, EnumVal, Name)
471 #define MEMBER_RECORD(EnumName, EnumVal, Name) \
472 Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
473 return visitKnownMemberImpl(Record); \
475 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
476 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
477 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
479 template <typename T
> Error
visitKnownMemberImpl(T
&Record
) {
480 TypeLeafKind K
= static_cast<TypeLeafKind
>(Record
.getKind());
481 auto Impl
= std::make_shared
<MemberRecordImpl
<T
>>(K
);
482 Impl
->Record
= Record
;
483 Records
.push_back(MemberRecord
{Impl
});
484 return Error::success();
487 std::vector
<MemberRecord
> &Records
;
490 } // end anonymous namespace
492 Error LeafRecordImpl
<FieldListRecord
>::fromCodeViewRecord(CVType Type
) {
493 MemberRecordConversionVisitor
V(Members
);
494 FieldListRecord FieldList
;
495 cantFail(TypeDeserializer::deserializeAs
<FieldListRecord
>(Type
,
497 return visitMemberRecordStream(FieldList
.Data
, V
);
500 CVType LeafRecordImpl
<FieldListRecord
>::toCodeViewRecord(
501 AppendingTypeTableBuilder
&TS
) const {
502 ContinuationRecordBuilder CRB
;
503 CRB
.begin(ContinuationRecordKind::FieldList
);
504 for (const auto &Member
: Members
) {
505 Member
.Member
->writeTo(CRB
);
507 TS
.insertRecord(CRB
);
508 return CVType(TS
.records().back());
511 void MappingTraits
<OneMethodRecord
>::mapping(IO
&io
, OneMethodRecord
&Record
) {
512 io
.mapRequired("Type", Record
.Type
);
513 io
.mapRequired("Attrs", Record
.Attrs
.Attrs
);
514 io
.mapRequired("VFTableOffset", Record
.VFTableOffset
);
515 io
.mapRequired("Name", Record
.Name
);
519 namespace CodeViewYAML
{
522 template <> void LeafRecordImpl
<ClassRecord
>::map(IO
&IO
) {
523 IO
.mapRequired("MemberCount", Record
.MemberCount
);
524 IO
.mapRequired("Options", Record
.Options
);
525 IO
.mapRequired("FieldList", Record
.FieldList
);
526 IO
.mapRequired("Name", Record
.Name
);
527 IO
.mapRequired("UniqueName", Record
.UniqueName
);
528 IO
.mapRequired("DerivationList", Record
.DerivationList
);
529 IO
.mapRequired("VTableShape", Record
.VTableShape
);
530 IO
.mapRequired("Size", Record
.Size
);
533 template <> void LeafRecordImpl
<UnionRecord
>::map(IO
&IO
) {
534 IO
.mapRequired("MemberCount", 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("Size", Record
.Size
);
542 template <> void LeafRecordImpl
<EnumRecord
>::map(IO
&IO
) {
543 IO
.mapRequired("NumEnumerators", Record
.MemberCount
);
544 IO
.mapRequired("Options", Record
.Options
);
545 IO
.mapRequired("FieldList", Record
.FieldList
);
546 IO
.mapRequired("Name", Record
.Name
);
547 IO
.mapRequired("UniqueName", Record
.UniqueName
);
548 IO
.mapRequired("UnderlyingType", Record
.UnderlyingType
);
551 template <> void LeafRecordImpl
<BitFieldRecord
>::map(IO
&IO
) {
552 IO
.mapRequired("Type", Record
.Type
);
553 IO
.mapRequired("BitSize", Record
.BitSize
);
554 IO
.mapRequired("BitOffset", Record
.BitOffset
);
557 template <> void LeafRecordImpl
<VFTableShapeRecord
>::map(IO
&IO
) {
558 IO
.mapRequired("Slots", Record
.Slots
);
561 template <> void LeafRecordImpl
<TypeServer2Record
>::map(IO
&IO
) {
562 IO
.mapRequired("Guid", Record
.Guid
);
563 IO
.mapRequired("Age", Record
.Age
);
564 IO
.mapRequired("Name", Record
.Name
);
567 template <> void LeafRecordImpl
<StringIdRecord
>::map(IO
&IO
) {
568 IO
.mapRequired("Id", Record
.Id
);
569 IO
.mapRequired("String", Record
.String
);
572 template <> void LeafRecordImpl
<FuncIdRecord
>::map(IO
&IO
) {
573 IO
.mapRequired("ParentScope", Record
.ParentScope
);
574 IO
.mapRequired("FunctionType", Record
.FunctionType
);
575 IO
.mapRequired("Name", Record
.Name
);
578 template <> void LeafRecordImpl
<UdtSourceLineRecord
>::map(IO
&IO
) {
579 IO
.mapRequired("UDT", Record
.UDT
);
580 IO
.mapRequired("SourceFile", Record
.SourceFile
);
581 IO
.mapRequired("LineNumber", Record
.LineNumber
);
584 template <> void LeafRecordImpl
<UdtModSourceLineRecord
>::map(IO
&IO
) {
585 IO
.mapRequired("UDT", Record
.UDT
);
586 IO
.mapRequired("SourceFile", Record
.SourceFile
);
587 IO
.mapRequired("LineNumber", Record
.LineNumber
);
588 IO
.mapRequired("Module", Record
.Module
);
591 template <> void LeafRecordImpl
<BuildInfoRecord
>::map(IO
&IO
) {
592 IO
.mapRequired("ArgIndices", Record
.ArgIndices
);
595 template <> void LeafRecordImpl
<VFTableRecord
>::map(IO
&IO
) {
596 IO
.mapRequired("CompleteClass", Record
.CompleteClass
);
597 IO
.mapRequired("OverriddenVFTable", Record
.OverriddenVFTable
);
598 IO
.mapRequired("VFPtrOffset", Record
.VFPtrOffset
);
599 IO
.mapRequired("MethodNames", Record
.MethodNames
);
602 template <> void LeafRecordImpl
<MethodOverloadListRecord
>::map(IO
&IO
) {
603 IO
.mapRequired("Methods", Record
.Methods
);
606 template <> void LeafRecordImpl
<PrecompRecord
>::map(IO
&IO
) {
607 IO
.mapRequired("StartTypeIndex", Record
.StartTypeIndex
);
608 IO
.mapRequired("TypesCount", Record
.TypesCount
);
609 IO
.mapRequired("Signature", Record
.Signature
);
610 IO
.mapRequired("PrecompFilePath", Record
.PrecompFilePath
);
613 template <> void LeafRecordImpl
<EndPrecompRecord
>::map(IO
&IO
) {
614 IO
.mapRequired("Signature", Record
.Signature
);
617 template <> void MemberRecordImpl
<OneMethodRecord
>::map(IO
&IO
) {
618 MappingTraits
<OneMethodRecord
>::mapping(IO
, Record
);
621 template <> void MemberRecordImpl
<OverloadedMethodRecord
>::map(IO
&IO
) {
622 IO
.mapRequired("NumOverloads", Record
.NumOverloads
);
623 IO
.mapRequired("MethodList", Record
.MethodList
);
624 IO
.mapRequired("Name", Record
.Name
);
627 template <> void MemberRecordImpl
<NestedTypeRecord
>::map(IO
&IO
) {
628 IO
.mapRequired("Type", Record
.Type
);
629 IO
.mapRequired("Name", Record
.Name
);
632 template <> void MemberRecordImpl
<DataMemberRecord
>::map(IO
&IO
) {
633 IO
.mapRequired("Attrs", Record
.Attrs
.Attrs
);
634 IO
.mapRequired("Type", Record
.Type
);
635 IO
.mapRequired("FieldOffset", Record
.FieldOffset
);
636 IO
.mapRequired("Name", Record
.Name
);
639 template <> void MemberRecordImpl
<StaticDataMemberRecord
>::map(IO
&IO
) {
640 IO
.mapRequired("Attrs", Record
.Attrs
.Attrs
);
641 IO
.mapRequired("Type", Record
.Type
);
642 IO
.mapRequired("Name", Record
.Name
);
645 template <> void MemberRecordImpl
<EnumeratorRecord
>::map(IO
&IO
) {
646 IO
.mapRequired("Attrs", Record
.Attrs
.Attrs
);
647 IO
.mapRequired("Value", Record
.Value
);
648 IO
.mapRequired("Name", Record
.Name
);
651 template <> void MemberRecordImpl
<VFPtrRecord
>::map(IO
&IO
) {
652 IO
.mapRequired("Type", Record
.Type
);
655 template <> void MemberRecordImpl
<BaseClassRecord
>::map(IO
&IO
) {
656 IO
.mapRequired("Attrs", Record
.Attrs
.Attrs
);
657 IO
.mapRequired("Type", Record
.Type
);
658 IO
.mapRequired("Offset", Record
.Offset
);
661 template <> void MemberRecordImpl
<VirtualBaseClassRecord
>::map(IO
&IO
) {
662 IO
.mapRequired("Attrs", Record
.Attrs
.Attrs
);
663 IO
.mapRequired("BaseType", Record
.BaseType
);
664 IO
.mapRequired("VBPtrType", Record
.VBPtrType
);
665 IO
.mapRequired("VBPtrOffset", Record
.VBPtrOffset
);
666 IO
.mapRequired("VTableIndex", Record
.VTableIndex
);
669 template <> void MemberRecordImpl
<ListContinuationRecord
>::map(IO
&IO
) {
670 IO
.mapRequired("ContinuationIndex", Record
.ContinuationIndex
);
673 } // end namespace detail
674 } // end namespace CodeViewYAML
675 } // end namespace llvm
677 template <typename T
>
678 static inline Expected
<LeafRecord
> fromCodeViewRecordImpl(CVType Type
) {
681 auto Impl
= std::make_shared
<LeafRecordImpl
<T
>>(Type
.kind());
682 if (auto EC
= Impl
->fromCodeViewRecord(Type
))
683 return std::move(EC
);
688 Expected
<LeafRecord
> LeafRecord::fromCodeViewRecord(CVType Type
) {
689 #define TYPE_RECORD(EnumName, EnumVal, ClassName) \
691 return fromCodeViewRecordImpl<ClassName##Record>(Type);
692 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
693 TYPE_RECORD(EnumName, EnumVal, ClassName)
694 #define MEMBER_RECORD(EnumName, EnumVal, ClassName)
695 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
696 switch (Type
.kind()) {
697 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
699 llvm_unreachable("Unknown leaf kind!");
701 return make_error
<CodeViewError
>(cv_error_code::corrupt_record
);
705 LeafRecord::toCodeViewRecord(AppendingTypeTableBuilder
&Serializer
) const {
706 return Leaf
->toCodeViewRecord(Serializer
);
712 template <> struct MappingTraits
<LeafRecordBase
> {
713 static void mapping(IO
&io
, LeafRecordBase
&Record
) { Record
.map(io
); }
716 template <> struct MappingTraits
<MemberRecordBase
> {
717 static void mapping(IO
&io
, MemberRecordBase
&Record
) { Record
.map(io
); }
720 } // end namespace yaml
721 } // end namespace llvm
723 template <typename ConcreteType
>
724 static void mapLeafRecordImpl(IO
&IO
, const char *Class
, TypeLeafKind Kind
,
726 if (!IO
.outputting())
727 Obj
.Leaf
= std::make_shared
<LeafRecordImpl
<ConcreteType
>>(Kind
);
729 if (Kind
== LF_FIELDLIST
)
732 IO
.mapRequired(Class
, *Obj
.Leaf
);
735 void MappingTraits
<LeafRecord
>::mapping(IO
&IO
, LeafRecord
&Obj
) {
738 Kind
= Obj
.Leaf
->Kind
;
739 IO
.mapRequired("Kind", Kind
);
741 #define TYPE_RECORD(EnumName, EnumVal, ClassName) \
743 mapLeafRecordImpl<ClassName##Record>(IO, #ClassName, Kind, Obj); \
745 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
746 TYPE_RECORD(EnumName, EnumVal, ClassName)
747 #define MEMBER_RECORD(EnumName, EnumVal, ClassName)
748 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
750 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
751 default: { llvm_unreachable("Unknown leaf kind!"); }
755 template <typename ConcreteType
>
756 static void mapMemberRecordImpl(IO
&IO
, const char *Class
, TypeLeafKind Kind
,
758 if (!IO
.outputting())
759 Obj
.Member
= std::make_shared
<MemberRecordImpl
<ConcreteType
>>(Kind
);
761 IO
.mapRequired(Class
, *Obj
.Member
);
764 void MappingTraits
<MemberRecord
>::mapping(IO
&IO
, MemberRecord
&Obj
) {
767 Kind
= Obj
.Member
->Kind
;
768 IO
.mapRequired("Kind", Kind
);
770 #define MEMBER_RECORD(EnumName, EnumVal, ClassName) \
772 mapMemberRecordImpl<ClassName##Record>(IO, #ClassName, Kind, Obj); \
774 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
775 MEMBER_RECORD(EnumName, EnumVal, ClassName)
776 #define TYPE_RECORD(EnumName, EnumVal, ClassName)
777 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)
779 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
780 default: { llvm_unreachable("Unknown member kind!"); }
784 std::vector
<LeafRecord
>
785 llvm::CodeViewYAML::fromDebugT(ArrayRef
<uint8_t> DebugTorP
,
786 StringRef SectionName
) {
787 ExitOnError
Err("Invalid " + std::string(SectionName
) + " section!");
788 BinaryStreamReader
Reader(DebugTorP
, llvm::endianness::little
);
792 Err(Reader
.readInteger(Magic
));
793 assert(Magic
== COFF::DEBUG_SECTION_MAGIC
&&
794 "Invalid .debug$T or .debug$P section!");
796 std::vector
<LeafRecord
> Result
;
797 Err(Reader
.readArray(Types
, Reader
.bytesRemaining()));
798 for (const auto &T
: Types
) {
799 auto CVT
= Err(LeafRecord::fromCodeViewRecord(T
));
800 Result
.push_back(CVT
);
805 ArrayRef
<uint8_t> llvm::CodeViewYAML::toDebugT(ArrayRef
<LeafRecord
> Leafs
,
806 BumpPtrAllocator
&Alloc
,
807 StringRef SectionName
) {
808 AppendingTypeTableBuilder
TS(Alloc
);
809 uint32_t Size
= sizeof(uint32_t);
810 for (const auto &Leaf
: Leafs
) {
811 CVType T
= Leaf
.Leaf
->toCodeViewRecord(TS
);
813 assert(T
.length() % 4 == 0 && "Improper type record alignment!");
815 uint8_t *ResultBuffer
= Alloc
.Allocate
<uint8_t>(Size
);
816 MutableArrayRef
<uint8_t> Output(ResultBuffer
, Size
);
817 BinaryStreamWriter
Writer(Output
, llvm::endianness::little
);
818 ExitOnError
Err("Error writing type record to " + std::string(SectionName
) +
820 Err(Writer
.writeInteger
<uint32_t>(COFF::DEBUG_SECTION_MAGIC
));
821 for (const auto &R
: TS
.records()) {
822 Err(Writer
.writeBytes(R
));
824 assert(Writer
.bytesRemaining() == 0 && "Didn't write all type record bytes!");