brintos

brintos / llvm-project-archived public Read only

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