[llvm] r268580 - [codeview] Move dumper into lib/DebugInfo/CodeView
Reid Kleckner via llvm-commits
llvm-commits at lists.llvm.org
Wed May 4 17:34:34 PDT 2016
Author: rnk
Date: Wed May 4 19:34:33 2016
New Revision: 268580
URL: http://llvm.org/viewvc/llvm-project?rev=268580&view=rev
Log:
[codeview] Move dumper into lib/DebugInfo/CodeView
So that we can call it from llvm-pdbdump.
Added:
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h
llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp
llvm/trunk/lib/DebugInfo/CodeView/TypeStream.cpp
Modified:
llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h
llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt
llvm/trunk/tools/llvm-readobj/CMakeLists.txt
llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h?rev=268580&r1=268579&r2=268580&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h Wed May 4 19:34:33 2016
@@ -115,8 +115,7 @@ public:
// Field list records do not describe their own length, so we cannot
// continue parsing past an unknown member type.
visitUnknownMember(Leaf);
- HadError = true;
- return;
+ return parseError();
#define MEMBER_RECORD(ClassName, LeafEnum) \
case LeafEnum: { \
const ClassName *Rec; \
@@ -142,6 +141,9 @@ public:
/// method is only called at most once per field list record.
void visitUnknownMember(TypeLeafKind Leaf) {}
+ /// Helper for returning from a void function when the stream is corrupted.
+ void parseError() { HadError = true; }
+
private:
/// Whether a type stream parsing error was encountered.
bool HadError = false;
Added: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h?rev=268580&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h Wed May 4 19:34:33 2016
@@ -0,0 +1,65 @@
+//===-- TypeDumper.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_TYPEDUMPER_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+
+namespace llvm {
+class ScopedPrinter;
+
+namespace codeview {
+
+/// Dumper for CodeView type streams found in COFF object files and PDB files.
+class CVTypeDumper {
+public:
+ CVTypeDumper(ScopedPrinter &W, bool PrintRecordBytes)
+ : W(W), PrintRecordBytes(PrintRecordBytes) {}
+
+ StringRef getTypeName(TypeIndex TI);
+ void printTypeIndex(StringRef FieldName, TypeIndex TI);
+
+ /// Dumps the type records in Data. Returns false if there was a type stream
+ /// parse error, and true otherwise.
+ bool dump(ArrayRef<uint8_t> Data);
+
+ /// Gets the type index for the next type record.
+ unsigned getNextTypeIndex() const {
+ return 0x1000 + CVUDTNames.size();
+ }
+
+ /// Records the name of a type, and reserves its type index.
+ void recordType(StringRef Name) { CVUDTNames.push_back(Name); }
+
+ /// Saves the name in a StringSet and creates a stable StringRef.
+ StringRef saveName(StringRef TypeName) {
+ return TypeNames.insert(TypeName).first->getKey();
+ }
+
+private:
+ ScopedPrinter &W;
+
+ bool PrintRecordBytes = false;
+
+ /// All user defined type records in .debug$T live in here. Type indices
+ /// greater than 0x1000 are user defined. Subtract 0x1000 from the index to
+ /// index into this vector.
+ SmallVector<StringRef, 10> CVUDTNames;
+
+ StringSet<> TypeNames;
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h?rev=268580&r1=268579&r2=268580&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h Wed May 4 19:34:33 2016
@@ -21,6 +21,8 @@
#include <stdint.h>
namespace llvm {
+class APSInt;
+
namespace codeview {
/// Consumes sizeof(T) bytes from the given byte sequence. Returns an error if
@@ -43,6 +45,23 @@ inline std::error_code consumeUInt32(Str
return std::error_code();
}
+/// Decodes a numeric "leaf" value. These are integer literals encountered in
+/// the type stream. If the value is positive and less than LF_NUMERIC (1 <<
+/// 15), it is emitted directly in Data. Otherwise, it has a tag like LF_CHAR
+/// that indicates the bitwidth and sign of the numeric data.
+bool decodeNumericLeaf(ArrayRef<uint8_t> &Data, APSInt &Num);
+
+inline bool decodeNumericLeaf(StringRef &Data, APSInt &Num) {
+ ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(Data.data()),
+ Data.size());
+ bool Success = decodeNumericLeaf(Bytes, Num);
+ Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
+ return Success;
+}
+
+/// Decode a numeric leaf value that is known to be a uint32_t.
+bool decodeUIntLeaf(ArrayRef<uint8_t> &Data, uint64_t &Num);
+
// A const input iterator interface to the CodeView type stream.
class TypeIterator {
public:
Modified: llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt?rev=268580&r1=268579&r2=268580&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt Wed May 4 19:34:33 2016
@@ -4,8 +4,10 @@ add_llvm_library(LLVMDebugInfoCodeView
ListRecordBuilder.cpp
MemoryTypeTableBuilder.cpp
MethodListRecordBuilder.cpp
+ TypeDumper.cpp
TypeRecordBuilder.cpp
TypeTableBuilder.cpp
+ TypeStream.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/CodeView
Added: llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp?rev=268580&view=auto
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp (added)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp Wed May 4 19:34:33 2016
@@ -0,0 +1,753 @@
+//===-- TypeDumper.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/TypeDumper.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeStream.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+/// The names here all end in "*". If the simple type is a pointer type, we
+/// return the whole name. Otherwise we lop off the last character in our
+/// StringRef.
+static const EnumEntry<SimpleTypeKind> SimpleTypeNames[] = {
+ {"void*", SimpleTypeKind::Void},
+ {"<not translated>*", SimpleTypeKind::NotTranslated},
+ {"HRESULT*", SimpleTypeKind::HResult},
+ {"signed char*", SimpleTypeKind::SignedCharacter},
+ {"unsigned char*", SimpleTypeKind::UnsignedCharacter},
+ {"char*", SimpleTypeKind::NarrowCharacter},
+ {"wchar_t*", SimpleTypeKind::WideCharacter},
+ {"char16_t*", SimpleTypeKind::Character16},
+ {"char32_t*", SimpleTypeKind::Character32},
+ {"__int8*", SimpleTypeKind::SByte},
+ {"unsigned __int8*", SimpleTypeKind::Byte},
+ {"short*", SimpleTypeKind::Int16Short},
+ {"unsigned short*", SimpleTypeKind::UInt16Short},
+ {"__int16*", SimpleTypeKind::Int16},
+ {"unsigned __int16*", SimpleTypeKind::UInt16},
+ {"long*", SimpleTypeKind::Int32Long},
+ {"unsigned long*", SimpleTypeKind::UInt32Long},
+ {"int*", SimpleTypeKind::Int32},
+ {"unsigned*", SimpleTypeKind::UInt32},
+ {"__int64*", SimpleTypeKind::Int64Quad},
+ {"unsigned __int64*", SimpleTypeKind::UInt64Quad},
+ {"__int64*", SimpleTypeKind::Int64},
+ {"unsigned __int64*", SimpleTypeKind::UInt64},
+ {"__int128*", SimpleTypeKind::Int128},
+ {"unsigned __int128*", SimpleTypeKind::UInt128},
+ {"__half*", SimpleTypeKind::Float16},
+ {"float*", SimpleTypeKind::Float32},
+ {"float*", SimpleTypeKind::Float32PartialPrecision},
+ {"__float48*", SimpleTypeKind::Float48},
+ {"double*", SimpleTypeKind::Float64},
+ {"long double*", SimpleTypeKind::Float80},
+ {"__float128*", SimpleTypeKind::Float128},
+ {"_Complex float*", SimpleTypeKind::Complex32},
+ {"_Complex double*", SimpleTypeKind::Complex64},
+ {"_Complex long double*", SimpleTypeKind::Complex80},
+ {"_Complex __float128*", SimpleTypeKind::Complex128},
+ {"bool*", SimpleTypeKind::Boolean8},
+ {"__bool16*", SimpleTypeKind::Boolean16},
+ {"__bool32*", SimpleTypeKind::Boolean32},
+ {"__bool64*", SimpleTypeKind::Boolean64},
+};
+
+static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
+#define LEAF_TYPE(enum, val) { #enum, enum },
+#include "llvm/DebugInfo/CodeView/CVLeafTypes.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
+
+
+namespace {
+
+/// Use this private dumper implementation to keep implementation details about
+/// the visitor out of TypeDumper.h.
+class CVTypeDumperImpl : public CVTypeVisitor<CVTypeDumperImpl> {
+public:
+ CVTypeDumperImpl(CVTypeDumper &CVTD, ScopedPrinter &W, bool PrintRecordBytes)
+ : CVTD(CVTD), W(W), PrintRecordBytes(PrintRecordBytes) {}
+
+ /// CVTypeVisitor overrides.
+ /// FIXME: Bury these in the .cc file to hide implementation details.
+#define TYPE_RECORD(ClassName, LeafEnum) \
+ void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
+ ArrayRef<uint8_t> LeafData);
+#define TYPE_RECORD_ALIAS(ClassName, LeafEnum)
+#define MEMBER_RECORD(ClassName, LeafEnum) \
+ void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
+ ArrayRef<uint8_t> &FieldData);
+#define MEMBER_RECORD_ALIAS(ClassName, LeafEnum)
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+
+ /// Method overload lists are a special case.
+ void visitMethodList(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData);
+
+ void visitUnknownMember(TypeLeafKind Leaf);
+
+ void visitTypeBegin(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData);
+ void visitTypeEnd(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData);
+
+ void printMemberAttributes(MemberAttributes Attrs);
+
+private:
+ /// Forwards to the dumper, which holds the persistent state from visitation.
+ StringRef getTypeName(TypeIndex TI) {
+ return CVTD.getTypeName(TI);
+ }
+
+ void printTypeIndex(StringRef FieldName, TypeIndex TI) {
+ CVTD.printTypeIndex(FieldName, TI);
+ }
+
+ CVTypeDumper &CVTD;
+ ScopedPrinter &W;
+ bool PrintRecordBytes = false;
+
+ /// Name of the current type. Only valid before visitTypeEnd.
+ StringRef Name;
+};
+
+} // end anonymous namespace
+
+/// Reinterpret a byte array as an array of characters. Does not interpret as
+/// a C string, as StringRef has several helpers (split) that make that easy.
+static StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
+ return StringRef(reinterpret_cast<const char *>(LeafData.data()),
+ LeafData.size());
+}
+
+static StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData) {
+ return getBytesAsCharacters(LeafData).split('\0').first;
+}
+
+static StringRef getLeafTypeName(TypeLeafKind LT) {
+ switch (LT) {
+#define KNOWN_TYPE(LeafName, Value, ClassName) \
+ case LeafName: return #ClassName;
+#include "llvm/DebugInfo/CodeView/CVLeafTypes.def"
+ default:
+ break;
+ }
+ return "UnknownLeaf";
+}
+
+void CVTypeDumperImpl::visitTypeBegin(TypeLeafKind Leaf,
+ ArrayRef<uint8_t> LeafData) {
+ // Reset Name to the empty string. If the visitor sets it, we know it.
+ Name = "";
+
+ W.startLine() << getLeafTypeName(Leaf) << " {\n";
+ W.indent();
+ W.printEnum("TypeLeafKind", unsigned(Leaf), makeArrayRef(LeafTypeNames));
+ W.printHex("TypeIndex", CVTD.getNextTypeIndex());
+}
+
+void CVTypeDumperImpl::visitTypeEnd(TypeLeafKind Leaf,
+ ArrayRef<uint8_t> LeafData) {
+ // Always record some name for every type, even if Name is empty. CVUDTNames
+ // is indexed by type index, and must have one entry for every type.
+ CVTD.recordType(Name);
+
+ if (PrintRecordBytes)
+ W.printBinaryBlock("LeafData", getBytesAsCharacters(LeafData));
+
+ W.unindent();
+ W.startLine() << "}\n";
+}
+
+void CVTypeDumperImpl::visitStringId(TypeLeafKind Leaf, const StringId *String,
+ ArrayRef<uint8_t> LeafData) {
+ W.printHex("Id", String->id.getIndex());
+ StringRef StringData = getBytesAsCString(LeafData);
+ W.printString("StringData", StringData);
+ // Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE.
+ Name = StringData;
+}
+
+void CVTypeDumperImpl::visitArgList(TypeLeafKind Leaf, const ArgList *Args,
+ ArrayRef<uint8_t> LeafData) {
+ W.printNumber("NumArgs", Args->NumArgs);
+ ListScope Arguments(W, "Arguments");
+ SmallString<256> TypeName("(");
+ for (uint32_t ArgI = 0; ArgI != Args->NumArgs; ++ArgI) {
+ const TypeIndex *Type;
+ if (!consumeObject(LeafData, Type))
+ return;
+ printTypeIndex("ArgType", *Type);
+ StringRef ArgTypeName = getTypeName(*Type);
+ TypeName.append(ArgTypeName);
+ if (ArgI + 1 != Args->NumArgs)
+ TypeName.append(", ");
+ }
+ TypeName.push_back(')');
+ Name = CVTD.saveName(TypeName);
+}
+
+void CVTypeDumperImpl::visitClassType(TypeLeafKind Leaf, const ClassType *Class,
+ ArrayRef<uint8_t> LeafData) {
+ W.printNumber("MemberCount", Class->MemberCount);
+ uint16_t Props = Class->Properties;
+ W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
+ printTypeIndex("FieldList", Class->FieldList);
+ printTypeIndex("DerivedFrom", Class->DerivedFrom);
+ printTypeIndex("VShape", Class->VShape);
+ uint64_t SizeOf;
+ if (!decodeUIntLeaf(LeafData, SizeOf))
+ return parseError();
+ W.printNumber("SizeOf", SizeOf);
+ StringRef LeafChars = getBytesAsCharacters(LeafData);
+ StringRef LinkageName;
+ std::tie(Name, LinkageName) = LeafChars.split('\0');
+ W.printString("Name", Name);
+ if (Props & uint16_t(ClassOptions::HasUniqueName)) {
+ LinkageName = LinkageName.split('\0').first;
+ if (LinkageName.empty())
+ return parseError();
+ W.printString("LinkageName", LinkageName);
+ }
+}
+
+void CVTypeDumperImpl::visitUnionType(TypeLeafKind Leaf, const UnionType *Union,
+ ArrayRef<uint8_t> LeafData) {
+ W.printNumber("MemberCount", Union->MemberCount);
+ uint16_t Props = Union->Properties;
+ W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
+ printTypeIndex("FieldList", Union->FieldList);
+ uint64_t SizeOf;
+ if (!decodeUIntLeaf(LeafData, SizeOf))
+ return parseError();
+ W.printNumber("SizeOf", SizeOf);
+ StringRef LeafChars = getBytesAsCharacters(LeafData);
+ StringRef LinkageName;
+ std::tie(Name, LinkageName) = LeafChars.split('\0');
+ W.printString("Name", Name);
+ if (Props & uint16_t(ClassOptions::HasUniqueName)) {
+ LinkageName = LinkageName.split('\0').first;
+ if (LinkageName.empty())
+ return parseError();
+ W.printString("LinkageName", LinkageName);
+ }
+}
+
+void CVTypeDumperImpl::visitEnumType(TypeLeafKind Leaf, const EnumType *Enum,
+ ArrayRef<uint8_t> LeafData) {
+ W.printNumber("NumEnumerators", Enum->NumEnumerators);
+ W.printFlags("Properties", uint16_t(Enum->Properties),
+ makeArrayRef(ClassOptionNames));
+ printTypeIndex("UnderlyingType", Enum->UnderlyingType);
+ printTypeIndex("FieldListType", Enum->FieldListType);
+ Name = getBytesAsCString(LeafData);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumperImpl::visitArrayType(TypeLeafKind Leaf, const ArrayType *AT,
+ ArrayRef<uint8_t> LeafData) {
+ printTypeIndex("ElementType", AT->ElementType);
+ printTypeIndex("IndexType", AT->IndexType);
+ uint64_t SizeOf;
+ if (!decodeUIntLeaf(LeafData, SizeOf))
+ return parseError();
+ W.printNumber("SizeOf", SizeOf);
+ Name = getBytesAsCString(LeafData);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumperImpl::visitVFTableType(TypeLeafKind Leaf, const VFTableType *VFT,
+ ArrayRef<uint8_t> LeafData) {
+ printTypeIndex("CompleteClass", VFT->CompleteClass);
+ printTypeIndex("OverriddenVFTable", VFT->OverriddenVFTable);
+ W.printHex("VFPtrOffset", VFT->VFPtrOffset);
+ StringRef NamesData = getBytesAsCharacters(LeafData.slice(0, VFT->NamesLen));
+ std::tie(Name, NamesData) = NamesData.split('\0');
+ W.printString("VFTableName", Name);
+ while (!NamesData.empty()) {
+ StringRef MethodName;
+ std::tie(MethodName, NamesData) = NamesData.split('\0');
+ W.printString("MethodName", MethodName);
+ }
+}
+
+void CVTypeDumperImpl::visitMemberFuncId(TypeLeafKind Leaf, const MemberFuncId *Id,
+ ArrayRef<uint8_t> LeafData) {
+ printTypeIndex("ClassType", Id->ClassType);
+ printTypeIndex("FunctionType", Id->FunctionType);
+ Name = getBytesAsCString(LeafData);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumperImpl::visitProcedureType(TypeLeafKind Leaf,
+ const ProcedureType *Proc,
+ ArrayRef<uint8_t> LeafData) {
+ printTypeIndex("ReturnType", Proc->ReturnType);
+ W.printEnum("CallingConvention", uint8_t(Proc->CallConv),
+ makeArrayRef(CallingConventions));
+ W.printFlags("FunctionOptions", uint8_t(Proc->Options),
+ makeArrayRef(FunctionOptionEnum));
+ W.printNumber("NumParameters", Proc->NumParameters);
+ printTypeIndex("ArgListType", Proc->ArgListType);
+
+ StringRef ReturnTypeName = getTypeName(Proc->ReturnType);
+ StringRef ArgListTypeName = getTypeName(Proc->ArgListType);
+ SmallString<256> TypeName(ReturnTypeName);
+ TypeName.push_back(' ');
+ TypeName.append(ArgListTypeName);
+ Name = CVTD.saveName(TypeName);
+}
+
+void CVTypeDumperImpl::visitMemberFunctionType(TypeLeafKind Leaf,
+ const MemberFunctionType *MemberFunc,
+ ArrayRef<uint8_t> LeafData) {
+ printTypeIndex("ReturnType", MemberFunc->ReturnType);
+ printTypeIndex("ClassType", MemberFunc->ClassType);
+ printTypeIndex("ThisType", MemberFunc->ThisType);
+ W.printEnum("CallingConvention", uint8_t(MemberFunc->CallConv),
+ makeArrayRef(CallingConventions));
+ W.printFlags("FunctionOptions", uint8_t(MemberFunc->Options),
+ makeArrayRef(FunctionOptionEnum));
+ W.printNumber("NumParameters", MemberFunc->NumParameters);
+ printTypeIndex("ArgListType", MemberFunc->ArgListType);
+ W.printNumber("ThisAdjustment", MemberFunc->ThisAdjustment);
+
+ StringRef ReturnTypeName = getTypeName(MemberFunc->ReturnType);
+ StringRef ClassTypeName = getTypeName(MemberFunc->ClassType);
+ StringRef ArgListTypeName = getTypeName(MemberFunc->ArgListType);
+ SmallString<256> TypeName(ReturnTypeName);
+ TypeName.push_back(' ');
+ TypeName.append(ClassTypeName);
+ TypeName.append("::");
+ TypeName.append(ArgListTypeName);
+ Name = CVTD.saveName(TypeName);
+}
+
+void CVTypeDumperImpl::visitMethodList(TypeLeafKind Leaf,
+ ArrayRef<uint8_t> LeafData) {
+ while (!LeafData.empty()) {
+ const MethodListEntry *Method;
+ if (!consumeObject(LeafData, Method))
+ return;
+ ListScope S(W, "Method");
+ printMemberAttributes(Method->Attrs);
+ printTypeIndex("Type", Method->Type);
+ if (Method->isIntroducedVirtual()) {
+ const little32_t *VFTOffsetPtr;
+ if (!consumeObject(LeafData, VFTOffsetPtr))
+ return;
+ W.printHex("VFTableOffset", *VFTOffsetPtr);
+ }
+ }
+}
+
+void CVTypeDumperImpl::visitFuncId(TypeLeafKind Leaf, const FuncId *Func,
+ ArrayRef<uint8_t> LeafData) {
+ printTypeIndex("ParentScope", Func->ParentScope);
+ printTypeIndex("FunctionType", Func->FunctionType);
+ Name = getBytesAsCString(LeafData);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumperImpl::visitTypeServer2(TypeLeafKind Leaf,
+ const TypeServer2 *TypeServer,
+ ArrayRef<uint8_t> LeafData) {
+ W.printBinary("Signature", StringRef(TypeServer->Signature, 16));
+ W.printNumber("Age", TypeServer->Age);
+ Name = getBytesAsCString(LeafData);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumperImpl::visitPointerType(TypeLeafKind Leaf, const PointerType *Ptr,
+ ArrayRef<uint8_t> LeafData) {
+ printTypeIndex("PointeeType", Ptr->PointeeType);
+ W.printHex("PointerAttributes", Ptr->Attrs);
+ W.printEnum("PtrType", unsigned(Ptr->getPtrKind()),
+ makeArrayRef(PtrKindNames));
+ W.printEnum("PtrMode", unsigned(Ptr->getPtrMode()),
+ makeArrayRef(PtrModeNames));
+ W.printNumber("IsFlat", Ptr->isFlat());
+ W.printNumber("IsConst", Ptr->isConst());
+ W.printNumber("IsVolatile", Ptr->isVolatile());
+ W.printNumber("IsUnaligned", Ptr->isUnaligned());
+
+ if (Ptr->isPointerToMember()) {
+ const PointerToMemberTail *PMT;
+ if (!consumeObject(LeafData, PMT))
+ return;
+ printTypeIndex("ClassType", PMT->ClassType);
+ W.printEnum("Representation", PMT->Representation,
+ makeArrayRef(PtrMemberRepNames));
+
+ StringRef PointeeName = getTypeName(Ptr->PointeeType);
+ StringRef ClassName = getTypeName(PMT->ClassType);
+ SmallString<256> TypeName(PointeeName);
+ TypeName.push_back(' ');
+ TypeName.append(ClassName);
+ TypeName.append("::*");
+ Name = CVTD.saveName(TypeName);
+ } else {
+ W.printBinaryBlock("TailData", getBytesAsCharacters(LeafData));
+
+ SmallString<256> TypeName;
+ if (Ptr->isConst())
+ TypeName.append("const ");
+ if (Ptr->isVolatile())
+ TypeName.append("volatile ");
+ if (Ptr->isUnaligned())
+ TypeName.append("__unaligned ");
+
+ TypeName.append(getTypeName(Ptr->PointeeType));
+
+ if (Ptr->getPtrMode() == PointerMode::LValueReference)
+ TypeName.append("&");
+ else if (Ptr->getPtrMode() == PointerMode::RValueReference)
+ TypeName.append("&&");
+ else if (Ptr->getPtrMode() == PointerMode::Pointer)
+ TypeName.append("*");
+
+ Name = CVTD.saveName(TypeName);
+ }
+}
+
+void CVTypeDumperImpl::visitTypeModifier(TypeLeafKind Leaf, const TypeModifier *Mod,
+ ArrayRef<uint8_t> LeafData) {
+ printTypeIndex("ModifiedType", Mod->ModifiedType);
+ W.printFlags("Modifiers", Mod->Modifiers, makeArrayRef(TypeModifierNames));
+
+ StringRef ModifiedName = getTypeName(Mod->ModifiedType);
+ SmallString<256> TypeName;
+ if (Mod->Modifiers & uint16_t(ModifierOptions::Const))
+ TypeName.append("const ");
+ if (Mod->Modifiers & uint16_t(ModifierOptions::Volatile))
+ TypeName.append("volatile ");
+ if (Mod->Modifiers & uint16_t(ModifierOptions::Unaligned))
+ TypeName.append("__unaligned ");
+ TypeName.append(ModifiedName);
+ Name = CVTD.saveName(TypeName);
+}
+
+void CVTypeDumperImpl::visitVTableShape(TypeLeafKind Leaf, const VTableShape *Shape,
+ ArrayRef<uint8_t> LeafData) {
+ unsigned VFEntryCount = Shape->VFEntryCount;
+ W.printNumber("VFEntryCount", VFEntryCount);
+ // We could print out whether the methods are near or far, but in practice
+ // today everything is CV_VTS_near32, so it's just noise.
+}
+
+void CVTypeDumperImpl::visitUDTSrcLine(TypeLeafKind Leaf, const UDTSrcLine *Line,
+ ArrayRef<uint8_t> LeafData) {
+ printTypeIndex("UDT", Line->UDT);
+ printTypeIndex("SourceFile", Line->SourceFile);
+ W.printNumber("LineNumber", Line->LineNumber);
+}
+
+void CVTypeDumperImpl::visitBuildInfo(TypeLeafKind Leaf, const BuildInfo *Args,
+ ArrayRef<uint8_t> LeafData) {
+ W.printNumber("NumArgs", Args->NumArgs);
+
+ ListScope Arguments(W, "Arguments");
+ for (uint32_t ArgI = 0; ArgI != Args->NumArgs; ++ArgI) {
+ const TypeIndex *Type;
+ if (!consumeObject(LeafData, Type))
+ return;
+ printTypeIndex("ArgType", *Type);
+ }
+}
+
+void CVTypeDumperImpl::printMemberAttributes(MemberAttributes Attrs) {
+ W.printEnum("AccessSpecifier", uint8_t(Attrs.getAccess()),
+ makeArrayRef(MemberAccessNames));
+ auto MK = Attrs.getMethodKind();
+ // Data members will be vanilla. Don't try to print a method kind for them.
+ if (MK != MethodKind::Vanilla)
+ W.printEnum("MethodKind", unsigned(MK), makeArrayRef(MemberKindNames));
+ if (Attrs.getFlags() != MethodOptions::None) {
+ W.printFlags("MethodOptions", unsigned(Attrs.getFlags()),
+ makeArrayRef(MethodOptionNames));
+ }
+}
+
+void CVTypeDumperImpl::visitUnknownMember(TypeLeafKind Leaf) {
+ W.printHex("UnknownMember", unsigned(Leaf));
+}
+
+void CVTypeDumperImpl::visitNestedType(TypeLeafKind Leaf, const NestedType *Nested,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "NestedType");
+ printTypeIndex("Type", Nested->Type);
+ StringRef Name = getBytesAsCString(FieldData);
+ FieldData = FieldData.drop_front(Name.size() + 1);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumperImpl::visitOneMethod(TypeLeafKind Leaf, const OneMethod *Method,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "OneMethod");
+ printMemberAttributes(Method->Attrs);
+ printTypeIndex("Type", Method->Type);
+ // If virtual, then read the vftable offset.
+ if (Method->isIntroducedVirtual()) {
+ const little32_t *VFTOffsetPtr;
+ if (!consumeObject(FieldData, VFTOffsetPtr))
+ return;
+ W.printHex("VFTableOffset", *VFTOffsetPtr);
+ }
+ StringRef Name = getBytesAsCString(FieldData);
+ FieldData = FieldData.drop_front(Name.size() + 1);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumperImpl::visitOverloadedMethod(TypeLeafKind Leaf,
+ const OverloadedMethod *Method,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "OverloadedMethod");
+ W.printHex("MethodCount", Method->MethodCount);
+ W.printHex("MethodListIndex", Method->MethList.getIndex());
+ StringRef Name = getBytesAsCString(FieldData);
+ FieldData = FieldData.drop_front(Name.size() + 1);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumperImpl::visitDataMember(TypeLeafKind Leaf, const DataMember *Field,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "DataMember");
+ printMemberAttributes(Field->Attrs);
+ printTypeIndex("Type", Field->Type);
+ uint64_t FieldOffset;
+ if (!decodeUIntLeaf(FieldData, FieldOffset))
+ return parseError();
+ W.printHex("FieldOffset", FieldOffset);
+ StringRef Name = getBytesAsCString(FieldData);
+ FieldData = FieldData.drop_front(Name.size() + 1);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumperImpl::visitStaticDataMember(TypeLeafKind Leaf,
+ const StaticDataMember *Field,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "StaticDataMember");
+ printMemberAttributes(Field->Attrs);
+ printTypeIndex("Type", Field->Type);
+ StringRef Name = getBytesAsCString(FieldData);
+ FieldData = FieldData.drop_front(Name.size() + 1);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumperImpl::visitVirtualFunctionPointer(
+ TypeLeafKind Leaf, const VirtualFunctionPointer *VFTable,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "VirtualFunctionPointer");
+ printTypeIndex("Type", VFTable->Type);
+}
+
+void CVTypeDumperImpl::visitEnumerator(TypeLeafKind Leaf, const Enumerator *Enum,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "Enumerator");
+ printMemberAttributes(Enum->Attrs);
+ APSInt EnumValue;
+ if (!decodeNumericLeaf(FieldData, EnumValue))
+ return parseError();
+ W.printNumber("EnumValue", EnumValue);
+ StringRef Name = getBytesAsCString(FieldData);
+ FieldData = FieldData.drop_front(Name.size() + 1);
+ W.printString("Name", Name);
+}
+
+void CVTypeDumperImpl::visitBaseClass(TypeLeafKind Leaf, const BaseClass *Base,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "BaseClass");
+ printMemberAttributes(Base->Attrs);
+ printTypeIndex("BaseType", Base->BaseType);
+ uint64_t BaseOffset;
+ if (!decodeUIntLeaf(FieldData, BaseOffset))
+ return parseError();
+ W.printHex("BaseOffset", BaseOffset);
+}
+
+void CVTypeDumperImpl::visitVirtualBaseClass(TypeLeafKind Leaf,
+ const VirtualBaseClass *Base,
+ ArrayRef<uint8_t> &FieldData) {
+ DictScope S(W, "VirtualBaseClass");
+ printMemberAttributes(Base->Attrs);
+ printTypeIndex("BaseType", Base->BaseType);
+ printTypeIndex("VBPtrType", Base->VBPtrType);
+ uint64_t VBPtrOffset, VBTableIndex;
+ if (!decodeUIntLeaf(FieldData, VBPtrOffset))
+ return parseError();
+ if (!decodeUIntLeaf(FieldData, VBTableIndex))
+ return parseError();
+ W.printHex("VBPtrOffset", VBPtrOffset);
+ W.printHex("VBTableIndex", VBTableIndex);
+}
+
+StringRef CVTypeDumper::getTypeName(TypeIndex TI) {
+ if (TI.isNoType())
+ return "<no type>";
+
+ if (TI.isSimple()) {
+ // This is a simple type.
+ for (const auto &SimpleTypeName : SimpleTypeNames) {
+ if (SimpleTypeName.Value == TI.getSimpleKind()) {
+ if (TI.getSimpleMode() == SimpleTypeMode::Direct)
+ return SimpleTypeName.Name.drop_back(1);
+ // Otherwise, this is a pointer type. We gloss over the distinction
+ // between near, far, 64, 32, etc, and just give a pointer type.
+ return SimpleTypeName.Name;
+ }
+ }
+ return "<unknown simple type>";
+ }
+
+ // User-defined type.
+ StringRef UDTName;
+ unsigned UDTIndex = TI.getIndex() - 0x1000;
+ if (UDTIndex < CVUDTNames.size())
+ return CVUDTNames[UDTIndex];
+
+ return "<unknown UDT>";
+}
+
+void CVTypeDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) {
+ StringRef TypeName;
+ if (!TI.isNoType())
+ TypeName = getTypeName(TI);
+ if (!TypeName.empty())
+ W.printHex(FieldName, TypeName, TI.getIndex());
+ else
+ W.printHex(FieldName, TI.getIndex());
+}
+
+bool CVTypeDumper::dump(ArrayRef<uint8_t> Data) {
+ CVTypeDumperImpl Dumper(*this, W, PrintRecordBytes);
+ Dumper.visitTypeStream(Data);
+ return !Dumper.hadError();
+}
Added: llvm/trunk/lib/DebugInfo/CodeView/TypeStream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeStream.cpp?rev=268580&view=auto
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeStream.cpp (added)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeStream.cpp Wed May 4 19:34:33 2016
@@ -0,0 +1,97 @@
+//===-- TypeStream.cpp ----------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Utilities for parsing CodeView type streams.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/DebugInfo/CodeView/TypeStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::support;
+
+bool llvm::codeview::decodeNumericLeaf(ArrayRef<uint8_t> &Data, APSInt &Num) {
+ // Used to avoid overload ambiguity on APInt construtor.
+ bool FalseVal = false;
+ if (Data.size() < 2)
+ return false;
+ uint16_t Short = *reinterpret_cast<const ulittle16_t *>(Data.data());
+ Data = Data.drop_front(2);
+ if (Short < LF_NUMERIC) {
+ Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
+ /*isUnsigned=*/true);
+ return true;
+ }
+ switch (Short) {
+ case LF_CHAR:
+ Num = APSInt(APInt(/*numBits=*/8,
+ *reinterpret_cast<const int8_t *>(Data.data()),
+ /*isSigned=*/true),
+ /*isUnsigned=*/false);
+ Data = Data.drop_front(1);
+ return true;
+ case LF_SHORT:
+ Num = APSInt(APInt(/*numBits=*/16,
+ *reinterpret_cast<const little16_t *>(Data.data()),
+ /*isSigned=*/true),
+ /*isUnsigned=*/false);
+ Data = Data.drop_front(2);
+ return true;
+ case LF_USHORT:
+ Num = APSInt(APInt(/*numBits=*/16,
+ *reinterpret_cast<const ulittle16_t *>(Data.data()),
+ /*isSigned=*/false),
+ /*isUnsigned=*/true);
+ Data = Data.drop_front(2);
+ return true;
+ case LF_LONG:
+ Num = APSInt(APInt(/*numBits=*/32,
+ *reinterpret_cast<const little32_t *>(Data.data()),
+ /*isSigned=*/true),
+ /*isUnsigned=*/false);
+ Data = Data.drop_front(4);
+ return true;
+ case LF_ULONG:
+ Num = APSInt(APInt(/*numBits=*/32,
+ *reinterpret_cast<const ulittle32_t *>(Data.data()),
+ /*isSigned=*/FalseVal),
+ /*isUnsigned=*/true);
+ Data = Data.drop_front(4);
+ return true;
+ case LF_QUADWORD:
+ Num = APSInt(APInt(/*numBits=*/64,
+ *reinterpret_cast<const little64_t *>(Data.data()),
+ /*isSigned=*/true),
+ /*isUnsigned=*/false);
+ Data = Data.drop_front(8);
+ return true;
+ case LF_UQUADWORD:
+ Num = APSInt(APInt(/*numBits=*/64,
+ *reinterpret_cast<const ulittle64_t *>(Data.data()),
+ /*isSigned=*/false),
+ /*isUnsigned=*/true);
+ Data = Data.drop_front(8);
+ return true;
+ }
+ return false;
+}
+
+/// Decode a numeric leaf value that is known to be a uint32_t.
+bool llvm::codeview::decodeUIntLeaf(ArrayRef<uint8_t> &Data, uint64_t &Num) {
+ APSInt N;
+ if (!decodeNumericLeaf(Data, N))
+ return false;
+ if (N.isSigned() || !N.isIntN(64))
+ return false;
+ Num = N.getLimitedValue();
+ return true;
+}
Modified: llvm/trunk/tools/llvm-readobj/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/CMakeLists.txt?rev=268580&r1=268579&r2=268580&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-readobj/CMakeLists.txt Wed May 4 19:34:33 2016
@@ -1,4 +1,5 @@
set(LLVM_LINK_COMPONENTS
+ DebugInfoCodeView
Object
Support
)
Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=268580&r1=268579&r2=268580&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Wed May 4 19:34:33 2016
@@ -22,11 +22,10 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeDumper.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeStream.h"
@@ -54,65 +53,11 @@ using namespace llvm::Win64EH;
namespace {
-class CVTypeDumper : public CVTypeVisitor<CVTypeDumper> {
-public:
- CVTypeDumper(ScopedPrinter &W) : W(W) {}
-
- StringRef getTypeName(TypeIndex TI);
- void printTypeIndex(StringRef FieldName, TypeIndex TI);
-
- void dump(ArrayRef<uint8_t> Data);
-
- /// CVTypeVisitor overrides.
-#define TYPE_RECORD(ClassName, LeafEnum) \
- void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
- ArrayRef<uint8_t> LeafData);
-#define TYPE_RECORD_ALIAS(ClassName, LeafEnum)
-#define MEMBER_RECORD(ClassName, LeafEnum) \
- void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
- ArrayRef<uint8_t> &FieldData);
-#define MEMBER_RECORD_ALIAS(ClassName, LeafEnum)
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
-
- /// Method overload lists are a special case.
- void visitMethodList(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData);
-
- void visitUnknownMember(TypeLeafKind Leaf);
-
- void visitTypeBegin(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData);
- void visitTypeEnd(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData);
-
-private:
- void printMemberAttributes(MemberAttributes Attrs);
-
- /// Reinterpret a byte array as an array of characters. Does not interpret as
- /// a C string, as StringRef has several helpers (split) that make that easy.
- static StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
- return StringRef(reinterpret_cast<const char *>(LeafData.data()),
- LeafData.size());
- }
-
- static StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData) {
- return getBytesAsCharacters(LeafData).split('\0').first;
- }
-
- ScopedPrinter &W;
-
- /// Name of the current type. Only valid before visitTypeEnd.
- StringRef Name;
-
- /// All user defined type records in .debug$T live in here. Type indices
- /// greater than 0x1000 are user defined. Subtract 0x1000 from the index to
- /// index into this vector.
- SmallVector<StringRef, 10> CVUDTNames;
-
- StringSet<> TypeNames;
-};
-
class COFFDumper : public ObjDumper {
public:
COFFDumper(const llvm::object::COFFObjectFile *Obj, ScopedPrinter &Writer)
- : ObjDumper(Writer), Obj(Obj), CVTD(Writer) {}
+ : ObjDumper(Writer), Obj(Obj),
+ CVTD(Writer, opts::CodeViewSubsectionBytes) {}
void printFileHeaders() override;
void printSections() override;
@@ -194,8 +139,7 @@ private:
CVTypeDumper CVTD;
};
-} // namespace
-
+} // end namespace
namespace llvm {
@@ -653,178 +597,6 @@ static const EnumEntry<uint16_t> FrameCo
LLVM_READOBJ_ENUM_ENT(FrameCookieSym, XorR13),
};
-static const EnumEntry<uint16_t> ClassOptionNames[] = {
- LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, Packed),
- LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, HasConstructorOrDestructor),
- LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, HasOverloadedOperator),
- LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, Nested),
- LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, ContainsNestedClass),
- LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, HasOverloadedAssignmentOperator),
- LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, HasConversionOperator),
- LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, ForwardReference),
- LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, Scoped),
- LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, HasUniqueName),
- LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, Sealed),
- LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, Intrinsic),
-};
-
-static const EnumEntry<uint8_t> MemberAccessNames[] = {
- LLVM_READOBJ_ENUM_CLASS_ENT(MemberAccess, None),
- LLVM_READOBJ_ENUM_CLASS_ENT(MemberAccess, Private),
- LLVM_READOBJ_ENUM_CLASS_ENT(MemberAccess, Protected),
- LLVM_READOBJ_ENUM_CLASS_ENT(MemberAccess, Public),
-};
-
-static const EnumEntry<uint16_t> MethodOptionNames[] = {
- LLVM_READOBJ_ENUM_CLASS_ENT(MethodOptions, Pseudo),
- LLVM_READOBJ_ENUM_CLASS_ENT(MethodOptions, NoInherit),
- LLVM_READOBJ_ENUM_CLASS_ENT(MethodOptions, NoConstruct),
- LLVM_READOBJ_ENUM_CLASS_ENT(MethodOptions, CompilerGenerated),
- LLVM_READOBJ_ENUM_CLASS_ENT(MethodOptions, Sealed),
-};
-
-static const EnumEntry<uint16_t> MemberKindNames[] = {
- LLVM_READOBJ_ENUM_CLASS_ENT(MethodKind, Vanilla),
- LLVM_READOBJ_ENUM_CLASS_ENT(MethodKind, Virtual),
- LLVM_READOBJ_ENUM_CLASS_ENT(MethodKind, Static),
- LLVM_READOBJ_ENUM_CLASS_ENT(MethodKind, Friend),
- LLVM_READOBJ_ENUM_CLASS_ENT(MethodKind, IntroducingVirtual),
- LLVM_READOBJ_ENUM_CLASS_ENT(MethodKind, PureVirtual),
- LLVM_READOBJ_ENUM_CLASS_ENT(MethodKind, PureIntroducingVirtual),
-};
-
-/// The names here all end in "*". If the simple type is a pointer type, we
-/// return the whole name. Otherwise we lop off the last character in our
-/// StringRef.
-static const EnumEntry<SimpleTypeKind> SimpleTypeNames[] = {
- {"void*", SimpleTypeKind::Void},
- {"<not translated>*", SimpleTypeKind::NotTranslated},
- {"HRESULT*", SimpleTypeKind::HResult},
- {"signed char*", SimpleTypeKind::SignedCharacter},
- {"unsigned char*", SimpleTypeKind::UnsignedCharacter},
- {"char*", SimpleTypeKind::NarrowCharacter},
- {"wchar_t*", SimpleTypeKind::WideCharacter},
- {"char16_t*", SimpleTypeKind::Character16},
- {"char32_t*", SimpleTypeKind::Character32},
- {"__int8*", SimpleTypeKind::SByte},
- {"unsigned __int8*", SimpleTypeKind::Byte},
- {"short*", SimpleTypeKind::Int16Short},
- {"unsigned short*", SimpleTypeKind::UInt16Short},
- {"__int16*", SimpleTypeKind::Int16},
- {"unsigned __int16*", SimpleTypeKind::UInt16},
- {"long*", SimpleTypeKind::Int32Long},
- {"unsigned long*", SimpleTypeKind::UInt32Long},
- {"int*", SimpleTypeKind::Int32},
- {"unsigned*", SimpleTypeKind::UInt32},
- {"__int64*", SimpleTypeKind::Int64Quad},
- {"unsigned __int64*", SimpleTypeKind::UInt64Quad},
- {"__int64*", SimpleTypeKind::Int64},
- {"unsigned __int64*", SimpleTypeKind::UInt64},
- {"__int128*", SimpleTypeKind::Int128},
- {"unsigned __int128*", SimpleTypeKind::UInt128},
- {"__half*", SimpleTypeKind::Float16},
- {"float*", SimpleTypeKind::Float32},
- {"float*", SimpleTypeKind::Float32PartialPrecision},
- {"__float48*", SimpleTypeKind::Float48},
- {"double*", SimpleTypeKind::Float64},
- {"long double*", SimpleTypeKind::Float80},
- {"__float128*", SimpleTypeKind::Float128},
- {"_Complex float*", SimpleTypeKind::Complex32},
- {"_Complex double*", SimpleTypeKind::Complex64},
- {"_Complex long double*", SimpleTypeKind::Complex80},
- {"_Complex __float128*", SimpleTypeKind::Complex128},
- {"bool*", SimpleTypeKind::Boolean8},
- {"__bool16*", SimpleTypeKind::Boolean16},
- {"__bool32*", SimpleTypeKind::Boolean32},
- {"__bool64*", SimpleTypeKind::Boolean64},
-};
-
-static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
-#define LEAF_TYPE(name, val) LLVM_READOBJ_ENUM_ENT(TypeLeafKind, name),
-#include "llvm/DebugInfo/CodeView/CVLeafTypes.def"
-};
-
-static const EnumEntry<uint8_t> PtrKindNames[] = {
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, Near16),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, Far16),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, Huge16),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, BasedOnSegment),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, BasedOnValue),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, BasedOnSegmentValue),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, BasedOnAddress),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, BasedOnSegmentAddress),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, BasedOnType),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, BasedOnSelf),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, Near32),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, Far32),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, Near64),
-};
-
-static const EnumEntry<uint8_t> PtrModeNames[] = {
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerMode, Pointer),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerMode, LValueReference),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerMode, PointerToDataMember),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerMode, PointerToMemberFunction),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerMode, RValueReference),
-};
-
-static const EnumEntry<uint16_t> PtrMemberRepNames[] = {
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation, Unknown),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation,
- SingleInheritanceData),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation,
- MultipleInheritanceData),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation,
- VirtualInheritanceData),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation, GeneralData),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation,
- SingleInheritanceFunction),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation,
- MultipleInheritanceFunction),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation,
- VirtualInheritanceFunction),
- LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation, GeneralFunction),
-};
-
-static const EnumEntry<uint16_t> TypeModifierNames[] = {
- LLVM_READOBJ_ENUM_CLASS_ENT(ModifierOptions, Const),
- LLVM_READOBJ_ENUM_CLASS_ENT(ModifierOptions, Volatile),
- LLVM_READOBJ_ENUM_CLASS_ENT(ModifierOptions, Unaligned),
-};
-
-static const EnumEntry<uint8_t> CallingConventions[] = {
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, NearC),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, FarC),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, NearPascal),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, FarPascal),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, NearFast),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, FarFast),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, NearStdCall),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, FarStdCall),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, NearSysCall),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, FarSysCall),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, ThisCall),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, MipsCall),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, Generic),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, AlphaCall),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, PpcCall),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, SHCall),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, ArmCall),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, AM33Call),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, TriCall),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, SH5Call),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, M32RCall),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, ClrCall),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, Inline),
- LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, NearVector),
-};
-
-static const EnumEntry<uint8_t> FunctionOptionEnum[] = {
- LLVM_READOBJ_ENUM_CLASS_ENT(FunctionOptions, CxxReturnUdt),
- LLVM_READOBJ_ENUM_CLASS_ENT(FunctionOptions, Constructor),
- LLVM_READOBJ_ENUM_CLASS_ENT(FunctionOptions, ConstructorWithVirtualBases),
-};
-
static const EnumEntry<uint8_t> FileChecksumKindNames[] = {
LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, None),
LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, MD5),
@@ -1214,92 +986,6 @@ void COFFDumper::printCodeViewSymbolSect
}
}
-static std::error_code decodeNumerictLeaf(ArrayRef<uint8_t> &Data,
- APSInt &Num) {
- // Used to avoid overload ambiguity on APInt construtor.
- bool FalseVal = false;
- if (Data.size() < 2)
- return object_error::parse_failed;
- uint16_t Short = *reinterpret_cast<const ulittle16_t *>(Data.data());
- Data = Data.drop_front(2);
- if (Short < LF_NUMERIC) {
- Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
- /*isUnsigned=*/true);
- return std::error_code();
- }
- switch (Short) {
- case LF_CHAR:
- Num = APSInt(APInt(/*numBits=*/8,
- *reinterpret_cast<const int8_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(1);
- return std::error_code();
- case LF_SHORT:
- Num = APSInt(APInt(/*numBits=*/16,
- *reinterpret_cast<const little16_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(2);
- return std::error_code();
- case LF_USHORT:
- Num = APSInt(APInt(/*numBits=*/16,
- *reinterpret_cast<const ulittle16_t *>(Data.data()),
- /*isSigned=*/false),
- /*isUnsigned=*/true);
- Data = Data.drop_front(2);
- return std::error_code();
- case LF_LONG:
- Num = APSInt(APInt(/*numBits=*/32,
- *reinterpret_cast<const little32_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(4);
- return std::error_code();
- case LF_ULONG:
- Num = APSInt(APInt(/*numBits=*/32,
- *reinterpret_cast<const ulittle32_t *>(Data.data()),
- /*isSigned=*/FalseVal),
- /*isUnsigned=*/true);
- Data = Data.drop_front(4);
- return std::error_code();
- case LF_QUADWORD:
- Num = APSInt(APInt(/*numBits=*/64,
- *reinterpret_cast<const little64_t *>(Data.data()),
- /*isSigned=*/true),
- /*isUnsigned=*/false);
- Data = Data.drop_front(8);
- return std::error_code();
- case LF_UQUADWORD:
- Num = APSInt(APInt(/*numBits=*/64,
- *reinterpret_cast<const ulittle64_t *>(Data.data()),
- /*isSigned=*/false),
- /*isUnsigned=*/true);
- Data = Data.drop_front(8);
- return std::error_code();
- }
- return object_error::parse_failed;
-}
-
-static std::error_code decodeNumerictLeaf(StringRef &Data, APSInt &Num) {
- ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(Data.data()),
- Data.size());
- auto EC = decodeNumerictLeaf(Bytes, Num);
- Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
- return EC;
-}
-
-/// Decode an unsigned integer numeric leaf value.
-std::error_code decodeUIntLeaf(ArrayRef<uint8_t> &Data, uint64_t &Num) {
- APSInt N;
- if (std::error_code err = decodeNumerictLeaf(Data, N))
- return err;
- if (N.isSigned() || !N.isIntN(64))
- return object_error::parse_failed;
- Num = N.getLimitedValue();
- return std::error_code();
-}
-
void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
const SectionRef &Section,
StringRef SectionContents) {
@@ -1814,7 +1500,8 @@ void COFFDumper::printCodeViewSymbolsSub
error(consumeObject(SymData, Constant));
printTypeIndex("Type", Constant->Type);
APSInt Value;
- error(decodeNumerictLeaf(SymData, Value));
+ if (!decodeNumericLeaf(SymData, Value))
+ error(object_error::parse_failed);
W.printNumber("Value", Value);
StringRef Name = SymData.split('\0').first;
W.printString("Name", Name);
@@ -1889,43 +1576,6 @@ void COFFDumper::printCodeViewInlineeLin
}
}
-StringRef CVTypeDumper::getTypeName(TypeIndex TI) {
- if (TI.isNoType())
- return "<no type>";
-
- if (TI.isSimple()) {
- // This is a simple type.
- for (const auto &SimpleTypeName : SimpleTypeNames) {
- if (SimpleTypeName.Value == TI.getSimpleKind()) {
- if (TI.getSimpleMode() == SimpleTypeMode::Direct)
- return SimpleTypeName.Name.drop_back(1);
- // Otherwise, this is a pointer type. We gloss over the distinction
- // between near, far, 64, 32, etc, and just give a pointer type.
- return SimpleTypeName.Name;
- }
- }
- return "<unknown simple type>";
- }
-
- // User-defined type.
- StringRef UDTName;
- unsigned UDTIndex = TI.getIndex() - 0x1000;
- if (UDTIndex < CVUDTNames.size())
- return CVUDTNames[UDTIndex];
-
- return "<unknown UDT>";
-}
-
-void CVTypeDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) {
- StringRef TypeName;
- if (!TI.isNoType())
- TypeName = getTypeName(TI);
- if (!TypeName.empty())
- W.printHex(FieldName, TypeName, TI.getIndex());
- else
- W.printHex(FieldName, TI.getIndex());
-}
-
void COFFDumper::printLocalVariableAddrRange(
const LocalVariableAddrRange &Range, const coff_section *Sec,
StringRef SectionContents) {
@@ -1970,17 +1620,6 @@ void COFFDumper::printFileNameForOffset(
W.printHex(Label, getFileNameForFileOffset(FileOffset), FileOffset);
}
-static StringRef getLeafTypeName(TypeLeafKind LT) {
- switch (LT) {
-#define KNOWN_TYPE(LeafName, Value, ClassName) \
- case LeafName: return #ClassName;
-#include "llvm/DebugInfo/CodeView/CVLeafTypes.def"
- default:
- break;
- }
- return "UnknownLeaf";
-}
-
void COFFDumper::printCodeViewTypeSection(StringRef SectionName,
const SectionRef &Section) {
ListScope D(W, "CodeViewTypes");
@@ -1999,452 +1638,10 @@ void COFFDumper::printCodeViewTypeSectio
ArrayRef<uint8_t> BinaryData(reinterpret_cast<const uint8_t *>(Data.data()),
Data.size());
- CVTD.dump(BinaryData);
-}
-
-void CVTypeDumper::dump(ArrayRef<uint8_t> Data) {
- visitTypeStream(Data);
- if (hadError())
+ if (!CVTD.dump(BinaryData)) {
+ W.flush();
error(object_error::parse_failed);
-}
-
-void CVTypeDumper::visitTypeBegin(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData) {
- // Reset Name to the empty string. If the visitor sets it, we know it.
- Name = "";
-
- W.startLine() << getLeafTypeName(Leaf) << " {\n";
- W.indent();
- unsigned NextTypeIndex = 0x1000 + CVUDTNames.size();
- W.printEnum("TypeLeafKind", unsigned(Leaf), makeArrayRef(LeafTypeNames));
- W.printHex("TypeIndex", NextTypeIndex);
- W.flush();
-}
-
-void CVTypeDumper::visitTypeEnd(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData) {
- // Always record some name for every type, even if Name is empty, since
- // CVUDTNames is indexed by TypeIndex.
- CVUDTNames.push_back(Name);
-
- if (opts::CodeViewSubsectionBytes)
- W.printBinaryBlock("LeafData", getBytesAsCharacters(LeafData));
-
- W.unindent();
- W.startLine() << "}\n";
- W.flush();
-}
-
-void CVTypeDumper::visitStringId(TypeLeafKind Leaf, const StringId *String,
- ArrayRef<uint8_t> LeafData) {
- W.printHex("Id", String->id.getIndex());
- StringRef StringData = getBytesAsCString(LeafData);
- W.printString("StringData", StringData);
- // Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE.
- Name = StringData;
-}
-
-void CVTypeDumper::visitArgList(TypeLeafKind Leaf, const ArgList *Args,
- ArrayRef<uint8_t> LeafData) {
- W.printNumber("NumArgs", Args->NumArgs);
- ListScope Arguments(W, "Arguments");
- SmallString<256> TypeName("(");
- for (uint32_t ArgI = 0; ArgI != Args->NumArgs; ++ArgI) {
- const TypeIndex *Type;
- if (!consumeObject(LeafData, Type))
- return;
- printTypeIndex("ArgType", *Type);
- StringRef ArgTypeName = getTypeName(*Type);
- TypeName.append(ArgTypeName);
- if (ArgI + 1 != Args->NumArgs)
- TypeName.append(", ");
- }
- TypeName.push_back(')');
- Name = TypeNames.insert(TypeName).first->getKey();
-}
-
-void CVTypeDumper::visitClassType(TypeLeafKind Leaf, const ClassType *Class,
- ArrayRef<uint8_t> LeafData) {
- W.printNumber("MemberCount", Class->MemberCount);
- uint16_t Props = Class->Properties;
- W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
- printTypeIndex("FieldList", Class->FieldList);
- printTypeIndex("DerivedFrom", Class->DerivedFrom);
- printTypeIndex("VShape", Class->VShape);
- uint64_t SizeOf;
- error(decodeUIntLeaf(LeafData, SizeOf));
- W.printNumber("SizeOf", SizeOf);
- StringRef LeafChars = getBytesAsCharacters(LeafData);
- StringRef LinkageName;
- std::tie(Name, LinkageName) = LeafChars.split('\0');
- W.printString("Name", Name);
- if (Props & uint16_t(ClassOptions::HasUniqueName)) {
- LinkageName = LinkageName.split('\0').first;
- if (LinkageName.empty())
- return error(object_error::parse_failed);
- W.printString("LinkageName", LinkageName);
- }
-}
-
-void CVTypeDumper::visitUnionType(TypeLeafKind Leaf, const UnionType *Union,
- ArrayRef<uint8_t> LeafData) {
- W.printNumber("MemberCount", Union->MemberCount);
- uint16_t Props = Union->Properties;
- W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
- printTypeIndex("FieldList", Union->FieldList);
- uint64_t SizeOf;
- error(decodeUIntLeaf(LeafData, SizeOf));
- W.printNumber("SizeOf", SizeOf);
- StringRef LeafChars = getBytesAsCharacters(LeafData);
- StringRef LinkageName;
- std::tie(Name, LinkageName) = LeafChars.split('\0');
- W.printString("Name", Name);
- if (Props & uint16_t(ClassOptions::HasUniqueName)) {
- LinkageName = LinkageName.split('\0').first;
- if (LinkageName.empty())
- return error(object_error::parse_failed);
- W.printString("LinkageName", LinkageName);
- }
-}
-
-void CVTypeDumper::visitEnumType(TypeLeafKind Leaf, const EnumType *Enum,
- ArrayRef<uint8_t> LeafData) {
- W.printNumber("NumEnumerators", Enum->NumEnumerators);
- W.printFlags("Properties", uint16_t(Enum->Properties),
- makeArrayRef(ClassOptionNames));
- printTypeIndex("UnderlyingType", Enum->UnderlyingType);
- printTypeIndex("FieldListType", Enum->FieldListType);
- Name = getBytesAsCString(LeafData);
- W.printString("Name", Name);
-}
-
-void CVTypeDumper::visitArrayType(TypeLeafKind Leaf, const ArrayType *AT,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("ElementType", AT->ElementType);
- printTypeIndex("IndexType", AT->IndexType);
- uint64_t SizeOf;
- error(decodeUIntLeaf(LeafData, SizeOf));
- W.printNumber("SizeOf", SizeOf);
- Name = getBytesAsCString(LeafData);
- W.printString("Name", Name);
-}
-
-void CVTypeDumper::visitVFTableType(TypeLeafKind Leaf, const VFTableType *VFT,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("CompleteClass", VFT->CompleteClass);
- printTypeIndex("OverriddenVFTable", VFT->OverriddenVFTable);
- W.printHex("VFPtrOffset", VFT->VFPtrOffset);
- StringRef NamesData = getBytesAsCharacters(LeafData.slice(0, VFT->NamesLen));
- std::tie(Name, NamesData) = NamesData.split('\0');
- W.printString("VFTableName", Name);
- while (!NamesData.empty()) {
- StringRef MethodName;
- std::tie(MethodName, NamesData) = NamesData.split('\0');
- W.printString("MethodName", MethodName);
- }
-}
-
-void CVTypeDumper::visitMemberFuncId(TypeLeafKind Leaf, const MemberFuncId *Id,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("ClassType", Id->ClassType);
- printTypeIndex("FunctionType", Id->FunctionType);
- Name = getBytesAsCString(LeafData);
- W.printString("Name", Name);
-}
-
-void CVTypeDumper::visitProcedureType(TypeLeafKind Leaf,
- const ProcedureType *Proc,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("ReturnType", Proc->ReturnType);
- W.printEnum("CallingConvention", uint8_t(Proc->CallConv),
- makeArrayRef(CallingConventions));
- W.printFlags("FunctionOptions", uint8_t(Proc->Options),
- makeArrayRef(FunctionOptionEnum));
- W.printNumber("NumParameters", Proc->NumParameters);
- printTypeIndex("ArgListType", Proc->ArgListType);
-
- StringRef ReturnTypeName = getTypeName(Proc->ReturnType);
- StringRef ArgListTypeName = getTypeName(Proc->ArgListType);
- SmallString<256> TypeName(ReturnTypeName);
- TypeName.push_back(' ');
- TypeName.append(ArgListTypeName);
- Name = TypeNames.insert(TypeName).first->getKey();
-}
-
-void CVTypeDumper::visitMemberFunctionType(TypeLeafKind Leaf,
- const MemberFunctionType *MemberFunc,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("ReturnType", MemberFunc->ReturnType);
- printTypeIndex("ClassType", MemberFunc->ClassType);
- printTypeIndex("ThisType", MemberFunc->ThisType);
- W.printEnum("CallingConvention", uint8_t(MemberFunc->CallConv),
- makeArrayRef(CallingConventions));
- W.printFlags("FunctionOptions", uint8_t(MemberFunc->Options),
- makeArrayRef(FunctionOptionEnum));
- W.printNumber("NumParameters", MemberFunc->NumParameters);
- printTypeIndex("ArgListType", MemberFunc->ArgListType);
- W.printNumber("ThisAdjustment", MemberFunc->ThisAdjustment);
-
- StringRef ReturnTypeName = getTypeName(MemberFunc->ReturnType);
- StringRef ClassTypeName = getTypeName(MemberFunc->ClassType);
- StringRef ArgListTypeName = getTypeName(MemberFunc->ArgListType);
- SmallString<256> TypeName(ReturnTypeName);
- TypeName.push_back(' ');
- TypeName.append(ClassTypeName);
- TypeName.append("::");
- TypeName.append(ArgListTypeName);
- Name = TypeNames.insert(TypeName).first->getKey();
-}
-
-void CVTypeDumper::visitMethodList(TypeLeafKind Leaf,
- ArrayRef<uint8_t> LeafData) {
- while (!LeafData.empty()) {
- const MethodListEntry *Method;
- if (!consumeObject(LeafData, Method))
- return;
- ListScope S(W, "Method");
- printMemberAttributes(Method->Attrs);
- printTypeIndex("Type", Method->Type);
- if (Method->isIntroducedVirtual()) {
- const little32_t *VFTOffsetPtr;
- if (!consumeObject(LeafData, VFTOffsetPtr))
- return;
- W.printHex("VFTableOffset", *VFTOffsetPtr);
- }
- }
-}
-
-void CVTypeDumper::visitFuncId(TypeLeafKind Leaf, const FuncId *Func,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("ParentScope", Func->ParentScope);
- printTypeIndex("FunctionType", Func->FunctionType);
- Name = getBytesAsCString(LeafData);
- W.printString("Name", Name);
-}
-
-void CVTypeDumper::visitTypeServer2(TypeLeafKind Leaf,
- const TypeServer2 *TypeServer,
- ArrayRef<uint8_t> LeafData) {
- W.printBinary("Signature", StringRef(TypeServer->Signature, 16));
- W.printNumber("Age", TypeServer->Age);
- Name = getBytesAsCString(LeafData);
- W.printString("Name", Name);
-}
-
-void CVTypeDumper::visitPointerType(TypeLeafKind Leaf, const PointerType *Ptr,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("PointeeType", Ptr->PointeeType);
- W.printHex("PointerAttributes", Ptr->Attrs);
- W.printEnum("PtrType", unsigned(Ptr->getPtrKind()),
- makeArrayRef(PtrKindNames));
- W.printEnum("PtrMode", unsigned(Ptr->getPtrMode()),
- makeArrayRef(PtrModeNames));
- W.printNumber("IsFlat", Ptr->isFlat());
- W.printNumber("IsConst", Ptr->isConst());
- W.printNumber("IsVolatile", Ptr->isVolatile());
- W.printNumber("IsUnaligned", Ptr->isUnaligned());
-
- if (Ptr->isPointerToMember()) {
- const PointerToMemberTail *PMT;
- if (!consumeObject(LeafData, PMT))
- return;
- printTypeIndex("ClassType", PMT->ClassType);
- W.printEnum("Representation", PMT->Representation,
- makeArrayRef(PtrMemberRepNames));
-
- StringRef PointeeName = getTypeName(Ptr->PointeeType);
- StringRef ClassName = getTypeName(PMT->ClassType);
- SmallString<256> TypeName(PointeeName);
- TypeName.push_back(' ');
- TypeName.append(ClassName);
- TypeName.append("::*");
- Name = TypeNames.insert(TypeName).first->getKey();
- } else {
- W.printBinaryBlock("TailData", getBytesAsCharacters(LeafData));
-
- SmallString<256> TypeName;
- if (Ptr->isConst())
- TypeName.append("const ");
- if (Ptr->isVolatile())
- TypeName.append("volatile ");
- if (Ptr->isUnaligned())
- TypeName.append("__unaligned ");
-
- TypeName.append(getTypeName(Ptr->PointeeType));
-
- if (Ptr->getPtrMode() == PointerMode::LValueReference)
- TypeName.append("&");
- else if (Ptr->getPtrMode() == PointerMode::RValueReference)
- TypeName.append("&&");
- else if (Ptr->getPtrMode() == PointerMode::Pointer)
- TypeName.append("*");
-
- Name = TypeNames.insert(TypeName).first->getKey();
- }
-}
-
-void CVTypeDumper::visitTypeModifier(TypeLeafKind Leaf, const TypeModifier *Mod,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("ModifiedType", Mod->ModifiedType);
- W.printFlags("Modifiers", Mod->Modifiers, makeArrayRef(TypeModifierNames));
-
- StringRef ModifiedName = getTypeName(Mod->ModifiedType);
- SmallString<256> TypeName;
- if (Mod->Modifiers & uint16_t(ModifierOptions::Const))
- TypeName.append("const ");
- if (Mod->Modifiers & uint16_t(ModifierOptions::Volatile))
- TypeName.append("volatile ");
- if (Mod->Modifiers & uint16_t(ModifierOptions::Unaligned))
- TypeName.append("__unaligned ");
- TypeName.append(ModifiedName);
- Name = TypeNames.insert(TypeName).first->getKey();
-}
-
-void CVTypeDumper::visitVTableShape(TypeLeafKind Leaf, const VTableShape *Shape,
- ArrayRef<uint8_t> LeafData) {
- unsigned VFEntryCount = Shape->VFEntryCount;
- W.printNumber("VFEntryCount", VFEntryCount);
- // We could print out whether the methods are near or far, but in practice
- // today everything is CV_VTS_near32, so it's just noise.
-}
-
-void CVTypeDumper::visitUDTSrcLine(TypeLeafKind Leaf, const UDTSrcLine *Line,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("UDT", Line->UDT);
- printTypeIndex("SourceFile", Line->SourceFile);
- W.printNumber("LineNumber", Line->LineNumber);
-}
-
-void CVTypeDumper::visitBuildInfo(TypeLeafKind Leaf, const BuildInfo *Args,
- ArrayRef<uint8_t> LeafData) {
- W.printNumber("NumArgs", Args->NumArgs);
-
- ListScope Arguments(W, "Arguments");
- for (uint32_t ArgI = 0; ArgI != Args->NumArgs; ++ArgI) {
- const TypeIndex *Type;
- if (!consumeObject(LeafData, Type))
- return;
- printTypeIndex("ArgType", *Type);
- }
-}
-
-void CVTypeDumper::printMemberAttributes(MemberAttributes Attrs) {
- W.printEnum("AccessSpecifier", uint8_t(Attrs.getAccess()),
- makeArrayRef(MemberAccessNames));
- auto MK = Attrs.getMethodKind();
- // Data members will be vanilla. Don't try to print a method kind for them.
- if (MK != MethodKind::Vanilla)
- W.printEnum("MethodKind", unsigned(MK), makeArrayRef(MemberKindNames));
- if (Attrs.getFlags() != MethodOptions::None) {
- W.printFlags("MethodOptions", unsigned(Attrs.getFlags()),
- makeArrayRef(MethodOptionNames));
- }
-}
-
-void CVTypeDumper::visitUnknownMember(TypeLeafKind Leaf) {
- W.printHex("UnknownMember", unsigned(Leaf));
-}
-
-void CVTypeDumper::visitNestedType(TypeLeafKind Leaf, const NestedType *Nested,
- ArrayRef<uint8_t> &FieldData) {
- DictScope S(W, "NestedType");
- printTypeIndex("Type", Nested->Type);
- StringRef Name = getBytesAsCString(FieldData);
- FieldData = FieldData.drop_front(Name.size() + 1);
- W.printString("Name", Name);
-}
-
-void CVTypeDumper::visitOneMethod(TypeLeafKind Leaf, const OneMethod *Method,
- ArrayRef<uint8_t> &FieldData) {
- DictScope S(W, "OneMethod");
- printMemberAttributes(Method->Attrs);
- printTypeIndex("Type", Method->Type);
- // If virtual, then read the vftable offset.
- if (Method->isIntroducedVirtual()) {
- const little32_t *VFTOffsetPtr;
- if (!consumeObject(FieldData, VFTOffsetPtr))
- return;
- W.printHex("VFTableOffset", *VFTOffsetPtr);
}
- StringRef Name = getBytesAsCString(FieldData);
- FieldData = FieldData.drop_front(Name.size() + 1);
- W.printString("Name", Name);
-}
-
-void CVTypeDumper::visitOverloadedMethod(TypeLeafKind Leaf,
- const OverloadedMethod *Method,
- ArrayRef<uint8_t> &FieldData) {
- DictScope S(W, "OverloadedMethod");
- W.printHex("MethodCount", Method->MethodCount);
- W.printHex("MethodListIndex", Method->MethList.getIndex());
- StringRef Name = getBytesAsCString(FieldData);
- FieldData = FieldData.drop_front(Name.size() + 1);
- W.printString("Name", Name);
-}
-
-void CVTypeDumper::visitDataMember(TypeLeafKind Leaf, const DataMember *Field,
- ArrayRef<uint8_t> &FieldData) {
- DictScope S(W, "DataMember");
- printMemberAttributes(Field->Attrs);
- printTypeIndex("Type", Field->Type);
- uint64_t FieldOffset;
- error(decodeUIntLeaf(FieldData, FieldOffset));
- W.printHex("FieldOffset", FieldOffset);
- StringRef Name = getBytesAsCString(FieldData);
- FieldData = FieldData.drop_front(Name.size() + 1);
- W.printString("Name", Name);
-}
-
-void CVTypeDumper::visitStaticDataMember(TypeLeafKind Leaf,
- const StaticDataMember *Field,
- ArrayRef<uint8_t> &FieldData) {
- DictScope S(W, "StaticDataMember");
- printMemberAttributes(Field->Attrs);
- printTypeIndex("Type", Field->Type);
- StringRef Name = getBytesAsCString(FieldData);
- FieldData = FieldData.drop_front(Name.size() + 1);
- W.printString("Name", Name);
-}
-
-void CVTypeDumper::visitVirtualFunctionPointer(
- TypeLeafKind Leaf, const VirtualFunctionPointer *VFTable,
- ArrayRef<uint8_t> &FieldData) {
- DictScope S(W, "VirtualFunctionPointer");
- printTypeIndex("Type", VFTable->Type);
-}
-
-void CVTypeDumper::visitEnumerator(TypeLeafKind Leaf, const Enumerator *Enum,
- ArrayRef<uint8_t> &FieldData) {
- DictScope S(W, "Enumerator");
- printMemberAttributes(Enum->Attrs);
- APSInt EnumValue;
- error(decodeNumerictLeaf(FieldData, EnumValue));
- W.printNumber("EnumValue", EnumValue);
- StringRef Name = getBytesAsCString(FieldData);
- FieldData = FieldData.drop_front(Name.size() + 1);
- W.printString("Name", Name);
-}
-
-void CVTypeDumper::visitBaseClass(TypeLeafKind Leaf, const BaseClass *Base,
- ArrayRef<uint8_t> &FieldData) {
- DictScope S(W, "BaseClass");
- printMemberAttributes(Base->Attrs);
- printTypeIndex("BaseType", Base->BaseType);
- uint64_t BaseOffset;
- error(decodeUIntLeaf(FieldData, BaseOffset));
- W.printHex("BaseOffset", BaseOffset);
-}
-
-void CVTypeDumper::visitVirtualBaseClass(TypeLeafKind Leaf,
- const VirtualBaseClass *Base,
- ArrayRef<uint8_t> &FieldData) {
- DictScope S(W, "VirtualBaseClass");
- printMemberAttributes(Base->Attrs);
- printTypeIndex("BaseType", Base->BaseType);
- printTypeIndex("VBPtrType", Base->VBPtrType);
- uint64_t VBPtrOffset, VBTableIndex;
- error(decodeUIntLeaf(FieldData, VBPtrOffset));
- error(decodeUIntLeaf(FieldData, VBTableIndex));
- W.printHex("VBPtrOffset", VBPtrOffset);
- W.printHex("VBTableIndex", VBTableIndex);
}
void COFFDumper::printSections() {
More information about the llvm-commits
mailing list