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