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