brintos

brintos / llvm-project-archived public Read only

0
0
Text · 30.8 KiB · f4ca1b2 Raw
827 lines · cpp
1//===- CodeViewYAMLTypes.cpp - CodeView YAMLIO types 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/CodeViewYAMLTypes.h"15#include "llvm/ADT/APSInt.h"16#include "llvm/ADT/ArrayRef.h"17#include "llvm/ADT/StringRef.h"18#include "llvm/BinaryFormat/COFF.h"19#include "llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h"20#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"21#include "llvm/DebugInfo/CodeView/CodeView.h"22#include "llvm/DebugInfo/CodeView/CodeViewError.h"23#include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"24#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"25#include "llvm/DebugInfo/CodeView/TypeIndex.h"26#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"27#include "llvm/Support/Allocator.h"28#include "llvm/Support/BinaryStreamReader.h"29#include "llvm/Support/BinaryStreamWriter.h"30#include "llvm/Support/Endian.h"31#include "llvm/Support/Error.h"32#include "llvm/Support/ErrorHandling.h"33#include "llvm/Support/YAMLTraits.h"34#include "llvm/Support/raw_ostream.h"35#include <algorithm>36#include <cassert>37#include <cstdint>38#include <vector>39 40using namespace llvm;41using namespace llvm::codeview;42using namespace llvm::CodeViewYAML;43using namespace llvm::CodeViewYAML::detail;44using namespace llvm::yaml;45 46LLVM_YAML_IS_SEQUENCE_VECTOR(OneMethodRecord)47LLVM_YAML_IS_SEQUENCE_VECTOR(VFTableSlotKind)48LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)49 50LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, QuotingType::None)51LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, QuotingType::None)52 53LLVM_YAML_DECLARE_ENUM_TRAITS(TypeLeafKind)54LLVM_YAML_DECLARE_ENUM_TRAITS(PointerToMemberRepresentation)55LLVM_YAML_DECLARE_ENUM_TRAITS(VFTableSlotKind)56LLVM_YAML_DECLARE_ENUM_TRAITS(CallingConvention)57LLVM_YAML_DECLARE_ENUM_TRAITS(PointerKind)58LLVM_YAML_DECLARE_ENUM_TRAITS(PointerMode)59LLVM_YAML_DECLARE_ENUM_TRAITS(HfaKind)60LLVM_YAML_DECLARE_ENUM_TRAITS(MemberAccess)61LLVM_YAML_DECLARE_ENUM_TRAITS(MethodKind)62LLVM_YAML_DECLARE_ENUM_TRAITS(WindowsRTClassKind)63LLVM_YAML_DECLARE_ENUM_TRAITS(LabelType)64 65LLVM_YAML_DECLARE_BITSET_TRAITS(PointerOptions)66LLVM_YAML_DECLARE_BITSET_TRAITS(ModifierOptions)67LLVM_YAML_DECLARE_BITSET_TRAITS(FunctionOptions)68LLVM_YAML_DECLARE_BITSET_TRAITS(ClassOptions)69LLVM_YAML_DECLARE_BITSET_TRAITS(MethodOptions)70 71LLVM_YAML_DECLARE_MAPPING_TRAITS(OneMethodRecord)72LLVM_YAML_DECLARE_MAPPING_TRAITS(MemberPointerInfo)73 74namespace llvm {75namespace CodeViewYAML {76namespace detail {77 78struct LeafRecordBase {79  TypeLeafKind Kind;80 81  explicit LeafRecordBase(TypeLeafKind K) : Kind(K) {}82  virtual ~LeafRecordBase() = default;83 84  virtual void map(yaml::IO &io) = 0;85  virtual CVType toCodeViewRecord(AppendingTypeTableBuilder &TS) const = 0;86  virtual Error fromCodeViewRecord(CVType Type) = 0;87};88 89template <typename T> struct LeafRecordImpl : public LeafRecordBase {90  explicit LeafRecordImpl(TypeLeafKind K)91      : LeafRecordBase(K), Record(static_cast<TypeRecordKind>(K)) {}92 93  void map(yaml::IO &io) override;94 95  Error fromCodeViewRecord(CVType Type) override {96    return TypeDeserializer::deserializeAs<T>(Type, Record);97  }98 99  CVType toCodeViewRecord(AppendingTypeTableBuilder &TS) const override {100    TS.writeLeafType(Record);101    return CVType(TS.records().back());102  }103 104  mutable T Record;105};106 107template <> struct LeafRecordImpl<FieldListRecord> : public LeafRecordBase {108  explicit LeafRecordImpl(TypeLeafKind K) : LeafRecordBase(K) {}109 110  void map(yaml::IO &io) override;111  CVType toCodeViewRecord(AppendingTypeTableBuilder &TS) const override;112  Error fromCodeViewRecord(CVType Type) override;113 114  std::vector<MemberRecord> Members;115};116 117struct MemberRecordBase {118  TypeLeafKind Kind;119 120  explicit MemberRecordBase(TypeLeafKind K) : Kind(K) {}121  virtual ~MemberRecordBase() = default;122 123  virtual void map(yaml::IO &io) = 0;124  virtual void writeTo(ContinuationRecordBuilder &CRB) = 0;125};126 127template <typename T> struct MemberRecordImpl : public MemberRecordBase {128  explicit MemberRecordImpl(TypeLeafKind K)129      : MemberRecordBase(K), Record(static_cast<TypeRecordKind>(K)) {}130 131  void map(yaml::IO &io) override;132 133  void writeTo(ContinuationRecordBuilder &CRB) override {134    CRB.writeMemberType(Record);135  }136 137  mutable T Record;138};139 140} // end namespace detail141} // end namespace CodeViewYAML142} // end namespace llvm143 144void ScalarTraits<GUID>::output(const GUID &G, void *, llvm::raw_ostream &OS) {145  OS << G;146}147 148StringRef ScalarTraits<GUID>::input(StringRef Scalar, void *Ctx, GUID &S) {149  if (Scalar.size() != 38)150    return "GUID strings are 38 characters long";151  if (Scalar.front() != '{' || Scalar.back() != '}')152    return "GUID is not enclosed in {}";153  Scalar = Scalar.substr(1, Scalar.size() - 2);154  SmallVector<StringRef, 6> A;155  Scalar.split(A, '-', 5);156  if (A.size() != 5 || Scalar[8] != '-' || Scalar[13] != '-' ||157      Scalar[18] != '-' || Scalar[23] != '-')158    return "GUID sections are not properly delineated with dashes";159  struct MSGuid {160    support::ulittle32_t Data1;161    support::ulittle16_t Data2;162    support::ulittle16_t Data3;163    support::ubig64_t Data4;164  };165  MSGuid G = {};166  uint64_t D41{}, D42{};167  if (!to_integer(A[0], G.Data1, 16) || !to_integer(A[1], G.Data2, 16) ||168      !to_integer(A[2], G.Data3, 16) || !to_integer(A[3], D41, 16) ||169      !to_integer(A[4], D42, 16))170    return "GUID contains non hex digits";171  G.Data4 = (D41 << 48) | D42;172  ::memcpy(&S, &G, sizeof(GUID));173  return "";174}175 176void ScalarTraits<TypeIndex>::output(const TypeIndex &S, void *,177                                     raw_ostream &OS) {178  OS << S.getIndex();179}180 181StringRef ScalarTraits<TypeIndex>::input(StringRef Scalar, void *Ctx,182                                         TypeIndex &S) {183  uint32_t I;184  StringRef Result = ScalarTraits<uint32_t>::input(Scalar, Ctx, I);185  S.setIndex(I);186  return Result;187}188 189void ScalarTraits<APSInt>::output(const APSInt &S, void *, raw_ostream &OS) {190  S.print(OS, S.isSigned());191}192 193StringRef ScalarTraits<APSInt>::input(StringRef Scalar, void *Ctx, APSInt &S) {194  S = APSInt(Scalar);195  return "";196}197 198void ScalarEnumerationTraits<TypeLeafKind>::enumeration(IO &io,199                                                        TypeLeafKind &Value) {200#define CV_TYPE(name, val) io.enumCase(Value, #name, name);201#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"202#undef CV_TYPE203}204 205void ScalarEnumerationTraits<PointerToMemberRepresentation>::enumeration(206    IO &IO, PointerToMemberRepresentation &Value) {207  IO.enumCase(Value, "Unknown", PointerToMemberRepresentation::Unknown);208  IO.enumCase(Value, "SingleInheritanceData",209              PointerToMemberRepresentation::SingleInheritanceData);210  IO.enumCase(Value, "MultipleInheritanceData",211              PointerToMemberRepresentation::MultipleInheritanceData);212  IO.enumCase(Value, "VirtualInheritanceData",213              PointerToMemberRepresentation::VirtualInheritanceData);214  IO.enumCase(Value, "GeneralData", PointerToMemberRepresentation::GeneralData);215  IO.enumCase(Value, "SingleInheritanceFunction",216              PointerToMemberRepresentation::SingleInheritanceFunction);217  IO.enumCase(Value, "MultipleInheritanceFunction",218              PointerToMemberRepresentation::MultipleInheritanceFunction);219  IO.enumCase(Value, "VirtualInheritanceFunction",220              PointerToMemberRepresentation::VirtualInheritanceFunction);221  IO.enumCase(Value, "GeneralFunction",222              PointerToMemberRepresentation::GeneralFunction);223}224 225void ScalarEnumerationTraits<VFTableSlotKind>::enumeration(226    IO &IO, VFTableSlotKind &Kind) {227  IO.enumCase(Kind, "Near16", VFTableSlotKind::Near16);228  IO.enumCase(Kind, "Far16", VFTableSlotKind::Far16);229  IO.enumCase(Kind, "This", VFTableSlotKind::This);230  IO.enumCase(Kind, "Outer", VFTableSlotKind::Outer);231  IO.enumCase(Kind, "Meta", VFTableSlotKind::Meta);232  IO.enumCase(Kind, "Near", VFTableSlotKind::Near);233  IO.enumCase(Kind, "Far", VFTableSlotKind::Far);234}235 236void ScalarEnumerationTraits<CallingConvention>::enumeration(237    IO &IO, CallingConvention &Value) {238  IO.enumCase(Value, "NearC", CallingConvention::NearC);239  IO.enumCase(Value, "FarC", CallingConvention::FarC);240  IO.enumCase(Value, "NearPascal", CallingConvention::NearPascal);241  IO.enumCase(Value, "FarPascal", CallingConvention::FarPascal);242  IO.enumCase(Value, "NearFast", CallingConvention::NearFast);243  IO.enumCase(Value, "FarFast", CallingConvention::FarFast);244  IO.enumCase(Value, "NearStdCall", CallingConvention::NearStdCall);245  IO.enumCase(Value, "FarStdCall", CallingConvention::FarStdCall);246  IO.enumCase(Value, "NearSysCall", CallingConvention::NearSysCall);247  IO.enumCase(Value, "FarSysCall", CallingConvention::FarSysCall);248  IO.enumCase(Value, "ThisCall", CallingConvention::ThisCall);249  IO.enumCase(Value, "MipsCall", CallingConvention::MipsCall);250  IO.enumCase(Value, "Generic", CallingConvention::Generic);251  IO.enumCase(Value, "AlphaCall", CallingConvention::AlphaCall);252  IO.enumCase(Value, "PpcCall", CallingConvention::PpcCall);253  IO.enumCase(Value, "SHCall", CallingConvention::SHCall);254  IO.enumCase(Value, "ArmCall", CallingConvention::ArmCall);255  IO.enumCase(Value, "AM33Call", CallingConvention::AM33Call);256  IO.enumCase(Value, "TriCall", CallingConvention::TriCall);257  IO.enumCase(Value, "SH5Call", CallingConvention::SH5Call);258  IO.enumCase(Value, "M32RCall", CallingConvention::M32RCall);259  IO.enumCase(Value, "ClrCall", CallingConvention::ClrCall);260  IO.enumCase(Value, "Inline", CallingConvention::Inline);261  IO.enumCase(Value, "NearVector", CallingConvention::NearVector);262  IO.enumCase(Value, "Swift", CallingConvention::Swift);263}264 265void ScalarEnumerationTraits<PointerKind>::enumeration(IO &IO,266                                                       PointerKind &Kind) {267  IO.enumCase(Kind, "Near16", PointerKind::Near16);268  IO.enumCase(Kind, "Far16", PointerKind::Far16);269  IO.enumCase(Kind, "Huge16", PointerKind::Huge16);270  IO.enumCase(Kind, "BasedOnSegment", PointerKind::BasedOnSegment);271  IO.enumCase(Kind, "BasedOnValue", PointerKind::BasedOnValue);272  IO.enumCase(Kind, "BasedOnSegmentValue", PointerKind::BasedOnSegmentValue);273  IO.enumCase(Kind, "BasedOnAddress", PointerKind::BasedOnAddress);274  IO.enumCase(Kind, "BasedOnSegmentAddress",275              PointerKind::BasedOnSegmentAddress);276  IO.enumCase(Kind, "BasedOnType", PointerKind::BasedOnType);277  IO.enumCase(Kind, "BasedOnSelf", PointerKind::BasedOnSelf);278  IO.enumCase(Kind, "Near32", PointerKind::Near32);279  IO.enumCase(Kind, "Far32", PointerKind::Far32);280  IO.enumCase(Kind, "Near64", PointerKind::Near64);281}282 283void ScalarEnumerationTraits<PointerMode>::enumeration(IO &IO,284                                                       PointerMode &Mode) {285  IO.enumCase(Mode, "Pointer", PointerMode::Pointer);286  IO.enumCase(Mode, "LValueReference", PointerMode::LValueReference);287  IO.enumCase(Mode, "PointerToDataMember", PointerMode::PointerToDataMember);288  IO.enumCase(Mode, "PointerToMemberFunction",289              PointerMode::PointerToMemberFunction);290  IO.enumCase(Mode, "RValueReference", PointerMode::RValueReference);291}292 293void ScalarEnumerationTraits<HfaKind>::enumeration(IO &IO, HfaKind &Value) {294  IO.enumCase(Value, "None", HfaKind::None);295  IO.enumCase(Value, "Float", HfaKind::Float);296  IO.enumCase(Value, "Double", HfaKind::Double);297  IO.enumCase(Value, "Other", HfaKind::Other);298}299 300void ScalarEnumerationTraits<MemberAccess>::enumeration(IO &IO,301                                                        MemberAccess &Access) {302  IO.enumCase(Access, "None", MemberAccess::None);303  IO.enumCase(Access, "Private", MemberAccess::Private);304  IO.enumCase(Access, "Protected", MemberAccess::Protected);305  IO.enumCase(Access, "Public", MemberAccess::Public);306}307 308void ScalarEnumerationTraits<MethodKind>::enumeration(IO &IO,309                                                      MethodKind &Kind) {310  IO.enumCase(Kind, "Vanilla", MethodKind::Vanilla);311  IO.enumCase(Kind, "Virtual", MethodKind::Virtual);312  IO.enumCase(Kind, "Static", MethodKind::Static);313  IO.enumCase(Kind, "Friend", MethodKind::Friend);314  IO.enumCase(Kind, "IntroducingVirtual", MethodKind::IntroducingVirtual);315  IO.enumCase(Kind, "PureVirtual", MethodKind::PureVirtual);316  IO.enumCase(Kind, "PureIntroducingVirtual",317              MethodKind::PureIntroducingVirtual);318}319 320void ScalarEnumerationTraits<WindowsRTClassKind>::enumeration(321    IO &IO, WindowsRTClassKind &Value) {322  IO.enumCase(Value, "None", WindowsRTClassKind::None);323  IO.enumCase(Value, "Ref", WindowsRTClassKind::RefClass);324  IO.enumCase(Value, "Value", WindowsRTClassKind::ValueClass);325  IO.enumCase(Value, "Interface", WindowsRTClassKind::Interface);326}327 328void ScalarEnumerationTraits<LabelType>::enumeration(IO &IO, LabelType &Value) {329  IO.enumCase(Value, "Near", LabelType::Near);330  IO.enumCase(Value, "Far", LabelType::Far);331}332 333void ScalarBitSetTraits<PointerOptions>::bitset(IO &IO,334                                                PointerOptions &Options) {335  IO.bitSetCase(Options, "None", PointerOptions::None);336  IO.bitSetCase(Options, "Flat32", PointerOptions::Flat32);337  IO.bitSetCase(Options, "Volatile", PointerOptions::Volatile);338  IO.bitSetCase(Options, "Const", PointerOptions::Const);339  IO.bitSetCase(Options, "Unaligned", PointerOptions::Unaligned);340  IO.bitSetCase(Options, "Restrict", PointerOptions::Restrict);341  IO.bitSetCase(Options, "WinRTSmartPointer",342                PointerOptions::WinRTSmartPointer);343}344 345void ScalarBitSetTraits<ModifierOptions>::bitset(IO &IO,346                                                 ModifierOptions &Options) {347  IO.bitSetCase(Options, "None", ModifierOptions::None);348  IO.bitSetCase(Options, "Const", ModifierOptions::Const);349  IO.bitSetCase(Options, "Volatile", ModifierOptions::Volatile);350  IO.bitSetCase(Options, "Unaligned", ModifierOptions::Unaligned);351}352 353void ScalarBitSetTraits<FunctionOptions>::bitset(IO &IO,354                                                 FunctionOptions &Options) {355  IO.bitSetCase(Options, "None", FunctionOptions::None);356  IO.bitSetCase(Options, "CxxReturnUdt", FunctionOptions::CxxReturnUdt);357  IO.bitSetCase(Options, "Constructor", FunctionOptions::Constructor);358  IO.bitSetCase(Options, "ConstructorWithVirtualBases",359                FunctionOptions::ConstructorWithVirtualBases);360}361 362void ScalarBitSetTraits<ClassOptions>::bitset(IO &IO, ClassOptions &Options) {363  IO.bitSetCase(Options, "None", ClassOptions::None);364  IO.bitSetCase(Options, "HasConstructorOrDestructor",365                ClassOptions::HasConstructorOrDestructor);366  IO.bitSetCase(Options, "HasOverloadedOperator",367                ClassOptions::HasOverloadedOperator);368  IO.bitSetCase(Options, "Nested", ClassOptions::Nested);369  IO.bitSetCase(Options, "ContainsNestedClass",370                ClassOptions::ContainsNestedClass);371  IO.bitSetCase(Options, "HasOverloadedAssignmentOperator",372                ClassOptions::HasOverloadedAssignmentOperator);373  IO.bitSetCase(Options, "HasConversionOperator",374                ClassOptions::HasConversionOperator);375  IO.bitSetCase(Options, "ForwardReference", ClassOptions::ForwardReference);376  IO.bitSetCase(Options, "Scoped", ClassOptions::Scoped);377  IO.bitSetCase(Options, "HasUniqueName", ClassOptions::HasUniqueName);378  IO.bitSetCase(Options, "Sealed", ClassOptions::Sealed);379  IO.bitSetCase(Options, "Intrinsic", ClassOptions::Intrinsic);380}381 382void ScalarBitSetTraits<MethodOptions>::bitset(IO &IO, MethodOptions &Options) {383  IO.bitSetCase(Options, "None", MethodOptions::None);384  IO.bitSetCase(Options, "Pseudo", MethodOptions::Pseudo);385  IO.bitSetCase(Options, "NoInherit", MethodOptions::NoInherit);386  IO.bitSetCase(Options, "NoConstruct", MethodOptions::NoConstruct);387  IO.bitSetCase(Options, "CompilerGenerated", MethodOptions::CompilerGenerated);388  IO.bitSetCase(Options, "Sealed", MethodOptions::Sealed);389}390 391void MappingTraits<MemberPointerInfo>::mapping(IO &IO, MemberPointerInfo &MPI) {392  IO.mapRequired("ContainingType", MPI.ContainingType);393  IO.mapRequired("Representation", MPI.Representation);394}395 396namespace llvm {397namespace CodeViewYAML {398namespace detail {399 400template <> void LeafRecordImpl<ModifierRecord>::map(IO &IO) {401  IO.mapRequired("ModifiedType", Record.ModifiedType);402  IO.mapRequired("Modifiers", Record.Modifiers);403}404 405template <> void LeafRecordImpl<ProcedureRecord>::map(IO &IO) {406  IO.mapRequired("ReturnType", Record.ReturnType);407  IO.mapRequired("CallConv", Record.CallConv);408  IO.mapRequired("Options", Record.Options);409  IO.mapRequired("ParameterCount", Record.ParameterCount);410  IO.mapRequired("ArgumentList", Record.ArgumentList);411}412 413template <> void LeafRecordImpl<MemberFunctionRecord>::map(IO &IO) {414  IO.mapRequired("ReturnType", Record.ReturnType);415  IO.mapRequired("ClassType", Record.ClassType);416  IO.mapRequired("ThisType", Record.ThisType);417  IO.mapRequired("CallConv", Record.CallConv);418  IO.mapRequired("Options", Record.Options);419  IO.mapRequired("ParameterCount", Record.ParameterCount);420  IO.mapRequired("ArgumentList", Record.ArgumentList);421  IO.mapRequired("ThisPointerAdjustment", Record.ThisPointerAdjustment);422}423 424template <> void LeafRecordImpl<LabelRecord>::map(IO &IO) {425  IO.mapRequired("Mode", Record.Mode);426}427 428template <> void LeafRecordImpl<MemberFuncIdRecord>::map(IO &IO) {429  IO.mapRequired("ClassType", Record.ClassType);430  IO.mapRequired("FunctionType", Record.FunctionType);431  IO.mapRequired("Name", Record.Name);432}433 434template <> void LeafRecordImpl<ArgListRecord>::map(IO &IO) {435  IO.mapRequired("ArgIndices", Record.ArgIndices);436}437 438template <> void LeafRecordImpl<StringListRecord>::map(IO &IO) {439  IO.mapRequired("StringIndices", Record.StringIndices);440}441 442template <> void LeafRecordImpl<PointerRecord>::map(IO &IO) {443  IO.mapRequired("ReferentType", Record.ReferentType);444  IO.mapRequired("Attrs", Record.Attrs);445  IO.mapOptional("MemberInfo", Record.MemberInfo);446}447 448template <> void LeafRecordImpl<ArrayRecord>::map(IO &IO) {449  IO.mapRequired("ElementType", Record.ElementType);450  IO.mapRequired("IndexType", Record.IndexType);451  IO.mapRequired("Size", Record.Size);452  IO.mapRequired("Name", Record.Name);453}454 455void LeafRecordImpl<FieldListRecord>::map(IO &IO) {456  IO.mapRequired("FieldList", Members);457}458 459} // end namespace detail460} // end namespace CodeViewYAML461} // end namespace llvm462 463namespace {464 465class MemberRecordConversionVisitor : public TypeVisitorCallbacks {466public:467  explicit MemberRecordConversionVisitor(std::vector<MemberRecord> &Records)468      : Records(Records) {}469 470#define TYPE_RECORD(EnumName, EnumVal, Name)471#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \472  Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \473    return visitKnownMemberImpl(Record);                                       \474  }475#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)476#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)477#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"478private:479  template <typename T> Error visitKnownMemberImpl(T &Record) {480    TypeLeafKind K = static_cast<TypeLeafKind>(Record.getKind());481    auto Impl = std::make_shared<MemberRecordImpl<T>>(K);482    Impl->Record = Record;483    Records.push_back(MemberRecord{Impl});484    return Error::success();485  }486 487  std::vector<MemberRecord> &Records;488};489 490} // end anonymous namespace491 492Error LeafRecordImpl<FieldListRecord>::fromCodeViewRecord(CVType Type) {493  MemberRecordConversionVisitor V(Members);494  FieldListRecord FieldList;495  cantFail(TypeDeserializer::deserializeAs<FieldListRecord>(Type,496                                                            FieldList));497  return visitMemberRecordStream(FieldList.Data, V);498}499 500CVType LeafRecordImpl<FieldListRecord>::toCodeViewRecord(501    AppendingTypeTableBuilder &TS) const {502  ContinuationRecordBuilder CRB;503  CRB.begin(ContinuationRecordKind::FieldList);504  for (const auto &Member : Members) {505    Member.Member->writeTo(CRB);506  }507  TS.insertRecord(CRB);508  return CVType(TS.records().back());509}510 511void MappingTraits<OneMethodRecord>::mapping(IO &io, OneMethodRecord &Record) {512  io.mapRequired("Type", Record.Type);513  io.mapRequired("Attrs", Record.Attrs.Attrs);514  io.mapRequired("VFTableOffset", Record.VFTableOffset);515  io.mapRequired("Name", Record.Name);516}517 518namespace llvm {519namespace CodeViewYAML {520namespace detail {521 522template <> void LeafRecordImpl<ClassRecord>::map(IO &IO) {523  IO.mapRequired("MemberCount", Record.MemberCount);524  IO.mapRequired("Options", Record.Options);525  IO.mapRequired("FieldList", Record.FieldList);526  IO.mapRequired("Name", Record.Name);527  IO.mapRequired("UniqueName", Record.UniqueName);528  IO.mapRequired("DerivationList", Record.DerivationList);529  IO.mapRequired("VTableShape", Record.VTableShape);530  IO.mapRequired("Size", Record.Size);531}532 533template <> void LeafRecordImpl<UnionRecord>::map(IO &IO) {534  IO.mapRequired("MemberCount", Record.MemberCount);535  IO.mapRequired("Options", Record.Options);536  IO.mapRequired("FieldList", Record.FieldList);537  IO.mapRequired("Name", Record.Name);538  IO.mapRequired("UniqueName", Record.UniqueName);539  IO.mapRequired("Size", Record.Size);540}541 542template <> void LeafRecordImpl<EnumRecord>::map(IO &IO) {543  IO.mapRequired("NumEnumerators", Record.MemberCount);544  IO.mapRequired("Options", Record.Options);545  IO.mapRequired("FieldList", Record.FieldList);546  IO.mapRequired("Name", Record.Name);547  IO.mapRequired("UniqueName", Record.UniqueName);548  IO.mapRequired("UnderlyingType", Record.UnderlyingType);549}550 551template <> void LeafRecordImpl<BitFieldRecord>::map(IO &IO) {552  IO.mapRequired("Type", Record.Type);553  IO.mapRequired("BitSize", Record.BitSize);554  IO.mapRequired("BitOffset", Record.BitOffset);555}556 557template <> void LeafRecordImpl<VFTableShapeRecord>::map(IO &IO) {558  IO.mapRequired("Slots", Record.Slots);559}560 561template <> void LeafRecordImpl<TypeServer2Record>::map(IO &IO) {562  IO.mapRequired("Guid", Record.Guid);563  IO.mapRequired("Age", Record.Age);564  IO.mapRequired("Name", Record.Name);565}566 567template <> void LeafRecordImpl<StringIdRecord>::map(IO &IO) {568  IO.mapRequired("Id", Record.Id);569  IO.mapRequired("String", Record.String);570}571 572template <> void LeafRecordImpl<FuncIdRecord>::map(IO &IO) {573  IO.mapRequired("ParentScope", Record.ParentScope);574  IO.mapRequired("FunctionType", Record.FunctionType);575  IO.mapRequired("Name", Record.Name);576}577 578template <> void LeafRecordImpl<UdtSourceLineRecord>::map(IO &IO) {579  IO.mapRequired("UDT", Record.UDT);580  IO.mapRequired("SourceFile", Record.SourceFile);581  IO.mapRequired("LineNumber", Record.LineNumber);582}583 584template <> void LeafRecordImpl<UdtModSourceLineRecord>::map(IO &IO) {585  IO.mapRequired("UDT", Record.UDT);586  IO.mapRequired("SourceFile", Record.SourceFile);587  IO.mapRequired("LineNumber", Record.LineNumber);588  IO.mapRequired("Module", Record.Module);589}590 591template <> void LeafRecordImpl<BuildInfoRecord>::map(IO &IO) {592  IO.mapRequired("ArgIndices", Record.ArgIndices);593}594 595template <> void LeafRecordImpl<VFTableRecord>::map(IO &IO) {596  IO.mapRequired("CompleteClass", Record.CompleteClass);597  IO.mapRequired("OverriddenVFTable", Record.OverriddenVFTable);598  IO.mapRequired("VFPtrOffset", Record.VFPtrOffset);599  IO.mapRequired("MethodNames", Record.MethodNames);600}601 602template <> void LeafRecordImpl<MethodOverloadListRecord>::map(IO &IO) {603  IO.mapRequired("Methods", Record.Methods);604}605 606template <> void LeafRecordImpl<PrecompRecord>::map(IO &IO) {607  IO.mapRequired("StartTypeIndex", Record.StartTypeIndex);608  IO.mapRequired("TypesCount", Record.TypesCount);609  IO.mapRequired("Signature", Record.Signature);610  IO.mapRequired("PrecompFilePath", Record.PrecompFilePath);611}612 613template <> void LeafRecordImpl<EndPrecompRecord>::map(IO &IO) {614  IO.mapRequired("Signature", Record.Signature);615}616 617template <> void MemberRecordImpl<OneMethodRecord>::map(IO &IO) {618  MappingTraits<OneMethodRecord>::mapping(IO, Record);619}620 621template <> void MemberRecordImpl<OverloadedMethodRecord>::map(IO &IO) {622  IO.mapRequired("NumOverloads", Record.NumOverloads);623  IO.mapRequired("MethodList", Record.MethodList);624  IO.mapRequired("Name", Record.Name);625}626 627template <> void MemberRecordImpl<NestedTypeRecord>::map(IO &IO) {628  IO.mapRequired("Type", Record.Type);629  IO.mapRequired("Name", Record.Name);630}631 632template <> void MemberRecordImpl<DataMemberRecord>::map(IO &IO) {633  IO.mapRequired("Attrs", Record.Attrs.Attrs);634  IO.mapRequired("Type", Record.Type);635  IO.mapRequired("FieldOffset", Record.FieldOffset);636  IO.mapRequired("Name", Record.Name);637}638 639template <> void MemberRecordImpl<StaticDataMemberRecord>::map(IO &IO) {640  IO.mapRequired("Attrs", Record.Attrs.Attrs);641  IO.mapRequired("Type", Record.Type);642  IO.mapRequired("Name", Record.Name);643}644 645template <> void MemberRecordImpl<EnumeratorRecord>::map(IO &IO) {646  IO.mapRequired("Attrs", Record.Attrs.Attrs);647  IO.mapRequired("Value", Record.Value);648  IO.mapRequired("Name", Record.Name);649}650 651template <> void MemberRecordImpl<VFPtrRecord>::map(IO &IO) {652  IO.mapRequired("Type", Record.Type);653}654 655template <> void MemberRecordImpl<BaseClassRecord>::map(IO &IO) {656  IO.mapRequired("Attrs", Record.Attrs.Attrs);657  IO.mapRequired("Type", Record.Type);658  IO.mapRequired("Offset", Record.Offset);659}660 661template <> void MemberRecordImpl<VirtualBaseClassRecord>::map(IO &IO) {662  IO.mapRequired("Attrs", Record.Attrs.Attrs);663  IO.mapRequired("BaseType", Record.BaseType);664  IO.mapRequired("VBPtrType", Record.VBPtrType);665  IO.mapRequired("VBPtrOffset", Record.VBPtrOffset);666  IO.mapRequired("VTableIndex", Record.VTableIndex);667}668 669template <> void MemberRecordImpl<ListContinuationRecord>::map(IO &IO) {670  IO.mapRequired("ContinuationIndex", Record.ContinuationIndex);671}672 673} // end namespace detail674} // end namespace CodeViewYAML675} // end namespace llvm676 677template <typename T>678static inline Expected<LeafRecord> fromCodeViewRecordImpl(CVType Type) {679  LeafRecord Result;680 681  auto Impl = std::make_shared<LeafRecordImpl<T>>(Type.kind());682  if (auto EC = Impl->fromCodeViewRecord(Type))683    return std::move(EC);684  Result.Leaf = Impl;685  return Result;686}687 688Expected<LeafRecord> LeafRecord::fromCodeViewRecord(CVType Type) {689#define TYPE_RECORD(EnumName, EnumVal, ClassName)                              \690  case EnumName:                                                               \691    return fromCodeViewRecordImpl<ClassName##Record>(Type);692#define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)             \693  TYPE_RECORD(EnumName, EnumVal, ClassName)694#define MEMBER_RECORD(EnumName, EnumVal, ClassName)695#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)696  switch (Type.kind()) {697#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"698  default:699      llvm_unreachable("Unknown leaf kind!");700  }701  return make_error<CodeViewError>(cv_error_code::corrupt_record);702}703 704CVType705LeafRecord::toCodeViewRecord(AppendingTypeTableBuilder &Serializer) const {706  return Leaf->toCodeViewRecord(Serializer);707}708 709namespace llvm {710namespace yaml {711 712template <> struct MappingTraits<LeafRecordBase> {713  static void mapping(IO &io, LeafRecordBase &Record) { Record.map(io); }714};715 716template <> struct MappingTraits<MemberRecordBase> {717  static void mapping(IO &io, MemberRecordBase &Record) { Record.map(io); }718};719 720} // end namespace yaml721} // end namespace llvm722 723template <typename ConcreteType>724static void mapLeafRecordImpl(IO &IO, const char *Class, TypeLeafKind Kind,725                              LeafRecord &Obj) {726  if (!IO.outputting())727    Obj.Leaf = std::make_shared<LeafRecordImpl<ConcreteType>>(Kind);728 729  if (Kind == LF_FIELDLIST)730    Obj.Leaf->map(IO);731  else732    IO.mapRequired(Class, *Obj.Leaf);733}734 735void MappingTraits<LeafRecord>::mapping(IO &IO, LeafRecord &Obj) {736  TypeLeafKind Kind;737  if (IO.outputting())738    Kind = Obj.Leaf->Kind;739  IO.mapRequired("Kind", Kind);740 741#define TYPE_RECORD(EnumName, EnumVal, ClassName)                              \742  case EnumName:                                                               \743    mapLeafRecordImpl<ClassName##Record>(IO, #ClassName, Kind, Obj);           \744    break;745#define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)             \746  TYPE_RECORD(EnumName, EnumVal, ClassName)747#define MEMBER_RECORD(EnumName, EnumVal, ClassName)748#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)749  switch (Kind) {750#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"751  default: { llvm_unreachable("Unknown leaf kind!"); }752  }753}754 755template <typename ConcreteType>756static void mapMemberRecordImpl(IO &IO, const char *Class, TypeLeafKind Kind,757                                MemberRecord &Obj) {758  if (!IO.outputting())759    Obj.Member = std::make_shared<MemberRecordImpl<ConcreteType>>(Kind);760 761  IO.mapRequired(Class, *Obj.Member);762}763 764void MappingTraits<MemberRecord>::mapping(IO &IO, MemberRecord &Obj) {765  TypeLeafKind Kind;766  if (IO.outputting())767    Kind = Obj.Member->Kind;768  IO.mapRequired("Kind", Kind);769 770#define MEMBER_RECORD(EnumName, EnumVal, ClassName)                            \771  case EnumName:                                                               \772    mapMemberRecordImpl<ClassName##Record>(IO, #ClassName, Kind, Obj);         \773    break;774#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)           \775  MEMBER_RECORD(EnumName, EnumVal, ClassName)776#define TYPE_RECORD(EnumName, EnumVal, ClassName)777#define TYPE_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)778  switch (Kind) {779#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"780  default: { llvm_unreachable("Unknown member kind!"); }781  }782}783 784std::vector<LeafRecord>785llvm::CodeViewYAML::fromDebugT(ArrayRef<uint8_t> DebugTorP,786                               StringRef SectionName) {787  ExitOnError Err("Invalid " + std::string(SectionName) + " section!");788  BinaryStreamReader Reader(DebugTorP, llvm::endianness::little);789  CVTypeArray Types;790  uint32_t Magic;791 792  Err(Reader.readInteger(Magic));793  assert(Magic == COFF::DEBUG_SECTION_MAGIC &&794         "Invalid .debug$T or .debug$P section!");795 796  std::vector<LeafRecord> Result;797  Err(Reader.readArray(Types, Reader.bytesRemaining()));798  for (const auto &T : Types) {799    auto CVT = Err(LeafRecord::fromCodeViewRecord(T));800    Result.push_back(CVT);801  }802  return Result;803}804 805ArrayRef<uint8_t> llvm::CodeViewYAML::toDebugT(ArrayRef<LeafRecord> Leafs,806                                               BumpPtrAllocator &Alloc,807                                               StringRef SectionName) {808  AppendingTypeTableBuilder TS(Alloc);809  uint32_t Size = sizeof(uint32_t);810  for (const auto &Leaf : Leafs) {811    CVType T = Leaf.Leaf->toCodeViewRecord(TS);812    Size += T.length();813    assert(T.length() % 4 == 0 && "Improper type record alignment!");814  }815  uint8_t *ResultBuffer = Alloc.Allocate<uint8_t>(Size);816  MutableArrayRef<uint8_t> Output(ResultBuffer, Size);817  BinaryStreamWriter Writer(Output, llvm::endianness::little);818  ExitOnError Err("Error writing type record to " + std::string(SectionName) +819                  " section");820  Err(Writer.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC));821  for (const auto &R : TS.records()) {822    Err(Writer.writeBytes(R));823  }824  assert(Writer.bytesRemaining() == 0 && "Didn't write all type record bytes!");825  return Output;826}827