#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/Support/ScopedPrinter.h"
namespace llvm {
-class ScopedPrinter;
namespace codeview {
/// Dumper for CodeView type streams found in COFF object files and PDB files.
-class CVTypeDumper : public TypeVisitorCallbacks {
+class CVTypeDumper {
public:
- CVTypeDumper(ScopedPrinter *W, bool PrintRecordBytes)
- : W(W), PrintRecordBytes(PrintRecordBytes) {}
-
- void printTypeIndex(StringRef FieldName, TypeIndex TI);
+ explicit CVTypeDumper(TypeDatabase &TypeDB) : TypeDB(TypeDB) {}
/// Dumps one type record. Returns false if there was a type parsing error,
/// and true otherwise. This should be called in order, since the dumper
/// maintains state about previous records which are necessary for cross
/// type references.
- Error dump(const CVRecord<TypeLeafKind> &Record);
+ Error dump(const CVType &Record, TypeVisitorCallbacks &Dumper);
/// Dumps the type records in Types. Returns false if there was a type stream
/// parse error, and true otherwise.
- Error dump(const CVTypeArray &Types);
+ Error dump(const CVTypeArray &Types, TypeVisitorCallbacks &Dumper);
/// Dumps the type records in Data. Returns false if there was a type stream
/// parse error, and true otherwise. Use this method instead of the
/// CVTypeArray overload when type records are laid out contiguously in
/// memory.
- Error dump(ArrayRef<uint8_t> Data);
-
- void setPrinter(ScopedPrinter *P);
- ScopedPrinter *getPrinter() { return W; }
-
- /// Action to take on unknown types. By default, they are ignored.
- Error visitUnknownType(CVType &Record) override;
- Error visitUnknownMember(CVMemberRecord &Record) override;
-
- /// Paired begin/end actions for all types. Receives all record data,
- /// including the fixed-length record prefix.
- Error visitTypeBegin(CVType &Record) override;
- Error visitTypeEnd(CVType &Record) override;
- Error visitMemberBegin(CVMemberRecord &Record) override;
- Error visitMemberEnd(CVMemberRecord &Record) override;
+ Error dump(ArrayRef<uint8_t> Data, TypeVisitorCallbacks &Dumper);
-#define TYPE_RECORD(EnumName, EnumVal, Name) \
- Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
-#define MEMBER_RECORD(EnumName, EnumVal, Name) \
- Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
-#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "TypeRecords.def"
+ static void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
+ TypeIndex TI, TypeDatabase &DB);
private:
- void printMemberAttributes(MemberAttributes Attrs);
- void printMemberAttributes(MemberAccess Access, MethodKind Kind,
- MethodOptions Options);
-
- ScopedPrinter *W;
-
- bool PrintRecordBytes = false;
-
- TypeDatabase TypeDB;
+ TypeDatabase &TypeDB;
};
} // end namespace codeview
class ScopedPrinter;
namespace codeview {
-class CVTypeDumper;
+class TypeDatabase;
/// Dumper for CodeView symbol streams found in COFF object files and PDB files.
class CVSymbolDumper {
public:
- CVSymbolDumper(ScopedPrinter &W, CVTypeDumper &CVTD,
+ CVSymbolDumper(ScopedPrinter &W, TypeDatabase &TypeDB,
std::unique_ptr<SymbolDumpDelegate> ObjDelegate,
bool PrintRecordBytes)
- : W(W), CVTD(CVTD), ObjDelegate(std::move(ObjDelegate)),
+ : W(W), TypeDB(TypeDB), ObjDelegate(std::move(ObjDelegate)),
PrintRecordBytes(PrintRecordBytes) {}
/// Dumps one type record. Returns false if there was a type parsing error,
private:
ScopedPrinter &W;
- CVTypeDumper &CVTD;
+ TypeDatabase &TypeDB;
std::unique_ptr<SymbolDumpDelegate> ObjDelegate;
bool PrintRecordBytes;
--- /dev/null
+//===-- TypeDumpVisitor.h - CodeView type info dumper -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPVISITOR_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPVISITOR_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+
+namespace llvm {
+class ScopedPrinter;
+
+namespace codeview {
+
+/// Dumper for CodeView type streams found in COFF object files and PDB files.
+class TypeDumpVisitor : public TypeVisitorCallbacks {
+public:
+ TypeDumpVisitor(TypeDatabase &TypeDB, ScopedPrinter *W, bool PrintRecordBytes)
+ : W(W), PrintRecordBytes(PrintRecordBytes), TypeDB(TypeDB) {}
+
+ void printTypeIndex(StringRef FieldName, TypeIndex TI) const;
+
+ /// Action to take on unknown types. By default, they are ignored.
+ Error visitUnknownType(CVType &Record) override;
+ Error visitUnknownMember(CVMemberRecord &Record) override;
+
+ /// Paired begin/end actions for all types. Receives all record data,
+ /// including the fixed-length record prefix.
+ Error visitTypeBegin(CVType &Record) override;
+ Error visitTypeEnd(CVType &Record) override;
+ Error visitMemberBegin(CVMemberRecord &Record) override;
+ Error visitMemberEnd(CVMemberRecord &Record) override;
+
+#define TYPE_RECORD(EnumName, EnumVal, Name) \
+ Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
+#define MEMBER_RECORD(EnumName, EnumVal, Name) \
+ Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "TypeRecords.def"
+
+private:
+ void printMemberAttributes(MemberAttributes Attrs);
+ void printMemberAttributes(MemberAccess Access, MethodKind Kind,
+ MethodOptions Options);
+
+ ScopedPrinter *W;
+
+ bool PrintRecordBytes = false;
+
+ TypeDatabase &TypeDB;
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
CommentPrefix += ' ';
}
- CVTypeDumper CVTD(nullptr, /*PrintRecordBytes=*/false);
+ TypeDatabase TypeDB;
+ CVTypeDumper CVTD(TypeDB);
TypeTable.ForEachRecord([&](TypeIndex Index, ArrayRef<uint8_t> Record) {
if (OS.isVerboseAsm()) {
// Emit a block comment describing the type record for readability.
raw_svector_ostream CommentOS(CommentBlock);
ScopedPrinter SP(CommentOS);
SP.setPrefix(CommentPrefix);
- CVTD.setPrinter(&SP);
- Error E = CVTD.dump(Record);
+ TypeDumpVisitor TDV(TypeDB, &SP, false);
+ Error E = CVTD.dump(Record, TDV);
if (E) {
logAllUnhandledErrors(std::move(E), errs(), "error: ");
llvm_unreachable("produced malformed type record");
SymbolDumper.cpp
TypeDatabase.cpp
TypeDatabaseVisitor.cpp
+ TypeDumpVisitor.cpp
TypeRecord.cpp
TypeRecordMapping.cpp
TypeSerializer.cpp
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/MSF/ByteStream.h"
-#include "llvm/Support/ScopedPrinter.h"
using namespace llvm;
using namespace llvm::codeview;
-static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
-#define CV_TYPE(enum, val) {#enum, enum},
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
-};
-
-#define ENUM_ENTRY(enum_class, enum) \
- { #enum, std::underlying_type < enum_class > ::type(enum_class::enum) }
-
-static const EnumEntry<uint16_t> ClassOptionNames[] = {
- ENUM_ENTRY(ClassOptions, Packed),
- ENUM_ENTRY(ClassOptions, HasConstructorOrDestructor),
- ENUM_ENTRY(ClassOptions, HasOverloadedOperator),
- ENUM_ENTRY(ClassOptions, Nested),
- ENUM_ENTRY(ClassOptions, ContainsNestedClass),
- ENUM_ENTRY(ClassOptions, HasOverloadedAssignmentOperator),
- ENUM_ENTRY(ClassOptions, HasConversionOperator),
- ENUM_ENTRY(ClassOptions, ForwardReference),
- ENUM_ENTRY(ClassOptions, Scoped),
- ENUM_ENTRY(ClassOptions, HasUniqueName),
- ENUM_ENTRY(ClassOptions, Sealed),
- ENUM_ENTRY(ClassOptions, Intrinsic),
-};
-
-static const EnumEntry<uint8_t> MemberAccessNames[] = {
- ENUM_ENTRY(MemberAccess, None), ENUM_ENTRY(MemberAccess, Private),
- ENUM_ENTRY(MemberAccess, Protected), ENUM_ENTRY(MemberAccess, Public),
-};
-
-static const EnumEntry<uint16_t> MethodOptionNames[] = {
- ENUM_ENTRY(MethodOptions, Pseudo),
- ENUM_ENTRY(MethodOptions, NoInherit),
- ENUM_ENTRY(MethodOptions, NoConstruct),
- ENUM_ENTRY(MethodOptions, CompilerGenerated),
- ENUM_ENTRY(MethodOptions, Sealed),
-};
-
-static const EnumEntry<uint16_t> MemberKindNames[] = {
- ENUM_ENTRY(MethodKind, Vanilla),
- ENUM_ENTRY(MethodKind, Virtual),
- ENUM_ENTRY(MethodKind, Static),
- ENUM_ENTRY(MethodKind, Friend),
- ENUM_ENTRY(MethodKind, IntroducingVirtual),
- ENUM_ENTRY(MethodKind, PureVirtual),
- ENUM_ENTRY(MethodKind, PureIntroducingVirtual),
-};
-
-static const EnumEntry<uint8_t> PtrKindNames[] = {
- ENUM_ENTRY(PointerKind, Near16),
- ENUM_ENTRY(PointerKind, Far16),
- ENUM_ENTRY(PointerKind, Huge16),
- ENUM_ENTRY(PointerKind, BasedOnSegment),
- ENUM_ENTRY(PointerKind, BasedOnValue),
- ENUM_ENTRY(PointerKind, BasedOnSegmentValue),
- ENUM_ENTRY(PointerKind, BasedOnAddress),
- ENUM_ENTRY(PointerKind, BasedOnSegmentAddress),
- ENUM_ENTRY(PointerKind, BasedOnType),
- ENUM_ENTRY(PointerKind, BasedOnSelf),
- ENUM_ENTRY(PointerKind, Near32),
- ENUM_ENTRY(PointerKind, Far32),
- ENUM_ENTRY(PointerKind, Near64),
-};
-
-static const EnumEntry<uint8_t> PtrModeNames[] = {
- ENUM_ENTRY(PointerMode, Pointer),
- ENUM_ENTRY(PointerMode, LValueReference),
- ENUM_ENTRY(PointerMode, PointerToDataMember),
- ENUM_ENTRY(PointerMode, PointerToMemberFunction),
- ENUM_ENTRY(PointerMode, RValueReference),
-};
-
-static const EnumEntry<uint16_t> PtrMemberRepNames[] = {
- ENUM_ENTRY(PointerToMemberRepresentation, Unknown),
- ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceData),
- ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceData),
- ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceData),
- ENUM_ENTRY(PointerToMemberRepresentation, GeneralData),
- ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceFunction),
- ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceFunction),
- ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceFunction),
- ENUM_ENTRY(PointerToMemberRepresentation, GeneralFunction),
-};
-
-static const EnumEntry<uint16_t> TypeModifierNames[] = {
- ENUM_ENTRY(ModifierOptions, Const), ENUM_ENTRY(ModifierOptions, Volatile),
- ENUM_ENTRY(ModifierOptions, Unaligned),
-};
-
-static const EnumEntry<uint8_t> CallingConventions[] = {
- ENUM_ENTRY(CallingConvention, NearC),
- ENUM_ENTRY(CallingConvention, FarC),
- ENUM_ENTRY(CallingConvention, NearPascal),
- ENUM_ENTRY(CallingConvention, FarPascal),
- ENUM_ENTRY(CallingConvention, NearFast),
- ENUM_ENTRY(CallingConvention, FarFast),
- ENUM_ENTRY(CallingConvention, NearStdCall),
- ENUM_ENTRY(CallingConvention, FarStdCall),
- ENUM_ENTRY(CallingConvention, NearSysCall),
- ENUM_ENTRY(CallingConvention, FarSysCall),
- ENUM_ENTRY(CallingConvention, ThisCall),
- ENUM_ENTRY(CallingConvention, MipsCall),
- ENUM_ENTRY(CallingConvention, Generic),
- ENUM_ENTRY(CallingConvention, AlphaCall),
- ENUM_ENTRY(CallingConvention, PpcCall),
- ENUM_ENTRY(CallingConvention, SHCall),
- ENUM_ENTRY(CallingConvention, ArmCall),
- ENUM_ENTRY(CallingConvention, AM33Call),
- ENUM_ENTRY(CallingConvention, TriCall),
- ENUM_ENTRY(CallingConvention, SH5Call),
- ENUM_ENTRY(CallingConvention, M32RCall),
- ENUM_ENTRY(CallingConvention, ClrCall),
- ENUM_ENTRY(CallingConvention, Inline),
- ENUM_ENTRY(CallingConvention, NearVector),
-};
-
-static const EnumEntry<uint8_t> FunctionOptionEnum[] = {
- ENUM_ENTRY(FunctionOptions, CxxReturnUdt),
- ENUM_ENTRY(FunctionOptions, Constructor),
- ENUM_ENTRY(FunctionOptions, ConstructorWithVirtualBases),
-};
-
-#undef ENUM_ENTRY
-
-static StringRef getLeafTypeName(TypeLeafKind LT) {
- switch (LT) {
-#define TYPE_RECORD(ename, value, name) \
- case ename: \
- return #name;
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
- default:
- break;
- }
- return "UnknownLeaf";
-}
-
-Error CVTypeDumper::visitTypeBegin(CVType &Record) {
- W->startLine() << getLeafTypeName(Record.Type);
- W->getOStream() << " (" << HexNumber(TypeDB.getNextTypeIndex().getIndex())
- << ")";
- W->getOStream() << " {\n";
- W->indent();
- W->printEnum("TypeLeafKind", unsigned(Record.Type),
- makeArrayRef(LeafTypeNames));
- return Error::success();
-}
-
-Error CVTypeDumper::visitTypeEnd(CVType &Record) {
- if (PrintRecordBytes)
- W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.content()));
-
- W->unindent();
- W->startLine() << "}\n";
- return Error::success();
-}
-
-Error CVTypeDumper::visitMemberBegin(CVMemberRecord &Record) {
- W->startLine() << getLeafTypeName(Record.Kind);
- W->getOStream() << " {\n";
- W->indent();
- W->printEnum("TypeLeafKind", unsigned(Record.Kind),
- makeArrayRef(LeafTypeNames));
- return Error::success();
-}
-
-Error CVTypeDumper::visitMemberEnd(CVMemberRecord &Record) {
- if (PrintRecordBytes)
- W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data));
-
- W->unindent();
- W->startLine() << "}\n";
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, FieldListRecord &FieldList) {
- CVTypeVisitor Visitor(*this);
- if (auto EC = Visitor.visitFieldListMemberStream(FieldList.Data))
- return EC;
-
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, StringIdRecord &String) {
- printTypeIndex("Id", String.getId());
- W->printString("StringData", String.getString());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
- auto Indices = Args.getIndices();
- uint32_t Size = Indices.size();
- W->printNumber("NumArgs", Size);
- ListScope Arguments(*W, "Arguments");
- for (uint32_t I = 0; I < Size; ++I) {
- printTypeIndex("ArgType", Indices[I]);
- }
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
- uint16_t Props = static_cast<uint16_t>(Class.getOptions());
- W->printNumber("MemberCount", Class.getMemberCount());
- W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
- printTypeIndex("FieldList", Class.getFieldList());
- printTypeIndex("DerivedFrom", Class.getDerivationList());
- printTypeIndex("VShape", Class.getVTableShape());
- W->printNumber("SizeOf", Class.getSize());
- W->printString("Name", Class.getName());
- if (Props & uint16_t(ClassOptions::HasUniqueName))
- W->printString("LinkageName", Class.getUniqueName());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
- uint16_t Props = static_cast<uint16_t>(Union.getOptions());
- W->printNumber("MemberCount", Union.getMemberCount());
- W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
- printTypeIndex("FieldList", Union.getFieldList());
- W->printNumber("SizeOf", Union.getSize());
- W->printString("Name", Union.getName());
- if (Props & uint16_t(ClassOptions::HasUniqueName))
- W->printString("LinkageName", Union.getUniqueName());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
- uint16_t Props = static_cast<uint16_t>(Enum.getOptions());
- W->printNumber("NumEnumerators", Enum.getMemberCount());
- W->printFlags("Properties", uint16_t(Enum.getOptions()),
- makeArrayRef(ClassOptionNames));
- printTypeIndex("UnderlyingType", Enum.getUnderlyingType());
- printTypeIndex("FieldListType", Enum.getFieldList());
- W->printString("Name", Enum.getName());
- if (Props & uint16_t(ClassOptions::HasUniqueName))
- W->printString("LinkageName", Enum.getUniqueName());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
- printTypeIndex("ElementType", AT.getElementType());
- printTypeIndex("IndexType", AT.getIndexType());
- W->printNumber("SizeOf", AT.getSize());
- W->printString("Name", AT.getName());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
- printTypeIndex("CompleteClass", VFT.getCompleteClass());
- printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable());
- W->printHex("VFPtrOffset", VFT.getVFPtrOffset());
- W->printString("VFTableName", VFT.getName());
- for (auto N : VFT.getMethodNames())
- W->printString("MethodName", N);
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
- printTypeIndex("ClassType", Id.getClassType());
- printTypeIndex("FunctionType", Id.getFunctionType());
- W->printString("Name", Id.getName());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
- printTypeIndex("ReturnType", Proc.getReturnType());
- W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()),
- makeArrayRef(CallingConventions));
- W->printFlags("FunctionOptions", uint8_t(Proc.getOptions()),
- makeArrayRef(FunctionOptionEnum));
- W->printNumber("NumParameters", Proc.getParameterCount());
- printTypeIndex("ArgListType", Proc.getArgumentList());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, MemberFunctionRecord &MF) {
- printTypeIndex("ReturnType", MF.getReturnType());
- printTypeIndex("ClassType", MF.getClassType());
- printTypeIndex("ThisType", MF.getThisType());
- W->printEnum("CallingConvention", uint8_t(MF.getCallConv()),
- makeArrayRef(CallingConventions));
- W->printFlags("FunctionOptions", uint8_t(MF.getOptions()),
- makeArrayRef(FunctionOptionEnum));
- W->printNumber("NumParameters", MF.getParameterCount());
- printTypeIndex("ArgListType", MF.getArgumentList());
- W->printNumber("ThisAdjustment", MF.getThisPointerAdjustment());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR,
- MethodOverloadListRecord &MethodList) {
- for (auto &M : MethodList.getMethods()) {
- ListScope S(*W, "Method");
- printMemberAttributes(M.getAccess(), M.getMethodKind(), M.getOptions());
- printTypeIndex("Type", M.getType());
- if (M.isIntroducingVirtual())
- W->printHex("VFTableOffset", M.getVFTableOffset());
- }
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
- printTypeIndex("ParentScope", Func.getParentScope());
- printTypeIndex("FunctionType", Func.getFunctionType());
- W->printString("Name", Func.getName());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
- W->printBinary("Signature", TS.getGuid());
- W->printNumber("Age", TS.getAge());
- W->printString("Name", TS.getName());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
- printTypeIndex("PointeeType", Ptr.getReferentType());
- W->printHex("PointerAttributes", uint32_t(Ptr.getOptions()));
- W->printEnum("PtrType", unsigned(Ptr.getPointerKind()),
- makeArrayRef(PtrKindNames));
- W->printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames));
-
- W->printNumber("IsFlat", Ptr.isFlat());
- W->printNumber("IsConst", Ptr.isConst());
- W->printNumber("IsVolatile", Ptr.isVolatile());
- W->printNumber("IsUnaligned", Ptr.isUnaligned());
- W->printNumber("SizeOf", Ptr.getSize());
-
- if (Ptr.isPointerToMember()) {
- const MemberPointerInfo &MI = Ptr.getMemberInfo();
-
- printTypeIndex("ClassType", MI.getContainingType());
- W->printEnum("Representation", uint16_t(MI.getRepresentation()),
- makeArrayRef(PtrMemberRepNames));
- }
-
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
- uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
- printTypeIndex("ModifiedType", Mod.getModifiedType());
- W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
-
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, BitFieldRecord &BitField) {
- printTypeIndex("Type", BitField.getType());
- W->printNumber("BitSize", BitField.getBitSize());
- W->printNumber("BitOffset", BitField.getBitOffset());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, VFTableShapeRecord &Shape) {
- W->printNumber("VFEntryCount", Shape.getEntryCount());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, UdtSourceLineRecord &Line) {
- printTypeIndex("UDT", Line.getUDT());
- printTypeIndex("SourceFile", Line.getSourceFile());
- W->printNumber("LineNumber", Line.getLineNumber());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR,
- UdtModSourceLineRecord &Line) {
- printTypeIndex("UDT", Line.getUDT());
- printTypeIndex("SourceFile", Line.getSourceFile());
- W->printNumber("LineNumber", Line.getLineNumber());
- W->printNumber("Module", Line.getModule());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownRecord(CVType &CVR, BuildInfoRecord &Args) {
- W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size()));
-
- ListScope Arguments(*W, "Arguments");
- for (auto Arg : Args.getArgs()) {
- printTypeIndex("ArgType", Arg);
- }
- return Error::success();
-}
-
-void CVTypeDumper::printMemberAttributes(MemberAttributes Attrs) {
- return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(),
- Attrs.getFlags());
-}
-
-void CVTypeDumper::printMemberAttributes(MemberAccess Access, MethodKind Kind,
- MethodOptions Options) {
- W->printEnum("AccessSpecifier", uint8_t(Access),
- makeArrayRef(MemberAccessNames));
- // Data members will be vanilla. Don't try to print a method kind for them.
- if (Kind != MethodKind::Vanilla)
- W->printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames));
- if (Options != MethodOptions::None) {
- W->printFlags("MethodOptions", unsigned(Options),
- makeArrayRef(MethodOptionNames));
- }
-}
-
-Error CVTypeDumper::visitUnknownMember(CVMemberRecord &Record) {
- W->printHex("UnknownMember", unsigned(Record.Kind));
- return Error::success();
-}
-
-Error CVTypeDumper::visitUnknownType(CVType &Record) {
- W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames));
- W->printNumber("Length", uint32_t(Record.content().size()));
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
- NestedTypeRecord &Nested) {
- printTypeIndex("Type", Nested.getNestedType());
- W->printString("Name", Nested.getName());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
- OneMethodRecord &Method) {
- MethodKind K = Method.getMethodKind();
- printMemberAttributes(Method.getAccess(), K, Method.getOptions());
- printTypeIndex("Type", Method.getType());
- // If virtual, then read the vftable offset.
- if (Method.isIntroducingVirtual())
- W->printHex("VFTableOffset", Method.getVFTableOffset());
- W->printString("Name", Method.getName());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
- OverloadedMethodRecord &Method) {
- W->printHex("MethodCount", Method.getNumOverloads());
- printTypeIndex("MethodListIndex", Method.getMethodList());
- W->printString("Name", Method.getName());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
- DataMemberRecord &Field) {
- printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
- MethodOptions::None);
- printTypeIndex("Type", Field.getType());
- W->printHex("FieldOffset", Field.getFieldOffset());
- W->printString("Name", Field.getName());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
- StaticDataMemberRecord &Field) {
- printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
- MethodOptions::None);
- printTypeIndex("Type", Field.getType());
- W->printString("Name", Field.getName());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
- VFPtrRecord &VFTable) {
- printTypeIndex("Type", VFTable.getType());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
- EnumeratorRecord &Enum) {
- printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
- MethodOptions::None);
- W->printNumber("EnumValue", Enum.getValue());
- W->printString("Name", Enum.getName());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
- BaseClassRecord &Base) {
- printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
- MethodOptions::None);
- printTypeIndex("BaseType", Base.getBaseType());
- W->printHex("BaseOffset", Base.getBaseOffset());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
- VirtualBaseClassRecord &Base) {
- printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
- MethodOptions::None);
- printTypeIndex("BaseType", Base.getBaseType());
- printTypeIndex("VBPtrType", Base.getVBPtrType());
- W->printHex("VBPtrOffset", Base.getVBPtrOffset());
- W->printHex("VBTableIndex", Base.getVTableIndex());
- return Error::success();
-}
-
-Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
- ListContinuationRecord &Cont) {
- printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
- return Error::success();
-}
-
-void CVTypeDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) {
- StringRef TypeName;
- if (!TI.isNoneType())
- TypeName = TypeDB.getTypeName(TI);
- if (!TypeName.empty())
- W->printHex(FieldName, TypeName, TI.getIndex());
- else
- W->printHex(FieldName, TI.getIndex());
-}
-
-Error CVTypeDumper::dump(const CVType &Record) {
- assert(W && "printer should not be null");
+Error CVTypeDumper::dump(const CVType &Record, TypeVisitorCallbacks &Dumper) {
TypeDatabaseVisitor DBV(TypeDB);
TypeDeserializer Deserializer;
TypeVisitorCallbackPipeline Pipeline;
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(DBV);
- Pipeline.addCallbackToPipeline(*this);
+ Pipeline.addCallbackToPipeline(Dumper);
CVTypeVisitor Visitor(Pipeline);
return Error::success();
}
-Error CVTypeDumper::dump(const CVTypeArray &Types) {
- assert(W && "printer should not be null");
+Error CVTypeDumper::dump(const CVTypeArray &Types,
+ TypeVisitorCallbacks &Dumper) {
TypeDatabaseVisitor DBV(TypeDB);
TypeDeserializer Deserializer;
TypeVisitorCallbackPipeline Pipeline;
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(DBV);
- Pipeline.addCallbackToPipeline(*this);
+ Pipeline.addCallbackToPipeline(Dumper);
CVTypeVisitor Visitor(Pipeline);
return Error::success();
}
-Error CVTypeDumper::dump(ArrayRef<uint8_t> Data) {
+Error CVTypeDumper::dump(ArrayRef<uint8_t> Data, TypeVisitorCallbacks &Dumper) {
msf::ByteStream Stream(Data);
CVTypeArray Types;
msf::StreamReader Reader(Stream);
if (auto EC = Reader.readArray(Types, Reader.getLength()))
return EC;
- return dump(Types);
+ return dump(Types, Dumper);
}
-void CVTypeDumper::setPrinter(ScopedPrinter *P) {
- static ScopedPrinter NullP(llvm::nulls());
- W = P ? P : &NullP;
+void CVTypeDumper::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
+ TypeIndex TI, TypeDatabase &DB) {
+ StringRef TypeName;
+ if (!TI.isNoneType())
+ TypeName = DB.getTypeName(TI);
+ if (!TypeName.empty())
+ Printer.printHex(FieldName, TypeName, TI.getIndex());
+ else
+ Printer.printHex(FieldName, TI.getIndex());
}
/// the visitor out of SymbolDumper.h.
class CVSymbolDumperImpl : public SymbolVisitorCallbacks {
public:
- CVSymbolDumperImpl(CVTypeDumper &CVTD, SymbolDumpDelegate *ObjDelegate,
+ CVSymbolDumperImpl(TypeDatabase &TypeDB, SymbolDumpDelegate *ObjDelegate,
ScopedPrinter &W, bool PrintRecordBytes)
- : CVTD(CVTD), ObjDelegate(ObjDelegate), W(W),
+ : TypeDB(TypeDB), ObjDelegate(ObjDelegate), W(W),
PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
/// CVSymbolVisitor overrides.
void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
uint32_t RelocationOffset);
void printLocalVariableAddrGap(ArrayRef<LocalVariableAddrGap> Gaps);
+ void printTypeIndex(StringRef FieldName, TypeIndex TI);
- CVTypeDumper &CVTD;
+ TypeDatabase &TypeDB;
SymbolDumpDelegate *ObjDelegate;
ScopedPrinter &W;
}
}
+void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName, TypeIndex TI) {
+ CVTypeDumper::printTypeIndex(W, FieldName, TI, TypeDB);
+}
+
Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) {
return Error::success();
}
DictScope S(W, "BPRelativeSym");
W.printNumber("Offset", BPRel.Offset);
- CVTD.printTypeIndex("Type", BPRel.Type);
+ printTypeIndex("Type", BPRel.Type);
W.printString("VarName", BPRel.Name);
return Error::success();
}
CallSiteInfo.CodeOffset, &LinkageName);
}
W.printHex("Segment", CallSiteInfo.Segment);
- CVTD.printTypeIndex("Type", CallSiteInfo.Type);
+ printTypeIndex("Type", CallSiteInfo.Type);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
return Error::success();
ConstantSym &Constant) {
DictScope S(W, "Constant");
- CVTD.printTypeIndex("Type", Constant.Type);
+ printTypeIndex("Type", Constant.Type);
W.printNumber("Value", Constant.Value);
W.printString("Name", Constant.Name);
return Error::success();
ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
Data.DataOffset, &LinkageName);
}
- CVTD.printTypeIndex("Type", Data.Type);
+ printTypeIndex("Type", Data.Type);
W.printString("DisplayName", Data.Name);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
}
W.printHex("Segment", HeapAllocSite.Segment);
W.printHex("CallInstructionSize", HeapAllocSite.CallInstructionSize);
- CVTD.printTypeIndex("Type", HeapAllocSite.Type);
+ printTypeIndex("Type", HeapAllocSite.Type);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
return Error::success();
W.printHex("PtrParent", InlineSite.Parent);
W.printHex("PtrEnd", InlineSite.End);
- CVTD.printTypeIndex("Inlinee", InlineSite.Inlinee);
+ printTypeIndex("Inlinee", InlineSite.Inlinee);
ListScope BinaryAnnotations(W, "BinaryAnnotations");
for (auto &Annotation : InlineSite.annotations()) {
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
DictScope S(W, "Local");
- CVTD.printTypeIndex("Type", Local.Type);
+ printTypeIndex("Type", Local.Type);
W.printFlags("Flags", uint16_t(Local.Flags), getLocalFlagNames());
W.printString("VarName", Local.Name);
return Error::success();
W.printHex("CodeSize", Proc.CodeSize);
W.printHex("DbgStart", Proc.DbgStart);
W.printHex("DbgEnd", Proc.DbgEnd);
- CVTD.printTypeIndex("FunctionType", Proc.FunctionType);
+ printTypeIndex("FunctionType", Proc.FunctionType);
if (ObjDelegate) {
ObjDelegate->printRelocatedField("CodeOffset", Proc.getRelocationOffset(),
Proc.CodeOffset, &LinkageName);
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
ListScope S(W, CVR.kind() == S_CALLEES ? "Callees" : "Callers");
for (auto FuncID : Caller.Indices)
- CVTD.printTypeIndex("FuncID", FuncID);
+ printTypeIndex("FuncID", FuncID);
return Error::success();
}
DictScope S(W, "RegRelativeSym");
W.printHex("Offset", RegRel.Offset);
- CVTD.printTypeIndex("Type", RegRel.Type);
+ printTypeIndex("Type", RegRel.Type);
W.printHex("Register", RegRel.Register);
W.printString("VarName", RegRel.Name);
return Error::success();
ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
Data.DataOffset, &LinkageName);
}
- CVTD.printTypeIndex("Type", Data.Type);
+ printTypeIndex("Type", Data.Type);
W.printString("DisplayName", Data.Name);
if (!LinkageName.empty())
W.printString("LinkageName", LinkageName);
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
DictScope S(W, "UDT");
- CVTD.printTypeIndex("Type", UDT.Type);
+ printTypeIndex("Type", UDT.Type);
W.printString("UDTName", UDT.Name);
return Error::success();
}
Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) {
SymbolVisitorCallbackPipeline Pipeline;
SymbolDeserializer Deserializer(ObjDelegate.get());
- CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
+ CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes);
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Dumper);
Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
SymbolVisitorCallbackPipeline Pipeline;
SymbolDeserializer Deserializer(ObjDelegate.get());
- CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
+ CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes);
Pipeline.addCallbackToPipeline(Deserializer);
Pipeline.addCallbackToPipeline(Dumper);
--- /dev/null
+//===-- TypeDumpVisitor.cpp - CodeView type info dumper -----------*- C++
+//-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
+#define CV_TYPE(enum, val) {#enum, enum},
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+};
+
+#define ENUM_ENTRY(enum_class, enum) \
+ { #enum, std::underlying_type < enum_class > ::type(enum_class::enum) }
+
+static const EnumEntry<uint16_t> ClassOptionNames[] = {
+ ENUM_ENTRY(ClassOptions, Packed),
+ ENUM_ENTRY(ClassOptions, HasConstructorOrDestructor),
+ ENUM_ENTRY(ClassOptions, HasOverloadedOperator),
+ ENUM_ENTRY(ClassOptions, Nested),
+ ENUM_ENTRY(ClassOptions, ContainsNestedClass),
+ ENUM_ENTRY(ClassOptions, HasOverloadedAssignmentOperator),
+ ENUM_ENTRY(ClassOptions, HasConversionOperator),
+ ENUM_ENTRY(ClassOptions, ForwardReference),
+ ENUM_ENTRY(ClassOptions, Scoped),
+ ENUM_ENTRY(ClassOptions, HasUniqueName),
+ ENUM_ENTRY(ClassOptions, Sealed),
+ ENUM_ENTRY(ClassOptions, Intrinsic),
+};
+
+static const EnumEntry<uint8_t> MemberAccessNames[] = {
+ ENUM_ENTRY(MemberAccess, None), ENUM_ENTRY(MemberAccess, Private),
+ ENUM_ENTRY(MemberAccess, Protected), ENUM_ENTRY(MemberAccess, Public),
+};
+
+static const EnumEntry<uint16_t> MethodOptionNames[] = {
+ ENUM_ENTRY(MethodOptions, Pseudo),
+ ENUM_ENTRY(MethodOptions, NoInherit),
+ ENUM_ENTRY(MethodOptions, NoConstruct),
+ ENUM_ENTRY(MethodOptions, CompilerGenerated),
+ ENUM_ENTRY(MethodOptions, Sealed),
+};
+
+static const EnumEntry<uint16_t> MemberKindNames[] = {
+ ENUM_ENTRY(MethodKind, Vanilla),
+ ENUM_ENTRY(MethodKind, Virtual),
+ ENUM_ENTRY(MethodKind, Static),
+ ENUM_ENTRY(MethodKind, Friend),
+ ENUM_ENTRY(MethodKind, IntroducingVirtual),
+ ENUM_ENTRY(MethodKind, PureVirtual),
+ ENUM_ENTRY(MethodKind, PureIntroducingVirtual),
+};
+
+static const EnumEntry<uint8_t> PtrKindNames[] = {
+ ENUM_ENTRY(PointerKind, Near16),
+ ENUM_ENTRY(PointerKind, Far16),
+ ENUM_ENTRY(PointerKind, Huge16),
+ ENUM_ENTRY(PointerKind, BasedOnSegment),
+ ENUM_ENTRY(PointerKind, BasedOnValue),
+ ENUM_ENTRY(PointerKind, BasedOnSegmentValue),
+ ENUM_ENTRY(PointerKind, BasedOnAddress),
+ ENUM_ENTRY(PointerKind, BasedOnSegmentAddress),
+ ENUM_ENTRY(PointerKind, BasedOnType),
+ ENUM_ENTRY(PointerKind, BasedOnSelf),
+ ENUM_ENTRY(PointerKind, Near32),
+ ENUM_ENTRY(PointerKind, Far32),
+ ENUM_ENTRY(PointerKind, Near64),
+};
+
+static const EnumEntry<uint8_t> PtrModeNames[] = {
+ ENUM_ENTRY(PointerMode, Pointer),
+ ENUM_ENTRY(PointerMode, LValueReference),
+ ENUM_ENTRY(PointerMode, PointerToDataMember),
+ ENUM_ENTRY(PointerMode, PointerToMemberFunction),
+ ENUM_ENTRY(PointerMode, RValueReference),
+};
+
+static const EnumEntry<uint16_t> PtrMemberRepNames[] = {
+ ENUM_ENTRY(PointerToMemberRepresentation, Unknown),
+ ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceData),
+ ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceData),
+ ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceData),
+ ENUM_ENTRY(PointerToMemberRepresentation, GeneralData),
+ ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceFunction),
+ ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceFunction),
+ ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceFunction),
+ ENUM_ENTRY(PointerToMemberRepresentation, GeneralFunction),
+};
+
+static const EnumEntry<uint16_t> TypeModifierNames[] = {
+ ENUM_ENTRY(ModifierOptions, Const), ENUM_ENTRY(ModifierOptions, Volatile),
+ ENUM_ENTRY(ModifierOptions, Unaligned),
+};
+
+static const EnumEntry<uint8_t> CallingConventions[] = {
+ ENUM_ENTRY(CallingConvention, NearC),
+ ENUM_ENTRY(CallingConvention, FarC),
+ ENUM_ENTRY(CallingConvention, NearPascal),
+ ENUM_ENTRY(CallingConvention, FarPascal),
+ ENUM_ENTRY(CallingConvention, NearFast),
+ ENUM_ENTRY(CallingConvention, FarFast),
+ ENUM_ENTRY(CallingConvention, NearStdCall),
+ ENUM_ENTRY(CallingConvention, FarStdCall),
+ ENUM_ENTRY(CallingConvention, NearSysCall),
+ ENUM_ENTRY(CallingConvention, FarSysCall),
+ ENUM_ENTRY(CallingConvention, ThisCall),
+ ENUM_ENTRY(CallingConvention, MipsCall),
+ ENUM_ENTRY(CallingConvention, Generic),
+ ENUM_ENTRY(CallingConvention, AlphaCall),
+ ENUM_ENTRY(CallingConvention, PpcCall),
+ ENUM_ENTRY(CallingConvention, SHCall),
+ ENUM_ENTRY(CallingConvention, ArmCall),
+ ENUM_ENTRY(CallingConvention, AM33Call),
+ ENUM_ENTRY(CallingConvention, TriCall),
+ ENUM_ENTRY(CallingConvention, SH5Call),
+ ENUM_ENTRY(CallingConvention, M32RCall),
+ ENUM_ENTRY(CallingConvention, ClrCall),
+ ENUM_ENTRY(CallingConvention, Inline),
+ ENUM_ENTRY(CallingConvention, NearVector),
+};
+
+static const EnumEntry<uint8_t> FunctionOptionEnum[] = {
+ ENUM_ENTRY(FunctionOptions, CxxReturnUdt),
+ ENUM_ENTRY(FunctionOptions, Constructor),
+ ENUM_ENTRY(FunctionOptions, ConstructorWithVirtualBases),
+};
+
+#undef ENUM_ENTRY
+
+static StringRef getLeafTypeName(TypeLeafKind LT) {
+ switch (LT) {
+#define TYPE_RECORD(ename, value, name) \
+ case ename: \
+ return #name;
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+ default:
+ break;
+ }
+ return "UnknownLeaf";
+}
+
+void TypeDumpVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const {
+ CVTypeDumper::printTypeIndex(*W, FieldName, TI, TypeDB);
+}
+
+Error TypeDumpVisitor::visitTypeBegin(CVType &Record) {
+ W->startLine() << getLeafTypeName(Record.Type);
+ W->getOStream() << " (" << HexNumber(TypeDB.getNextTypeIndex().getIndex())
+ << ")";
+ W->getOStream() << " {\n";
+ W->indent();
+ W->printEnum("TypeLeafKind", unsigned(Record.Type),
+ makeArrayRef(LeafTypeNames));
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitTypeEnd(CVType &Record) {
+ if (PrintRecordBytes)
+ W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.content()));
+
+ W->unindent();
+ W->startLine() << "}\n";
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitMemberBegin(CVMemberRecord &Record) {
+ W->startLine() << getLeafTypeName(Record.Kind);
+ W->getOStream() << " {\n";
+ W->indent();
+ W->printEnum("TypeLeafKind", unsigned(Record.Kind),
+ makeArrayRef(LeafTypeNames));
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitMemberEnd(CVMemberRecord &Record) {
+ if (PrintRecordBytes)
+ W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data));
+
+ W->unindent();
+ W->startLine() << "}\n";
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ FieldListRecord &FieldList) {
+ CVTypeVisitor Visitor(*this);
+ if (auto EC = Visitor.visitFieldListMemberStream(FieldList.Data))
+ return EC;
+
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, StringIdRecord &String) {
+ printTypeIndex("Id", String.getId());
+ W->printString("StringData", String.getString());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
+ auto Indices = Args.getIndices();
+ uint32_t Size = Indices.size();
+ W->printNumber("NumArgs", Size);
+ ListScope Arguments(*W, "Arguments");
+ for (uint32_t I = 0; I < Size; ++I) {
+ printTypeIndex("ArgType", Indices[I]);
+ }
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
+ uint16_t Props = static_cast<uint16_t>(Class.getOptions());
+ W->printNumber("MemberCount", Class.getMemberCount());
+ W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
+ printTypeIndex("FieldList", Class.getFieldList());
+ printTypeIndex("DerivedFrom", Class.getDerivationList());
+ printTypeIndex("VShape", Class.getVTableShape());
+ W->printNumber("SizeOf", Class.getSize());
+ W->printString("Name", Class.getName());
+ if (Props & uint16_t(ClassOptions::HasUniqueName))
+ W->printString("LinkageName", Class.getUniqueName());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
+ uint16_t Props = static_cast<uint16_t>(Union.getOptions());
+ W->printNumber("MemberCount", Union.getMemberCount());
+ W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
+ printTypeIndex("FieldList", Union.getFieldList());
+ W->printNumber("SizeOf", Union.getSize());
+ W->printString("Name", Union.getName());
+ if (Props & uint16_t(ClassOptions::HasUniqueName))
+ W->printString("LinkageName", Union.getUniqueName());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
+ uint16_t Props = static_cast<uint16_t>(Enum.getOptions());
+ W->printNumber("NumEnumerators", Enum.getMemberCount());
+ W->printFlags("Properties", uint16_t(Enum.getOptions()),
+ makeArrayRef(ClassOptionNames));
+ printTypeIndex("UnderlyingType", Enum.getUnderlyingType());
+ printTypeIndex("FieldListType", Enum.getFieldList());
+ W->printString("Name", Enum.getName());
+ if (Props & uint16_t(ClassOptions::HasUniqueName))
+ W->printString("LinkageName", Enum.getUniqueName());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
+ printTypeIndex("ElementType", AT.getElementType());
+ printTypeIndex("IndexType", AT.getIndexType());
+ W->printNumber("SizeOf", AT.getSize());
+ W->printString("Name", AT.getName());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
+ printTypeIndex("CompleteClass", VFT.getCompleteClass());
+ printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable());
+ W->printHex("VFPtrOffset", VFT.getVFPtrOffset());
+ W->printString("VFTableName", VFT.getName());
+ for (auto N : VFT.getMethodNames())
+ W->printString("MethodName", N);
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, MemberFuncIdRecord &Id) {
+ printTypeIndex("ClassType", Id.getClassType());
+ printTypeIndex("FunctionType", Id.getFunctionType());
+ W->printString("Name", Id.getName());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ProcedureRecord &Proc) {
+ printTypeIndex("ReturnType", Proc.getReturnType());
+ W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()),
+ makeArrayRef(CallingConventions));
+ W->printFlags("FunctionOptions", uint8_t(Proc.getOptions()),
+ makeArrayRef(FunctionOptionEnum));
+ W->printNumber("NumParameters", Proc.getParameterCount());
+ printTypeIndex("ArgListType", Proc.getArgumentList());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, MemberFunctionRecord &MF) {
+ printTypeIndex("ReturnType", MF.getReturnType());
+ printTypeIndex("ClassType", MF.getClassType());
+ printTypeIndex("ThisType", MF.getThisType());
+ W->printEnum("CallingConvention", uint8_t(MF.getCallConv()),
+ makeArrayRef(CallingConventions));
+ W->printFlags("FunctionOptions", uint8_t(MF.getOptions()),
+ makeArrayRef(FunctionOptionEnum));
+ W->printNumber("NumParameters", MF.getParameterCount());
+ printTypeIndex("ArgListType", MF.getArgumentList());
+ W->printNumber("ThisAdjustment", MF.getThisPointerAdjustment());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ MethodOverloadListRecord &MethodList) {
+ for (auto &M : MethodList.getMethods()) {
+ ListScope S(*W, "Method");
+ printMemberAttributes(M.getAccess(), M.getMethodKind(), M.getOptions());
+ printTypeIndex("Type", M.getType());
+ if (M.isIntroducingVirtual())
+ W->printHex("VFTableOffset", M.getVFTableOffset());
+ }
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
+ printTypeIndex("ParentScope", Func.getParentScope());
+ printTypeIndex("FunctionType", Func.getFunctionType());
+ W->printString("Name", Func.getName());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, TypeServer2Record &TS) {
+ W->printBinary("Signature", TS.getGuid());
+ W->printNumber("Age", TS.getAge());
+ W->printString("Name", TS.getName());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
+ printTypeIndex("PointeeType", Ptr.getReferentType());
+ W->printHex("PointerAttributes", uint32_t(Ptr.getOptions()));
+ W->printEnum("PtrType", unsigned(Ptr.getPointerKind()),
+ makeArrayRef(PtrKindNames));
+ W->printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames));
+
+ W->printNumber("IsFlat", Ptr.isFlat());
+ W->printNumber("IsConst", Ptr.isConst());
+ W->printNumber("IsVolatile", Ptr.isVolatile());
+ W->printNumber("IsUnaligned", Ptr.isUnaligned());
+ W->printNumber("SizeOf", Ptr.getSize());
+
+ if (Ptr.isPointerToMember()) {
+ const MemberPointerInfo &MI = Ptr.getMemberInfo();
+
+ printTypeIndex("ClassType", MI.getContainingType());
+ W->printEnum("Representation", uint16_t(MI.getRepresentation()),
+ makeArrayRef(PtrMemberRepNames));
+ }
+
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
+ uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
+ printTypeIndex("ModifiedType", Mod.getModifiedType());
+ W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
+
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BitField) {
+ printTypeIndex("Type", BitField.getType());
+ W->printNumber("BitSize", BitField.getBitSize());
+ W->printNumber("BitOffset", BitField.getBitOffset());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ VFTableShapeRecord &Shape) {
+ W->printNumber("VFEntryCount", Shape.getEntryCount());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ UdtSourceLineRecord &Line) {
+ printTypeIndex("UDT", Line.getUDT());
+ printTypeIndex("SourceFile", Line.getSourceFile());
+ W->printNumber("LineNumber", Line.getLineNumber());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ UdtModSourceLineRecord &Line) {
+ printTypeIndex("UDT", Line.getUDT());
+ printTypeIndex("SourceFile", Line.getSourceFile());
+ W->printNumber("LineNumber", Line.getLineNumber());
+ W->printNumber("Module", Line.getModule());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &Args) {
+ W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size()));
+
+ ListScope Arguments(*W, "Arguments");
+ for (auto Arg : Args.getArgs()) {
+ printTypeIndex("ArgType", Arg);
+ }
+ return Error::success();
+}
+
+void TypeDumpVisitor::printMemberAttributes(MemberAttributes Attrs) {
+ return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(),
+ Attrs.getFlags());
+}
+
+void TypeDumpVisitor::printMemberAttributes(MemberAccess Access,
+ MethodKind Kind,
+ MethodOptions Options) {
+ W->printEnum("AccessSpecifier", uint8_t(Access),
+ makeArrayRef(MemberAccessNames));
+ // Data members will be vanilla. Don't try to print a method kind for them.
+ if (Kind != MethodKind::Vanilla)
+ W->printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames));
+ if (Options != MethodOptions::None) {
+ W->printFlags("MethodOptions", unsigned(Options),
+ makeArrayRef(MethodOptionNames));
+ }
+}
+
+Error TypeDumpVisitor::visitUnknownMember(CVMemberRecord &Record) {
+ W->printHex("UnknownMember", unsigned(Record.Kind));
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitUnknownType(CVType &Record) {
+ W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames));
+ W->printNumber("Length", uint32_t(Record.content().size()));
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ NestedTypeRecord &Nested) {
+ printTypeIndex("Type", Nested.getNestedType());
+ W->printString("Name", Nested.getName());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ OneMethodRecord &Method) {
+ MethodKind K = Method.getMethodKind();
+ printMemberAttributes(Method.getAccess(), K, Method.getOptions());
+ printTypeIndex("Type", Method.getType());
+ // If virtual, then read the vftable offset.
+ if (Method.isIntroducingVirtual())
+ W->printHex("VFTableOffset", Method.getVFTableOffset());
+ W->printString("Name", Method.getName());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ OverloadedMethodRecord &Method) {
+ W->printHex("MethodCount", Method.getNumOverloads());
+ printTypeIndex("MethodListIndex", Method.getMethodList());
+ W->printString("Name", Method.getName());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ DataMemberRecord &Field) {
+ printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
+ MethodOptions::None);
+ printTypeIndex("Type", Field.getType());
+ W->printHex("FieldOffset", Field.getFieldOffset());
+ W->printString("Name", Field.getName());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ StaticDataMemberRecord &Field) {
+ printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
+ MethodOptions::None);
+ printTypeIndex("Type", Field.getType());
+ W->printString("Name", Field.getName());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ VFPtrRecord &VFTable) {
+ printTypeIndex("Type", VFTable.getType());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ EnumeratorRecord &Enum) {
+ printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
+ MethodOptions::None);
+ W->printNumber("EnumValue", Enum.getValue());
+ W->printString("Name", Enum.getName());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ BaseClassRecord &Base) {
+ printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
+ MethodOptions::None);
+ printTypeIndex("BaseType", Base.getBaseType());
+ W->printHex("BaseOffset", Base.getBaseOffset());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ VirtualBaseClassRecord &Base) {
+ printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
+ MethodOptions::None);
+ printTypeIndex("BaseType", Base.getBaseType());
+ printTypeIndex("VBPtrType", Base.getVBPtrType());
+ W->printHex("VBPtrOffset", Base.getVBPtrOffset());
+ W->printHex("VBTableIndex", Base.getVTableIndex());
+ return Error::success();
+}
+
+Error TypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ ListContinuationRecord &Cont) {
+ printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
+ return Error::success();
+}
#include "LLVMOutputStyle.h"
#include "llvm-pdbdump.h"
+#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/ModuleSubstreamVisitor.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/MSF/StreamReader.h"
#include "llvm/DebugInfo/PDB/PDBExtras.h"
OS << Off.Off << ", " << Off.Isect;
}
-LLVMOutputStyle::LLVMOutputStyle(PDBFile &File)
- : File(File), P(outs()), Dumper(&P, false) {}
+LLVMOutputStyle::LLVMOutputStyle(PDBFile &File) : File(File), P(outs()) {}
Error LLVMOutputStyle::dump() {
if (auto EC = dumpFileHeaders())
if (!Tpi)
return Tpi.takeError();
+ CVTypeDumper Dumper(TypeDB);
if (DumpRecords || DumpRecordBytes) {
DictScope D(P, Label);
DictScope DD(P, "");
if (DumpRecords) {
- if (auto EC = Dumper.dump(Type))
+ TypeDumpVisitor TDV(TypeDB, &P, false);
+ if (auto EC = Dumper.dump(Type, TDV))
return EC;
}
"TPI stream contained corrupt record");
} else if (opts::raw::DumpModuleSyms) {
// Even if the user doesn't want to dump type records, we still need to
- // iterate them in order to build the list of types so that we can print
- // them when dumping module symbols. So when they want to dump symbols
- // but not types, use a null output stream.
- ScopedPrinter *OldP = Dumper.getPrinter();
- Dumper.setPrinter(nullptr);
+ // iterate them in order to build the type database. So when they want to
+ // dump symbols but not types, don't stick a dumper on the end, just build
+ // the type database.
+ TypeDatabaseVisitor DBV(TypeDB);
+ TypeDeserializer Deserializer;
+ TypeVisitorCallbackPipeline Pipeline;
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(DBV);
+
+ CVTypeVisitor Visitor(Pipeline);
bool HadError = false;
- for (auto &Type : Tpi->types(&HadError)) {
- if (auto EC = Dumper.dump(Type))
+ for (auto Type : Tpi->types(&HadError)) {
+ if (auto EC = Visitor.visitTypeRecord(Type))
return EC;
}
- Dumper.setPrinter(OldP);
dumpTpiHash(P, *Tpi);
if (HadError)
return make_error<RawError>(raw_error_code::corrupt_file,
if (ShouldDumpSymbols) {
ListScope SS(P, "Symbols");
- codeview::CVSymbolDumper SD(P, Dumper, nullptr, false);
+ codeview::CVSymbolDumper SD(P, TypeDB, nullptr, false);
bool HadError = false;
for (auto S : ModS.symbols(&HadError)) {
DictScope LL(P, "");
P.printList("Section Offsets", Publics->getSectionOffsets(),
printSectionOffset);
ListScope L(P, "Symbols");
- codeview::CVSymbolDumper SD(P, Dumper, nullptr, false);
+ codeview::CVSymbolDumper SD(P, TypeDB, nullptr, false);
bool HadError = false;
for (auto S : Publics->getSymbols(&HadError)) {
DictScope DD(P, "");
#include "OutputStyle.h"
-#include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
#include "llvm/Support/ScopedPrinter.h"
namespace llvm {
PDBFile &File;
ScopedPrinter P;
- codeview::CVTypeDumper Dumper;
+ codeview::TypeDatabase TypeDB;
std::vector<std::string> StreamPurposes;
};
}
#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
public:
friend class COFFObjectDumpDelegate;
COFFDumper(const llvm::object::COFFObjectFile *Obj, ScopedPrinter &Writer)
- : ObjDumper(Writer), Obj(Obj),
- CVTD(&Writer, opts::CodeViewSubsectionBytes) {}
+ : ObjDumper(Writer), Obj(Obj), Writer(Writer) {}
void printFileHeaders() override;
void printSections() override;
void printFileNameForOffset(StringRef Label, uint32_t FileOffset);
void printTypeIndex(StringRef FieldName, TypeIndex TI) {
// Forward to CVTypeDumper for simplicity.
- CVTD.printTypeIndex(FieldName, TI);
+ CVTypeDumper::printTypeIndex(Writer, FieldName, TI, TypeDB);
}
void printCodeViewSymbolsSubsection(StringRef Subsection,
StringRef CVFileChecksumTable;
StringRef CVStringTable;
- CVTypeDumper CVTD;
+ ScopedPrinter &Writer;
+ TypeDatabase TypeDB;
};
class COFFObjectDumpDelegate : public SymbolDumpDelegate {
auto CODD = llvm::make_unique<COFFObjectDumpDelegate>(*this, Section, Obj,
SectionContents);
- CVSymbolDumper CVSD(W, CVTD, std::move(CODD), opts::CodeViewSubsectionBytes);
+ CVSymbolDumper CVSD(W, TypeDB, std::move(CODD),
+ opts::CodeViewSubsectionBytes);
ByteStream Stream(BinaryData);
CVSymbolArray Symbols;
StreamReader Reader(Stream);
if (Magic != COFF::DEBUG_SECTION_MAGIC)
return error(object_error::parse_failed);
- if (auto EC = CVTD.dump({Data.bytes_begin(), Data.bytes_end()})) {
+ CVTypeDumper CVTD(TypeDB);
+ TypeDumpVisitor TDV(TypeDB, &W, opts::CodeViewSubsectionBytes);
+ if (auto EC = CVTD.dump({Data.bytes_begin(), Data.bytes_end()}, TDV)) {
W.flush();
error(llvm::errorToErrorCode(std::move(EC)));
}
CVTypes.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Record) {
Buf.append(Record.begin(), Record.end());
});
- CVTypeDumper CVTD(&Writer, opts::CodeViewSubsectionBytes);
- if (auto EC = CVTD.dump({Buf.str().bytes_begin(), Buf.str().bytes_end()})) {
+
+ TypeDatabase TypeDB;
+ CVTypeDumper CVTD(TypeDB);
+ TypeDumpVisitor TDV(TypeDB, &Writer, opts::CodeViewSubsectionBytes);
+ if (auto EC =
+ CVTD.dump({Buf.str().bytes_begin(), Buf.str().bytes_end()}, TDV)) {
Writer.flush();
error(llvm::errorToErrorCode(std::move(EC)));
}