PrettyClassLayoutGraphicalDumper.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. //===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "PrettyClassLayoutGraphicalDumper.h"
  9. #include "PrettyClassDefinitionDumper.h"
  10. #include "PrettyEnumDumper.h"
  11. #include "PrettyFunctionDumper.h"
  12. #include "PrettyTypedefDumper.h"
  13. #include "PrettyVariableDumper.h"
  14. #include "PrettyVariableDumper.h"
  15. #include "llvm-pdbutil.h"
  16. #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
  17. #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
  18. #include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
  19. #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
  20. #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
  21. #include "llvm/DebugInfo/PDB/UDTLayout.h"
  22. #include "llvm/Support/Format.h"
  23. using namespace llvm;
  24. using namespace llvm::pdb;
  25. PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper(
  26. LinePrinter &P, uint32_t RecurseLevel, uint32_t InitialOffset)
  27. : PDBSymDumper(true), Printer(P), RecursionLevel(RecurseLevel),
  28. ClassOffsetZero(InitialOffset), CurrentAbsoluteOffset(InitialOffset) {}
  29. bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) {
  30. if (RecursionLevel == 1 &&
  31. opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::All) {
  32. for (const auto &Other : Layout.other_items())
  33. Other->dump(*this);
  34. for (const auto &Func : Layout.funcs())
  35. Func->dump(*this);
  36. }
  37. const BitVector &UseMap = Layout.usedBytes();
  38. int NextPaddingByte = UseMap.find_first_unset();
  39. for (const auto &Item : Layout.layout_items()) {
  40. // Calculate the absolute offset of the first byte of the next field.
  41. uint32_t RelativeOffset = Item->getOffsetInParent();
  42. CurrentAbsoluteOffset = ClassOffsetZero + RelativeOffset;
  43. // This might be an empty base, in which case it could extend outside the
  44. // bounds of the parent class.
  45. if (RelativeOffset < UseMap.size() && (Item->getSize() > 0)) {
  46. // If there is any remaining padding in this class, and the offset of the
  47. // new item is after the padding, then we must have just jumped over some
  48. // padding. Print a padding row and then look for where the next block
  49. // of padding begins.
  50. if ((NextPaddingByte >= 0) &&
  51. (RelativeOffset > uint32_t(NextPaddingByte))) {
  52. printPaddingRow(RelativeOffset - NextPaddingByte);
  53. NextPaddingByte = UseMap.find_next_unset(RelativeOffset);
  54. }
  55. }
  56. CurrentItem = Item;
  57. if (Item->isVBPtr()) {
  58. VTableLayoutItem &Layout = static_cast<VTableLayoutItem &>(*CurrentItem);
  59. VariableDumper VarDumper(Printer);
  60. VarDumper.startVbptr(CurrentAbsoluteOffset, Layout.getSize());
  61. } else {
  62. if (auto Sym = Item->getSymbol())
  63. Sym->dump(*this);
  64. }
  65. if (Item->getLayoutSize() > 0) {
  66. uint32_t Prev = RelativeOffset + Item->getLayoutSize() - 1;
  67. if (Prev < UseMap.size())
  68. NextPaddingByte = UseMap.find_next_unset(Prev);
  69. }
  70. }
  71. auto TailPadding = Layout.tailPadding();
  72. if (TailPadding > 0) {
  73. if (TailPadding != 1 || Layout.getSize() != 1) {
  74. Printer.NewLine();
  75. WithColor(Printer, PDB_ColorItem::Padding).get()
  76. << "<padding> (" << TailPadding << " bytes)";
  77. DumpedAnything = true;
  78. }
  79. }
  80. return DumpedAnything;
  81. }
  82. void PrettyClassLayoutGraphicalDumper::printPaddingRow(uint32_t Amount) {
  83. if (Amount == 0)
  84. return;
  85. Printer.NewLine();
  86. WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
  87. << " bytes)";
  88. DumpedAnything = true;
  89. }
  90. void PrettyClassLayoutGraphicalDumper::dump(
  91. const PDBSymbolTypeBaseClass &Symbol) {
  92. assert(CurrentItem != nullptr);
  93. Printer.NewLine();
  94. BaseClassLayout &Layout = static_cast<BaseClassLayout &>(*CurrentItem);
  95. std::string Label = "base";
  96. if (Layout.isVirtualBase()) {
  97. Label.insert(Label.begin(), 'v');
  98. if (Layout.getBase().isIndirectVirtualBaseClass())
  99. Label.insert(Label.begin(), 'i');
  100. }
  101. Printer << Label << " ";
  102. uint32_t Size = Layout.isEmptyBase() ? 1 : Layout.getLayoutSize();
  103. WithColor(Printer, PDB_ColorItem::Offset).get()
  104. << "+" << format_hex(CurrentAbsoluteOffset, 4) << " [sizeof=" << Size
  105. << "] ";
  106. WithColor(Printer, PDB_ColorItem::Identifier).get() << Layout.getName();
  107. if (shouldRecurse()) {
  108. Printer.Indent();
  109. uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
  110. PrettyClassLayoutGraphicalDumper BaseDumper(Printer, RecursionLevel + 1,
  111. ChildOffsetZero);
  112. DumpedAnything |= BaseDumper.start(Layout);
  113. Printer.Unindent();
  114. }
  115. DumpedAnything = true;
  116. }
  117. bool PrettyClassLayoutGraphicalDumper::shouldRecurse() const {
  118. uint32_t Limit = opts::pretty::ClassRecursionDepth;
  119. if (Limit == 0)
  120. return true;
  121. return RecursionLevel < Limit;
  122. }
  123. void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {
  124. VariableDumper VarDumper(Printer);
  125. VarDumper.start(Symbol, ClassOffsetZero);
  126. if (CurrentItem != nullptr) {
  127. DataMemberLayoutItem &Layout =
  128. static_cast<DataMemberLayoutItem &>(*CurrentItem);
  129. if (Layout.hasUDTLayout() && shouldRecurse()) {
  130. uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
  131. Printer.Indent();
  132. PrettyClassLayoutGraphicalDumper TypeDumper(Printer, RecursionLevel + 1,
  133. ChildOffsetZero);
  134. TypeDumper.start(Layout.getUDTLayout());
  135. Printer.Unindent();
  136. }
  137. }
  138. DumpedAnything = true;
  139. }
  140. void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) {
  141. assert(CurrentItem != nullptr);
  142. VariableDumper VarDumper(Printer);
  143. VarDumper.start(Symbol, ClassOffsetZero);
  144. DumpedAnything = true;
  145. }
  146. void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeEnum &Symbol) {
  147. DumpedAnything = true;
  148. Printer.NewLine();
  149. EnumDumper Dumper(Printer);
  150. Dumper.start(Symbol);
  151. }
  152. void PrettyClassLayoutGraphicalDumper::dump(
  153. const PDBSymbolTypeTypedef &Symbol) {
  154. DumpedAnything = true;
  155. Printer.NewLine();
  156. TypedefDumper Dumper(Printer);
  157. Dumper.start(Symbol);
  158. }
  159. void PrettyClassLayoutGraphicalDumper::dump(
  160. const PDBSymbolTypeBuiltin &Symbol) {}
  161. void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeUDT &Symbol) {}
  162. void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolFunc &Symbol) {
  163. if (Printer.IsSymbolExcluded(Symbol.getName()))
  164. return;
  165. if (Symbol.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
  166. return;
  167. if (Symbol.getLength() == 0 && !Symbol.isPureVirtual() &&
  168. !Symbol.isIntroVirtualFunction())
  169. return;
  170. DumpedAnything = true;
  171. Printer.NewLine();
  172. FunctionDumper Dumper(Printer);
  173. Dumper.start(Symbol, FunctionDumper::PointerType::None);
  174. }