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