[llvm-pdbdump] Display full enum definitions.

This will now display enum definitions both at the global
scope as well as nested inside of classes.  Additionally,
it will no longer display enums at the global scope if the
enum is nested.  Instead, it will omit the definition of
the enum globally and instead emit it in the corresponding
class definition.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231215 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Zachary Turner 2015-03-04 06:09:53 +00:00
parent cc8f2c2156
commit b9c28bc7f1
15 changed files with 188 additions and 63 deletions

View File

@ -26,6 +26,9 @@ public:
void dump(PDBSymDumper &Dumper) const override;
std::unique_ptr<PDBSymbolTypeUDT> getClassParent() const;
std::unique_ptr<PDBSymbolTypeBuiltin> getUnderlyingType() const;
FORWARD_SYMBOL_METHOD(getBuiltinType)
FORWARD_SYMBOL_METHOD(getClassParentId)
FORWARD_SYMBOL_METHOD(getUnmodifiedTypeId)

View File

@ -303,7 +303,7 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const Variant &Value) {
OS << Value.Int64;
break;
case PDB_VariantType::Int8:
OS << Value.Int8;
OS << static_cast<int>(Value.Int8);
break;
case PDB_VariantType::Single:
OS << Value.Single;
@ -318,7 +318,7 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const Variant &Value) {
OS << Value.UInt64;
break;
case PDB_VariantType::UInt8:
OS << Value.UInt8;
OS << static_cast<unsigned>(Value.UInt8);
break;
default:
OS << Value.Type;

View File

@ -9,7 +9,10 @@
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
#include <utility>
@ -19,4 +22,13 @@ PDBSymbolTypeEnum::PDBSymbolTypeEnum(const IPDBSession &PDBSession,
std::unique_ptr<IPDBRawSymbol> Symbol)
: PDBSymbol(PDBSession, std::move(Symbol)) {}
std::unique_ptr<PDBSymbolTypeUDT> PDBSymbolTypeEnum::getClassParent() const {
return Session.getConcreteSymbolById<PDBSymbolTypeUDT>(getClassParentId());
}
std::unique_ptr<PDBSymbolTypeBuiltin>
PDBSymbolTypeEnum::getUnderlyingType() const {
return Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(getTypeId());
}
void PDBSymbolTypeEnum::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }

View File

@ -1,6 +1,5 @@
; RUN: llvm-pdbdump -symbols %p/Inputs/symbolformat.pdb | FileCheck --check-prefix=SYM_FORMAT %s
; RUN: llvm-pdbdump -types %p/Inputs/symbolformat.pdb | FileCheck --check-prefix=TYPES_FORMAT %s
; RUN: llvm-pdbdump -types -class-definitions %p/Inputs/symbolformat.pdb | FileCheck --check-prefix=FULL_CLASS %s
; RUN: llvm-pdbdump -globals %p/Inputs/symbolformat.pdb | FileCheck --check-prefix=GLOBALS %s
; The format is func [0x<rva_start>+<prologue_length> - 0x<rva_end>-<epilogue_length>]
@ -25,33 +24,28 @@
; TYPES_FORMAT-DAG: typedef int IntType
; TYPES_FORMAT-DAG: typedef class A ClassAType
; TYPES_FORMAT: Classes
; TYPES_FORMAT-DAG: class A
; TYPES_FORMAT-DAG: class B
; FULL_CLASS: ---TYPES---
; FULL_CLASS: Classes
; FULL_CLASS-DAG: struct A {
; FULL_CLASS: public:
; FULL_CLASS: virtual void PureFunc() = 0
; FULL_CLASS: virtual void VirtualFunc()
; FULL_CLASS: void RegularFunc()
; FULL_CLASS: }
; FULL_CLASS-DAG: struct MemberTest {
; FULL_CLASS: data +0x00 MemberTest::NestedEnum m_nested_enum
; FULL_CLASS: data +0x04 int m_typedef
; FULL_CLASS: data +0x08 bool m_bool
; FULL_CLASS: data +0x09 char m_char
; FULL_CLASS: data +0x0a wchar_t m_wchar_t
; FULL_CLASS: data +0x0c int m_int
; FULL_CLASS: data +0x10 unsigned m_unsigned
; FULL_CLASS: data +0x14 long m_long
; FULL_CLASS: data +0x18 unsigned long m_unsigned_long
; FULL_CLASS: data +0x20 __int64 m_int64
; FULL_CLASS: data +0x28 unsigned __int64 m_unsigned_int64
; FULL_CLASS: data +0x30 float m_float
; FULL_CLASS: data +0x38 double m_double
; FULL_CLASS: data +0x40 void (__cdecl *m_pfn_2_args)(int, double)
; FULL_CLASS: }
; TYPES_FORMAT: struct A {
; TYPES_FORMAT: public:
; TYPES_FORMAT: virtual void PureFunc() = 0
; TYPES_FORMAT: virtual void VirtualFunc()
; TYPES_FORMAT: void RegularFunc()
; TYPES_FORMAT: }
; TYPES_FORMAT-DAG: struct MemberTest {
; TYPES_FORMAT: data +0x00 MemberTest::NestedEnum m_nested_enum
; TYPES_FORMAT: data +0x04 int m_typedef
; TYPES_FORMAT: data +0x08 bool m_bool
; TYPES_FORMAT: data +0x09 char m_char
; TYPES_FORMAT: data +0x0a wchar_t m_wchar_t
; TYPES_FORMAT: data +0x0c int m_int
; TYPES_FORMAT: data +0x10 unsigned m_unsigned
; TYPES_FORMAT: data +0x14 long m_long
; TYPES_FORMAT: data +0x18 unsigned long m_unsigned_long
; TYPES_FORMAT: data +0x20 __int64 m_int64
; TYPES_FORMAT: data +0x28 unsigned __int64 m_unsigned_int64
; TYPES_FORMAT: data +0x30 float m_float
; TYPES_FORMAT: data +0x38 double m_double
; TYPES_FORMAT: data +0x40 void (__cdecl *m_pfn_2_args)(int, double)
; TYPES_FORMAT: }
; GLOBALS: ---GLOBALS---
; GLOBALS-DAG: func [{{.*}}] (FPO) unsigned __cdecl fpo_func(unsigned n)

