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