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