Path: blob/main/contrib/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp
35259 views
//===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "PrettyClassLayoutGraphicalDumper.h"910#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"1718#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"2526using namespace llvm;27using namespace llvm::pdb;2829PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper(30LinePrinter &P, uint32_t RecurseLevel, uint32_t InitialOffset)31: PDBSymDumper(true), Printer(P), RecursionLevel(RecurseLevel),32ClassOffsetZero(InitialOffset), CurrentAbsoluteOffset(InitialOffset) {}3334bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) {3536if (RecursionLevel == 1 &&37opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::All) {38for (const auto &Other : Layout.other_items())39Other->dump(*this);40for (const auto &Func : Layout.funcs())41Func->dump(*this);42}4344const BitVector &UseMap = Layout.usedBytes();45int NextPaddingByte = UseMap.find_first_unset();4647for (const auto &Item : Layout.layout_items()) {48// Calculate the absolute offset of the first byte of the next field.49uint32_t RelativeOffset = Item->getOffsetInParent();50CurrentAbsoluteOffset = ClassOffsetZero + RelativeOffset;5152// This might be an empty base, in which case it could extend outside the53// bounds of the parent class.54if (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.59if ((NextPaddingByte >= 0) &&60(RelativeOffset > uint32_t(NextPaddingByte))) {61printPaddingRow(RelativeOffset - NextPaddingByte);62NextPaddingByte = UseMap.find_next_unset(RelativeOffset);63}64}6566CurrentItem = Item;67if (Item->isVBPtr()) {68VTableLayoutItem &Layout = static_cast<VTableLayoutItem &>(*CurrentItem);6970VariableDumper VarDumper(Printer);71VarDumper.startVbptr(CurrentAbsoluteOffset, Layout.getSize());72} else {73if (auto Sym = Item->getSymbol())74Sym->dump(*this);75}7677if (Item->getLayoutSize() > 0) {78uint32_t Prev = RelativeOffset + Item->getLayoutSize() - 1;79if (Prev < UseMap.size())80NextPaddingByte = UseMap.find_next_unset(Prev);81}82}8384auto TailPadding = Layout.tailPadding();85if (TailPadding > 0) {86if (TailPadding != 1 || Layout.getSize() != 1) {87Printer.NewLine();88WithColor(Printer, PDB_ColorItem::Padding).get()89<< "<padding> (" << TailPadding << " bytes)";90DumpedAnything = true;91}92}9394return DumpedAnything;95}9697void PrettyClassLayoutGraphicalDumper::printPaddingRow(uint32_t Amount) {98if (Amount == 0)99return;100101Printer.NewLine();102WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount103<< " bytes)";104DumpedAnything = true;105}106107void PrettyClassLayoutGraphicalDumper::dump(108const PDBSymbolTypeBaseClass &Symbol) {109assert(CurrentItem != nullptr);110111Printer.NewLine();112BaseClassLayout &Layout = static_cast<BaseClassLayout &>(*CurrentItem);113114std::string Label = "base";115if (Layout.isVirtualBase()) {116Label.insert(Label.begin(), 'v');117if (Layout.getBase().isIndirectVirtualBaseClass())118Label.insert(Label.begin(), 'i');119}120Printer << Label << " ";121122uint32_t Size = Layout.isEmptyBase() ? 1 : Layout.getLayoutSize();123124WithColor(Printer, PDB_ColorItem::Offset).get()125<< "+" << format_hex(CurrentAbsoluteOffset, 4) << " [sizeof=" << Size126<< "] ";127128WithColor(Printer, PDB_ColorItem::Identifier).get() << Layout.getName();129130if (shouldRecurse()) {131Printer.Indent();132uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();133PrettyClassLayoutGraphicalDumper BaseDumper(Printer, RecursionLevel + 1,134ChildOffsetZero);135DumpedAnything |= BaseDumper.start(Layout);136Printer.Unindent();137}138139DumpedAnything = true;140}141142bool PrettyClassLayoutGraphicalDumper::shouldRecurse() const {143uint32_t Limit = opts::pretty::ClassRecursionDepth;144if (Limit == 0)145return true;146return RecursionLevel < Limit;147}148149void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {150VariableDumper VarDumper(Printer);151VarDumper.start(Symbol, ClassOffsetZero);152153if (CurrentItem != nullptr) {154DataMemberLayoutItem &Layout =155static_cast<DataMemberLayoutItem &>(*CurrentItem);156157if (Layout.hasUDTLayout() && shouldRecurse()) {158uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();159Printer.Indent();160PrettyClassLayoutGraphicalDumper TypeDumper(Printer, RecursionLevel + 1,161ChildOffsetZero);162TypeDumper.start(Layout.getUDTLayout());163Printer.Unindent();164}165}166167DumpedAnything = true;168}169170void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) {171assert(CurrentItem != nullptr);172173VariableDumper VarDumper(Printer);174VarDumper.start(Symbol, ClassOffsetZero);175176DumpedAnything = true;177}178179void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeEnum &Symbol) {180DumpedAnything = true;181Printer.NewLine();182EnumDumper Dumper(Printer);183Dumper.start(Symbol);184}185186void PrettyClassLayoutGraphicalDumper::dump(187const PDBSymbolTypeTypedef &Symbol) {188DumpedAnything = true;189Printer.NewLine();190TypedefDumper Dumper(Printer);191Dumper.start(Symbol);192}193194void PrettyClassLayoutGraphicalDumper::dump(195const PDBSymbolTypeBuiltin &Symbol) {}196197void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeUDT &Symbol) {}198199void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolFunc &Symbol) {200if (Printer.IsSymbolExcluded(Symbol.getName()))201return;202if (Symbol.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)203return;204if (Symbol.getLength() == 0 && !Symbol.isPureVirtual() &&205!Symbol.isIntroVirtualFunction())206return;207208DumpedAnything = true;209Printer.NewLine();210FunctionDumper Dumper(Printer);211Dumper.start(Symbol, FunctionDumper::PointerType::None);212}213214215