1 //===- CodeViewYAMLSymbols.cpp - CodeView YAMLIO Symbol implementation ----===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines classes for handling the YAML representation of CodeView
11 // Debug Info.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
19 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
20 #include "llvm/DebugInfo/CodeView/EnumTables.h"
21 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
22 #include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
23 
24 using namespace llvm;
25 using namespace llvm::codeview;
26 using namespace llvm::CodeViewYAML;
27 using namespace llvm::CodeViewYAML::detail;
28 using namespace llvm::yaml;
29 
30 LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
31 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)
32 
33 // We only need to declare these, the definitions are in CodeViewYAMLTypes.cpp
34 LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, false)
35 LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, false)
36 
37 LLVM_YAML_DECLARE_ENUM_TRAITS(SymbolKind)
38 
39 LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym2Flags)
40 LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym3Flags)
41 LLVM_YAML_DECLARE_BITSET_TRAITS(ExportFlags)
42 LLVM_YAML_DECLARE_BITSET_TRAITS(LocalSymFlags)
43 LLVM_YAML_DECLARE_BITSET_TRAITS(ProcSymFlags)
44 LLVM_YAML_DECLARE_BITSET_TRAITS(FrameProcedureOptions)
45 LLVM_YAML_DECLARE_ENUM_TRAITS(CPUType)
46 LLVM_YAML_DECLARE_ENUM_TRAITS(RegisterId)
47 LLVM_YAML_DECLARE_ENUM_TRAITS(TrampolineType)
48 LLVM_YAML_DECLARE_ENUM_TRAITS(ThunkOrdinal)
49 
50 void ScalarEnumerationTraits<SymbolKind>::enumeration(IO &io,
51                                                       SymbolKind &Value) {
52   auto SymbolNames = getSymbolTypeNames();
53   for (const auto &E : SymbolNames)
54     io.enumCase(Value, E.Name.str().c_str(), E.Value);
55 }
56 
57 void ScalarBitSetTraits<CompileSym2Flags>::bitset(IO &io,
58                                                   CompileSym2Flags &Flags) {
59   auto FlagNames = getCompileSym2FlagNames();
60   for (const auto &E : FlagNames) {
61     io.bitSetCase(Flags, E.Name.str().c_str(),
62                   static_cast<CompileSym2Flags>(E.Value));
63   }
64 }
65 
66 void ScalarBitSetTraits<CompileSym3Flags>::bitset(IO &io,
67                                                   CompileSym3Flags &Flags) {
68   auto FlagNames = getCompileSym3FlagNames();
69   for (const auto &E : FlagNames) {
70     io.bitSetCase(Flags, E.Name.str().c_str(),
71                   static_cast<CompileSym3Flags>(E.Value));
72   }
73 }
74 
75 void ScalarBitSetTraits<ExportFlags>::bitset(IO &io, ExportFlags &Flags) {
76   auto FlagNames = getExportSymFlagNames();
77   for (const auto &E : FlagNames) {
78     io.bitSetCase(Flags, E.Name.str().c_str(),
79                   static_cast<ExportFlags>(E.Value));
80   }
81 }
82 
83 void ScalarBitSetTraits<LocalSymFlags>::bitset(IO &io, LocalSymFlags &Flags) {
84   auto FlagNames = getLocalFlagNames();
85   for (const auto &E : FlagNames) {
86     io.bitSetCase(Flags, E.Name.str().c_str(),
87                   static_cast<LocalSymFlags>(E.Value));
88   }
89 }
90 
91 void ScalarBitSetTraits<ProcSymFlags>::bitset(IO &io, ProcSymFlags &Flags) {
92   auto FlagNames = getProcSymFlagNames();
93   for (const auto &E : FlagNames) {
94     io.bitSetCase(Flags, E.Name.str().c_str(),
95                   static_cast<ProcSymFlags>(E.Value));
96   }
97 }
98 
99 void ScalarBitSetTraits<FrameProcedureOptions>::bitset(
100     IO &io, FrameProcedureOptions &Flags) {
101   auto FlagNames = getFrameProcSymFlagNames();
102   for (const auto &E : FlagNames) {
103     io.bitSetCase(Flags, E.Name.str().c_str(),
104                   static_cast<FrameProcedureOptions>(E.Value));
105   }
106 }
107 
108 void ScalarEnumerationTraits<CPUType>::enumeration(IO &io, CPUType &Cpu) {
109   auto CpuNames = getCPUTypeNames();
110   for (const auto &E : CpuNames) {
111     io.enumCase(Cpu, E.Name.str().c_str(), static_cast<CPUType>(E.Value));
112   }
113 }
114 
115 void ScalarEnumerationTraits<RegisterId>::enumeration(IO &io, RegisterId &Reg) {
116   auto RegNames = getRegisterNames();
117   for (const auto &E : RegNames) {
118     io.enumCase(Reg, E.Name.str().c_str(), static_cast<RegisterId>(E.Value));
119   }
120   io.enumFallback<Hex16>(Reg);
121 }
122 
123 void ScalarEnumerationTraits<TrampolineType>::enumeration(
124     IO &io, TrampolineType &Tramp) {
125   auto TrampNames = getTrampolineNames();
126   for (const auto &E : TrampNames) {
127     io.enumCase(Tramp, E.Name.str().c_str(),
128                 static_cast<TrampolineType>(E.Value));
129   }
130 }
131 
132 void ScalarEnumerationTraits<ThunkOrdinal>::enumeration(IO &io,
133                                                         ThunkOrdinal &Ord) {
134   auto ThunkNames = getThunkOrdinalNames();
135   for (const auto &E : ThunkNames) {
136     io.enumCase(Ord, E.Name.str().c_str(), static_cast<ThunkOrdinal>(E.Value));
137   }
138 }
139 
140 namespace llvm {
141 namespace CodeViewYAML {
142 namespace detail {
143 
144 struct SymbolRecordBase {
145   codeview::SymbolKind Kind;
146   explicit SymbolRecordBase(codeview::SymbolKind K) : Kind(K) {}
147 
148   virtual ~SymbolRecordBase() {}
149   virtual void map(yaml::IO &io) = 0;
150   virtual codeview::CVSymbol
151   toCodeViewSymbol(BumpPtrAllocator &Allocator,
152                    CodeViewContainer Container) const = 0;
153   virtual Error fromCodeViewSymbol(codeview::CVSymbol Type) = 0;
154 };
155 
156 template <typename T> struct SymbolRecordImpl : public SymbolRecordBase {
157   explicit SymbolRecordImpl(codeview::SymbolKind K)
158       : SymbolRecordBase(K), Symbol(static_cast<SymbolRecordKind>(K)) {}
159 
160   void map(yaml::IO &io) override;
161 
162   codeview::CVSymbol
163   toCodeViewSymbol(BumpPtrAllocator &Allocator,
164                    CodeViewContainer Container) const override {
165     return SymbolSerializer::writeOneSymbol(Symbol, Allocator, Container);
166   }
167   Error fromCodeViewSymbol(codeview::CVSymbol CVS) override {
168     return SymbolDeserializer::deserializeAs<T>(CVS, Symbol);
169   }
170 
171   mutable T Symbol;
172 };
173 
174 template <> void SymbolRecordImpl<ScopeEndSym>::map(IO &IO) {}
175 
176 template <> void SymbolRecordImpl<Thunk32Sym>::map(IO &IO) {
177   IO.mapRequired("Parent", Symbol.Parent);
178   IO.mapRequired("End", Symbol.End);
179   IO.mapRequired("Next", Symbol.Next);
180   IO.mapRequired("Off", Symbol.Offset);
181   IO.mapRequired("Seg", Symbol.Segment);
182   IO.mapRequired("Len", Symbol.Length);
183   IO.mapRequired("Ordinal", Symbol.Thunk);
184 }
185 
186 template <> void SymbolRecordImpl<TrampolineSym>::map(IO &IO) {
187   IO.mapRequired("Type", Symbol.Type);
188   IO.mapRequired("Size", Symbol.Size);
189   IO.mapRequired("ThunkOff", Symbol.ThunkOffset);
190   IO.mapRequired("TargetOff", Symbol.TargetOffset);
191   IO.mapRequired("ThunkSection", Symbol.ThunkSection);
192   IO.mapRequired("TargetSection", Symbol.TargetSection);
193 }
194 
195 template <> void SymbolRecordImpl<SectionSym>::map(IO &IO) {
196   IO.mapRequired("SectionNumber", Symbol.SectionNumber);
197   IO.mapRequired("Alignment", Symbol.Alignment);
198   IO.mapRequired("Rva", Symbol.Rva);
199   IO.mapRequired("Length", Symbol.Length);
200   IO.mapRequired("Characteristics", Symbol.Characteristics);
201   IO.mapRequired("Name", Symbol.Name);
202 }
203 
204 template <> void SymbolRecordImpl<CoffGroupSym>::map(IO &IO) {
205   IO.mapRequired("Size", Symbol.Size);
206   IO.mapRequired("Characteristics", Symbol.Characteristics);
207   IO.mapRequired("Offset", Symbol.Offset);
208   IO.mapRequired("Segment", Symbol.Segment);
209   IO.mapRequired("Name", Symbol.Name);
210 }
211 
212 template <> void SymbolRecordImpl<ExportSym>::map(IO &IO) {
213   IO.mapRequired("Ordinal", Symbol.Ordinal);
214   IO.mapRequired("Flags", Symbol.Flags);
215   IO.mapRequired("Name", Symbol.Name);
216 }
217 
218 template <> void SymbolRecordImpl<ProcSym>::map(IO &IO) {
219   // TODO: Print the linkage name
220 
221   IO.mapRequired("PtrParent", Symbol.Parent);
222   IO.mapRequired("PtrEnd", Symbol.End);
223   IO.mapRequired("PtrNext", Symbol.Next);
224   IO.mapRequired("CodeSize", Symbol.CodeSize);
225   IO.mapRequired("DbgStart", Symbol.DbgStart);
226   IO.mapRequired("DbgEnd", Symbol.DbgEnd);
227   IO.mapRequired("FunctionType", Symbol.FunctionType);
228   IO.mapRequired("Segment", Symbol.Segment);
229   IO.mapRequired("Flags", Symbol.Flags);
230   IO.mapRequired("DisplayName", Symbol.Name);
231 }
232 
233 template <> void SymbolRecordImpl<RegisterSym>::map(IO &IO) {
234   IO.mapRequired("Type", Symbol.Index);
235   IO.mapRequired("Seg", Symbol.Register);
236   IO.mapRequired("Name", Symbol.Name);
237 }
238 
239 template <> void SymbolRecordImpl<PublicSym32>::map(IO &IO) {
240   IO.mapRequired("Type", Symbol.Index);
241   IO.mapRequired("Seg", Symbol.Segment);
242   IO.mapRequired("Off", Symbol.Offset);
243   IO.mapRequired("Name", Symbol.Name);
244 }
245 
246 template <> void SymbolRecordImpl<ProcRefSym>::map(IO &IO) {
247   IO.mapRequired("SumName", Symbol.SumName);
248   IO.mapRequired("SymOffset", Symbol.SymOffset);
249   IO.mapRequired("Mod", Symbol.Module);
250   IO.mapRequired("Name", Symbol.Name);
251 }
252 
253 template <> void SymbolRecordImpl<EnvBlockSym>::map(IO &IO) {
254   IO.mapRequired("Entries", Symbol.Fields);
255 }
256 
257 template <> void SymbolRecordImpl<InlineSiteSym>::map(IO &IO) {
258   IO.mapRequired("PtrParent", Symbol.Parent);
259   IO.mapRequired("PtrEnd", Symbol.End);
260   IO.mapRequired("Inlinee", Symbol.Inlinee);
261   // TODO: The binary annotations
262 }
263 
264 template <> void SymbolRecordImpl<LocalSym>::map(IO &IO) {
265   IO.mapRequired("Type", Symbol.Type);
266   IO.mapRequired("Flags", Symbol.Flags);
267   IO.mapRequired("VarName", Symbol.Name);
268 }
269 
270 template <> void SymbolRecordImpl<DefRangeSym>::map(IO &IO) {
271   // TODO: Print the subfields
272 }
273 
274 template <> void SymbolRecordImpl<DefRangeSubfieldSym>::map(IO &IO) {
275   // TODO: Print the subfields
276 }
277 
278 template <> void SymbolRecordImpl<DefRangeRegisterSym>::map(IO &IO) {
279   // TODO: Print the subfields
280 }
281 
282 template <> void SymbolRecordImpl<DefRangeFramePointerRelSym>::map(IO &IO) {
283   // TODO: Print the subfields
284 }
285 
286 template <> void SymbolRecordImpl<DefRangeSubfieldRegisterSym>::map(IO &IO) {
287   // TODO: Print the subfields
288 }
289 
290 template <>
291 void SymbolRecordImpl<DefRangeFramePointerRelFullScopeSym>::map(IO &IO) {
292   // TODO: Print the subfields
293 }
294 
295 template <> void SymbolRecordImpl<DefRangeRegisterRelSym>::map(IO &IO) {
296   // TODO: Print the subfields
297 }
298 
299 template <> void SymbolRecordImpl<BlockSym>::map(IO &IO) {
300   // TODO: Print the linkage name
301   IO.mapRequired("PtrParent", Symbol.Parent);
302   IO.mapRequired("PtrEnd", Symbol.End);
303   IO.mapRequired("CodeSize", Symbol.CodeSize);
304   IO.mapRequired("Segment", Symbol.Segment);
305   IO.mapRequired("BlockName", Symbol.Name);
306 }
307 
308 template <> void SymbolRecordImpl<LabelSym>::map(IO &IO) {
309   // TODO: Print the linkage name
310   IO.mapRequired("Segment", Symbol.Segment);
311   IO.mapRequired("Flags", Symbol.Flags);
312   IO.mapRequired("Flags", Symbol.Flags);
313   IO.mapRequired("DisplayName", Symbol.Name);
314 }
315 
316 template <> void SymbolRecordImpl<ObjNameSym>::map(IO &IO) {
317   IO.mapRequired("Signature", Symbol.Signature);
318   IO.mapRequired("ObjectName", Symbol.Name);
319 }
320 
321 template <> void SymbolRecordImpl<Compile2Sym>::map(IO &IO) {
322   IO.mapRequired("Flags", Symbol.Flags);
323   IO.mapRequired("Machine", Symbol.Machine);
324   IO.mapRequired("FrontendMajor", Symbol.VersionFrontendMajor);
325   IO.mapRequired("FrontendMinor", Symbol.VersionFrontendMinor);
326   IO.mapRequired("FrontendBuild", Symbol.VersionFrontendBuild);
327   IO.mapRequired("BackendMajor", Symbol.VersionBackendMajor);
328   IO.mapRequired("BackendMinor", Symbol.VersionBackendMinor);
329   IO.mapRequired("BackendBuild", Symbol.VersionBackendBuild);
330   IO.mapRequired("Version", Symbol.Version);
331 }
332 
333 template <> void SymbolRecordImpl<Compile3Sym>::map(IO &IO) {
334   IO.mapRequired("Flags", Symbol.Flags);
335   IO.mapRequired("Machine", Symbol.Machine);
336   IO.mapRequired("FrontendMajor", Symbol.VersionFrontendMajor);
337   IO.mapRequired("FrontendMinor", Symbol.VersionFrontendMinor);
338   IO.mapRequired("FrontendBuild", Symbol.VersionFrontendBuild);
339   IO.mapRequired("FrontendQFE", Symbol.VersionFrontendQFE);
340   IO.mapRequired("BackendMajor", Symbol.VersionBackendMajor);
341   IO.mapRequired("BackendMinor", Symbol.VersionBackendMinor);
342   IO.mapRequired("BackendBuild", Symbol.VersionBackendBuild);
343   IO.mapRequired("BackendQFE", Symbol.VersionBackendQFE);
344   IO.mapRequired("Version", Symbol.Version);
345 }
346 
347 template <> void SymbolRecordImpl<FrameProcSym>::map(IO &IO) {
348   IO.mapRequired("TotalFrameBytes", Symbol.TotalFrameBytes);
349   IO.mapRequired("PaddingFrameBytes", Symbol.PaddingFrameBytes);
350   IO.mapRequired("OffsetToPadding", Symbol.OffsetToPadding);
351   IO.mapRequired("BytesOfCalleeSavedRegisters",
352                  Symbol.BytesOfCalleeSavedRegisters);
353   IO.mapRequired("OffsetOfExceptionHandler", Symbol.OffsetOfExceptionHandler);
354   IO.mapRequired("SectionIdOfExceptionHandler",
355                  Symbol.SectionIdOfExceptionHandler);
356   IO.mapRequired("Flags", Symbol.Flags);
357 }
358 
359 template <> void SymbolRecordImpl<CallSiteInfoSym>::map(IO &IO) {
360   // TODO: Map Linkage Name
361   IO.mapRequired("Segment", Symbol.Segment);
362   IO.mapRequired("Type", Symbol.Type);
363 }
364 
365 template <> void SymbolRecordImpl<FileStaticSym>::map(IO &IO) {
366   IO.mapRequired("Index", Symbol.Index);
367   IO.mapRequired("ModFilenameOffset", Symbol.ModFilenameOffset);
368   IO.mapRequired("Flags", Symbol.Flags);
369   IO.mapRequired("Name", Symbol.Name);
370 }
371 
372 template <> void SymbolRecordImpl<HeapAllocationSiteSym>::map(IO &IO) {
373   // TODO: Map Linkage Name
374   IO.mapRequired("Segment", Symbol.Segment);
375   IO.mapRequired("CallInstructionSize", Symbol.CallInstructionSize);
376   IO.mapRequired("Type", Symbol.Type);
377 }
378 
379 template <> void SymbolRecordImpl<FrameCookieSym>::map(IO &IO) {
380   // TODO: Map Linkage Name
381   IO.mapRequired("Register", Symbol.Register);
382   IO.mapRequired("CookieKind", Symbol.CookieKind);
383   IO.mapRequired("Flags", Symbol.Flags);
384 }
385 
386 template <> void SymbolRecordImpl<CallerSym>::map(IO &IO) {
387   IO.mapRequired("FuncID", Symbol.Indices);
388 }
389 
390 template <> void SymbolRecordImpl<UDTSym>::map(IO &IO) {
391   IO.mapRequired("Type", Symbol.Type);
392   IO.mapRequired("UDTName", Symbol.Name);
393 }
394 
395 template <> void SymbolRecordImpl<BuildInfoSym>::map(IO &IO) {
396   IO.mapRequired("BuildId", Symbol.BuildId);
397 }
398 
399 template <> void SymbolRecordImpl<BPRelativeSym>::map(IO &IO) {
400   IO.mapRequired("Offset", Symbol.Offset);
401   IO.mapRequired("Type", Symbol.Type);
402   IO.mapRequired("VarName", Symbol.Name);
403 }
404 
405 template <> void SymbolRecordImpl<RegRelativeSym>::map(IO &IO) {
406   IO.mapRequired("Offset", Symbol.Offset);
407   IO.mapRequired("Type", Symbol.Type);
408   IO.mapRequired("Register", Symbol.Register);
409   IO.mapRequired("VarName", Symbol.Name);
410 }
411 
412 template <> void SymbolRecordImpl<ConstantSym>::map(IO &IO) {
413   IO.mapRequired("Type", Symbol.Type);
414   IO.mapRequired("Value", Symbol.Value);
415   IO.mapRequired("Name", Symbol.Name);
416 }
417 
418 template <> void SymbolRecordImpl<DataSym>::map(IO &IO) {
419   // TODO: Map linkage name
420   IO.mapRequired("Type", Symbol.Type);
421   IO.mapRequired("DisplayName", Symbol.Name);
422 }
423 
424 template <> void SymbolRecordImpl<ThreadLocalDataSym>::map(IO &IO) {
425   // TODO: Map linkage name
426   IO.mapRequired("Type", Symbol.Type);
427   IO.mapRequired("DisplayName", Symbol.Name);
428 }
429 }
430 }
431 }
432 
433 CVSymbol CodeViewYAML::SymbolRecord::toCodeViewSymbol(
434     BumpPtrAllocator &Allocator, CodeViewContainer Container) const {
435   return Symbol->toCodeViewSymbol(Allocator, Container);
436 }
437 
438 namespace llvm {
439 namespace yaml {
440 template <> struct MappingTraits<SymbolRecordBase> {
441   static void mapping(IO &io, SymbolRecordBase &Record) { Record.map(io); }
442 };
443 }
444 }
445 
446 template <typename SymbolType>
447 static inline Expected<CodeViewYAML::SymbolRecord>
448 fromCodeViewSymbolImpl(CVSymbol Symbol) {
449   CodeViewYAML::SymbolRecord Result;
450 
451   auto Impl = std::make_shared<SymbolRecordImpl<SymbolType>>(Symbol.kind());
452   if (auto EC = Impl->fromCodeViewSymbol(Symbol))
453     return std::move(EC);
454   Result.Symbol = Impl;
455   return Result;
456 }
457 
458 Expected<CodeViewYAML::SymbolRecord>
459 CodeViewYAML::SymbolRecord::fromCodeViewSymbol(CVSymbol Symbol) {
460 #define SYMBOL_RECORD(EnumName, EnumVal, ClassName)                            \
461   case EnumName:                                                               \
462     return fromCodeViewSymbolImpl<ClassName>(Symbol);
463 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)           \
464   SYMBOL_RECORD(EnumName, EnumVal, ClassName)
465   switch (Symbol.kind()) {
466 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
467   default: { llvm_unreachable("Unknown symbol kind!"); }
468   }
469   return make_error<CodeViewError>(cv_error_code::corrupt_record);
470 }
471 
472 template <typename ConcreteType>
473 static void mapSymbolRecordImpl(IO &IO, const char *Class, SymbolKind Kind,
474                                 CodeViewYAML::SymbolRecord &Obj) {
475   if (!IO.outputting())
476     Obj.Symbol = std::make_shared<SymbolRecordImpl<ConcreteType>>(Kind);
477 
478   IO.mapRequired(Class, *Obj.Symbol);
479 }
480 
481 void MappingTraits<CodeViewYAML::SymbolRecord>::mapping(
482     IO &IO, CodeViewYAML::SymbolRecord &Obj) {
483   SymbolKind Kind;
484   if (IO.outputting())
485     Kind = Obj.Symbol->Kind;
486   IO.mapRequired("Kind", Kind);
487 
488 #define SYMBOL_RECORD(EnumName, EnumVal, ClassName)                            \
489   case EnumName:                                                               \
490     mapSymbolRecordImpl<ClassName>(IO, #ClassName, Kind, Obj);                 \
491     break;
492 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)           \
493   SYMBOL_RECORD(EnumName, EnumVal, ClassName)
494   switch (Kind) {
495 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
496   default: { llvm_unreachable("Unknown symbol kind!"); }
497   }
498 }
499