forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			631 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			631 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
//===- CodeViewYAMLSymbols.cpp - CodeView YAMLIO Symbol implementation ----===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This file defines classes for handling the YAML representation of CodeView
 | 
						|
// Debug Info.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
 | 
						|
#include "llvm/ADT/ArrayRef.h"
 | 
						|
#include "llvm/ADT/StringRef.h"
 | 
						|
#include "llvm/DebugInfo/CodeView/CodeView.h"
 | 
						|
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
 | 
						|
#include "llvm/DebugInfo/CodeView/EnumTables.h"
 | 
						|
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
 | 
						|
#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
 | 
						|
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 | 
						|
#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
 | 
						|
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
 | 
						|
#include "llvm/ObjectYAML/YAML.h"
 | 
						|
#include "llvm/Support/Allocator.h"
 | 
						|
#include "llvm/Support/Error.h"
 | 
						|
#include "llvm/Support/YAMLTraits.h"
 | 
						|
#include <algorithm>
 | 
						|
#include <cstdint>
 | 
						|
#include <cstring>
 | 
						|
#include <string>
 | 
						|
#include <vector>
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
using namespace llvm::codeview;
 | 
						|
using namespace llvm::CodeViewYAML;
 | 
						|
using namespace llvm::CodeViewYAML::detail;
 | 
						|
using namespace llvm::yaml;
 | 
						|
 | 
						|
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(TypeIndex)
 | 
						|
LLVM_YAML_IS_SEQUENCE_VECTOR(LocalVariableAddrGap)
 | 
						|
 | 
						|
// We only need to declare these, the definitions are in CodeViewYAMLTypes.cpp
 | 
						|
LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, QuotingType::None)
 | 
						|
LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, QuotingType::None)
 | 
						|
 | 
						|
LLVM_YAML_DECLARE_ENUM_TRAITS(SymbolKind)
 | 
						|
LLVM_YAML_DECLARE_ENUM_TRAITS(FrameCookieKind)
 | 
						|
 | 
						|
LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym2Flags)
 | 
						|
LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym3Flags)
 | 
						|
LLVM_YAML_DECLARE_BITSET_TRAITS(ExportFlags)
 | 
						|
LLVM_YAML_DECLARE_BITSET_TRAITS(PublicSymFlags)
 | 
						|
LLVM_YAML_DECLARE_BITSET_TRAITS(LocalSymFlags)
 | 
						|
LLVM_YAML_DECLARE_BITSET_TRAITS(ProcSymFlags)
 | 
						|
LLVM_YAML_DECLARE_BITSET_TRAITS(FrameProcedureOptions)
 | 
						|
LLVM_YAML_DECLARE_ENUM_TRAITS(CPUType)
 | 
						|
LLVM_YAML_DECLARE_ENUM_TRAITS(RegisterId)
 | 
						|
LLVM_YAML_DECLARE_ENUM_TRAITS(TrampolineType)
 | 
						|
LLVM_YAML_DECLARE_ENUM_TRAITS(ThunkOrdinal)
 | 
						|
 | 
						|
LLVM_YAML_STRONG_TYPEDEF(StringRef, TypeName)
 | 
						|
 | 
						|
LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeName, QuotingType::Single)
 | 
						|
 | 
						|
StringRef ScalarTraits<TypeName>::input(StringRef S, void *V, TypeName &T) {
 | 
						|
  return ScalarTraits<StringRef>::input(S, V, T.value);
 | 
						|
}
 | 
						|
 | 
						|
void ScalarTraits<TypeName>::output(const TypeName &T, void *V,
 | 
						|
                                    raw_ostream &R) {
 | 
						|
  ScalarTraits<StringRef>::output(T.value, V, R);
 | 
						|
}
 | 
						|
 | 
						|
