mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-25 04:39:51 +00:00
[llvm-pdbdump] Many minor fixes and improvements
A short list of some of the improvements: 1) Now supports -all command line argument, which implies many other command line arguments to simplify usage. 2) Now supports -no-compiler-generated command line argument to exclude compiler generated types. 3) Prints base class list. 4) -class-definitions implies -types. 5) Proper display of bitfields. 6) Can now distinguish between struct/class/interface/union. And a few other minor tweaks. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230933 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5e871d0b9c
commit
0c7c98a27d
@ -26,6 +26,8 @@ raw_ostream &operator<<(raw_ostream &OS, const PDB_ThunkOrdinal &Thunk);
|
||||
raw_ostream &operator<<(raw_ostream &OS, const PDB_Checksum &Checksum);
|
||||
raw_ostream &operator<<(raw_ostream &OS, const PDB_Lang &Lang);
|
||||
raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag);
|
||||
raw_ostream &operator<<(raw_ostream &OS, const PDB_MemberAccess &Access);
|
||||
raw_ostream &operator<<(raw_ostream &OS, const PDB_UdtType &Type);
|
||||
raw_ostream &operator<<(raw_ostream &OS, const PDB_UniqueId &Id);
|
||||
|
||||
raw_ostream &operator<<(raw_ostream &OS, const Variant &Value);
|
||||
|
@ -470,8 +470,31 @@ struct Variant {
|
||||
uint16_t UInt16;
|
||||
uint32_t UInt32;
|
||||
uint64_t UInt64;
|
||||
void* Pointer;
|
||||
};
|
||||
#define VARIANT_EQUAL_CASE(Enum) \
|
||||
case PDB_VariantType::Enum: \
|
||||
return Enum == Other.Enum;
|
||||
bool operator==(const Variant &Other) const {
|
||||
if (Type != Other.Type)
|
||||
return false;
|
||||
switch (Type) {
|
||||
VARIANT_EQUAL_CASE(Bool)
|
||||
VARIANT_EQUAL_CASE(Int8)
|
||||
VARIANT_EQUAL_CASE(Int16)
|
||||
VARIANT_EQUAL_CASE(Int32)
|
||||
VARIANT_EQUAL_CASE(Int64)
|
||||
VARIANT_EQUAL_CASE(Single)
|
||||
VARIANT_EQUAL_CASE(Double)
|
||||
VARIANT_EQUAL_CASE(UInt8)
|
||||
VARIANT_EQUAL_CASE(UInt16)
|
||||
VARIANT_EQUAL_CASE(UInt32)
|
||||
VARIANT_EQUAL_CASE(UInt64)
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#undef VARIANT_EQUAL_CASE
|
||||
bool operator!=(const Variant &Other) const { return !(*this == Other); }
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
@ -247,6 +247,25 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_SymType &Tag) {
|
||||
return OS;
|
||||
}
|
||||
|
||||
raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_MemberAccess &Access) {
|
||||
switch (Access) {
|
||||
CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Public, "public", OS)
|
||||
CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Protected, "protected", OS)
|
||||
CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Private, "private", OS)
|
||||
}
|
||||
return OS;
|
||||
}
|
||||
|
||||
raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_UdtType &Type) {
|
||||
switch (Type) {
|
||||
CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Class, "class", OS)
|
||||
CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Struct, "struct", OS)
|
||||
CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Interface, "interface", OS)
|
||||
CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Union, "union", OS)
|
||||
}
|
||||
return OS;
|
||||
}
|
||||
|
||||
raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_UniqueId &Id) {
|
||||
static const char *Lookup = "0123456789ABCDEF";
|
||||
|
||||
@ -304,7 +323,6 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const Variant &Value) {
|
||||
default:
|
||||
OS << Value.Type;
|
||||
}
|
||||
OS << " {" << Value.Type << "}";
|
||||
return OS;
|
||||
}
|
||||
|
||||
|
@ -30,13 +30,13 @@
|
||||
|
||||
; FULL_CLASS: ---TYPES---
|
||||
; FULL_CLASS: Classes
|
||||
; FULL_CLASS-DAG: class A {
|
||||
; 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: class MemberTest {
|
||||
; 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
|
||||
|
64
test/tools/llvm-pdbdump/Inputs/ClassLayoutTest.cpp
Normal file
64
test/tools/llvm-pdbdump/Inputs/ClassLayoutTest.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
// Compile with "cl /c /Zi /GR- ClassLayoutTest.cpp"
|
||||
// Link with "link ClassLayoutTest.obj /debug /nodefaultlib /entry:main"
|
||||
|
||||
namespace MembersTest {
|
||||
class A {
|
||||
public:
|
||||
typedef int NestedTypedef;
|
||||
enum NestedEnum {
|
||||
NestedEnumValue1
|
||||
};
|
||||
|
||||
void MemberFunc() {}
|
||||
|
||||
private:
|
||||
int IntMemberVar;
|
||||
double DoubleMemberVar;
|
||||
};
|
||||
}
|
||||
|
||||
namespace GlobalsTest {
|
||||
int IntVar;
|
||||
double DoubleVar;
|
||||
|
||||
typedef int Typedef;
|
||||
enum Enum {
|
||||
Val1
|
||||
} EnumVar;
|
||||
Typedef TypedefVar;
|
||||
}
|
||||
|
||||
namespace BaseClassTest {
|
||||
class A {};
|
||||
class B : public virtual A {};
|
||||
class C : public virtual A {};
|
||||
class D : protected B, private C {};
|
||||
}
|
||||
|
||||
namespace UdtKindTest {
|
||||
struct A {};
|
||||
class B {};
|
||||
union C {};
|
||||
}
|
||||
|
||||
namespace BitFieldTest {
|
||||
struct A {
|
||||
int Bits1 : 1;
|
||||
int Bits2 : 2;
|
||||
int Bits3 : 3;
|
||||
int Bits4 : 4;
|
||||
int Bits22 : 22;
|
||||
int Offset0x04;
|
||||
};
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
MembersTest::A v1;
|
||||
v1.MemberFunc();
|
||||
BaseClassTest::D v2;
|
||||
UdtKindTest::A v3;
|
||||
UdtKindTest::B v4;
|
||||
UdtKindTest::C v5;
|
||||
BitFieldTest::A v7;
|
||||
return 0;
|
||||
}
|
BIN
test/tools/llvm-pdbdump/Inputs/ClassLayoutTest.pdb
Normal file
BIN
test/tools/llvm-pdbdump/Inputs/ClassLayoutTest.pdb
Normal file
Binary file not shown.
57
test/tools/llvm-pdbdump/class-layout.test
Normal file
57
test/tools/llvm-pdbdump/class-layout.test
Normal file
@ -0,0 +1,57 @@
|
||||
; RUN: llvm-pdbdump -all %p/Inputs/ClassLayoutTest.pdb > %t
|
||||
; RUN: FileCheck -input-file=%t %s -check-prefix=GLOBALS_TEST
|
||||
; RUN: FileCheck -input-file=%t %s -check-prefix=MEMBERS_TEST
|
||||
; RUN: FileCheck -input-file=%t %s -check-prefix=BASE_CLASS_A
|
||||
; RUN: FileCheck -input-file=%t %s -check-prefix=BASE_CLASS_B
|
||||
; RUN: FileCheck -input-file=%t %s -check-prefix=BASE_CLASS_C
|
||||
; RUN: FileCheck -input-file=%t %s -check-prefix=BASE_CLASS_D
|
||||
; RUN: FileCheck -input-file=%t %s -check-prefix=UDT_KIND_TEST
|
||||
; RUN: FileCheck -input-file=%t %s -check-prefix=BITFIELD_TEST
|
||||
|
||||
; GLOBALS_TEST: ---GLOBALS---
|
||||
; GLOBALS_TEST-DAG: int GlobalsTest::IntVar
|
||||
; GLOBALS_TEST-DAG: double GlobalsTest::DoubleVar
|
||||
; GLOBALS_TEST-DAG: GlobalsTest::Enum GlobalsTest::EnumVar
|
||||
|
||||
; MEMBERS_TEST: ---TYPES---
|
||||
; MEMBERS_TEST: class MembersTest::A {
|
||||
; MEMBERS_TEST-DAG: typedef int NestedTypedef
|
||||
; MEMBERS_TEST-DAG: enum NestedEnum
|
||||
; MEMBERS_TEST: public:
|
||||
; MEMBERS_TEST-NEXT: void MemberFunc()
|
||||
; MEMBERS_TEST-NEXT: private:
|
||||
; MEMBERS_TEST-DAG: int IntMemberVar
|
||||
; MEMBERS_TEST-DAG: double DoubleMemberVar
|
||||
; MEMBERS_TEST: }
|
||||
|
||||
; BASE_CLASS_A: ---TYPES---
|
||||
; BASE_CLASS_A: class BaseClassTest::A {}
|
||||
|
||||
; BASE_CLASS_B: ---TYPES---
|
||||
; BASE_CLASS_B: class BaseClassTest::B
|
||||
; BASE_CLASS_B-NEXT: : public virtual BaseClassTest::A {
|
||||
|
||||
; BASE_CLASS_C: ---TYPES---
|
||||
; BASE_CLASS_C: class BaseClassTest::C
|
||||
; BASE_CLASS_C-NEXT: : public virtual BaseClassTest::A {
|
||||
|
||||
; BASE_CLASS_D: ---TYPES---
|
||||
; BASE_CLASS_D: class BaseClassTest::D
|
||||
; BASE_CLASS_D-DAG: protected BaseClassTest::B
|
||||
; BASE_CLASS_D-DAG: private BaseClassTest::C
|
||||
; BASE_CLASS_D-DAG: protected virtual BaseClassTest::A
|
||||
|
||||
; UDT_KIND_TEST: ---TYPES---
|
||||
; UDT_KIND_TEST-DAG: union UdtKindTest::C {}
|
||||
; UDT_KIND_TEST-DAG: class UdtKindTest::B {}
|
||||
; UDT_KIND_TEST-DAG: struct UdtKindTest::A {}
|
||||
|
||||
; BITFIELD_TEST: ---TYPES---
|
||||
; BITFIELD_TEST: struct BitFieldTest::A {
|
||||
; BITFIELD_TEST-NEXT: public:
|
||||
; BITFIELD_TEST-NEXT: +0x00 int Bits1 : 1
|
||||
; BITFIELD_TEST-NEXT: +0x00 int Bits2 : 2
|
||||
; BITFIELD_TEST-NEXT: +0x00 int Bits3 : 3
|
||||
; BITFIELD_TEST-NEXT: +0x00 int Bits4 : 4
|
||||
; BITFIELD_TEST-NEXT: +0x00 int Bits22 : 22
|
||||
; BITFIELD_TEST-NEXT: +0x04 int Offset0x04
|
@ -18,7 +18,7 @@
|
||||
; NO_FILTER: Typedefs
|
||||
; NO_FILTER: typedef int GlobalTypedef
|
||||
; NO_FILTER: Classes:
|
||||
; NO_FILTER: class __vc_attributes
|
||||
; NO_FILTER: struct __vc_attributes
|
||||
; NO_FILTER: class FilterTestClass
|
||||
; NO_FILTER-DAG: typedef int NestedTypedef
|
||||
; NO_FILTER-DAG: enum NestedEnum
|
||||
|
@ -81,7 +81,7 @@ void BuiltinDumper::start(const PDBSymbolTypeBuiltin &Symbol) {
|
||||
WithColor(Printer, PDB_ColorItem::Type).get() << "HRESULT";
|
||||
break;
|
||||
default:
|
||||
WithColor(Printer, PDB_ColorItem::Type).get() << "(unknown)";
|
||||
WithColor(Printer, PDB_ColorItem::Type).get() << "void";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -33,8 +33,29 @@ ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P)
|
||||
|
||||
void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
|
||||
std::string Name = Class.getName();
|
||||
WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
|
||||
WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
|
||||
WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
|
||||
|
||||
auto Bases = Class.findAllChildren<PDBSymbolTypeBaseClass>();
|
||||
if (Bases->getChildCount() > 0) {
|
||||
Printer.Indent();
|
||||
Printer.NewLine();
|
||||
Printer << ":";
|
||||
uint32_t BaseIndex = 0;
|
||||
while (auto Base = Bases->getNext()) {
|
||||
Printer << " ";
|
||||
WithColor(Printer, PDB_ColorItem::Keyword).get() << Base->getAccess();
|
||||
if (Base->isVirtualBaseClass())
|
||||
WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual";
|
||||
WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base->getName();
|
||||
if (++BaseIndex < Bases->getChildCount()) {
|
||||
Printer.NewLine();
|
||||
Printer << ",";
|
||||
}
|
||||
}
|
||||
Printer.Unindent();
|
||||
}
|
||||
|
||||
Printer << " {";
|
||||
auto Children = Class.findAllChildren();
|
||||
if (Children->getChildCount() == 0) {
|
||||
@ -62,9 +83,10 @@ void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
|
||||
auto &AccessGroup = Groups.find((int)Access)->second;
|
||||
|
||||
if (auto Func = dyn_cast<PDBSymbolFunc>(Child.get())) {
|
||||
if (Func->isCompilerGenerated())
|
||||
if (Func->isCompilerGenerated() && opts::ExcludeCompilerGenerated)
|
||||
continue;
|
||||
if (Func->getLength() == 0 && !Func->isPureVirtual())
|
||||
if (Func->getLength() == 0 && !Func->isPureVirtual() &&
|
||||
!Func->isIntroVirtualFunction())
|
||||
continue;
|
||||
Child.release();
|
||||
AccessGroup.Functions.push_back(std::unique_ptr<PDBSymbolFunc>(Func));
|
||||
|
@ -124,7 +124,9 @@ void CompilandDumper::dump(const PDBSymbolThunk &Symbol) {
|
||||
<< "[" << format_hex(RVA, 10) << " - "
|
||||
<< format_hex(RVA + Symbol.getLength(), 10) << "]";
|
||||
}
|
||||
Printer << " (" << Ordinal << ") ";
|
||||
Printer << " (";
|
||||
WithColor(Printer, PDB_ColorItem::Register).get() << Ordinal;
|
||||
Printer << ") ";
|
||||
std::string Name = Symbol.getName();
|
||||
if (!Name.empty())
|
||||
WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
|
||||
|
@ -112,28 +112,28 @@ void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) {
|
||||
uint32_t FuncStart = Symbol.getRelativeVirtualAddress();
|
||||
uint32_t FuncEnd = FuncStart + Symbol.getLength();
|
||||
|
||||
Printer << "func ";
|
||||
WithColor(Printer, PDB_ColorItem::Address).get() << "["
|
||||
<< format_hex(FuncStart, 8);
|
||||
Printer << "func [";
|
||||
WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10);
|
||||
if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) {
|
||||
uint32_t Prologue = DebugStart->getRelativeVirtualAddress() - FuncStart;
|
||||
WithColor(Printer, PDB_ColorItem::Offset).get() << "+" << Prologue;
|
||||
}
|
||||
WithColor(Printer, PDB_ColorItem::Address).get() << " - "
|
||||
<< format_hex(FuncEnd, 8);
|
||||
Printer << " - ";
|
||||
WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10);
|
||||
if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) {
|
||||
uint32_t Epilogue = FuncEnd - DebugEnd->getRelativeVirtualAddress();
|
||||
WithColor(Printer, PDB_ColorItem::Offset).get() << "-" << Epilogue;
|
||||
}
|
||||
WithColor(Printer, PDB_ColorItem::Address).get() << "] ";
|
||||
Printer << "] (";
|
||||
|
||||
if (Symbol.hasFramePointer())
|
||||
WithColor(Printer, PDB_ColorItem::Address).get()
|
||||
<< "(" << Symbol.getLocalBasePointerRegisterId() << ")";
|
||||
else
|
||||
WithColor(Printer, PDB_ColorItem::Address).get() << "(FPO)";
|
||||
if (Symbol.hasFramePointer()) {
|
||||
WithColor(Printer, PDB_ColorItem::Register).get()
|
||||
<< Symbol.getLocalBasePointerRegisterId();
|
||||
} else {
|
||||
WithColor(Printer, PDB_ColorItem::Register).get() << "FPO";
|
||||
}
|
||||
Printer << ") ";
|
||||
|
||||
Printer << " ";
|
||||
if (Symbol.isVirtual() || Symbol.isPureVirtual())
|
||||
WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual ";
|
||||
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include "LinePrinter.h"
|
||||
|
||||
#include "llvm-pdbdump.h"
|
||||
|
||||
#include "llvm/Support/Regex.h"
|
||||
|
||||
#include <algorithm>
|
||||
@ -16,7 +18,13 @@
|
||||
using namespace llvm;
|
||||
|
||||
LinePrinter::LinePrinter(int Indent, llvm::raw_ostream &Stream)
|
||||
: OS(Stream), IndentSpaces(Indent), CurrentIndent(0) {}
|
||||
: OS(Stream), IndentSpaces(Indent), CurrentIndent(0) {
|
||||
SetFilters(TypeFilters, opts::ExcludeTypes.begin(), opts::ExcludeTypes.end());
|
||||
SetFilters(SymbolFilters, opts::ExcludeSymbols.begin(),
|
||||
opts::ExcludeSymbols.end());
|
||||
SetFilters(CompilandFilters, opts::ExcludeCompilands.begin(),
|
||||
opts::ExcludeCompilands.end());
|
||||
}
|
||||
|
||||
void LinePrinter::Indent() { CurrentIndent += IndentSpaces; }
|
||||
|
||||
@ -86,6 +94,7 @@ void WithColor::translateColor(PDB_ColorItem C, raw_ostream::Colors &Color,
|
||||
Color = raw_ostream::MAGENTA;
|
||||
Bold = true;
|
||||
return;
|
||||
case PDB_ColorItem::Register:
|
||||
case PDB_ColorItem::Offset:
|
||||
Color = raw_ostream::YELLOW;
|
||||
Bold = false;
|
||||
|
@ -25,33 +25,25 @@ class LinePrinter {
|
||||
public:
|
||||
LinePrinter(int Indent, raw_ostream &Stream);
|
||||
|
||||
template <typename Iter> void SetTypeFilters(Iter Begin, Iter End) {
|
||||
TypeFilters.clear();
|
||||
for (; Begin != End; ++Begin)
|
||||
TypeFilters.push_back(StringRef(*Begin));
|
||||
}
|
||||
template <typename Iter> void SetSymbolFilters(Iter Begin, Iter End) {
|
||||
SymbolFilters.clear();
|
||||
for (; Begin != End; ++Begin)
|
||||
SymbolFilters.push_back(StringRef(*Begin));
|
||||
}
|
||||
template <typename Iter> void SetCompilandFilters(Iter Begin, Iter End) {
|
||||
CompilandFilters.clear();
|
||||
for (; Begin != End; ++Begin)
|
||||
CompilandFilters.push_back(StringRef(*Begin));
|
||||
}
|
||||
|
||||
void Indent();
|
||||
void Unindent();
|
||||
void NewLine();
|
||||
|
||||
raw_ostream &getStream() { return OS; }
|
||||
int getIndentLevel() const { return CurrentIndent; }
|
||||
|
||||
bool IsTypeExcluded(llvm::StringRef TypeName);
|
||||
bool IsSymbolExcluded(llvm::StringRef SymbolName);
|
||||
bool IsCompilandExcluded(llvm::StringRef CompilandName);
|
||||
|
||||
private:
|
||||
template <typename Iter>
|
||||
void SetFilters(std::list<Regex> &List, Iter Begin, Iter End) {
|
||||
List.clear();
|
||||
for (; Begin != End; ++Begin)
|
||||
List.push_back(StringRef(*Begin));
|
||||
}
|
||||
|
||||
raw_ostream &OS;
|
||||
int IndentSpaces;
|
||||
int CurrentIndent;
|
||||
@ -77,6 +69,7 @@ enum class PDB_ColorItem {
|
||||
Path,
|
||||
SectionHeader,
|
||||
LiteralValue,
|
||||
Register,
|
||||
};
|
||||
|
||||
class WithColor {
|
||||
|
@ -31,7 +31,8 @@ void TypedefDumper::start(const PDBSymbolTypeTypedef &Symbol) {
|
||||
uint32_t TargetId = Symbol.getTypeId();
|
||||
if (auto TypeSymbol = Symbol.getSession().getSymbolById(TargetId))
|
||||
TypeSymbol->dump(*this);
|
||||
WithColor(Printer, PDB_ColorItem::Type).get() << " " << Symbol.getName();
|
||||
WithColor(Printer, PDB_ColorItem::Identifier).get() << " "
|
||||
<< Symbol.getName();
|
||||
}
|
||||
|
||||
void TypedefDumper::dump(const PDBSymbolTypeArray &Symbol) {}
|
||||
@ -74,5 +75,5 @@ void TypedefDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
|
||||
|
||||
void TypedefDumper::dump(const PDBSymbolTypeUDT &Symbol) {
|
||||
WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
|
||||
WithColor(Printer, PDB_ColorItem::Type).get() << " " << Symbol.getName();
|
||||
WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
|
||||
}
|
||||
|
@ -31,6 +31,8 @@ VariableDumper::VariableDumper(LinePrinter &P)
|
||||
: PDBSymDumper(true), Printer(P) {}
|
||||
|
||||
void VariableDumper::start(const PDBSymbolData &Var) {
|
||||
if (Var.isCompilerGenerated() && opts::ExcludeCompilerGenerated)
|
||||
return;
|
||||
if (Printer.IsSymbolExcluded(Var.getName()))
|
||||
return;
|
||||
|
||||
@ -41,23 +43,31 @@ void VariableDumper::start(const PDBSymbolData &Var) {
|
||||
|
||||
switch (auto LocType = Var.getLocationType()) {
|
||||
case PDB_LocType::Static:
|
||||
Printer << "[";
|
||||
WithColor(Printer, PDB_ColorItem::Address).get()
|
||||
<< "[" << format_hex(Var.getRelativeVirtualAddress(), 10) << "] ";
|
||||
<< format_hex(Var.getRelativeVirtualAddress(), 10);
|
||||
Printer << "] ";
|
||||
WithColor(Printer, PDB_ColorItem::Keyword).get() << "static ";
|
||||
dumpSymbolTypeAndName(*VarType, Var.getName());
|
||||
break;
|
||||
case PDB_LocType::Constant:
|
||||
WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
|
||||
dumpSymbolTypeAndName(*VarType, Var.getName());
|
||||
Printer << "[";
|
||||
Printer << " = ";
|
||||
WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue();
|
||||
Printer << "]";
|
||||
break;
|
||||
case PDB_LocType::ThisRel:
|
||||
WithColor(Printer, PDB_ColorItem::Offset).get()
|
||||
<< "+" << format_hex(Var.getOffset(), 4) << " ";
|
||||
dumpSymbolTypeAndName(*VarType, Var.getName());
|
||||
break;
|
||||
case PDB_LocType::BitField:
|
||||
WithColor(Printer, PDB_ColorItem::Offset).get()
|
||||
<< "+" << format_hex(Var.getOffset(), 4) << " ";
|
||||
dumpSymbolTypeAndName(*VarType, Var.getName());
|
||||
Printer << " : ";
|
||||
WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getLength();
|
||||
break;
|
||||
default:
|
||||
Printer << "unknown(" << LocType << ") ";
|
||||
WithColor(Printer, PDB_ColorItem::Identifier).get() << Var.getName();
|
||||
|
@ -56,26 +56,44 @@ cl::list<std::string> InputFilenames(cl::Positional,
|
||||
cl::desc("<input PDB files>"),
|
||||
cl::OneOrMore);
|
||||
|
||||
cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"));
|
||||
cl::opt<bool> Symbols("symbols",
|
||||
cl::desc("Display symbols for each compiland"));
|
||||
cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"));
|
||||
cl::opt<bool> Types("types", cl::desc("Display types"));
|
||||
cl::opt<bool> ClassDefs("class-definitions",
|
||||
cl::desc("Display full class definitions"));
|
||||
cl::OptionCategory TypeCategory("Symbol Type Options");
|
||||
cl::OptionCategory FilterCategory("Filtering Options");
|
||||
|
||||
cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
|
||||
cl::cat(TypeCategory));
|
||||
cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
|
||||
cl::cat(TypeCategory));
|
||||
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));
|
||||
|
||||
cl::list<std::string>
|
||||
ExcludeTypes("exclude-types",
|
||||
cl::desc("Exclude types by regular expression"),
|
||||
cl::ZeroOrMore);
|
||||
cl::ZeroOrMore, cl::cat(FilterCategory));
|
||||
cl::list<std::string>
|
||||
ExcludeSymbols("exclude-symbols",
|
||||
cl::desc("Exclude symbols by regular expression"),
|
||||
cl::ZeroOrMore);
|
||||
cl::ZeroOrMore, cl::cat(FilterCategory));
|
||||
cl::list<std::string>
|
||||
ExcludeCompilands("exclude-compilands",
|
||||
cl::desc("Exclude compilands by regular expression"),
|
||||
cl::ZeroOrMore);
|
||||
cl::ZeroOrMore, cl::cat(FilterCategory));
|
||||
cl::opt<bool> ExcludeCompilerGenerated(
|
||||
"no-compiler-generated",
|
||||
cl::desc("Don't show compiler generated types and symbols"),
|
||||
cl::cat(FilterCategory));
|
||||
cl::opt<bool>
|
||||
ExcludeSystemLibraries("no-system-libs",
|
||||
cl::desc("Don't show symbols from system libraries"),
|
||||
cl::cat(FilterCategory));
|
||||
}
|
||||
|
||||
static void dumpInput(StringRef Path) {
|
||||
@ -103,11 +121,6 @@ static void dumpInput(StringRef Path) {
|
||||
}
|
||||
|
||||
LinePrinter Printer(2, outs());
|
||||
Printer.SetTypeFilters(opts::ExcludeTypes.begin(), opts::ExcludeTypes.end());
|
||||
Printer.SetSymbolFilters(opts::ExcludeSymbols.begin(),
|
||||
opts::ExcludeSymbols.end());
|
||||
Printer.SetCompilandFilters(opts::ExcludeCompilands.begin(),
|
||||
opts::ExcludeCompilands.end());
|
||||
|
||||
auto GlobalScope(Session->getGlobalScope());
|
||||
std::string FileName(GlobalScope->getSymbolsFileName());
|
||||
@ -220,6 +233,23 @@ 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");
|
||||
opts::ExcludeCompilands.push_back("* Linker *");
|
||||
}
|
||||
if (opts::ExcludeSystemLibraries) {
|
||||
opts::ExcludeCompilands.push_back(
|
||||
"f:\\binaries\\Intermediate\\vctools\\crt_bld");
|
||||
}
|
||||
|
||||
#if defined(HAVE_DIA_SDK)
|
||||
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
|
@ -10,19 +10,22 @@
|
||||
#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
|
||||
#define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace llvm {
|
||||
struct newline {
|
||||
newline(int IndentWidth) : Width(IndentWidth) {}
|
||||
int Width;
|
||||
};
|
||||
namespace opts {
|
||||
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;
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const newline &Indent) {
|
||||
OS << "\n";
|
||||
OS.indent(Indent.Width);
|
||||
return OS;
|
||||
}
|
||||
extern llvm::cl::opt<bool> ExcludeCompilerGenerated;
|
||||
|
||||
extern llvm::cl::list<std::string> ExcludeTypes;
|
||||
extern llvm::cl::list<std::string> ExcludeSymbols;
|
||||
extern llvm::cl::list<std::string> ExcludeCompilands;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user