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