blob: a522935e34f14331804f32468545b858bf4254f2 [file] [log] [blame]
Zachary Turner9e7dda32017-04-12 23:18:51 +00001//===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Zachary Turner9e7dda32017-04-12 23:18:51 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "PrettyClassLayoutGraphicalDumper.h"
10
Zachary Turner4dc4f012017-04-13 21:11:00 +000011#include "LinePrinter.h"
12#include "PrettyClassDefinitionDumper.h"
Zachary Turnerda949c12017-04-24 17:47:52 +000013#include "PrettyEnumDumper.h"
14#include "PrettyFunctionDumper.h"
15#include "PrettyTypedefDumper.h"
Zachary Turner4dc4f012017-04-13 21:11:00 +000016#include "PrettyVariableDumper.h"
Zachary Turnerda949c12017-04-24 17:47:52 +000017#include "PrettyVariableDumper.h"
Zachary Turnerbd336e42017-06-09 20:46:17 +000018#include "llvm-pdbutil.h"
Zachary Turner4dc4f012017-04-13 21:11:00 +000019
20#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
21#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
22#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
23#include "llvm/DebugInfo/PDB/UDTLayout.h"
24#include "llvm/Support/Format.h"
25
Zachary Turner9e7dda32017-04-12 23:18:51 +000026using namespace llvm;
27using namespace llvm::pdb;
28
29PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper(
Zachary Turnerda949c12017-04-24 17:47:52 +000030 LinePrinter &P, uint32_t RecurseLevel, uint32_t InitialOffset)
31 : PDBSymDumper(true), Printer(P), RecursionLevel(RecurseLevel),
32 ClassOffsetZero(InitialOffset), CurrentAbsoluteOffset(InitialOffset) {}
Zachary Turner9e7dda32017-04-12 23:18:51 +000033
Zachary Turner4dc4f012017-04-13 21:11:00 +000034bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) {
Zachary Turnerda949c12017-04-24 17:47:52 +000035
36 if (RecursionLevel == 1 &&
37 opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::All) {
38 for (auto &Other : Layout.other_items())
39 Other->dump(*this);
40 for (auto &Func : Layout.funcs())
41 Func->dump(*this);
42 }
43
Zachary Turner4dc4f012017-04-13 21:11:00 +000044 const BitVector &UseMap = Layout.usedBytes();
45 int NextPaddingByte = UseMap.find_first_unset();
46
47 for (auto &Item : Layout.layout_items()) {
48 // Calculate the absolute offset of the first byte of the next field.
49 uint32_t RelativeOffset = Item->getOffsetInParent();
50 CurrentAbsoluteOffset = ClassOffsetZero + RelativeOffset;
51
Adrian McCarthy978aae42018-04-16 17:01:18 +000052 // This might be an empty base, in which case it could extend outside the
53 // bounds of the parent class.
Zachary Turner4dc4f012017-04-13 21:11:00 +000054 if (RelativeOffset < UseMap.size() && (Item->getSize() > 0)) {
Zachary Turner4dc4f012017-04-13 21:11:00 +000055 // If there is any remaining padding in this class, and the offset of the
56 // new item is after the padding, then we must have just jumped over some
57 // padding. Print a padding row and then look for where the next block
58 // of padding begins.
59 if ((NextPaddingByte >= 0) &&
60 (RelativeOffset > uint32_t(NextPaddingByte))) {
61 printPaddingRow(RelativeOffset - NextPaddingByte);
62 NextPaddingByte = UseMap.find_next_unset(RelativeOffset);
63 }
64 }
65
Zachary Turner16901642017-04-24 17:47:24 +000066 CurrentItem = Item;
67 if (Item->isVBPtr()) {
68 VTableLayoutItem &Layout = static_cast<VTableLayoutItem &>(*CurrentItem);
69
70 VariableDumper VarDumper(Printer);
71 VarDumper.startVbptr(CurrentAbsoluteOffset, Layout.getSize());
72 } else {
73 if (auto Sym = Item->getSymbol())
74 Sym->dump(*this);
75 }
76
77 if (Item->getLayoutSize() > 0) {
78 uint32_t Prev = RelativeOffset + Item->getLayoutSize() - 1;
Zachary Turnerf5cdd402017-05-26 00:15:15 +000079 if (Prev < UseMap.size())
80 NextPaddingByte = UseMap.find_next_unset(Prev);
Zachary Turner16901642017-04-24 17:47:24 +000081 }
Zachary Turner4dc4f012017-04-13 21:11:00 +000082 }
83
Zachary Turner16901642017-04-24 17:47:24 +000084 auto TailPadding = Layout.tailPadding();
85 if (TailPadding > 0) {
Zachary Turnerda949c12017-04-24 17:47:52 +000086 if (TailPadding != 1 || Layout.getSize() != 1) {
87 Printer.NewLine();
88 WithColor(Printer, PDB_ColorItem::Padding).get()
89 << "<padding> (" << TailPadding << " bytes)";
90 DumpedAnything = true;
91 }
Zachary Turner4dc4f012017-04-13 21:11:00 +000092 }
93
94 return DumpedAnything;
95}
96
97void PrettyClassLayoutGraphicalDumper::printPaddingRow(uint32_t Amount) {
98 if (Amount == 0)
99 return;
100
101 Printer.NewLine();
102 WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
103 << " bytes)";
104 DumpedAnything = true;
Zachary Turner9e7dda32017-04-12 23:18:51 +0000105}
106
107void PrettyClassLayoutGraphicalDumper::dump(
Zachary Turner4dc4f012017-04-13 21:11:00 +0000108 const PDBSymbolTypeBaseClass &Symbol) {
109 assert(CurrentItem != nullptr);
Zachary Turner9e7dda32017-04-12 23:18:51 +0000110
Zachary Turner4dc4f012017-04-13 21:11:00 +0000111 Printer.NewLine();
112 BaseClassLayout &Layout = static_cast<BaseClassLayout &>(*CurrentItem);
Zachary Turner9e7dda32017-04-12 23:18:51 +0000113
Zachary Turner16901642017-04-24 17:47:24 +0000114 std::string Label = "base";
115 if (Layout.isVirtualBase()) {
116 Label.insert(Label.begin(), 'v');
117 if (Layout.getBase().isIndirectVirtualBaseClass())
118 Label.insert(Label.begin(), 'i');
119 }
Zachary Turner4dc4f012017-04-13 21:11:00 +0000120 Printer << Label << " ";
Zachary Turner9e7dda32017-04-12 23:18:51 +0000121
Zachary Turner16901642017-04-24 17:47:24 +0000122 uint32_t Size = Layout.isEmptyBase() ? 1 : Layout.getLayoutSize();
123
Zachary Turner4dc4f012017-04-13 21:11:00 +0000124 WithColor(Printer, PDB_ColorItem::Offset).get()
Zachary Turner16901642017-04-24 17:47:24 +0000125 << "+" << format_hex(CurrentAbsoluteOffset, 4) << " [sizeof=" << Size
126 << "] ";
Zachary Turner9e7dda32017-04-12 23:18:51 +0000127
Zachary Turner4dc4f012017-04-13 21:11:00 +0000128 WithColor(Printer, PDB_ColorItem::Identifier).get() << Layout.getName();
Zachary Turner9e7dda32017-04-12 23:18:51 +0000129
Zachary Turnerda949c12017-04-24 17:47:52 +0000130 if (shouldRecurse()) {
131 Printer.Indent();
132 uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
133 PrettyClassLayoutGraphicalDumper BaseDumper(Printer, RecursionLevel + 1,
134 ChildOffsetZero);
135 DumpedAnything |= BaseDumper.start(Layout);
136 Printer.Unindent();
137 }
Zachary Turner4dc4f012017-04-13 21:11:00 +0000138
139 DumpedAnything = true;
140}
141
Zachary Turnerda949c12017-04-24 17:47:52 +0000142bool PrettyClassLayoutGraphicalDumper::shouldRecurse() const {
143 uint32_t Limit = opts::pretty::ClassRecursionDepth;
144 if (Limit == 0)
145 return true;
146 return RecursionLevel < Limit;
147}
148
Zachary Turner4dc4f012017-04-13 21:11:00 +0000149void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {
Zachary Turner4dc4f012017-04-13 21:11:00 +0000150 VariableDumper VarDumper(Printer);
151 VarDumper.start(Symbol, ClassOffsetZero);
152
Zachary Turnerd334ceb2017-06-12 20:46:35 +0000153 if (CurrentItem != nullptr) {
154 DataMemberLayoutItem &Layout =
155 static_cast<DataMemberLayoutItem &>(*CurrentItem);
156
157 if (Layout.hasUDTLayout() && shouldRecurse()) {
158 uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
159 Printer.Indent();
160 PrettyClassLayoutGraphicalDumper TypeDumper(Printer, RecursionLevel + 1,
161 ChildOffsetZero);
162 TypeDumper.start(Layout.getUDTLayout());
163 Printer.Unindent();
164 }
Zachary Turner4dc4f012017-04-13 21:11:00 +0000165 }
166
167 DumpedAnything = true;
168}
Zachary Turner9e7dda32017-04-12 23:18:51 +0000169
170void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) {
Zachary Turner4dc4f012017-04-13 21:11:00 +0000171 assert(CurrentItem != nullptr);
172
Zachary Turner4dc4f012017-04-13 21:11:00 +0000173 VariableDumper VarDumper(Printer);
174 VarDumper.start(Symbol, ClassOffsetZero);
175
Zachary Turner4dc4f012017-04-13 21:11:00 +0000176 DumpedAnything = true;
Zachary Turner9e7dda32017-04-12 23:18:51 +0000177}
Zachary Turnerda949c12017-04-24 17:47:52 +0000178
179void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeEnum &Symbol) {
180 DumpedAnything = true;
181 Printer.NewLine();
182 EnumDumper Dumper(Printer);
183 Dumper.start(Symbol);
184}
185
186void PrettyClassLayoutGraphicalDumper::dump(
187 const PDBSymbolTypeTypedef &Symbol) {
188 DumpedAnything = true;
189 Printer.NewLine();
190 TypedefDumper Dumper(Printer);
191 Dumper.start(Symbol);
192}
193
194void PrettyClassLayoutGraphicalDumper::dump(
195 const PDBSymbolTypeBuiltin &Symbol) {}
196
197void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeUDT &Symbol) {}
198
199void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolFunc &Symbol) {
200 if (Printer.IsSymbolExcluded(Symbol.getName()))
201 return;
202 if (Symbol.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
203 return;
204 if (Symbol.getLength() == 0 && !Symbol.isPureVirtual() &&
205 !Symbol.isIntroVirtualFunction())
206 return;
207
208 DumpedAnything = true;
209 Printer.NewLine();
210 FunctionDumper Dumper(Printer);
211 Dumper.start(Symbol, FunctionDumper::PointerType::None);
212}