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