void ScalarEnumerationTraits<SymbolKind>::enumeration(IO &io,
 | 
						|
                                                      SymbolKind &Value) {
 | 
						|
  auto SymbolNames = getSymbolTypeNames();
 | 
						|
  for (const auto &E : SymbolNames)
 | 
						|
    io.enumCase(Value, E.Name.str().c_str(), E.Value);
 | 
						|
}
 | 
						|
 | 
						|
void ScalarBitSetTraits<CompileSym2Flags>::bitset(IO &io,
 | 
						|
                                                  CompileSym2Flags &Flags) {
 | 
						|
  auto FlagNames = getCompileSym2FlagNames();
 | 
						|
  for (const auto &E : FlagNames) {
 | 
						|
    io.bitSetCase(Flags, E.Name.str().c_str(),
 | 
						|
                  static_cast<CompileSym2Flags>(E.Value));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void ScalarBitSetTraits<CompileSym3Flags>::bitset(IO &io,
 | 
						|
                                                  CompileSym3Flags &Flags) {
 | 
						|
  auto FlagNames = getCompileSym3FlagNames();
 | 
						|
  for (const auto &E : FlagNames) {
 | 
						|
    io.bitSetCase(Flags, E.Name.str().c_str(),
 | 
						|
                  static_cast<CompileSym3Flags>(E.Value));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void ScalarBitSetTraits<ExportFlags>::bitset(IO &io, ExportFlags &Flags) {
 | 
						|
  auto FlagNames = getExportSymFlagNames();
 | 
						|
  for (const auto &E : FlagNames) {
 | 
						|
    io.bitSetCase(Flags, E.Name.str().c_str(),
 | 
						|
                  static_cast<ExportFlags>(E.Value));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void ScalarBitSetTraits<PublicSymFlags>::bitset(IO &io, PublicSymFlags &Flags) {
 | 
						|
  auto FlagNames = getPublicSymFlagNames();
 | 
						|
  for (const auto &E : FlagNames) {
 | 
						|
    io.bitSetCase(Flags, E.Name.str().c_str(),
 | 
						|
                  static_cast<PublicSymFlags>(E.Value));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void ScalarBitSetTraits<LocalSymFlags>::bitset(IO &io, LocalSymFlags &Flags) {
 | 
						|
  auto FlagNames = getLocalFlagNames();
 | 
						|
  for (const auto &E : FlagNames) {
 | 
						|
    io.bitSetCase(Flags, E.Name.str().c_str(),
 | 
						|
                  static_cast<LocalSymFlags>(E.Value));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void ScalarBitSetTraits<ProcSymFlags>::bitset(IO &io, ProcSymFlags &Flags) {
 | 
						|
  auto FlagNames = getProcSymFlagNames();
 | 
						|
  for (const auto &E : FlagNames) {
 | 
						|
    io.bitSetCase(Flags, E.Name.str().c_str(),
 | 
						|
                  static_cast<ProcSymFlags>(E.Value));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void ScalarBitSetTraits<FrameProcedureOptions>::bitset(
 | 
						|
    IO &io, FrameProcedureOptions &Flags) {
 | 
						|
  auto FlagNames = getFrameProcSymFlagNames();
 | 
						|
  for (const auto &E : FlagNames) {
 | 
						|
    io.bitSetCase(Flags, E.Name.str().c_str(),
 | 
						|
                  static_cast<FrameProcedureOptions>(E.Value));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void ScalarEnumerationTraits<CPUType>::enumeration(IO &io, CPUType &Cpu) {
 | 
						|
  auto CpuNames = getCPUTypeNames();
 | 
						|
  for (const auto &E : CpuNames) {
 | 
						|
    io.enumCase(Cpu, E.Name.str().c_str(), static_cast<CPUType>(E.Value));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void ScalarEnumerationTraits<RegisterId>::enumeration(IO &io, RegisterId &Reg) {
 | 
						|
  auto RegNames = getRegisterNames();
 | 
						|
  for (const auto &E : RegNames) {
 | 
						|
    io.enumCase(Reg, E.Name.str().c_str(), static_cast<RegisterId>(E.Value));
 | 
						|
  }
 | 
						|
  io.enumFallback<Hex16>(Reg);
 | 
						|
}
 | 
						|
 | 
						|
void ScalarEnumerationTraits<TrampolineType>::enumeration(
 | 
						|
    IO &io, TrampolineType &Tramp) {
 | 
						|
  auto TrampNames = getTrampolineNames();
 | 
						|
  for (const auto &E : TrampNames) {
 | 
						|
    io.enumCase(Tramp, E.Name.str().c_str(),
 | 
						|
                static_cast<TrampolineType>(E.Value));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void ScalarEnumerationTraits<ThunkOrdinal>::enumeration(IO &io,
 | 
						|
                                                        ThunkOrdinal &Ord) {
 | 
						|
  auto ThunkNames = getThunkOrdinalNames();
 | 
						|
  for (const auto &E : ThunkNames) {
 | 
						|
    io.enumCase(Ord, E.Name.str().c_str(), static_cast<ThunkOrdinal>(E.Value));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void ScalarEnumerationTraits<FrameCookieKind>::enumeration(
 | 
						|
    IO &io, FrameCookieKind &FC) {
 | 
						|
  auto ThunkNames = getFrameCookieKindNames();
 | 
						|
  for (const auto &E : ThunkNames) {
 | 
						|
    io.enumCase(FC, E.Name.str().c_str(),
 | 
						|
                static_cast<FrameCookieKind>(E.Value));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
namespace yaml {
 | 
						|
template <> struct MappingTraits<LocalVariableAddrRange> {
 | 
						|
  static void mapping(IO &io, LocalVariableAddrRange &Range) {
 | 
						|
    io.mapRequired("OffsetStart", Range.OffsetStart);
 | 
						|
    io.mapRequired("ISectStart", Range.ISectStart);
 | 
						|
    io.mapRequired("Range", Range.Range);
 | 
						|
  }
 | 
						|
};
 | 
						|
template <> struct MappingTraits<LocalVariableAddrGap> {
 | 
						|
  static void mapping(IO &io, LocalVariableAddrGap &Gap) {
 | 
						|
    io.mapRequired("GapStartOffset", Gap.GapStartOffset);
 | 
						|
    io.mapRequired("Range", Gap.Range);
 | 
						|
  }
 | 
						|
};
 | 
						|
} // namespace yaml
 | 
						|
} // namespace llvm
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
namespace CodeViewYAML {
 | 
						|
namespace detail {
 | 
						|
 | 
						|
struct SymbolRecordBase {
 | 
						|
  codeview::SymbolKind Kind;
 | 
						|
 | 
						|
  explicit SymbolRecordBase(codeview::SymbolKind K) : Kind(K) {}
 | 
						|
  virtual ~SymbolRecordBase() = default;
 | 
						|
 | 
						|
  virtual void map(yaml::IO &io) = 0;
 | 
						|
  virtual codeview::CVSymbol
 | 
						|
  toCodeViewSymbol(BumpPtrAllocator &Allocator,
 | 
						|
                   CodeViewContainer Container) const = 0;
 | 
						|
  virtual Error fromCodeViewSymbol(codeview::CVSymbol Type) = 0;
 | 
						|
};
 | 
						|
 | 
						|
template <typename T> struct SymbolRecordImpl : public SymbolRecordBase {
 | 
						|
  explicit SymbolRecordImpl(codeview::SymbolKind K)
 | 
						|
      : SymbolRecordBase(K), Symbol(static_cast<SymbolRecordKind>(K)) {}
 | 
						|
 | 
						|
  void map(yaml::IO &io) override;
 | 
						|
 | 
						|
  codeview::CVSymbol
 | 
						|
  toCodeViewSymbol(BumpPtrAllocator &Allocator,
 | 
						|
                   CodeViewContainer Container) const override {
 | 
						|
    return SymbolSerializer::writeOneSymbol(Symbol, Allocator, Container);
 | 
						|
  }
 | 
						|
 | 
						|
  Error fromCodeViewSymbol(codeview::CVSymbol CVS) override {
 | 
						|
    return SymbolDeserializer::deserializeAs<T>(CVS, Symbol);
 | 
						|
  }
 | 
						|
 | 
						|
  mutable T Symbol;
 | 
						|
};
 | 
						|
 | 
						|
struct UnknownSymbolRecord : public SymbolRecordBase {
 | 
						|
  explicit UnknownSymbolRecord(codeview::SymbolKind K) : SymbolRecordBase(K) {}
 | 
						|
 | 
						|
  void map(yaml::IO &io) override;
 | 
						|
 | 
						|
  CVSymbol toCodeViewSymbol(BumpPtrAllocator &Allocator,
 | 
						|
                            CodeViewContainer Container) const override {
 | 
						|
    RecordPrefix Prefix;
 | 
						|
    uint32_t TotalLen = sizeof(RecordPrefix) + Data.size();
 | 
						|
    Prefix.RecordKind = Kind;
 | 
						|
    Prefix.RecordLen = TotalLen - 2;
 | 
						|
    uint8_t *Buffer = Allocator.Allocate<uint8_t>(TotalLen);
 | 
						|
    ::memcpy(Buffer, &Prefix, sizeof(RecordPrefix));
 | 
						|
    ::memcpy(Buffer + sizeof(RecordPrefix), Data.data(), Data.size());
 | 
						|
    return CVSymbol(Kind, ArrayRef<uint8_t>(Buffer, TotalLen));
 | 
						|
  }
 | 
						|
 | 
						|
  Error fromCodeViewSymbol(CVSymbol CVS) override {
 | 
						|
    this->Kind = CVS.kind();
 | 
						|
    Data = CVS.RecordData.drop_front(sizeof(RecordPrefix));
 | 
						|
    return Error::success();
 | 
						|
  }
 | 
						|
 | 
						|
  std::vector<uint8_t> Data;
 | 
						|
};
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<ScopeEndSym>::map(IO &IO) {}
 | 
						|
 | 
						|
void UnknownSymbolRecord::map(yaml::IO &io) {
 | 
						|
  yaml::BinaryRef Binary;
 | 
						|
  if (io.outputting())
 | 
						|
    Binary = yaml::BinaryRef(Data);
 | 
						|
  io.mapRequired("Data", Binary);
 | 
						|
  if (!io.outputting()) {
 | 
						|
    std::string Str;
 | 
						|
    raw_string_ostream OS(Str);
 | 
						|
    Binary.writeAsBinary(OS);
 | 
						|
    OS.flush();
 | 
						|
    Data.assign(Str.begin(), Str.end());
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<Thunk32Sym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Parent", Symbol.Parent);
 | 
						|
  IO.mapRequired("End", Symbol.End);
 | 
						|
  IO.mapRequired("Next", Symbol.Next);
 | 
						|
  IO.mapRequired("Off", Symbol.Offset);
 | 
						|
  IO.mapRequired("Seg", Symbol.Segment);
 | 
						|
  IO.mapRequired("Len", Symbol.Length);
 | 
						|
  IO.mapRequired("Ordinal", Symbol.Thunk);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<TrampolineSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Type", Symbol.Type);
 | 
						|
  IO.mapRequired("Size", Symbol.Size);
 | 
						|
  IO.mapRequired("ThunkOff", Symbol.ThunkOffset);
 | 
						|
  IO.mapRequired("TargetOff", Symbol.TargetOffset);
 | 
						|
  IO.mapRequired("ThunkSection", Symbol.ThunkSection);
 | 
						|
  IO.mapRequired("TargetSection", Symbol.TargetSection);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<SectionSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("SectionNumber", Symbol.SectionNumber);
 | 
						|
  IO.mapRequired("Alignment", Symbol.Alignment);
 | 
						|
  IO.mapRequired("Rva", Symbol.Rva);
 | 
						|
  IO.mapRequired("Length", Symbol.Length);
 | 
						|
  IO.mapRequired("Characteristics", Symbol.Characteristics);
 | 
						|
  IO.mapRequired("Name", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<CoffGroupSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Size", Symbol.Size);
 | 
						|
  IO.mapRequired("Characteristics", Symbol.Characteristics);
 | 
						|
  IO.mapRequired("Offset", Symbol.Offset);
 | 
						|
  IO.mapRequired("Segment", Symbol.Segment);
 | 
						|
  IO.mapRequired("Name", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<ExportSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Ordinal", Symbol.Ordinal);
 | 
						|
  IO.mapRequired("Flags", Symbol.Flags);
 | 
						|
  IO.mapRequired("Name", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<ProcSym>::map(IO &IO) {
 | 
						|
  IO.mapOptional("PtrParent", Symbol.Parent, 0U);
 | 
						|
  IO.mapOptional("PtrEnd", Symbol.End, 0U);
 | 
						|
  IO.mapOptional("PtrNext", Symbol.Next, 0U);
 | 
						|
  IO.mapRequired("CodeSize", Symbol.CodeSize);
 | 
						|
  IO.mapRequired("DbgStart", Symbol.DbgStart);
 | 
						|
  IO.mapRequired("DbgEnd", Symbol.DbgEnd);
 | 
						|
  IO.mapRequired("FunctionType", Symbol.FunctionType);
 | 
						|
  IO.mapOptional("Offset", Symbol.CodeOffset, 0U);
 | 
						|
  IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
 | 
						|
  IO.mapRequired("Flags", Symbol.Flags);
 | 
						|
  IO.mapRequired("DisplayName", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<RegisterSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Type", Symbol.Index);
 | 
						|
  IO.mapRequired("Seg", Symbol.Register);
 | 
						|
  IO.mapRequired("Name", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<PublicSym32>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Flags", Symbol.Flags);
 | 
						|
  IO.mapOptional("Offset", Symbol.Offset, 0U);
 | 
						|
  IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
 | 
						|
  IO.mapRequired("Name", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<ProcRefSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("SumName", Symbol.SumName);
 | 
						|
  IO.mapRequired("SymOffset", Symbol.SymOffset);
 | 
						|
  IO.mapRequired("Mod", Symbol.Module);
 | 
						|
  IO.mapRequired("Name", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<EnvBlockSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Entries", Symbol.Fields);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<InlineSiteSym>::map(IO &IO) {
 | 
						|
  IO.mapOptional("PtrParent", Symbol.Parent, 0U);
 | 
						|
  IO.mapOptional("PtrEnd", Symbol.End, 0U);
 | 
						|
  IO.mapRequired("Inlinee", Symbol.Inlinee);
 | 
						|
  // TODO: The binary annotations
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<LocalSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Type", Symbol.Type);
 | 
						|
  IO.mapRequired("Flags", Symbol.Flags);
 | 
						|
 | 
						|
  IO.mapRequired("VarName", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<DefRangeSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Program", Symbol.Program);
 | 
						|
  IO.mapRequired("Range", Symbol.Range);
 | 
						|
  IO.mapRequired("Gaps", Symbol.Gaps);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<DefRangeSubfieldSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Program", Symbol.Program);
 | 
						|
  IO.mapRequired("OffsetInParent", Symbol.OffsetInParent);
 | 
						|
  IO.mapRequired("Range", Symbol.Range);
 | 
						|
  IO.mapRequired("Gaps", Symbol.Gaps);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<DefRangeRegisterSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Register", Symbol.Hdr.Register);
 | 
						|
  IO.mapRequired("MayHaveNoName", Symbol.Hdr.MayHaveNoName);
 | 
						|
  IO.mapRequired("Range", Symbol.Range);
 | 
						|
  IO.mapRequired("Gaps", Symbol.Gaps);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<DefRangeFramePointerRelSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Offset", Symbol.Offset);
 | 
						|
  IO.mapRequired("Range", Symbol.Range);
 | 
						|
  IO.mapRequired("Gaps", Symbol.Gaps);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<DefRangeSubfieldRegisterSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Register", Symbol.Hdr.Register);
 | 
						|
  IO.mapRequired("MayHaveNoName", Symbol.Hdr.MayHaveNoName);
 | 
						|
  IO.mapRequired("OffsetInParent", Symbol.Hdr.OffsetInParent);
 | 
						|
  IO.mapRequired("Range", Symbol.Range);
 | 
						|
  IO.mapRequired("Gaps", Symbol.Gaps);
 | 
						|
}
 | 
						|
 | 
						|
template <>
 | 
						|
void SymbolRecordImpl<DefRangeFramePointerRelFullScopeSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Register", Symbol.Offset);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<DefRangeRegisterRelSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Register", Symbol.Hdr.Register);
 | 
						|
  IO.mapRequired("Flags", Symbol.Hdr.Flags);
 | 
						|
  IO.mapRequired("BasePointerOffset", Symbol.Hdr.BasePointerOffset);
 | 
						|
  IO.mapRequired("Range", Symbol.Range);
 | 
						|
  IO.mapRequired("Gaps", Symbol.Gaps);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<BlockSym>::map(IO &IO) {
 | 
						|
  IO.mapOptional("PtrParent", Symbol.Parent, 0U);
 | 
						|
  IO.mapOptional("PtrEnd", Symbol.End, 0U);
 | 
						|
  IO.mapRequired("CodeSize", Symbol.CodeSize);
 | 
						|
  IO.mapOptional("Offset", Symbol.CodeOffset, 0U);
 | 
						|
  IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
 | 
						|
  IO.mapRequired("BlockName", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<LabelSym>::map(IO &IO) {
 | 
						|
  IO.mapOptional("Offset", Symbol.CodeOffset, 0U);
 | 
						|
  IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
 | 
						|
  IO.mapRequired("Flags", Symbol.Flags);
 | 
						|
  IO.mapRequired("Flags", Symbol.Flags);
 | 
						|
  IO.mapRequired("DisplayName", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<ObjNameSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Signature", Symbol.Signature);
 | 
						|
  IO.mapRequired("ObjectName", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<Compile2Sym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Flags", Symbol.Flags);
 | 
						|
  IO.mapRequired("Machine", Symbol.Machine);
 | 
						|
  IO.mapRequired("FrontendMajor", Symbol.VersionFrontendMajor);
 | 
						|
  IO.mapRequired("FrontendMinor", Symbol.VersionFrontendMinor);
 | 
						|
  IO.mapRequired("FrontendBuild", Symbol.VersionFrontendBuild);
 | 
						|
  IO.mapRequired("BackendMajor", Symbol.VersionBackendMajor);
 | 
						|
  IO.mapRequired("BackendMinor", Symbol.VersionBackendMinor);
 | 
						|
  IO.mapRequired("BackendBuild", Symbol.VersionBackendBuild);
 | 
						|
  IO.mapRequired("Version", Symbol.Version);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<Compile3Sym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Flags", Symbol.Flags);
 | 
						|
  IO.mapRequired("Machine", Symbol.Machine);
 | 
						|
  IO.mapRequired("FrontendMajor", Symbol.VersionFrontendMajor);
 | 
						|
  IO.mapRequired("FrontendMinor", Symbol.VersionFrontendMinor);
 | 
						|
  IO.mapRequired("FrontendBuild", Symbol.VersionFrontendBuild);
 | 
						|
  IO.mapRequired("FrontendQFE", Symbol.VersionFrontendQFE);
 | 
						|
  IO.mapRequired("BackendMajor", Symbol.VersionBackendMajor);
 | 
						|
  IO.mapRequired("BackendMinor", Symbol.VersionBackendMinor);
 | 
						|
  IO.mapRequired("BackendBuild", Symbol.VersionBackendBuild);
 | 
						|
  IO.mapRequired("BackendQFE", Symbol.VersionBackendQFE);
 | 
						|
  IO.mapRequired("Version", Symbol.Version);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<FrameProcSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("TotalFrameBytes", Symbol.TotalFrameBytes);
 | 
						|
  IO.mapRequired("PaddingFrameBytes", Symbol.PaddingFrameBytes);
 | 
						|
  IO.mapRequired("OffsetToPadding", Symbol.OffsetToPadding);
 | 
						|
  IO.mapRequired("BytesOfCalleeSavedRegisters",
 | 
						|
                 Symbol.BytesOfCalleeSavedRegisters);
 | 
						|
  IO.mapRequired("OffsetOfExceptionHandler", Symbol.OffsetOfExceptionHandler);
 | 
						|
  IO.mapRequired("SectionIdOfExceptionHandler",
 | 
						|
                 Symbol.SectionIdOfExceptionHandler);
 | 
						|
  IO.mapRequired("Flags", Symbol.Flags);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<CallSiteInfoSym>::map(IO &IO) {
 | 
						|
  IO.mapOptional("Offset", Symbol.CodeOffset, 0U);
 | 
						|
  IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
 | 
						|
  IO.mapRequired("Type", Symbol.Type);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<FileStaticSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Index", Symbol.Index);
 | 
						|
  IO.mapRequired("ModFilenameOffset", Symbol.ModFilenameOffset);
 | 
						|
  IO.mapRequired("Flags", Symbol.Flags);
 | 
						|
  IO.mapRequired("Name", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<HeapAllocationSiteSym>::map(IO &IO) {
 | 
						|
  IO.mapOptional("Offset", Symbol.CodeOffset, 0U);
 | 
						|
  IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
 | 
						|
  IO.mapRequired("CallInstructionSize", Symbol.CallInstructionSize);
 | 
						|
  IO.mapRequired("Type", Symbol.Type);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<FrameCookieSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Register", Symbol.Register);
 | 
						|
  IO.mapRequired("CookieKind", Symbol.CookieKind);
 | 
						|
  IO.mapRequired("Flags", Symbol.Flags);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<CallerSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("FuncID", Symbol.Indices);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<UDTSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Type", Symbol.Type);
 | 
						|
  IO.mapRequired("UDTName", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<BuildInfoSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("BuildId", Symbol.BuildId);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<BPRelativeSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Offset", Symbol.Offset);
 | 
						|
  IO.mapRequired("Type", Symbol.Type);
 | 
						|
  IO.mapRequired("VarName", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<RegRelativeSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Offset", Symbol.Offset);
 | 
						|
  IO.mapRequired("Type", Symbol.Type);
 | 
						|
  IO.mapRequired("Register", Symbol.Register);
 | 
						|
  IO.mapRequired("VarName", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<ConstantSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Type", Symbol.Type);
 | 
						|
  IO.mapRequired("Value", Symbol.Value);
 | 
						|
  IO.mapRequired("Name", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<DataSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Type", Symbol.Type);
 | 
						|
  IO.mapOptional("Offset", Symbol.DataOffset, 0U);
 | 
						|
  IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
 | 
						|
  IO.mapRequired("DisplayName", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<ThreadLocalDataSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Type", Symbol.Type);
 | 
						|
  IO.mapOptional("Offset", Symbol.DataOffset, 0U);
 | 
						|
  IO.mapOptional("Segment", Symbol.Segment, uint16_t(0));
 | 
						|
  IO.mapRequired("DisplayName", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
template <> void SymbolRecordImpl<UsingNamespaceSym>::map(IO &IO) {
 | 
						|
  IO.mapRequired("Namespace", Symbol.Name);
 | 
						|
}
 | 
						|
 | 
						|
} // end namespace detail
 | 
						|
} // end namespace CodeViewYAML
 | 
						|
} // end namespace llvm
 | 
						|
 | 
						|
CVSymbol CodeViewYAML::SymbolRecord::toCodeViewSymbol(
 | 
						|
    BumpPtrAllocator &Allocator, CodeViewContainer Container) const {
 | 
						|
  return Symbol->toCodeViewSymbol(Allocator, Container);
 | 
						|
}
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
namespace yaml {
 | 
						|
 | 
						|
template <> struct MappingTraits<SymbolRecordBase> {
 | 
						|
  static void mapping(IO &io, SymbolRecordBase &Record) { Record.map(io); }
 | 
						|
};
 | 
						|
 | 
						|
} // end namespace yaml
 | 
						|
} // end namespace llvm
 | 
						|
 | 
						|
template <typename SymbolType>
 | 
						|
static inline Expected<CodeViewYAML::SymbolRecord>
 | 
						|
fromCodeViewSymbolImpl(CVSymbol Symbol) {
 | 
						|
  CodeViewYAML::SymbolRecord Result;
 | 
						|
 | 
						|
  auto Impl = std::make_shared<SymbolType>(Symbol.kind());
 | 
						|
  if (auto EC = Impl->fromCodeViewSymbol(Symbol))
 | 
						|
    return std::move(EC);
 | 
						|
  Result.Symbol = Impl;
 | 
						|
  return Result;
 | 
						|
}
 | 
						|
 | 
						|
Expected<CodeViewYAML::SymbolRecord>
 | 
						|
CodeViewYAML::SymbolRecord::fromCodeViewSymbol(CVSymbol Symbol) {
 | 
						|
#define SYMBOL_RECORD(EnumName, EnumVal, ClassName)                            \
 | 
						|
  case EnumName:                                                               \
 | 
						|
    return fromCodeViewSymbolImpl<SymbolRecordImpl<ClassName>>(Symbol);
 | 
						|
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)           \
 | 
						|
  SYMBOL_RECORD(EnumName, EnumVal, ClassName)
 | 
						|
  switch (Symbol.kind()) {
 | 
						|
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
 | 
						|
  default:
 | 
						|
    return fromCodeViewSymbolImpl<UnknownSymbolRecord>(Symbol);
 | 
						|
  }
 | 
						|
  return make_error<CodeViewError>(cv_error_code::corrupt_record);
 | 
						|
}
 | 
						|
 | 
						|
template <typename ConcreteType>
 | 
						|
static void mapSymbolRecordImpl(IO &IO, const char *Class, SymbolKind Kind,
 | 
						|
                                CodeViewYAML::SymbolRecord &Obj) {
 | 
						|
  if (!IO.outputting())
 | 
						|
    Obj.Symbol = std::make_shared<ConcreteType>(Kind);
 | 
						|
 | 
						|
  IO.mapRequired(Class, *Obj.Symbol);
 | 
						|
}
 | 
						|
 | 
						|
void MappingTraits<CodeViewYAML::SymbolRecord>::mapping(
 | 
						|
    IO &IO, CodeViewYAML::SymbolRecord &Obj) {
 | 
						|
  SymbolKind Kind;
 | 
						|
  if (IO.outputting())
 | 
						|
    Kind = Obj.Symbol->Kind;
 | 
						|
  IO.mapRequired("Kind", Kind);
 | 
						|
 | 
						|
#define SYMBOL_RECORD(EnumName, EnumVal, ClassName)                            \
 | 
						|
  case EnumName:                                                               \
 | 
						|
    mapSymbolRecordImpl<SymbolRecordImpl<ClassName>>(IO, #ClassName, Kind,     \
 | 
						|
                                                     Obj);                     \
 | 
						|
    break;
 | 
						|
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName)           \
 | 
						|
  SYMBOL_RECORD(EnumName, EnumVal, ClassName)
 | 
						|
  switch (Kind) {
 | 
						|
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
 | 
						|
  default:
 | 
						|
    mapSymbolRecordImpl<UnknownSymbolRecord>(IO, "UnknownSym", Kind, Obj);
 | 
						|
  }
 | 
						|
}
 |