213 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "PrettyClassLayoutGraphicalDumper.h"10 11#include "PrettyClassDefinitionDumper.h"12#include "PrettyEnumDumper.h"13#include "PrettyFunctionDumper.h"14#include "PrettyTypedefDumper.h"15#include "PrettyVariableDumper.h"16#include "llvm-pdbutil.h"17 18#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"19#include "llvm/DebugInfo/PDB/PDBSymbolData.h"20#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"21#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"22#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"23#include "llvm/DebugInfo/PDB/UDTLayout.h"24#include "llvm/Support/Format.h"25 26using namespace llvm;27using namespace llvm::pdb;28 29PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper(30 LinePrinter &P, uint32_t RecurseLevel, uint32_t InitialOffset)31 : PDBSymDumper(true), Printer(P), RecursionLevel(RecurseLevel),32 ClassOffsetZero(InitialOffset), CurrentAbsoluteOffset(InitialOffset) {}33 34bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) {35 36 if (RecursionLevel == 1 &&37 opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::All) {38 for (const auto &Other : Layout.other_items())39 Other->dump(*this);40 for (const auto &Func : Layout.funcs())41 Func->dump(*this);42 }43 44 const BitVector &UseMap = Layout.usedBytes();45 int NextPaddingByte = UseMap.find_first_unset();46 47 for (const 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 52 // This might be an empty base, in which case it could extend outside the53 // bounds of the parent class.54 if (RelativeOffset < UseMap.size() && (Item->getSize() > 0)) {55 // If there is any remaining padding in this class, and the offset of the56 // new item is after the padding, then we must have just jumped over some57 // padding. Print a padding row and then look for where the next block58 // 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 66 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;79 if (Prev < UseMap.size())80 NextPaddingByte = UseMap.find_next_unset(Prev);81 }82 }83 84 auto TailPadding = Layout.tailPadding();85 if (TailPadding > 0) {86 if (TailPadding != 1 || Layout.getSize() != 1) {87 Printer.NewLine();88 WithColor(Printer, PDB_ColorItem::Padding).get()89 << "<padding> (" << TailPadding << " bytes)";90 DumpedAnything = true;91 }92 }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> (" << Amount103 << " bytes)";104 DumpedAnything = true;105}106 107void PrettyClassLayoutGraphicalDumper::dump(108 const PDBSymbolTypeBaseClass &Symbol) {109 assert(CurrentItem != nullptr);110 111 Printer.NewLine();112 BaseClassLayout &Layout = static_cast<BaseClassLayout &>(*CurrentItem);113 114 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 }120 Printer << Label << " ";121 122 uint32_t Size = Layout.isEmptyBase() ? 1 : Layout.getLayoutSize();123 124 WithColor(Printer, PDB_ColorItem::Offset).get()125 << "+" << format_hex(CurrentAbsoluteOffset, 4) << " [sizeof=" << Size126 << "] ";127 128 WithColor(Printer, PDB_ColorItem::Identifier).get() << Layout.getName();129 130 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 }138 139 DumpedAnything = true;140}141 142bool PrettyClassLayoutGraphicalDumper::shouldRecurse() const {143 uint32_t Limit = opts::pretty::ClassRecursionDepth;144 if (Limit == 0)145 return true;146 return RecursionLevel < Limit;147}148 149void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {150 VariableDumper VarDumper(Printer);151 VarDumper.start(Symbol, ClassOffsetZero);152 153 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 }165 }166 167 DumpedAnything = true;168}169 170void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) {171 assert(CurrentItem != nullptr);172 173 VariableDumper VarDumper(Printer);174 VarDumper.start(Symbol, ClassOffsetZero);175 176 DumpedAnything = true;177}178 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}213