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