View File

@ -0,0 +1,20 @@
; RUN: llvm-pdbdump -types %p/Inputs/ClassLayoutTest.pdb > %t
; RUN: FileCheck -input-file=%t %s -check-prefix=GLOBAL_ENUM
; RUN: FileCheck -input-file=%t %s -check-prefix=MEMBER_ENUM
; GLOBAL_ENUM: ---TYPES---
; GLOBAL_ENUM: Enums:
; GLOBAL_ENUM: enum GlobalsTest::Enum {
; GLOBAL_ENUM-NEXT: Val1 = 0
; GLOBAL_ENUM-NEXT: }
; MEMBER_ENUM: ---TYPES---
; MEMBER_ENUM: Classes:
; MEMBER_ENUM: struct __vc_attributes::threadingAttribute {
; MEMBER_ENUM-NEXT: enum threading_e {
; MEMBER_ENUM-NEXT: apartment = 1
; MEMBER_ENUM-NEXT: single = 2
; MEMBER_ENUM-NEXT: free = 3
; MEMBER_ENUM-NEXT: neutral = 4
; MEMBER_ENUM-NEXT: both = 5
; MEMBER_ENUM-NEXT: }

View File

@ -1,13 +1,12 @@
; RUN: llvm-pdbdump -symbols -globals -class-definitions -types %p/Inputs/FilterTest.pdb \
; RUN: llvm-pdbdump -symbols -globals -types %p/Inputs/FilterTest.pdb \
; RUN: | FileCheck --check-prefix=NO_FILTER %s
; RUN: llvm-pdbdump -class-definitions -types -exclude-types="GlobalTypedef|NestedTypedef" \
; RUN: llvm-pdbdump -types -exclude-types="GlobalTypedef|NestedTypedef" \
; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_TYPEDEFS %s
; RUN: llvm-pdbdump -class-definitions -types -exclude-types="GlobalEnum|NestedEnum" \
; RUN: llvm-pdbdump -types -exclude-types="GlobalEnum|NestedEnum" \
; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_ENUMS %s
; RUN: llvm-pdbdump -class-definitions -types -symbols -globals \
; RUN: -exclude-symbols="MemberVar|GlobalVar" %p/Inputs/FilterTest.pdb | FileCheck \
; RUN: --check-prefix=EXCLUDE_VARS %s
; RUN: llvm-pdbdump -types -class-definitions -exclude-types="FilterTestClass" \
; RUN: llvm-pdbdump -types -symbols -globals -exclude-symbols="MemberVar|GlobalVar" \
; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_VARS %s
; RUN: llvm-pdbdump -types -exclude-types="FilterTestClass" \
; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_WHOLE_CLASS %s
; RUN: llvm-pdbdump -symbols -globals -exclude-compilands="FilterTest.obj" \
; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_COMPILAND %s

View File

@ -8,6 +8,7 @@ add_llvm_tool(llvm-pdbdump
BuiltinDumper.cpp
ClassDefinitionDumper.cpp
CompilandDumper.cpp
EnumDumper.cpp
FunctionDumper.cpp
LinePrinter.cpp
TypeDumper.cpp

View File

@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "ClassDefinitionDumper.h"
#include "EnumDumper.h"
#include "FunctionDumper.h"
#include "LinePrinter.h"
#include "llvm-pdbdump.h"
@ -173,8 +174,8 @@ void ClassDefinitionDumper::dump(const PDBSymbolTypeEnum &Symbol) {
return;
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
EnumDumper Dumper(Printer);
Dumper.start(Symbol);
}
void ClassDefinitionDumper::dump(const PDBSymbolTypeTypedef &Symbol) {

View File

@ -0,0 +1,52 @@
//===- EnumDumper.cpp -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "EnumDumper.h"
#include "BuiltinDumper.h"
#include "LinePrinter.h"
#include "llvm-pdbdump.h"
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
using namespace llvm;
EnumDumper::EnumDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
void EnumDumper::start(const PDBSymbolTypeEnum &Symbol) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
if (!opts::NoEnumDefs) {
auto BuiltinType = Symbol.getUnderlyingType();
if (BuiltinType->getBuiltinType() != PDB_BuiltinType::Int ||
BuiltinType->getLength() != 4) {
Printer << " : ";
BuiltinDumper Dumper(Printer);
Dumper.start(*BuiltinType);
}
Printer << " {";
Printer.Indent();
auto EnumValues = Symbol.findAllChildren<PDBSymbolData>();
while (auto EnumValue = EnumValues->getNext()) {
if (EnumValue->getDataKind() != PDB_DataKind::Constant)
continue;
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::Identifier).get()
<< EnumValue->getName();
Printer << " = ";
WithColor(Printer, PDB_ColorItem::LiteralValue).get()
<< EnumValue->getValue();
}
Printer.Unindent();
Printer.NewLine();
Printer << "}";
}
}

View File

@ -0,0 +1,30 @@
//===- EnumDumper.h - -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVMPDBDUMP_ENUMDUMPER_H
#define LLVM_TOOLS_LLVMPDBDUMP_ENUMDUMPER_H
#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
namespace llvm {
class LinePrinter;
class EnumDumper : public PDBSymDumper {
public:
EnumDumper(LinePrinter &P);
void start(const PDBSymbolTypeEnum &Symbol);
private:
LinePrinter &Printer;
};
}
#endif

View File

@ -9,21 +9,23 @@
#include "TypeDumper.h"
#include "BuiltinDumper.h"
#include "ClassDefinitionDumper.h"
#include "EnumDumper.h"
#include "LinePrinter.h"
#include "llvm-pdbdump.h"
#include "TypedefDumper.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
using namespace llvm;
TypeDumper::TypeDumper(LinePrinter &P, bool ClassDefs)
: PDBSymDumper(true), Printer(P), FullClassDefs(ClassDefs) {}
TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}
void TypeDumper::start(const PDBSymbolExe &Exe) {
auto Enums = Exe.findAllChildren<PDBSymbolTypeEnum>();
@ -59,10 +61,13 @@ void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) {
return;
if (Printer.IsTypeExcluded(Symbol.getName()))
return;
Printer.NewLine();
// Dump member enums when dumping their class definition.
if (Symbol.isNested())
return;
WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
Printer.NewLine();
EnumDumper Dumper(Printer);
Dumper.start(Symbol);
}
void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
@ -82,11 +87,11 @@ void TypeDumper::dump(const PDBSymbolTypeUDT &Symbol) {
Printer.NewLine();
if (FullClassDefs) {
ClassDefinitionDumper Dumper(Printer);
Dumper.start(Symbol);
} else {
if (opts::NoClassDefs) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
} else {
ClassDefinitionDumper Dumper(Printer);
Dumper.start(Symbol);
}
}

