ClassDefinitionDumper.cpp 6.3 KB

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