brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.4 KiB · 9547d4e Raw
362 lines · cpp
1//===- PrettyTypeDumper.cpp - PDBSymDumper type dumper *------------ 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 "PrettyTypeDumper.h"10 11#include "PrettyBuiltinDumper.h"12#include "PrettyClassDefinitionDumper.h"13#include "PrettyEnumDumper.h"14#include "PrettyFunctionDumper.h"15#include "PrettyTypedefDumper.h"16#include "llvm-pdbutil.h"17 18#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"19#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"20#include "llvm/DebugInfo/PDB/IPDBSession.h"21#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"22#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"23#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"24#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"25#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"26#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"27#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"28#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"29#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"30#include "llvm/DebugInfo/PDB/UDTLayout.h"31#include "llvm/Support/Compiler.h"32#include "llvm/Support/FormatVariadic.h"33 34using namespace llvm;35using namespace llvm::pdb;36 37using LayoutPtr = std::unique_ptr<ClassLayout>;38 39typedef bool (*CompareFunc)(const LayoutPtr &S1, const LayoutPtr &S2);40 41static bool CompareNames(const LayoutPtr &S1, const LayoutPtr &S2) {42  return S1->getName() < S2->getName();43}44 45static bool CompareSizes(const LayoutPtr &S1, const LayoutPtr &S2) {46  return S1->getSize() < S2->getSize();47}48 49static bool ComparePadding(const LayoutPtr &S1, const LayoutPtr &S2) {50  return S1->deepPaddingSize() < S2->deepPaddingSize();51}52 53static bool ComparePaddingPct(const LayoutPtr &S1, const LayoutPtr &S2) {54  double Pct1 = (double)S1->deepPaddingSize() / (double)S1->getSize();55  double Pct2 = (double)S2->deepPaddingSize() / (double)S2->getSize();56  return Pct1 < Pct2;57}58 59static bool ComparePaddingImmediate(const LayoutPtr &S1, const LayoutPtr &S2) {60  return S1->immediatePadding() < S2->immediatePadding();61}62 63static bool ComparePaddingPctImmediate(const LayoutPtr &S1,64                                       const LayoutPtr &S2) {65  double Pct1 = (double)S1->immediatePadding() / (double)S1->getSize();66  double Pct2 = (double)S2->immediatePadding() / (double)S2->getSize();67  return Pct1 < Pct2;68}69 70static CompareFunc getComparisonFunc(opts::pretty::ClassSortMode Mode) {71  switch (Mode) {72  case opts::pretty::ClassSortMode::Name:73    return CompareNames;74  case opts::pretty::ClassSortMode::Size:75    return CompareSizes;76  case opts::pretty::ClassSortMode::Padding:77    return ComparePadding;78  case opts::pretty::ClassSortMode::PaddingPct:79    return ComparePaddingPct;80  case opts::pretty::ClassSortMode::PaddingImmediate:81    return ComparePaddingImmediate;82  case opts::pretty::ClassSortMode::PaddingPctImmediate:83    return ComparePaddingPctImmediate;84  default:85    return nullptr;86  }87}88 89template <typename Enumerator>90static std::vector<std::unique_ptr<ClassLayout>>91filterAndSortClassDefs(LinePrinter &Printer, Enumerator &E,92                       uint32_t UnfilteredCount) {93  std::vector<std::unique_ptr<ClassLayout>> Filtered;94 95  Filtered.reserve(UnfilteredCount);96  CompareFunc Comp = getComparisonFunc(opts::pretty::ClassOrder);97 98  if (UnfilteredCount > 10000) {99    errs() << formatv("Filtering and sorting {0} types", UnfilteredCount);100    errs().flush();101  }102  uint32_t Examined = 0;103  uint32_t Discarded = 0;104  while (auto Class = E.getNext()) {105    ++Examined;106    if (Examined % 10000 == 0) {107      errs() << formatv("Examined {0}/{1} items.  {2} items discarded\n",108                        Examined, UnfilteredCount, Discarded);109      errs().flush();110    }111 112    if (Class->getUnmodifiedTypeId() != 0) {113      ++Discarded;114      continue;115    }116 117    if (Printer.IsTypeExcluded(Class->getName(), Class->getLength())) {118      ++Discarded;119      continue;120    }121 122    auto Layout = std::make_unique<ClassLayout>(std::move(Class));123    if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold) {124      ++Discarded;125      continue;126    }127    if (Layout->immediatePadding() < opts::pretty::ImmediatePaddingThreshold) {128      ++Discarded;129      continue;130    }131 132    Filtered.push_back(std::move(Layout));133  }134 135  if (Comp)136    llvm::sort(Filtered, Comp);137  return Filtered;138}139 140TypeDumper::TypeDumper(LinePrinter &P) : PDBSymDumper(true), Printer(P) {}141 142template <typename T>143static bool isTypeExcluded(LinePrinter &Printer, const T &Symbol) {144  return false;145}146 147static bool isTypeExcluded(LinePrinter &Printer,148                           const PDBSymbolTypeEnum &Enum) {149  if (Printer.IsTypeExcluded(Enum.getName(), Enum.getLength()))150    return true;151  // Dump member enums when dumping their class definition.152  if (nullptr != Enum.getClassParent())153    return true;154  return false;155}156 157static bool isTypeExcluded(LinePrinter &Printer,158                           const PDBSymbolTypeTypedef &Typedef) {159  return Printer.IsTypeExcluded(Typedef.getName(), Typedef.getLength());160}161 162template <typename SymbolT>163static void dumpSymbolCategory(LinePrinter &Printer, const PDBSymbolExe &Exe,164                               TypeDumper &TD, StringRef Label) {165  if (auto Children = Exe.findAllChildren<SymbolT>()) {166    Printer.NewLine();167    WithColor(Printer, PDB_ColorItem::Identifier).get() << Label;168    Printer << ": (" << Children->getChildCount() << " items)";169    Printer.Indent();170    while (auto Child = Children->getNext()) {171      if (isTypeExcluded(Printer, *Child))172        continue;173 174      Printer.NewLine();175      Child->dump(TD);176    }177    Printer.Unindent();178  }179}180 181static void printClassDecl(LinePrinter &Printer,182                           const PDBSymbolTypeUDT &Class) {183  if (Class.getUnmodifiedTypeId() != 0) {184    if (Class.isConstType())185      WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";186    if (Class.isVolatileType())187      WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";188    if (Class.isUnalignedType())189      WithColor(Printer, PDB_ColorItem::Keyword).get() << "unaligned ";190  }191  WithColor(Printer, PDB_ColorItem::Keyword).get() << Class.getUdtKind() << " ";192  WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();193}194 195void TypeDumper::start(const PDBSymbolExe &Exe) {196  if (opts::pretty::Enums)197    dumpSymbolCategory<PDBSymbolTypeEnum>(Printer, Exe, *this, "Enums");198 199  if (opts::pretty::Funcsigs)200    dumpSymbolCategory<PDBSymbolTypeFunctionSig>(Printer, Exe, *this,201                                                 "Function Signatures");202 203  if (opts::pretty::Typedefs)204    dumpSymbolCategory<PDBSymbolTypeTypedef>(Printer, Exe, *this, "Typedefs");205 206  if (opts::pretty::Arrays)207    dumpSymbolCategory<PDBSymbolTypeArray>(Printer, Exe, *this, "Arrays");208 209  if (opts::pretty::Pointers)210    dumpSymbolCategory<PDBSymbolTypePointer>(Printer, Exe, *this, "Pointers");211 212  if (opts::pretty::VTShapes)213    dumpSymbolCategory<PDBSymbolTypeVTableShape>(Printer, Exe, *this,214                                                 "VFTable Shapes");215 216  if (opts::pretty::Classes) {217    if (auto Classes = Exe.findAllChildren<PDBSymbolTypeUDT>()) {218      uint32_t All = Classes->getChildCount();219 220      Printer.NewLine();221      WithColor(Printer, PDB_ColorItem::Identifier).get() << "Classes";222 223      bool Precompute = false;224      Precompute =225          (opts::pretty::ClassOrder != opts::pretty::ClassSortMode::None);226 227      // If we're using no sort mode, then we can start getting immediate output228      // from the tool by just filtering as we go, rather than processing229      // everything up front so that we can sort it.  This makes the tool more230      // responsive.  So only precompute the filtered/sorted set of classes if231      // necessary due to the specified options.232      std::vector<LayoutPtr> Filtered;233      uint32_t Shown = All;234      if (Precompute) {235        Filtered = filterAndSortClassDefs(Printer, *Classes, All);236 237        Shown = Filtered.size();238      }239 240      Printer << ": (Showing " << Shown << " items";241      if (Shown < All)242        Printer << ", " << (All - Shown) << " filtered";243      Printer << ")";244      Printer.Indent();245 246      // If we pre-computed, iterate the filtered/sorted list, otherwise iterate247      // the DIA enumerator and filter on the fly.248      if (Precompute) {249        for (auto &Class : Filtered)250          dumpClassLayout(*Class);251      } else {252        while (auto Class = Classes->getNext()) {253          if (Printer.IsTypeExcluded(Class->getName(), Class->getLength()))254            continue;255 256          // No point duplicating a full class layout.  Just print the modified257          // declaration and continue.258          if (Class->getUnmodifiedTypeId() != 0) {259            Printer.NewLine();260            printClassDecl(Printer, *Class);261            continue;262          }263 264          auto Layout = std::make_unique<ClassLayout>(std::move(Class));265          if (Layout->deepPaddingSize() < opts::pretty::PaddingThreshold)266            continue;267 268          dumpClassLayout(*Layout);269        }270      }271 272      Printer.Unindent();273    }274  }275}276 277void TypeDumper::dump(const PDBSymbolTypeEnum &Symbol) {278  assert(opts::pretty::Enums);279 280  EnumDumper Dumper(Printer);281  Dumper.start(Symbol);282}283 284void TypeDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {285  BuiltinDumper BD(Printer);286  BD.start(Symbol);287}288 289void TypeDumper::dump(const PDBSymbolTypeUDT &Symbol) {290  printClassDecl(Printer, Symbol);291}292 293void TypeDumper::dump(const PDBSymbolTypeTypedef &Symbol) {294  assert(opts::pretty::Typedefs);295 296  TypedefDumper Dumper(Printer);297  Dumper.start(Symbol);298}299 300void TypeDumper::dump(const PDBSymbolTypeArray &Symbol) {301  auto ElementType = Symbol.getElementType();302 303  ElementType->dump(*this);304  Printer << "[";305  WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getCount();306  Printer << "]";307}308 309void TypeDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {310  FunctionDumper Dumper(Printer);311  Dumper.start(Symbol, nullptr, FunctionDumper::PointerType::None);312}313 314void TypeDumper::dump(const PDBSymbolTypePointer &Symbol) {315  std::unique_ptr<PDBSymbol> P = Symbol.getPointeeType();316 317  if (auto *FS = dyn_cast<PDBSymbolTypeFunctionSig>(P.get())) {318    FunctionDumper Dumper(Printer);319    FunctionDumper::PointerType PT =320        Symbol.isReference() ? FunctionDumper::PointerType::Reference321                             : FunctionDumper::PointerType::Pointer;322    Dumper.start(*FS, nullptr, PT);323    return;324  }325 326  if (auto *UDT = dyn_cast<PDBSymbolTypeUDT>(P.get())) {327    printClassDecl(Printer, *UDT);328  } else if (P) {329    P->dump(*this);330  }331 332  if (auto Parent = Symbol.getClassParent()) {333    auto UDT = llvm::unique_dyn_cast<PDBSymbolTypeUDT>(std::move(Parent));334    if (UDT)335      Printer << " " << UDT->getName() << "::";336  }337 338  if (Symbol.isReference())339    Printer << "&";340  else if (Symbol.isRValueReference())341    Printer << "&&";342  else343    Printer << "*";344}345 346void TypeDumper::dump(const PDBSymbolTypeVTableShape &Symbol) {347  Printer.format("<vtshape ({0} methods)>", Symbol.getCount());348}349 350void TypeDumper::dumpClassLayout(const ClassLayout &Class) {351  assert(opts::pretty::Classes);352 353  if (opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::None) {354    WithColor(Printer, PDB_ColorItem::Keyword).get()355        << Class.getClass().getUdtKind() << " ";356    WithColor(Printer, PDB_ColorItem::Type).get() << Class.getName();357  } else {358    ClassDefinitionDumper Dumper(Printer);359    Dumper.start(Class);360  }361}362