ClassDefinitionDumper.cpp revision 4c5e43da7792f75567b693105cc53e3f1992ad98
1//===- ClassDefinitionDumper.cpp --------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "ClassDefinitionDumper.h" 11#include "EnumDumper.h" 12#include "FunctionDumper.h" 13#include "LinePrinter.h" 14#include "llvm-pdbdump.h" 15#include "TypedefDumper.h" 16#include "VariableDumper.h" 17 18#include "llvm/DebugInfo/PDB/IPDBSession.h" 19#include "llvm/DebugInfo/PDB/PDBExtras.h" 20#include "llvm/DebugInfo/PDB/PDBSymbolData.h" 21#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" 22#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" 23#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" 24#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" 25#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" 26#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" 27#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" 28#include "llvm/Support/Format.h" 29 30using namespace llvm; 31 32ClassDefinitionDumper::ClassDefinitionDumper(LinePrinter &P) 33 : PDBSymDumper(true), Printer(P) {} 34 35void ClassDefinitionDumper::start(const PDBSymbolTypeUDT &Class) { 36 std::string Name = Class.getName(); 37 WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " "; 38 WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName(); 39 40 auto Bases = Class.findAllChildren<PDBSymbolTypeBaseClass>(); 41 if (Bases->getChildCount() > 0) { 42 Printer.Indent(); 43 Printer.NewLine(); 44 Printer << ":"; 45 uint32_t BaseIndex = 0; 46 while (auto Base = Bases->getNext()) { 47 Printer << " "; 48 WithColor(Printer, PDB_ColorItem::Keyword).get() << Base->getAccess(); 49 if (Base->isVirtualBaseClass()) 50 WithColor(Printer, PDB_ColorItem::Keyword).get() << " virtual"; 51 WithColor(Printer, PDB_ColorItem::Type).get() << " " << Base->getName(); 52 if (++BaseIndex < Bases->getChildCount()) { 53 Printer.NewLine(); 54 Printer << ","; 55 } 56 } 57 Printer.Unindent(); 58 } 59 60 Printer << " {"; 61 auto Children = Class.findAllChildren(); 62 if (Children->getChildCount() == 0) { 63 Printer << "}"; 64 return; 65 } 66 67 // Try to dump symbols organized by member access level. Public members 68 // first, then protected, then private. This might be slow, so it's worth 69 // reconsidering the value of this if performance of large PDBs is a problem. 70 // NOTE: Access level of nested types is not recorded in the PDB, so we have 71 // a special case for them. 72 SymbolGroupByAccess Groups; 73 Groups.insert(std::make_pair(0, SymbolGroup())); 74 Groups.insert(std::make_pair((int)PDB_MemberAccess::Private, SymbolGroup())); 75 Groups.insert( 76 std::make_pair((int)PDB_MemberAccess::Protected, SymbolGroup())); 77 Groups.insert(std::make_pair((int)PDB_MemberAccess::Public, SymbolGroup())); 78 79 while (auto Child = Children->getNext()) { 80 PDB_MemberAccess Access = Child->getRawSymbol().getAccess(); 81 if (isa<PDBSymbolTypeBaseClass>(*Child)) 82 continue; 83 84 auto &AccessGroup = Groups.find((int)Access)->second; 85 86 if (auto Func = dyn_cast<PDBSymbolFunc>(Child.get())) { 87 if (Func->isCompilerGenerated() && opts::ExcludeCompilerGenerated) 88 continue; 89 if (Func->getLength() == 0 && !Func->isPureVirtual() && 90 !Func->isIntroVirtualFunction()) 91 continue; 92 Child.release(); 93 AccessGroup.Functions.push_back(std::unique_ptr<PDBSymbolFunc>(Func)); 94 } else if (auto Data = dyn_cast<PDBSymbolData>(Child.get())) { 95 Child.release(); 96 AccessGroup.Data.push_back(std::unique_ptr<PDBSymbolData>(Data)); 97 } else { 98 AccessGroup.Unknown.push_back(std::move(Child)); 99 } 100 } 101 102 int Count = 0; 103 Count += dumpAccessGroup((PDB_MemberAccess)0, Groups[0]); 104 Count += dumpAccessGroup(PDB_MemberAccess::Public, 105 Groups[(int)PDB_MemberAccess::Public]); 106 Count += dumpAccessGroup(PDB_MemberAccess::Protected, 107 Groups[(int)PDB_MemberAccess::Protected]); 108 Count += dumpAccessGroup(PDB_MemberAccess::Private, 109 Groups[(int)PDB_MemberAccess::Private]); 110 if (Count > 0) 111 Printer.NewLine(); 112 Printer << "}"; 113} 114 115int ClassDefinitionDumper::dumpAccessGroup(PDB_MemberAccess Access, 116 const SymbolGroup &Group) { 117 if (Group.Functions.empty() && Group.Data.empty() && Group.Unknown.empty()) 118 return 0; 119 120 int Count = 0; 121 if (Access == PDB_MemberAccess::Private) { 122 Printer.NewLine(); 123 WithColor(Printer, PDB_ColorItem::Keyword).get() << "private"; 124 Printer << ":"; 125 } else if (Access == PDB_MemberAccess::Protected) { 126 Printer.NewLine(); 127 WithColor(Printer, PDB_ColorItem::Keyword).get() << "protected"; 128 Printer << ":"; 129 } else if (Access == PDB_MemberAccess::Public) { 130 Printer.NewLine(); 131 WithColor(Printer, PDB_ColorItem::Keyword).get() << "public"; 132 Printer << ":"; 133 } 134 Printer.Indent(); 135 for (auto iter = Group.Functions.begin(), end = Group.Functions.end(); 136 iter != end; ++iter) { 137 ++Count; 138 (*iter)->dump(*this); 139 } 140 for (auto iter = Group.Data.begin(), end = Group.Data.end(); iter != end; 141 ++iter) { 142 ++Count; 143 (*iter)->dump(*this); 144 } 145 for (auto iter = Group.Unknown.begin(), end = Group.Unknown.end(); 146 iter != end; ++iter) { 147 ++Count; 148 (*iter)->dump(*this); 149 } 150 Printer.Unindent(); 151 return Count; 152} 153 154void ClassDefinitionDumper::dump(const PDBSymbolTypeBaseClass &Symbol) {} 155 156void ClassDefinitionDumper::dump(const PDBSymbolData &Symbol) { 157 VariableDumper Dumper(Printer); 158 Dumper.start(Symbol); 159} 160 161void ClassDefinitionDumper::dump(const PDBSymbolFunc &Symbol) { 162 if (Printer.IsSymbolExcluded(Symbol.getName())) 163 return; 164 165 Printer.NewLine(); 166 FunctionDumper Dumper(Printer); 167 Dumper.start(Symbol, FunctionDumper::PointerType::None); 168} 169 170void ClassDefinitionDumper::dump(const PDBSymbolTypeVTable &Symbol) {} 171 172void ClassDefinitionDumper::dump(const PDBSymbolTypeEnum &Symbol) { 173 if (Printer.IsTypeExcluded(Symbol.getName())) 174 return; 175 176 Printer.NewLine(); 177 EnumDumper Dumper(Printer); 178 Dumper.start(Symbol); 179} 180 181void ClassDefinitionDumper::dump(const PDBSymbolTypeTypedef &Symbol) { 182 if (Printer.IsTypeExcluded(Symbol.getName())) 183 return; 184 185 Printer.NewLine(); 186 TypedefDumper Dumper(Printer); 187 Dumper.start(Symbol); 188} 189 190void ClassDefinitionDumper::dump(const PDBSymbolTypeUDT &Symbol) {} 191