mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-09-27 00:21:03 +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:
@@ -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_Checksum &Checksum);
|
||||||
raw_ostream &operator<<(raw_ostream &OS, const PDB_Lang &Lang);
|
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_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 PDB_UniqueId &Id);
|
||||||
|
|
||||||
raw_ostream &operator<<(raw_ostream &OS, const Variant &Value);
|
raw_ostream &operator<<(raw_ostream &OS, const Variant &Value);
|
||||||
|
@@ -470,8 +470,31 @@ struct Variant {
|
|||||||
uint16_t UInt16;
|
uint16_t UInt16;
|
||||||
uint32_t UInt32;
|
uint32_t UInt32;
|
||||||
uint64_t UInt64;
|
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
|
} // namespace llvm
|
||||||
|
@@ -247,6 +247,25 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_SymType &Tag) {
|
|||||||
return OS;
|
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) {
|
raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_UniqueId &Id) {
|
||||||
static const char *Lookup = "0123456789ABCDEF";
|
static const char *Lookup = "0123456789ABCDEF";
|
||||||
|
|
||||||
@@ -304,7 +323,6 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const Variant &Value) {
|
|||||||
default:
|
default:
|
||||||
OS << Value.Type;
|
OS << Value.Type;
|
||||||
}
|
}
|
||||||
OS << " {" << Value.Type << "}";
|
|
||||||
return OS;
|
return OS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -30,13 +30,13 @@
|
|||||||
|
|
||||||
; FULL_CLASS: ---TYPES---
|
; FULL_CLASS: ---TYPES---
|
||||||
; FULL_CLASS: Classes
|
; FULL_CLASS: Classes
|
||||||
; FULL_CLASS-DAG: class A {
|
; FULL_CLASS-DAG: struct A {
|
||||||
; FULL_CLASS: public:
|
; FULL_CLASS: public:
|
||||||
; FULL_CLASS: virtual void PureFunc() = 0
|
; FULL_CLASS: virtual void PureFunc() = 0
|
||||||
; FULL_CLASS: virtual void VirtualFunc()
|
; FULL_CLASS: virtual void VirtualFunc()
|
||||||
; FULL_CLASS: void RegularFunc()
|
; FULL_CLASS: void RegularFunc()
|
||||||
; FULL_CLASS: }
|
; FULL_CLASS: }
|
||||||
; FULL_CLASS-DAG: class MemberTest {
|
; FULL_CLASS-DAG: struct MemberTest {
|
||||||
; FULL_CLASS: data +0x00 MemberTest::NestedEnum m_nested_enum
|
; FULL_CLASS: data +0x00 MemberTest::NestedEnum m_nested_enum
|
||||||
; FULL_CLASS: data +0x04 int m_typedef
|
; FULL_CLASS: data +0x04 int m_typedef
|
||||||
; FULL_CLASS: data +0x08 bool m_bool
|
; 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: Typedefs
|
||||||
; NO_FILTER: typedef int GlobalTypedef
|
; NO_FILTER: typedef int GlobalTypedef
|
||||||
; NO_FILTER: Classes:
|
; NO_FILTER: Classes:
|
||||||
; NO_FILTER: class __vc_attributes
|
; NO_FILTER: struct __vc_attributes
|
||||||
; NO_FILTER: class FilterTestClass
|
; NO_FILTER: class FilterTestClass
|
||||||
; NO_FILTER-DAG: typedef int NestedTypedef
|
; NO_FILTER-DAG: typedef int NestedTypedef
|
||||||
; NO_FILTER-DAG: enum NestedEnum
|
; NO_FILTER-DAG: enum NestedEnum
|
||||||
|
@@ -81,7 +81,7 @@ void BuiltinDumper::start(const PDBSymbolTypeBuiltin &Symbol) {
|
|||||||
WithColor(Printer, PDB_ColorItem::Type).get() << "HRESULT";
|
WithColor(Printer, PDB_ColorItem::Type).get() << "HRESULT";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WithColor(Printer, PDB_ColorItem::Type).get() << "(unknown)";
|
WithColor(Printer, PDB_ColorItem::Type).get() << "void";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -33,8 +33,29 @@ ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P)
|
|||||||
|
|
||||||
void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
|
void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
|
||||||
std::string Name = Class.getName();
|
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();
|
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 << " {";
|
Printer << " {";
|
||||||
auto Children = Class.findAllChildren();
|
auto Children = Class.findAllChildren();
|
||||||
if (Children->getChildCount() == 0) {
|
if (Children->getChildCount() == 0) {
|
||||||
@@ -62,9 +83,10 @@ void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) {
|
|||||||
auto &AccessGroup = Groups.find((int)Access)->second;
|
auto &AccessGroup = Groups.find((int)Access)->second;
|
||||||
|
|
||||||
if (auto Func = dyn_cast<PDBSymbolFunc>(Child.get())) {
|
if (auto Func = dyn_cast<PDBSymbolFunc>(Child.get())) {
|
||||||
if (Func->isCompilerGenerated())
|
if (Func->isCompilerGenerated() && opts::ExcludeCompilerGenerated)
|
||||||
continue;
|
continue;
|
||||||
if (Func->getLength() == 0 && !Func->isPureVirtual())
|
if (Func->getLength() == 0 && !Func->isPureVirtual() &&
|
||||||
|
!Func->isIntroVirtualFunction())
|
||||||
continue;
|
continue;
|
||||||
Child.release();
|
Child.release();
|
||||||
AccessGroup.Functions.push_back(std::unique_ptr<PDBSymbolFunc>(Func));
|
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, 10) << " - "
|
||||||
<< format_hex(RVA + Symbol.getLength(), 10) << "]";
|
<< format_hex(RVA + Symbol.getLength(), 10) << "]";
|
||||||
}
|
}
|
||||||
Printer << " (" << Ordinal << ") ";
|
Printer << " (";
|
||||||
|
WithColor(Printer, PDB_ColorItem::Register).get() << Ordinal;
|
||||||
|
Printer << ") ";
|
||||||
std::string Name = Symbol.getName();
|
std::string Name = Symbol.getName();
|
||||||
if (!Name.empty())
|
if (!Name.empty())
|
||||||
WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
|
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 FuncStart = Symbol.getRelativeVirtualAddress();
|
||||||
uint32_t FuncEnd = FuncStart + Symbol.getLength();
|
uint32_t FuncEnd = FuncStart + Symbol.getLength();
|
||||||
|
|
||||||
Printer << "func ";
|
Printer << "func [";
|
||||||
WithColor(Printer, PDB_ColorItem::Address).get() << "["
|
WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10);
|
||||||
<< format_hex(FuncStart, 8);
|
|
||||||
if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) {
|
if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) {
|
||||||
uint32_t Prologue = DebugStart->getRelativeVirtualAddress() - FuncStart;
|
uint32_t Prologue = DebugStart->getRelativeVirtualAddress() - FuncStart;
|
||||||
WithColor(Printer, PDB_ColorItem::Offset).get() << "+" << Prologue;
|
WithColor(Printer, PDB_ColorItem::Offset).get() << "+" << Prologue;
|
||||||
}
|
}
|
||||||
WithColor(Printer, PDB_ColorItem::Address).get() << " - "
|
Printer << " - ";
|
||||||
<< format_hex(FuncEnd, 8);
|
WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10);
|
||||||
if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) {
|
if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) {
|
||||||
uint32_t Epilogue = FuncEnd - DebugEnd->getRelativeVirtualAddress();
|
uint32_t Epilogue = FuncEnd - DebugEnd->getRelativeVirtualAddress();
|
||||||
WithColor(Printer, PDB_ColorItem::Offset).get() << "-" << Epilogue;
|
WithColor(Printer, PDB_ColorItem::Offset).get() << "-" << Epilogue;
|
||||||
}
|
}
|
||||||
WithColor(Printer, PDB_ColorItem::Address).get() << "] ";
|
Printer << "] (";
|
||||||
|
|
||||||
if (Symbol.hasFramePointer())
|
if (Symbol.hasFramePointer()) {
|
||||||
WithColor(Printer, PDB_ColorItem::Address).get()
|
WithColor(Printer, PDB_ColorItem::Register).get()
|
||||||
<< "(" << Symbol.getLocalBasePointerRegisterId() << ")";
|
<< Symbol.getLocalBasePointerRegisterId();
|
||||||
else
|
} else {
|
||||||
WithColor(Printer, PDB_ColorItem::Address).get() << "(FPO)";
|
WithColor(Printer, PDB_ColorItem::Register).get() << "FPO";
|
||||||
|
}
|
||||||
|
Printer << ") ";
|
||||||
|
|
||||||
Printer << " ";
|
|
||||||
if (Symbol.isVirtual() || Symbol.isPureVirtual())
|
if (Symbol.isVirtual() || Symbol.isPureVirtual())
|
||||||
WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual ";
|
WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual ";
|
||||||
|
|
||||||
|
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#include "LinePrinter.h"
|
#include "LinePrinter.h"
|
||||||
|
|
||||||
|
#include "llvm-pdbdump.h"
|
||||||
|
|
||||||
#include "llvm/Support/Regex.h"
|
#include "llvm/Support/Regex.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -16,7 +18,13 @@
|
|||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
LinePrinter::LinePrinter(int Indent, llvm::raw_ostream &Stream)
|
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; }
|
void LinePrinter::Indent() { CurrentIndent += IndentSpaces; }
|
||||||
|
|
||||||
@@ -86,6 +94,7 @@ void WithColor::translateColor(PDB_ColorItem C, raw_ostream::Colors &Color,
|
|||||||
Color = raw_ostream::MAGENTA;
|
Color = raw_ostream::MAGENTA;
|
||||||
Bold = true;
|
Bold = true;
|
||||||
return;
|
return;
|
||||||
|
case PDB_ColorItem::Register:
|
||||||
case PDB_ColorItem::Offset:
|
case PDB_ColorItem::Offset:
|
||||||
Color = raw_ostream::YELLOW;
|
Color = raw_ostream::YELLOW;
|
||||||
Bold = false;
|
Bold = false;
|
||||||
|
@@ -25,33 +25,25 @@ class LinePrinter {
|
|||||||
public:
|
public:
|
||||||
LinePrinter(int Indent, raw_ostream &Stream);
|
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 Indent();
|
||||||
void Unindent();
|
void Unindent();
|
||||||
void NewLine();
|
void NewLine();
|
||||||
|
|
||||||
raw_ostream &getStream() { return OS; }
|
raw_ostream &getStream() { return OS; }
|
||||||
|
int getIndentLevel() const { return CurrentIndent; }
|
||||||
|
|
||||||
bool IsTypeExcluded(llvm::StringRef TypeName);
|
bool IsTypeExcluded(llvm::StringRef TypeName);
|
||||||
bool IsSymbolExcluded(llvm::StringRef SymbolName);
|
bool IsSymbolExcluded(llvm::StringRef SymbolName);
|
||||||
bool IsCompilandExcluded(llvm::StringRef CompilandName);
|
bool IsCompilandExcluded(llvm::StringRef CompilandName);
|
||||||
|
|
||||||
private:
|
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;
|
raw_ostream &OS;
|
||||||
int IndentSpaces;
|
int IndentSpaces;
|
||||||
int CurrentIndent;
|
int CurrentIndent;
|
||||||
@@ -77,6 +69,7 @@ enum class PDB_ColorItem {
|
|||||||
Path,
|
Path,
|
||||||
SectionHeader,
|
SectionHeader,
|
||||||
LiteralValue,
|
LiteralValue,
|
||||||
|
Register,
|
||||||
};
|
};
|
||||||
|
|
||||||
class WithColor {
|
class WithColor {
|
||||||
|
@@ -31,7 +31,8 @@ void TypedefDumper::start(const PDBSymbolTypeTypedef &Symbol) {
|
|||||||
uint32_t TargetId = Symbol.getTypeId();
|
uint32_t TargetId = Symbol.getTypeId();
|
||||||
if (auto TypeSymbol = Symbol.getSession().getSymbolById(TargetId))
|
if (auto TypeSymbol = Symbol.getSession().getSymbolById(TargetId))
|
||||||
TypeSymbol->dump(*this);
|
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) {}
|
void TypedefDumper::dump(const PDBSymbolTypeArray &Symbol) {}
|
||||||
@@ -74,5 +75,5 @@ void TypedefDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
|
|||||||
|
|
||||||
void TypedefDumper::dump(const PDBSymbolTypeUDT &Symbol) {
|
void TypedefDumper::dump(const PDBSymbolTypeUDT &Symbol) {
|
||||||
WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
|
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) {}
|
: PDBSymDumper(true), Printer(P) {}
|
||||||
|
|
||||||
void VariableDumper::start(const PDBSymbolData &Var) {
|
void VariableDumper::start(const PDBSymbolData &Var) {
|
||||||
|
if (Var.isCompilerGenerated() && opts::ExcludeCompilerGenerated)
|
||||||
|
return;
|
||||||
if (Printer.IsSymbolExcluded(Var.getName()))
|
if (Printer.IsSymbolExcluded(Var.getName()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -41,23 +43,31 @@ void VariableDumper::start(const PDBSymbolData &Var) {
|
|||||||
|
|
||||||
switch (auto LocType = Var.getLocationType()) {
|
switch (auto LocType = Var.getLocationType()) {
|
||||||
case PDB_LocType::Static:
|
case PDB_LocType::Static:
|
||||||
|
Printer << "[";
|
||||||
WithColor(Printer, PDB_ColorItem::Address).get()
|
WithColor(Printer, PDB_ColorItem::Address).get()
|
||||||
<< "[" << format_hex(Var.getRelativeVirtualAddress(), 10) << "] ";
|
<< format_hex(Var.getRelativeVirtualAddress(), 10);
|
||||||
|
Printer << "] ";
|
||||||
WithColor(Printer, PDB_ColorItem::Keyword).get() << "static ";
|
WithColor(Printer, PDB_ColorItem::Keyword).get() << "static ";
|
||||||
dumpSymbolTypeAndName(*VarType, Var.getName());
|
dumpSymbolTypeAndName(*VarType, Var.getName());
|
||||||
break;
|
break;
|
||||||
case PDB_LocType::Constant:
|
case PDB_LocType::Constant:
|
||||||
WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
|
WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
|
||||||
dumpSymbolTypeAndName(*VarType, Var.getName());
|
dumpSymbolTypeAndName(*VarType, Var.getName());
|
||||||
Printer << "[";
|
Printer << " = ";
|
||||||
WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue();
|
WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue();
|
||||||
Printer << "]";
|
|
||||||
break;
|
break;
|
||||||
case PDB_LocType::ThisRel:
|
case PDB_LocType::ThisRel:
|
||||||
WithColor(Printer, PDB_ColorItem::Offset).get()
|
WithColor(Printer, PDB_ColorItem::Offset).get()
|
||||||
<< "+" << format_hex(Var.getOffset(), 4) << " ";
|
<< "+" << format_hex(Var.getOffset(), 4) << " ";
|
||||||
dumpSymbolTypeAndName(*VarType, Var.getName());
|
dumpSymbolTypeAndName(*VarType, Var.getName());
|
||||||
break;
|
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:
|
default:
|
||||||
Printer << "unknown(" << LocType << ") ";
|
Printer << "unknown(" << LocType << ") ";
|
||||||
WithColor(Printer, PDB_ColorItem::Identifier).get() << Var.getName();
|
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::desc("<input PDB files>"),
|
||||||
cl::OneOrMore);
|
cl::OneOrMore);
|
||||||
|
|
||||||
cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"));
|
cl::OptionCategory TypeCategory("Symbol Type Options");
|
||||||
cl::opt<bool> Symbols("symbols",
|
cl::OptionCategory FilterCategory("Filtering Options");
|
||||||
cl::desc("Display symbols for each compiland"));
|
|
||||||
cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"));
|
cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
|
||||||
cl::opt<bool> Types("types", cl::desc("Display types"));
|
cl::cat(TypeCategory));
|
||||||
cl::opt<bool> ClassDefs("class-definitions",
|
cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
|
||||||
cl::desc("Display full class definitions"));
|
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>
|
cl::list<std::string>
|
||||||
ExcludeTypes("exclude-types",
|
ExcludeTypes("exclude-types",
|
||||||
cl::desc("Exclude types by regular expression"),
|
cl::desc("Exclude types by regular expression"),
|
||||||
cl::ZeroOrMore);
|
cl::ZeroOrMore, cl::cat(FilterCategory));
|
||||||
cl::list<std::string>
|
cl::list<std::string>
|
||||||
ExcludeSymbols("exclude-symbols",
|
ExcludeSymbols("exclude-symbols",
|
||||||
cl::desc("Exclude symbols by regular expression"),
|
cl::desc("Exclude symbols by regular expression"),
|
||||||
cl::ZeroOrMore);
|
cl::ZeroOrMore, cl::cat(FilterCategory));
|
||||||
cl::list<std::string>
|
cl::list<std::string>
|
||||||
ExcludeCompilands("exclude-compilands",
|
ExcludeCompilands("exclude-compilands",
|
||||||
cl::desc("Exclude compilands by regular expression"),
|
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) {
|
static void dumpInput(StringRef Path) {
|
||||||
@@ -103,11 +121,6 @@ static void dumpInput(StringRef Path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LinePrinter Printer(2, outs());
|
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());
|
auto GlobalScope(Session->getGlobalScope());
|
||||||
std::string FileName(GlobalScope->getSymbolsFileName());
|
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.
|
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
|
||||||
|
|
||||||
cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
|
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)
|
#if defined(HAVE_DIA_SDK)
|
||||||
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||||
|
@@ -10,19 +10,22 @@
|
|||||||
#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
|
#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
|
||||||
#define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
|
#define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
|
||||||
|
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace opts {
|
||||||
struct newline {
|
extern llvm::cl::opt<bool> Compilands;
|
||||||
newline(int IndentWidth) : Width(IndentWidth) {}
|
extern llvm::cl::opt<bool> Symbols;
|
||||||
int Width;
|
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) {
|
extern llvm::cl::opt<bool> ExcludeCompilerGenerated;
|
||||||
OS << "\n";
|
|
||||||
OS.indent(Indent.Width);
|
extern llvm::cl::list<std::string> ExcludeTypes;
|
||||||
return OS;
|
extern llvm::cl::list<std::string> ExcludeSymbols;
|
||||||
}
|
extern llvm::cl::list<std::string> ExcludeCompilands;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
Reference in New Issue
Block a user