View File

@ -18,7 +18,7 @@ class LinePrinter;
class TypeDumper : public PDBSymDumper {
public:
TypeDumper(LinePrinter &P, bool ClassDefs);
TypeDumper(LinePrinter &P);
void start(const PDBSymbolExe &Exe);
@ -28,7 +28,6 @@ public:
private:
LinePrinter &Printer;
bool FullClassDefs;
};
}

View File

@ -17,6 +17,7 @@
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
@ -36,14 +37,12 @@ void VariableDumper::start(const PDBSymbolData &Var) {
if (Printer.IsSymbolExcluded(Var.getName()))
return;
Printer.NewLine();
Printer << "data ";
auto VarType = Var.getType();
switch (auto LocType = Var.getLocationType()) {
case PDB_LocType::Static:
Printer << "[";
Printer.NewLine();
Printer << "data [";
WithColor(Printer, PDB_ColorItem::Address).get()
<< format_hex(Var.getRelativeVirtualAddress(), 10);
Printer << "] ";
@ -51,17 +50,25 @@ void VariableDumper::start(const PDBSymbolData &Var) {
dumpSymbolTypeAndName(*VarType, Var.getName());
break;
case PDB_LocType::Constant:
if (isa<PDBSymbolTypeEnum>(*VarType))
break;
Printer.NewLine();
Printer << "data ";
WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
dumpSymbolTypeAndName(*VarType, Var.getName());
Printer << " = ";
WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue();
break;
case PDB_LocType::ThisRel:
Printer.NewLine();
Printer << "data ";
WithColor(Printer, PDB_ColorItem::Offset).get()
<< "+" << format_hex(Var.getOffset(), 4) << " ";
dumpSymbolTypeAndName(*VarType, Var.getName());
break;
case PDB_LocType::BitField:
Printer.NewLine();
Printer << "data ";
WithColor(Printer, PDB_ColorItem::Offset).get()
<< "+" << format_hex(Var.getOffset(), 4) << " ";
dumpSymbolTypeAndName(*VarType, Var.getName());
@ -69,6 +76,8 @@ void VariableDumper::start(const PDBSymbolData &Var) {
WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getLength();
break;
default:
Printer.NewLine();
Printer << "data ";
Printer << "unknown(" << LocType << ") ";
WithColor(Printer, PDB_ColorItem::Identifier).get() << Var.getName();
break;

View File

@ -66,10 +66,6 @@ cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
cl::cat(TypeCategory));
cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory));
cl::opt<bool>
ClassDefs("class-definitions",
cl::desc("Display full class definitions (implies -types)"),
cl::cat(TypeCategory));
cl::opt<bool>
All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
cl::cat(TypeCategory));
@ -94,6 +90,12 @@ cl::opt<bool>
ExcludeSystemLibraries("no-system-libs",
cl::desc("Don't show symbols from system libraries"),
cl::cat(FilterCategory));
cl::opt<bool> NoClassDefs("no-class-definitions",
cl::desc("Don't display full class definitions"),
cl::cat(FilterCategory));
cl::opt<bool> NoEnumDefs("no-enum-definitions",
cl::desc("Don't display full enum definitions"),
cl::cat(FilterCategory));
}
static void dumpInput(StringRef Path) {
@ -171,7 +173,7 @@ static void dumpInput(StringRef Path) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
Printer.Indent();
TypeDumper Dumper(Printer, opts::ClassDefs);
TypeDumper Dumper(Printer);
Dumper.start(*GlobalScope);
Printer.Unindent();
}
@ -233,14 +235,11 @@ int main(int argc_, const char *argv_[]) {
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
if (opts::ClassDefs)
opts::Types = true;
if (opts::All) {
opts::Compilands = true;
opts::Symbols = true;
opts::Globals = true;
opts::Types = true;
opts::ClassDefs = true;
}
if (opts::ExcludeCompilerGenerated) {
opts::ExcludeTypes.push_back("__vc_attributes");

View File

@ -18,11 +18,12 @@ extern llvm::cl::opt<bool> Compilands;
extern llvm::cl::opt<bool> Symbols;
extern llvm::cl::opt<bool> Globals;
extern llvm::cl::opt<bool> Types;
extern llvm::cl::opt<bool> ClassDefs;
extern llvm::cl::opt<bool> All;
extern llvm::cl::opt<bool> ExcludeCompilerGenerated;
extern llvm::cl::opt<bool> NoClassDefs;
extern llvm::cl::opt<bool> NoEnumDefs;
extern llvm::cl::list<std::string> ExcludeTypes;
extern llvm::cl::list<std::string> ExcludeSymbols;
extern llvm::cl::list<std::string> ExcludeCompilands;