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