PrettyTypeDumper.cpp revision 353358
167754Smsmith//===- PrettyTypeDumper.cpp - PDBSymDumper type dumper *------------ C++ *-===// 267754Smsmith// 367754Smsmith// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4151937Sjkim// See https://llvm.org/LICENSE.txt for license information. 567754Smsmith// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 667754Smsmith// 767754Smsmith//===----------------------------------------------------------------------===// 867754Smsmith 967754Smsmith#include "PrettyTypeDumper.h" 1067754Smsmith 1167754Smsmith#include "LinePrinter.h" 12151937Sjkim#include "PrettyBuiltinDumper.h" 1370243Smsmith#include "PrettyClassDefinitionDumper.h" 1467754Smsmith#include "PrettyEnumDumper.h" 1567754Smsmith#include "PrettyFunctionDumper.h" 1667754Smsmith#include "PrettyTypedefDumper.h" 1767754Smsmith#include "llvm-pdbutil.h" 1867754Smsmith 1967754Smsmith#include "llvm/DebugInfo/PDB/IPDBSession.h" 2067754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" 2167754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h" 2267754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" 2367754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" 2467754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" 2567754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" 2667754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" 2767754Smsmith#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" 2867754Smsmith#include "llvm/DebugInfo/PDB/UDTLayout.h" 2967754Smsmith#include "llvm/Support/Compiler.h" 3067754Smsmith#include "llvm/Support/FormatVariadic.h" 3167754Smsmith 3267754Smsmithusing namespace llvm; 3367754Smsmithusing namespace llvm::pdb; 3467754Smsmith 3567754Smsmithusing LayoutPtr = std::unique_ptr<ClassLayout>; 3667754Smsmith 3767754Smsmithtypedef bool (*CompareFunc)(const LayoutPtr &S1, const LayoutPtr &S2); 3867754Smsmith 3967754Smsmithstatic bool CompareNames(const LayoutPtr &S1, const LayoutPtr &S2) { 4067754Smsmith return S1->getName() < S2->getName(); 4167754Smsmith} 4267754Smsmith 4367754Smsmithstatic bool CompareSizes(const LayoutPtr &S1, const LayoutPtr &S2) { 4467754Smsmith return S1->getSize() < S2->getSize(); 4567754Smsmith} 4667754Smsmith 4767754Smsmithstatic bool ComparePadding(const LayoutPtr &S1, const LayoutPtr &S2) { 4867754Smsmith return S1->deepPaddingSize() < S2->deepPaddingSize(); 4967754Smsmith} 5067754Smsmith 5167754Smsmithstatic bool ComparePaddingPct(const LayoutPtr &S1, const LayoutPtr &S2) { 5267754Smsmith double Pct1 = (double)S1->deepPaddingSize() / (double)S1->getSize(); 5367754Smsmith double Pct2 = (double)S2->deepPaddingSize() / (double)S2->getSize(); 5467754Smsmith return Pct1 < Pct2; 5567754Smsmith} 5667754Smsmith 5767754Smsmithstatic bool ComparePaddingImmediate(const LayoutPtr &S1, const LayoutPtr &S2) { 5867754Smsmith return S1->immediatePadding() < S2->immediatePadding(); 5967754Smsmith} 6067754Smsmith 6167754Smsmithstatic bool ComparePaddingPctImmediate(const LayoutPtr &S1, 6267754Smsmith const LayoutPtr &S2) { 6367754Smsmith double Pct1 = (double)S1->immediatePadding() / (double)S1->getSize(); 6467754Smsmith double Pct2 = (double)S2->immediatePadding() / (double)S2->getSize(); 6567754Smsmith return Pct1 < Pct2; 6667754Smsmith} 6767754Smsmith 6867754Smsmithstatic CompareFunc getComparisonFunc(opts::pretty::ClassSortMode Mode) { 6967754Smsmith switch (Mode) { 7067754Smsmith case opts::pretty::ClassSortMode::Name: 7167754Smsmith return CompareNames; 7267754Smsmith case opts::pretty::ClassSortMode::Size: 7367754Smsmith return CompareSizes; 7467754Smsmith case opts::pretty::ClassSortMode::Padding: 7567754Smsmith return ComparePadding; 7667754Smsmith case opts::pretty::ClassSortMode::PaddingPct: 7767754Smsmith return ComparePaddingPct; 7867754Smsmith case opts::pretty::ClassSortMode::PaddingImmediate: 7967754Smsmith return ComparePaddingImmediate; 8067754Smsmith case opts::pretty::ClassSortMode::PaddingPctImmediate: 8167754Smsmith return ComparePaddingPctImmediate; 8267754Smsmith default: 8367754Smsmith return nullptr; 8467754Smsmith } 8567754Smsmith} 8667754Smsmith 8767754Smsmithtemplate <typename Enumerator> 8867754Smsmithstatic std::vector<std::unique_ptr<ClassLayout>> 8967754SmsmithfilterAndSortClassDefs(LinePrinter &Printer, Enumerator &E, 9067754Smsmith uint32_t UnfilteredCount) { 9167754Smsmith std::vector<std::unique_ptr<ClassLayout>> Filtered; 9267754Smsmith 9367754Smsmith Filtered.reserve(UnfilteredCount); 9467754Smsmith CompareFunc Comp = getComparisonFunc(opts::pretty::ClassOrder); 9567754Smsmith 9667754Smsmith if (UnfilteredCount > 10000) { 9767754Smsmith errs() << formatv("Filtering and sorting {0} types", UnfilteredCount); 9867754Smsmith errs().flush(); 9967754Smsmith } 10067754Smsmith uint32_t Examined = 0; 10167754Smsmith uint32_t Discarded = 0; 10267754Smsmith while (auto Class = E.getNext()) { 10367754Smsmith ++Examined; 10467754Smsmith if (Examined % 10000 == 0) { 10567754Smsmith errs() << formatv("Examined {0}/{1} items. {2} items discarded\n", 10667754Smsmith Examined, UnfilteredCount, Discarded); 10767754Smsmith errs().flush(); 10867754Smsmith } 10967754Smsmith 11067754Smsmith if (Class->getUnmodifiedTypeId() != 0) { 11167754Smsmith ++Discarded; 11267754Smsmith continue; 11367754Smsmith } 11467754Smsmith 11567754Smsmith if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) { 11667754Smsmith ++Discarded; 11767754Smsmith continue; 11867754Smsmith } 11967754Smsmith 120151600Sobrien auto Layout = llvm::make_unique<ClassLayout>(std::move(Class)); 121151600Sobrien if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) { 122151600Sobrien ++Discarded; 123151600Sobrien continue; 12467754Smsmith } 12577424Smsmith if (Layout->immediatePadding() < opts::pretty::ImmediatePaddingThreshold) { 12691116Smsmith ++Discarded; 12767754Smsmith continue; 12867754Smsmith } 12977424Smsmith 13067754Smsmith Filtered.push_back(std::move(Layout)); 131138287Smarks } 132138287Smarks 133138287Smarks if (Comp) 134138287Smarks llvm::sort(Filtered, Comp); 135138287Smarks return Filtered; 136138287Smarks} 137138287Smarks 138138287SmarksTypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {} 139138287Smarks 140138287Smarkstemplate <typename T> 141138287Smarksstatic bool isTypeExcluded(LinePrinter &Printer, const T &Symbol) { 142138287Smarks return false; 143138287Smarks} 144138287Smarks 145138287Smarksstatic bool isTypeExcluded(LinePrinter &Printer, 146138287Smarks const PDBSymbolTypeEnum &Enum) { 147138287Smarks if (Printer.IsTypeExcluded(Enum.getName(), Enum.getLength())) 148138287Smarks return true; 149138287Smarks // Dump member enums when dumping their class definition. 150138287Smarks if (nullptr != Enum.getClassParent()) 151138287Smarks return true; 152138287Smarks return false; 153138287Smarks} 154138287Smarks 155138287Smarksstatic bool isTypeExcluded(LinePrinter &Printer, 156138287Smarks const PDBSymbolTypeTypedef &Typedef) { 157138287Smarks return Printer.IsTypeExcluded(Typedef.getName(), Typedef.getLength()); 158138287Smarks} 159138287Smarks 160138287Smarkstemplate <typename SymbolT> 161138287Smarksstatic void dumpSymbolCategory(LinePrinter &Printer, const PDBSymbolExe &Exe, 162138287Smarks TypeDumper &TD, StringRef Label) { 163138287Smarks if (auto Children = Exe.findAllChildren<SymbolT>()) { 164138287Smarks Printer.NewLine(); 165138287Smarks WithColor(Printer, PDB_ColorItem::Identifier).get() << Label; 166138287Smarks Printer << ": (" << Children->getChildCount() << " items)"; 167138287Smarks Printer.Indent(); 168138287Smarks while (auto Child = Children->getNext()) { 169138287Smarks if (isTypeExcluded(Printer, *Child)) 170138287Smarks continue; 171138287Smarks 172138287Smarks Printer.NewLine(); 173138287Smarks Child->dump(TD); 174138287Smarks } 175138287Smarks Printer.Unindent(); 176138287Smarks } 177138287Smarks} 17867754Smsmith 17967754Smsmithstatic void printClassDecl(LinePrinter &Printer, 18067754Smsmith const PDBSymbolTypeUDT &Class) { 18167754Smsmith if (Class.getUnmodifiedTypeId() != 0) { 18267754Smsmith if (Class.isConstType()) 18367754Smsmith WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; 18467754Smsmith if (Class.isVolatileType()) 18567754Smsmith WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; 18667754Smsmith if (Class.isUnalignedType()) 18767754Smsmith WithColor(Printer, PDB_ColorItem::Keyword).get() << "unaligned "; 18867754Smsmith } 18967754Smsmith WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " "; 19067754Smsmith WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName(); 19167754Smsmith} 19267754Smsmith 19367754Smsmithvoid TypeDumper::start(const PDBSymbolExe &Exe) { 19467754Smsmith if (opts::pretty::Enums) 19577424Smsmith dumpSymbolCategory<PDBSymbolTypeEnum>(Printer, Exe, *this, "Enums"); 19667754Smsmith 19767754Smsmith if (opts::pretty::Funcsigs) 19877424Smsmith dumpSymbolCategory<PDBSymbolTypeFunctionSig>(Printer, Exe, *this, 19967754Smsmith "Function Signatures"); 20067754Smsmith 20191116Smsmith if (opts::pretty::Typedefs) 20267754Smsmith dumpSymbolCategory<PDBSymbolTypeTypedef>(Printer, Exe, *this, "Typedefs"); 20367754Smsmith 20477424Smsmith if (opts::pretty::Arrays) 20577424Smsmith dumpSymbolCategory<PDBSymbolTypeArray>(Printer, Exe, *this, "Arrays"); 20677424Smsmith 20777424Smsmith if (opts::pretty::Pointers) 20867754Smsmith dumpSymbolCategory<PDBSymbolTypePointer>(Printer, Exe, *this, "Pointers"); 20967754Smsmith 21067754Smsmith if (opts::pretty::VTShapes) 21191116Smsmith dumpSymbolCategory<PDBSymbolTypeVTableShape>(Printer, Exe, *this, 21291116Smsmith "VFTable Shapes"); 21391116Smsmith 21491116Smsmith if (opts::pretty::Classes) { 21591116Smsmith if (auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>()) { 21667754Smsmith uint32_t All = Classes->getChildCount(); 21767754Smsmith 21867754Smsmith Printer.NewLine(); 21967754Smsmith WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes"; 22067754Smsmith 22187031Smsmith bool Precompute = false; 22267754Smsmith Precompute = 22367754Smsmith (opts::pretty::ClassOrder != opts::pretty::ClassSortMode::None); 22467754Smsmith 22585756Smsmith // If we're using no sort mode, then we can start getting immediate output 22667754Smsmith // from the tool by just filtering as we go, rather than processing 22767754Smsmith // everything up front so that we can sort it. This makes the tool more 22867754Smsmith // responsive. So only precompute the filtered/sorted set of classes if 22967754Smsmith // necessary due to the specified options. 230117521Snjl std::vector<LayoutPtr> Filtered; 23191116Smsmith uint32_t Shown = All; 23267754Smsmith if (Precompute) { 23382367Smsmith Filtered = filterAndSortClassDefs(Printer, *Classes, All); 23467754Smsmith 23567754Smsmith Shown = Filtered.size(); 23667754Smsmith } 23767754Smsmith 23867754Smsmith Printer << ": (Showing " << Shown << " items"; 23977424Smsmith if (Shown < All) 24077424Smsmith Printer << ", " << (All - Shown) << " filtered"; 24177424Smsmith Printer << ")"; 24282367Smsmith Printer.Indent(); 24382367Smsmith 24467754Smsmith // If we pre-computed, iterate the filtered/sorted list, otherwise iterate 24567754Smsmith // the DIA enumerator and filter on the fly. 24667754Smsmith if (Precompute) { 24767754Smsmith for (auto &Class : Filtered) 24891116Smsmith dumpClassLayout(*Class); 24967754Smsmith } else { 25067754Smsmith while (auto Class = Classes->getNext()) { 25167754Smsmith if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) 25267754Smsmith continue; 25377424Smsmith 25467754Smsmith // No point duplicating a full class layout. Just print the modified 25567754Smsmith // declaration and continue. 25667754Smsmith if (Class->getUnmodifiedTypeId() != 0) { 25767754Smsmith Printer.NewLine(); 25867754Smsmith printClassDecl(Printer, *Class); 25967754Smsmith continue; 26067754Smsmith } 26167754Smsmith 26267754Smsmith auto Layout = llvm::make_unique<ClassLayout>(std::move(Class)); 26367754Smsmith if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) 26467754Smsmith continue; 26567754Smsmith 26667754Smsmith dumpClassLayout(*Layout); 26767754Smsmith } 26867754Smsmith } 26977424Smsmith 27067754Smsmith Printer.Unindent(); 27167754Smsmith } 27267754Smsmith } 27367754Smsmith} 27491116Smsmith 27567754Smsmithvoid TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) { 27667754Smsmith assert(opts::pretty::Enums); 27777424Smsmith 27877424Smsmith EnumDumper Dumper(Printer); 27977424Smsmith Dumper.start(Symbol); 28077424Smsmith} 28167754Smsmith 28267754Smsmithvoid TypeDumper::dump(const PDBSymbolTypeBuiltin &Symbol) { 28367754Smsmith BuiltinDumper BD(Printer); 28491116Smsmith BD.start(Symbol); 28591116Smsmith} 28691116Smsmith 28791116Smsmithvoid TypeDumper::dump(const PDBSymbolTypeUDT &Symbol) { 28891116Smsmith printClassDecl(Printer, Symbol); 28967754Smsmith} 29085756Smsmith 29167754Smsmithvoid TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) { 292117521Snjl assert(opts::pretty::Typedefs); 29369450Smsmith 29477424Smsmith TypedefDumper Dumper(Printer); 29577424Smsmith Dumper.start(Symbol); 29677424Smsmith} 29777424Smsmith 29877424Smsmithvoid TypeDumper::dump(const PDBSymbolTypeArray &Symbol) { 29991116Smsmith auto ElementType = Symbol.getElementType(); 30067754Smsmith 30182367Smsmith ElementType->dump(*this); 30282367Smsmith Printer << "["; 30377424Smsmith WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getCount(); 30477424Smsmith Printer << "]"; 30577424Smsmith} 30682367Smsmith 30767754Smsmithvoid TypeDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) { 30867754Smsmith FunctionDumper Dumper(Printer); 30991116Smsmith Dumper.start(Symbol, nullptr, FunctionDumper::PointerType::None); 31067754Smsmith} 31167754Smsmith 31267754Smsmithvoid TypeDumper::dump(const PDBSymbolTypePointer &Symbol) { 31367754Smsmith std::unique_ptr<PDBSymbol> P = Symbol.getPointeeType(); 31477424Smsmith 31567754Smsmith if (auto *FS = dyn_cast<PDBSymbolTypeFunctionSig>(P.get())) { 31667754Smsmith FunctionDumper Dumper(Printer); 31767754Smsmith FunctionDumper::PointerType PT = 31867754Smsmith Symbol.isReference() ? FunctionDumper::PointerType::Reference 31967754Smsmith : FunctionDumper::PointerType::Pointer; 32067754Smsmith Dumper.start(*FS, nullptr, PT); 32167754Smsmith return; 322129684Snjl } 32367754Smsmith 32467754Smsmith if (auto *UDT = dyn_cast<PDBSymbolTypeUDT>(P.get())) { 32567754Smsmith printClassDecl(Printer, *UDT); 32667754Smsmith } else if (P) { 32767754Smsmith P->dump(*this); 32867754Smsmith } 32967754Smsmith 33067754Smsmith if (auto Parent = Symbol.getClassParent()) { 33167754Smsmith auto UDT = llvm::unique_dyn_cast<PDBSymbolTypeUDT>(std::move(Parent)); 33267754Smsmith if (UDT) 33367754Smsmith Printer << " " << UDT->getName() << "::"; 33467754Smsmith } 33567754Smsmith 33677424Smsmith if (Symbol.isReference()) 33767754Smsmith Printer << "&"; 33867754Smsmith else if (Symbol.isRValueReference()) 33967754Smsmith Printer << "&&"; 34067754Smsmith else 34199146Siwasaki Printer << "*"; 34291116Smsmith} 34367754Smsmith 34467754Smsmithvoid TypeDumper::dump(const PDBSymbolTypeVTableShape &Symbol) { 34591116Smsmith Printer.format("<vtshape ({0} methods)>", Symbol.getCount()); 34667754Smsmith} 34767754Smsmith 34867754Smsmithvoid TypeDumper::dumpClassLayout(const ClassLayout &Class) { 34967754Smsmith assert(opts::pretty::Classes); 35099146Siwasaki 35199146Siwasaki if (opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::None) { 35267754Smsmith WithColor(Printer, PDB_ColorItem::Keyword).get() 35367754Smsmith << Class.getClass().getUdtKind() << " "; 35467754Smsmith WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName(); 35567754Smsmith } else { 35667754Smsmith ClassDefinitionDumper Dumper(Printer); 35791116Smsmith Dumper.start(Class); 35891116Smsmith } 35991116Smsmith} 36091116Smsmith