blob: 6e8bb5c7372c8fc725b9ea047dcb3675bda4255f [file] [log] [blame]
Zachary Turner1b88f4f2017-05-31 04:17:13 +00001//===- 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
24using namespace llvm;
25using namespace llvm::codeview;
26using namespace llvm::CodeViewYAML;
27using namespace llvm::CodeViewYAML::detail;
28using namespace llvm::yaml;
29
30LLVM_YAML_IS_SEQUENCE_VECTOR(StringRef)
31LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)
32
33// We only need to declare these, the definitions are in CodeViewYAMLTypes.cpp
34LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, false)
35LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, false)
36
37LLVM_YAML_DECLARE_ENUM_TRAITS(SymbolKind)
38
39LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym2Flags)
40LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym3Flags)
41LLVM_YAML_DECLARE_BITSET_TRAITS(ExportFlags)
42LLVM_YAML_DECLARE_BITSET_TRAITS(LocalSymFlags)
43LLVM_YAML_DECLARE_BITSET_TRAITS(ProcSymFlags)
44LLVM_YAML_DECLARE_BITSET_TRAITS(FrameProcedureOptions)
45LLVM_YAML_DECLARE_ENUM_TRAITS(CPUType)
46LLVM_YAML_DECLARE_ENUM_TRAITS(RegisterId)
47LLVM_YAML_DECLARE_ENUM_TRAITS(TrampolineType)
48LLVM_YAML_DECLARE_ENUM_TRAITS(ThunkOrdinal)
49
50void 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
57void 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
66void 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
75void 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
83void 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
91void 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
99void 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
108void 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
115void 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
123void 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
132void 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
140namespace llvm {
141namespace CodeViewYAML {
142namespace detail {
143
144struct 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) const = 0;
152 virtual Error fromCodeViewSymbol(codeview::CVSymbol Type) = 0;
153};
154
155template <typename T> struct SymbolRecordImpl : public SymbolRecordBase {
156 explicit SymbolRecordImpl(codeview::SymbolKind K)
157 : SymbolRecordBase(K), Symbol(static_cast<SymbolRecordKind>(K)) {}
158
159 void map(yaml::IO &io) override;
160
161 codeview::CVSymbol
162 toCodeViewSymbol(BumpPtrAllocator &Allocator) const override {
163 return SymbolSerializer::writeOneSymbol(Symbol, Allocator);
164 }
165 Error fromCodeViewSymbol(codeview::CVSymbol CVS) override {
166 return SymbolDeserializer::deserializeAs<T>(CVS, Symbol);
167 }
168
169 mutable T Symbol;
170};
171
172template <> void SymbolRecordImpl<ScopeEndSym>::map(IO &IO) {}
173
174template <> void SymbolRecordImpl<Thunk32Sym>::map(IO &IO) {
175 IO.mapRequired("Parent", Symbol.Parent);
176 IO.mapRequired("End", Symbol.End);
177 IO.mapRequired("Next", Symbol.Next);
178 IO.mapRequired("Off", Symbol.Offset);
179 IO.mapRequired("Seg", Symbol.Segment);
180 IO.mapRequired("Len", Symbol.Length);
181 IO.mapRequired("Ordinal", Symbol.Thunk);
182}
183
184template <> void SymbolRecordImpl<TrampolineSym>::map(IO &IO) {
185 IO.mapRequired("Type", Symbol.Type);
186 IO.mapRequired("Size", Symbol.Size);
187 IO.mapRequired("ThunkOff", Symbol.ThunkOffset);
188 IO.mapRequired("TargetOff", Symbol.TargetOffset);
189 IO.mapRequired("ThunkSection", Symbol.ThunkSection);
190 IO.mapRequired("TargetSection", Symbol.TargetSection);
191}
192
193template <> void SymbolRecordImpl<SectionSym>::map(IO &IO) {
194 IO.mapRequired("SectionNumber", Symbol.SectionNumber);
195 IO.mapRequired("Alignment", Symbol.Alignment);
196 IO.mapRequired("Rva", Symbol.Rva);
197 IO.mapRequired("Length", Symbol.Length);
198 IO.mapRequired("Characteristics", Symbol.Characteristics);
199 IO.mapRequired("Name", Symbol.Name);
200}
201
202template <> void SymbolRecordImpl<CoffGroupSym>::map(IO &IO) {
203 IO.mapRequired("Size", Symbol.Size);
204 IO.mapRequired("Characteristics", Symbol.Characteristics);
205 IO.mapRequired("Offset", Symbol.Offset);
206 IO.mapRequired("Segment", Symbol.Segment);
207 IO.mapRequired("Name", Symbol.Name);
208}
209
210template <> void SymbolRecordImpl<ExportSym>::map(IO &IO) {
211 IO.mapRequired("Ordinal", Symbol.Ordinal);
212 IO.mapRequired("Flags", Symbol.Flags);
213 IO.mapRequired("Name", Symbol.Name);
214}
215
216template <> void SymbolRecordImpl<ProcSym>::map(IO &IO) {
217 // TODO: Print the linkage name
218
219 IO.mapRequired("PtrParent", Symbol.Parent);
220 IO.mapRequired("PtrEnd", Symbol.End);
221 IO.mapRequired("PtrNext", Symbol.Next);
222 IO.mapRequired("CodeSize", Symbol.CodeSize);
223 IO.mapRequired("DbgStart", Symbol.DbgStart);
224 IO.mapRequired("DbgEnd", Symbol.DbgEnd);
225 IO.mapRequired("FunctionType", Symbol.FunctionType);
226 IO.mapRequired("Segment", Symbol.Segment);
227 IO.mapRequired("Flags", Symbol.Flags);
228 IO.mapRequired("DisplayName", Symbol.Name);
229}
230
231template <> void SymbolRecordImpl<RegisterSym>::map(IO &IO) {
232 IO.mapRequired("Type", Symbol.Index);
233 IO.mapRequired("Seg", Symbol.Register);
234 IO.mapRequired("Name", Symbol.Name);
235}
236
237template <> void SymbolRecordImpl<PublicSym32>::map(IO &IO) {
238 IO.mapRequired("Type", Symbol.Index);
239 IO.mapRequired("Seg", Symbol.Segment);
240 IO.mapRequired("Off", Symbol.Offset);
241 IO.mapRequired("Name", Symbol.Name);
242}
243
244template <> void SymbolRecordImpl<ProcRefSym>::map(IO &IO) {
245 IO.mapRequired("SumName", Symbol.SumName);
246 IO.mapRequired("SymOffset", Symbol.SymOffset);
247 IO.mapRequired("Mod", Symbol.Module);
248 IO.mapRequired("Name", Symbol.Name);
249}
250
251template <> void SymbolRecordImpl<EnvBlockSym>::map(IO &IO) {
252 IO.mapRequired("Entries", Symbol.Fields);
253}
254
255template <> void SymbolRecordImpl<InlineSiteSym>::map(IO &IO) {
256 IO.mapRequired("PtrParent", Symbol.Parent);
257 IO.mapRequired("PtrEnd", Symbol.End);
258 IO.mapRequired("Inlinee", Symbol.Inlinee);
259 // TODO: The binary annotations
260}
261
262template <> void SymbolRecordImpl<LocalSym>::map(IO &IO) {
263 IO.mapRequired("Type", Symbol.Type);
264 IO.mapRequired("Flags", Symbol.Flags);
265 IO.mapRequired("VarName", Symbol.Name);
266}
267
268template <> void SymbolRecordImpl<DefRangeSym>::map(IO &IO) {
269 // TODO: Print the subfields
270}
271
272template <> void SymbolRecordImpl<DefRangeSubfieldSym>::map(IO &IO) {
273 // TODO: Print the subfields
274}
275
276template <> void SymbolRecordImpl<DefRangeRegisterSym>::map(IO &IO) {
277 // TODO: Print the subfields
278}
279
280template <> void SymbolRecordImpl<DefRangeFramePointerRelSym>::map(IO &IO) {
281 // TODO: Print the subfields
282}
283
284template <> void SymbolRecordImpl<DefRangeSubfieldRegisterSym>::map(IO &IO) {
285 // TODO: Print the subfields
286}
287
288template <>
289void SymbolRecordImpl<DefRangeFramePointerRelFullScopeSym>::map(IO &IO) {
290 // TODO: Print the subfields
291}
292
293template <> void SymbolRecordImpl<DefRangeRegisterRelSym>::map(IO &IO) {
294 // TODO: Print the subfields
295}
296
297template <> void SymbolRecordImpl<BlockSym>::map(IO &IO) {
298 // TODO: Print the linkage name
299 IO.mapRequired("PtrParent", Symbol.Parent);
300 IO.mapRequired("PtrEnd", Symbol.End);
301 IO.mapRequired("CodeSize", Symbol.CodeSize);
302 IO.mapRequired("Segment", Symbol.Segment);
303 IO.mapRequired("BlockName", Symbol.Name);
304}
305
306template <> void SymbolRecordImpl<LabelSym>::map(IO &IO) {
307 // TODO: Print the linkage name
308 IO.mapRequired("Segment", Symbol.Segment);
309 IO.mapRequired("Flags", Symbol.Flags);
310 IO.mapRequired("Flags", Symbol.Flags);
311 IO.mapRequired("DisplayName", Symbol.Name);
312}
313
314template <> void SymbolRecordImpl<ObjNameSym>::map(IO &IO) {
315 IO.mapRequired("Signature", Symbol.Signature);
316 IO.mapRequired("ObjectName", Symbol.Name);
317}
318
319template <> void SymbolRecordImpl<Compile2Sym>::map(IO &IO) {
320 IO.mapRequired("Flags", Symbol.Flags);
321 IO.mapRequired("Machine", Symbol.Machine);
322 IO.mapRequired("FrontendMajor", Symbol.VersionFrontendMajor);
323 IO.mapRequired("FrontendMinor", Symbol.VersionFrontendMinor);
324 IO.mapRequired("FrontendBuild", Symbol.VersionFrontendBuild);
325 IO.mapRequired("BackendMajor", Symbol.VersionBackendMajor);
326 IO.mapRequired("BackendMinor", Symbol.VersionBackendMinor);
327 IO.mapRequired("BackendBuild", Symbol.VersionBackendBuild);
328 IO.mapRequired("Version", Symbol.Version);
329}
330
331template <> void SymbolRecordImpl<Compile3Sym>::map(IO &IO) {
332 IO.mapRequired("Flags", Symbol.Flags);
333 IO.mapRequired("Machine", Symbol.Machine);
334 IO.mapRequired("FrontendMajor", Symbol.VersionFrontendMajor);
335 IO.mapRequired("FrontendMinor", Symbol.VersionFrontendMinor);
336 IO.mapRequired("FrontendBuild", Symbol.VersionFrontendBuild);
337 IO.mapRequired("FrontendQFE", Symbol.VersionFrontendQFE);
338 IO.mapRequired("BackendMajor", Symbol.VersionBackendMajor);
339 IO.mapRequired("BackendMinor", Symbol.VersionBackendMinor);
340 IO.mapRequired("BackendBuild", Symbol.VersionBackendBuild);
341 IO.mapRequired("BackendQFE", Symbol.VersionBackendQFE);
342 IO.mapRequired("Version", Symbol.Version);
343}
344
345template <> void SymbolRecordImpl<FrameProcSym>::map(IO &IO) {
346 IO.mapRequired("TotalFrameBytes", Symbol.TotalFrameBytes);
347 IO.mapRequired("PaddingFrameBytes", Symbol.PaddingFrameBytes);
348 IO.mapRequired("OffsetToPadding", Symbol.OffsetToPadding);
349 IO.mapRequired("BytesOfCalleeSavedRegisters",
350 Symbol.BytesOfCalleeSavedRegisters);
351 IO.mapRequired("OffsetOfExceptionHandler", Symbol.OffsetOfExceptionHandler);
352 IO.mapRequired("SectionIdOfExceptionHandler",
353 Symbol.SectionIdOfExceptionHandler);
354 IO.mapRequired("Flags", Symbol.Flags);
355}
356
357template <> void SymbolRecordImpl<CallSiteInfoSym>::map(IO &IO) {
358 // TODO: Map Linkage Name
359 IO.mapRequired("Segment", Symbol.Segment);
360 IO.mapRequired("Type", Symbol.Type);
361}
362
363template <> void SymbolRecordImpl<FileStaticSym>::map(IO &IO) {
364 IO.mapRequired("Index", Symbol.Index);
365 IO.mapRequired("ModFilenameOffset", Symbol.ModFilenameOffset);
366 IO.mapRequired("Flags", Symbol.Flags);
367 IO.mapRequired("Name", Symbol.Name);
368}
369
370template <> void SymbolRecordImpl<HeapAllocationSiteSym>::map(IO &IO) {
371 // TODO: Map Linkage Name
372 IO.mapRequired("Segment", Symbol.Segment);
373 IO.mapRequired("CallInstructionSize", Symbol.CallInstructionSize);
374 IO.mapRequired("Type", Symbol.Type);
375}
376
377template <> void SymbolRecordImpl<FrameCookieSym>::map(IO &IO) {
378 // TODO: Map Linkage Name
379 IO.mapRequired("Register", Symbol.Register);
380 IO.mapRequired("CookieKind", Symbol.CookieKind);
381 IO.mapRequired("Flags", Symbol.Flags);
382}
383
384template <> void SymbolRecordImpl<CallerSym>::map(IO &IO) {
385 IO.mapRequired("FuncID", Symbol.Indices);
386}
387
388template <> void SymbolRecordImpl<UDTSym>::map(IO &IO) {
389 IO.mapRequired("Type", Symbol.Type);
390 IO.mapRequired("UDTName", Symbol.Name);
391}
392
393template <> void SymbolRecordImpl<BuildInfoSym>::map(IO &IO) {
394 IO.mapRequired("BuildId", Symbol.BuildId);
395}
396
397template <> void SymbolRecordImpl<BPRelativeSym>::map(IO &IO) {
398 IO.mapRequired("Offset", Symbol.Offset);
399 IO.mapRequired("Type", Symbol.Type);
400 IO.mapRequired("VarName", Symbol.Name);
401}
402
403template <> void SymbolRecordImpl<RegRelativeSym>::map(IO &IO) {
404 IO.mapRequired("Offset", Symbol.Offset);
405 IO.mapRequired("Type", Symbol.Type);
406 IO.mapRequired("Register", Symbol.Register);
407 IO.mapRequired("VarName", Symbol.Name);
408}
409
410template <> void SymbolRecordImpl<ConstantSym>::map(IO &IO) {
411 IO.mapRequired("Type", Symbol.Type);
412 IO.mapRequired("Value", Symbol.Value);
413 IO.mapRequired("Name", Symbol.Name);
414}
415
416template <> void SymbolRecordImpl<DataSym>::map(IO &IO) {
417 // TODO: Map linkage name
418 IO.mapRequired("Type", Symbol.Type);
419 IO.mapRequired("DisplayName", Symbol.Name);
420}
421
422template <> void SymbolRecordImpl<ThreadLocalDataSym>::map(IO &IO) {
423 // TODO: Map linkage name
424 IO.mapRequired("Type", Symbol.Type);
425 IO.mapRequired("DisplayName", Symbol.Name);
426}
427}
428}
429}
430
431CVSymbol CodeViewYAML::SymbolRecord::toCodeViewSymbol(
432 BumpPtrAllocator &Allocator) const {
433 return Symbol->toCodeViewSymbol(Allocator);
434}
435
436namespace llvm {
437namespace yaml {
438template <> struct MappingTraits<SymbolRecordBase> {
439 static void mapping(IO &io, SymbolRecordBase &Record) { Record.map(io); }
440};
441}
442}
443
444template <typename SymbolType>
445static inline Expected<CodeViewYAML::SymbolRecord>
446fromCodeViewSymbolImpl(CVSymbol Symbol) {
447 CodeViewYAML::SymbolRecord Result;
448
449 auto Impl = std::make_shared<SymbolRecordImpl<SymbolType>>(Symbol.kind());
450 if (auto EC = Impl->fromCodeViewSymbol(Symbol))
451 return std::move(EC);
452 Result.Symbol = Impl;
453 return Result;
454}
455
456Expected<CodeViewYAML::SymbolRecord>
457CodeViewYAML::SymbolRecord::fromCodeViewSymbol(CVSymbol Symbol) {
458#define SYMBOL_RECORD(EnumName, EnumVal, ClassName) \
459 case EnumName: \
460 return fromCodeViewSymbolImpl<ClassName>(Symbol);
461#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
462 SYMBOL_RECORD(EnumName, EnumVal, ClassName)
463 switch (Symbol.kind()) {
464#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
465 default: { llvm_unreachable("Unknown symbol kind!"); }
466 }
467 return make_error<CodeViewError>(cv_error_code::corrupt_record);
468}
469
470template <typename ConcreteType>
471static void mapSymbolRecordImpl(IO &IO, const char *Class, SymbolKind Kind,
472 CodeViewYAML::SymbolRecord &Obj) {
473 if (!IO.outputting())
474 Obj.Symbol = std::make_shared<SymbolRecordImpl<ConcreteType>>(Kind);
475
476 IO.mapRequired(Class, *Obj.Symbol);
477}
478
479void MappingTraits<CodeViewYAML::SymbolRecord>::mapping(
480 IO &IO, CodeViewYAML::SymbolRecord &Obj) {
481 SymbolKind Kind;
482 if (IO.outputting())
483 Kind = Obj.Symbol->Kind;
484 IO.mapRequired("Kind", Kind);
485
486#define SYMBOL_RECORD(EnumName, EnumVal, ClassName) \
487 case EnumName: \
488 mapSymbolRecordImpl<ClassName>(IO, #ClassName, Kind, Obj); \
489 break;
490#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
491 SYMBOL_RECORD(EnumName, EnumVal, ClassName)
492 switch (Kind) {
493#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
494 default: { llvm_unreachable("Unknown symbol kind!"); }
495 }
496}