uint32_t getClassSize() const { return SizeOf; }
- const PDBSymbol &getSymbol() const { return Symbol; }
-
ArrayRef<std::unique_ptr<StorageItemBase>> layout_items() const {
return ChildStorage;
}
+ ArrayRef<BaseClassLayout *> base_classes() const { return BaseClasses; }
+
ArrayRef<std::unique_ptr<PDBSymbol>> other_items() const {
return NonStorageItems;
}
+ const PDBSymbol &getSymbolBase() const { return SymbolBase; }
+
protected:
void initializeChildren(const PDBSymbol &Sym);
uint32_t SizeOf = 0;
std::string Name;
- const PDBSymbol &Symbol;
+ const PDBSymbol &SymbolBase;
BitVector UsedBytes;
std::vector<std::unique_ptr<PDBSymbol>> NonStorageItems;
std::vector<std::unique_ptr<StorageItemBase>> ChildStorage;
class ClassLayout : public UDTLayoutBase {
public:
+ explicit ClassLayout(const PDBSymbolTypeUDT &UDT);
explicit ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT);
+ const PDBSymbolTypeUDT &getClass() const { return UDT; }
+
private:
- std::unique_ptr<PDBSymbolTypeUDT> Type;
+ std::unique_ptr<PDBSymbolTypeUDT> OwnedStorage;
+ const PDBSymbolTypeUDT &UDT;
};
class BaseClassLayout : public UDTLayoutBase, public StorageItemBase {
BaseClassLayout(const UDTLayoutBase &Parent,
std::unique_ptr<PDBSymbolTypeBaseClass> Base);
+ const PDBSymbolTypeBaseClass &getBase() const { return *Base; }
+
private:
std::unique_ptr<PDBSymbolTypeBaseClass> Base;
bool IsVirtualBase;
VTableType->getPointeeType())) {
VTableFuncs.resize(Shape->getCount());
- auto ParentFunctions = Parent.getSymbol().findAllChildren<PDBSymbolFunc>();
+ auto ParentFunctions =
+ Parent.getSymbolBase().findAllChildren<PDBSymbolFunc>();
while (auto Func = ParentFunctions->getNext()) {
if (Func->isVirtual()) {
uint32_t Index = Func->getVirtualBaseOffset();
UDTLayoutBase::UDTLayoutBase(const PDBSymbol &Symbol, const std::string &Name,
uint32_t Size)
- : Symbol(Symbol), Name(Name), SizeOf(Size) {
+ : SymbolBase(Symbol), Name(Name), SizeOf(Size) {
UsedBytes.resize(Size);
ChildrenPerByte.resize(Size);
initializeChildren(Symbol);
}
+ClassLayout::ClassLayout(const PDBSymbolTypeUDT &UDT)
+ : UDTLayoutBase(UDT, UDT.getName(), UDT.getLength()), UDT(UDT) {}
+
ClassLayout::ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT)
- : UDTLayoutBase(*UDT, UDT->getName(), UDT->getLength()),
- Type(std::move(UDT)) {}
+ : ClassLayout(*UDT) {
+ OwnedStorage = std::move(UDT);
+}
BaseClassLayout::BaseClassLayout(const UDTLayoutBase &Parent,
std::unique_ptr<PDBSymbolTypeBaseClass> Base)
-; RUN: llvm-pdbdump pretty -classes -class-definitions=layout \
+; RUN: llvm-pdbdump pretty -classes -class-definitions=layout-members \
; RUN: -include-types=SimplePad %p/Inputs/SimplePaddingTest.pdb > %t
; RUN: FileCheck -input-file=%t %s -check-prefix=NO_PADDING
PdbYaml.cpp
PrettyBuiltinDumper.cpp
PrettyClassDefinitionDumper.cpp
+ PrettyClassLayoutTextDumper.cpp
+ PrettyClassLayoutGraphicalDumper.cpp
PrettyCompilandDumper.cpp
PrettyEnumDumper.cpp
PrettyExternalSymbolDumper.cpp
#include "PrettyClassDefinitionDumper.h"
#include "LinePrinter.h"
-#include "PrettyEnumDumper.h"
-#include "PrettyFunctionDumper.h"
-#include "PrettyTypedefDumper.h"
-#include "PrettyVariableDumper.h"
+#include "PrettyClassLayoutGraphicalDumper.h"
+#include "PrettyClassLayoutTextDumper.h"
#include "llvm-pdbdump.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/DebugInfo/PDB/IPDBSession.h"
-#include "llvm/DebugInfo/PDB/PDBExtras.h"
-#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
-#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
-#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
-#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
-#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
-#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
#include "llvm/DebugInfo/PDB/UDTLayout.h"
#include "llvm/Support/Format.h"
assert(opts::pretty::ClassFormat !=
opts::pretty::ClassDefinitionFormat::None);
- uint32_t Size = Class.getLength();
-
- ClassLayout Layout(Class.clone());
+ ClassLayout Layout(Class);
if (opts::pretty::OnlyPaddingClasses && (Layout.shallowPaddingSize() == 0))
return;
+ prettyPrintClassIntro(Layout);
+
+ switch (opts::pretty::ClassFormat) {
+ case opts::pretty::ClassDefinitionFormat::Graphical: {
+ PrettyClassLayoutGraphicalDumper Dumper(Printer);
+ DumpedAnything = Dumper.start(Layout);
+ break;
+ }
+ case opts::pretty::ClassDefinitionFormat::Standard:
+ case opts::pretty::ClassDefinitionFormat::Layout: {
+ PrettyClassLayoutTextDumper Dumper(Printer);
+ DumpedAnything |= Dumper.start(Layout);
+ break;
+ }
+ default:
+ llvm_unreachable("Unreachable!");
+ }
+
+ prettyPrintClassOutro(Layout);
+}
+
+void ClassDefinitionDumper::prettyPrintClassIntro(const ClassLayout &Layout) {
+ DumpedAnything = false;
Printer.NewLine();
+ uint32_t Size = Layout.getClassSize();
+ const PDBSymbolTypeUDT &Class = Layout.getClass();
+
WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";
WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();
WithColor(Printer, PDB_ColorItem::Comment).get() << " [sizeof = " << Size
<< "]";
-
- auto Bases = Class.findAllChildren<PDBSymbolTypeBaseClass>();
- if (Bases->getChildCount() > 0) {
+ uint32_t BaseCount = Layout.base_classes().size();
+ if (BaseCount > 0) {
Printer.Indent();
Printer.NewLine();
Printer << ":";
uint32_t BaseIndex = 0;
- while (auto Base = Bases->getNext()) {
+ for (auto BC : Layout.base_classes()) {
+ const auto &Base = BC->getBase();
Printer << " ";
- WithColor(Printer, PDB_ColorItem::Keyword).get() << Base->getAccess();
- if (Base->isVirtualBaseClass())
+ 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()) {
+ WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base.getName();
+ if (++BaseIndex < BaseCount) {
Printer.NewLine();
Printer << ",";
}
Printer << " {";
Printer.Indent();
+}
- // Dump non-layout items first, but only if we're not in layout-only mode.
- if (opts::pretty::ClassFormat !=
- opts::pretty::ClassDefinitionFormat::Layout) {
- for (auto &Other : Layout.other_items())
- Other->dump(*this);
- }
-
- const BitVector &UseMap = Layout.usedBytes();
- int NextUnusedByte = Layout.usedBytes().find_first_unset();
- // Next dump items which affect class layout.
- for (auto &LayoutItem : Layout.layout_items()) {
- if (NextUnusedByte >= 0) {
- // If there are padding bytes remaining, see if this field is the first to
- // cross a padding boundary, and print a padding field indicator if so.
- int Off = LayoutItem->getOffsetInParent();
- if (Off > NextUnusedByte) {
- uint32_t Amount = Off - NextUnusedByte;
- Printer.NewLine();
- WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> ("
- << Amount << " bytes)";
- assert(UseMap.find_next(NextUnusedByte) == Off);
- NextUnusedByte = UseMap.find_next_unset(Off);
- }
- }
- LayoutItem->getSymbol().dump(*this);
- }
-
- if (NextUnusedByte >= 0 && Layout.getClassSize() > 1) {
- uint32_t Amount = Layout.getClassSize() - NextUnusedByte;
- Printer.NewLine();
- WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
- << " bytes)";
- DumpedAnything = true;
- }
-
+void ClassDefinitionDumper::prettyPrintClassOutro(const ClassLayout &Layout) {
Printer.Unindent();
if (DumpedAnything)
Printer.NewLine();
Printer << "}";
Printer.NewLine();
if (Layout.deepPaddingSize() > 0) {
- APFloat Pct(100.0 * (double)Layout.deepPaddingSize() / (double)Size);
+ APFloat Pct(100.0 * (double)Layout.deepPaddingSize() /
+ (double)Layout.getClassSize());
SmallString<8> PctStr;
Pct.toString(PctStr, 4);
WithColor(Printer, PDB_ColorItem::Padding).get()
Printer.NewLine();
}
}
-
-void ClassDefinitionDumper::dump(const PDBSymbolTypeBaseClass &Symbol) {}
-
-void ClassDefinitionDumper::dump(const PDBSymbolData &Symbol) {
- VariableDumper Dumper(Printer);
- Dumper.start(Symbol);
- DumpedAnything = true;
-}
-
-void ClassDefinitionDumper::dump(const PDBSymbolFunc &Symbol) {
- if (Printer.IsSymbolExcluded(Symbol.getName()))
- return;
- if (Symbol.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
- return;
- if (Symbol.getLength() == 0 && !Symbol.isPureVirtual() &&
- !Symbol.isIntroVirtualFunction())
- return;
-
- DumpedAnything = true;
- Printer.NewLine();
- FunctionDumper Dumper(Printer);
- Dumper.start(Symbol, FunctionDumper::PointerType::None);
-}
-
-void ClassDefinitionDumper::dump(const PDBSymbolTypeVTable &Symbol) {
- VariableDumper Dumper(Printer);
- Dumper.start(Symbol);
- DumpedAnything = true;
-}
-
-void ClassDefinitionDumper::dump(const PDBSymbolTypeEnum &Symbol) {
- if (Printer.IsTypeExcluded(Symbol.getName()))
- return;
-
- DumpedAnything = true;
- Printer.NewLine();
- EnumDumper Dumper(Printer);
- Dumper.start(Symbol);
-}
-
-void ClassDefinitionDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
- if (Printer.IsTypeExcluded(Symbol.getName()))
- return;
-
- DumpedAnything = true;
- Printer.NewLine();
- TypedefDumper Dumper(Printer);
- Dumper.start(Symbol);
-}
-
-void ClassDefinitionDumper::dump(const PDBSymbolTypeUDT &Symbol) {}
namespace pdb {
+class ClassLayout;
class LinePrinter;
class ClassDefinitionDumper : public PDBSymDumper {
void start(const PDBSymbolTypeUDT &Exe);
- void dump(const PDBSymbolTypeBaseClass &Symbol) override;
- void dump(const PDBSymbolData &Symbol) override;
- void dump(const PDBSymbolTypeEnum &Symbol) override;
- void dump(const PDBSymbolFunc &Symbol) override;
- void dump(const PDBSymbolTypeTypedef &Symbol) override;
- void dump(const PDBSymbolTypeUDT &Symbol) override;
- void dump(const PDBSymbolTypeVTable &Symbol) override;
-
private:
- bool maybeDumpSymbol(std::unique_ptr<PDBSymbolData> Data,
- const BitVector &Padding, int &NextUnusedByte);
- bool maybeDumpSymbol(std::unique_ptr<PDBSymbolFunc> Data);
+ void prettyPrintClassIntro(const ClassLayout &Class);
+ void prettyPrintClassOutro(const ClassLayout &Class);
+
bool DumpedAnything = false;
LinePrinter &Printer;
};
--- /dev/null
+//===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyClassLayoutGraphicalDumper.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper(
+ LinePrinter &P)
+ : PDBSymDumper(true), Printer(P) {}
+
+bool PrettyClassLayoutGraphicalDumper::start(const ClassLayout &Layout) {
+ return false;
+}
+
+void PrettyClassLayoutGraphicalDumper::dump(
+ const PDBSymbolTypeBaseClass &Symbol) {}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeEnum &Symbol) {}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolFunc &Symbol) {}
+
+void PrettyClassLayoutGraphicalDumper::dump(
+ const PDBSymbolTypeTypedef &Symbol) {}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeUDT &Symbol) {}
+
+void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) {
+}
--- /dev/null
+//===- PrettyClassLayoutGraphicalDumper.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_PRETTYCLASSLAYOUTGRAPHICALDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSLAYOUTGRAPHICALDUMPER_H
+
+#include "llvm/ADT/BitVector.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+namespace pdb {
+
+class ClassLayout;
+class LinePrinter;
+
+class PrettyClassLayoutGraphicalDumper : public PDBSymDumper {
+public:
+ explicit PrettyClassLayoutGraphicalDumper(LinePrinter &P);
+
+ bool start(const ClassLayout &Layout);
+
+ void dump(const PDBSymbolTypeBaseClass &Symbol) override;
+ void dump(const PDBSymbolData &Symbol) override;
+ void dump(const PDBSymbolTypeEnum &Symbol) override;
+ void dump(const PDBSymbolFunc &Symbol) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol) override;
+ void dump(const PDBSymbolTypeUDT &Symbol) override;
+ void dump(const PDBSymbolTypeVTable &Symbol) override;
+
+private:
+ bool DumpedAnything = false;
+ LinePrinter &Printer;
+};
+}
+}
+#endif
--- /dev/null
+//===- PrettyClassLayoutTextDumper.cpp --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PrettyClassLayoutTextDumper.h"
+
+#include "LinePrinter.h"
+#include "PrettyEnumDumper.h"
+#include "PrettyFunctionDumper.h"
+#include "PrettyTypedefDumper.h"
+#include "PrettyVariableDumper.h"
+#include "llvm-pdbdump.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+#include "llvm/DebugInfo/PDB/UDTLayout.h"
+
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+PrettyClassLayoutTextDumper::PrettyClassLayoutTextDumper(LinePrinter &P)
+ : PDBSymDumper(true), Printer(P) {}
+
+bool PrettyClassLayoutTextDumper::start(const ClassLayout &Layout) {
+ if (opts::pretty::ClassFormat ==
+ opts::pretty::ClassDefinitionFormat::Standard) {
+ for (auto &Other : Layout.other_items())
+ Other->dump(*this);
+ }
+
+ const BitVector &UseMap = Layout.usedBytes();
+ int NextUnusedByte = Layout.usedBytes().find_first_unset();
+ // Next dump items which affect class layout.
+ for (auto &LayoutItem : Layout.layout_items()) {
+ if (NextUnusedByte >= 0) {
+ // If there are padding bytes remaining, see if this field is the first to
+ // cross a padding boundary, and print a padding field indicator if so.
+ int Off = LayoutItem->getOffsetInParent();
+ if (Off > NextUnusedByte) {
+ uint32_t Amount = Off - NextUnusedByte;
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> ("
+ << Amount << " bytes)";
+ assert(UseMap.find_next(NextUnusedByte) == Off);
+ NextUnusedByte = UseMap.find_next_unset(Off);
+ }
+ }
+ LayoutItem->getSymbol().dump(*this);
+ }
+
+ if (NextUnusedByte >= 0 && Layout.getClassSize() > 1) {
+ uint32_t Amount = Layout.getClassSize() - NextUnusedByte;
+ Printer.NewLine();
+ WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
+ << " bytes)";
+ DumpedAnything = true;
+ }
+
+ return DumpedAnything;
+}
+
+void PrettyClassLayoutTextDumper::dump(const PDBSymbolTypeBaseClass &Symbol) {}
+
+void PrettyClassLayoutTextDumper::dump(const PDBSymbolData &Symbol) {
+ VariableDumper Dumper(Printer);
+ Dumper.start(Symbol);
+ DumpedAnything = true;
+}
+
+void PrettyClassLayoutTextDumper::dump(const PDBSymbolFunc &Symbol) {
+ if (Printer.IsSymbolExcluded(Symbol.getName()))
+ return;
+ if (Symbol.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
+ return;
+ if (Symbol.getLength() == 0 && !Symbol.isPureVirtual() &&
+ !Symbol.isIntroVirtualFunction())
+ return;
+
+ DumpedAnything = true;
+ Printer.NewLine();
+ FunctionDumper Dumper(Printer);
+ Dumper.start(Symbol, FunctionDumper::PointerType::None);
+}
+
+void PrettyClassLayoutTextDumper::dump(const PDBSymbolTypeVTable &Symbol) {
+ VariableDumper Dumper(Printer);
+ Dumper.start(Symbol);
+ DumpedAnything = true;
+}
+
+void PrettyClassLayoutTextDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+ if (Printer.IsTypeExcluded(Symbol.getName()))
+ return;
+
+ DumpedAnything = true;
+ Printer.NewLine();
+ EnumDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void PrettyClassLayoutTextDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
+ if (Printer.IsTypeExcluded(Symbol.getName()))
+ return;
+
+ DumpedAnything = true;
+ Printer.NewLine();
+ TypedefDumper Dumper(Printer);
+ Dumper.start(Symbol);
+}
+
+void PrettyClassLayoutTextDumper::dump(const PDBSymbolTypeUDT &Symbol) {}
--- /dev/null
+//===- PrettyClassLayoutTextDumper.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_PRETTYCLASSLAYOUTTEXTDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSLAYOUTTEXTDUMPER_H
+
+#include "llvm/ADT/BitVector.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+namespace pdb {
+
+class ClassLayout;
+class LinePrinter;
+
+class PrettyClassLayoutTextDumper : public PDBSymDumper {
+public:
+ PrettyClassLayoutTextDumper(LinePrinter &P);
+
+ bool start(const ClassLayout &Layout);
+
+ void dump(const PDBSymbolTypeBaseClass &Symbol) override;
+ void dump(const PDBSymbolData &Symbol) override;
+ void dump(const PDBSymbolTypeEnum &Symbol) override;
+ void dump(const PDBSymbolFunc &Symbol) override;
+ void dump(const PDBSymbolTypeTypedef &Symbol) override;
+ void dump(const PDBSymbolTypeUDT &Symbol) override;
+ void dump(const PDBSymbolTypeVTable &Symbol) override;
+
+private:
+ bool DumpedAnything = false;
+ LinePrinter &Printer;
+};
+}
+}
+#endif
"class-definitions", cl::desc("Class definition format"),
cl::init(ClassDefinitionFormat::Standard),
cl::values(
- clEnumValN(ClassDefinitionFormat::Standard, "full",
- "Display complete class definition"),
- clEnumValN(ClassDefinitionFormat::Layout, "layout",
+ clEnumValN(ClassDefinitionFormat::Standard, "all-members",
+ "Display all class members including data, constants, "
+ "typedefs, etc"),
+ clEnumValN(ClassDefinitionFormat::Layout, "layout-members",
"Only display members that contribute to class size."),
clEnumValN(ClassDefinitionFormat::None, "none",
"Don't display class definitions")),
namespace pretty {
-enum class ClassDefinitionFormat { None, Layout, Standard };
+enum class ClassDefinitionFormat { None, Layout, Graphical, Standard };
extern llvm::cl::opt<bool> Compilands;
extern llvm::cl::opt<bool> Symbols;