PrettyClassLayoutGraphicalDumper.cpp 6.8 KB

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