forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			213 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			213 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- PrettyClassLayoutGraphicalDumper.h -----------------------*- C++ -*-===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "PrettyClassLayoutGraphicalDumper.h"
 | |
| 
 | |
| #include "LinePrinter.h"
 | |
| #include "PrettyClassDefinitionDumper.h"
 | |
| #include "PrettyEnumDumper.h"
 | |
| #include "PrettyFunctionDumper.h"
 | |
| #include "PrettyTypedefDumper.h"
 | |
| #include "PrettyVariableDumper.h"
 | |
| #include "PrettyVariableDumper.h"
 | |
| #include "llvm-pdbutil.h"
 | |
| 
 | |
| #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
 | |
| #include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
 | |
| #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
 | |
| #include "llvm/DebugInfo/PDB/UDTLayout.h"
 | |
| #include "llvm/Support/Format.h"
 | |
| 
 | |
| using namespace llvm;
 | |
| using namespace llvm::pdb;
 | |
| 
 | |
| PrettyClassLayoutGraphicalDumper::PrettyClassLayoutGraphicalDumper(
 | |
|     LinePrinter &P, uint32_t RecurseLevel, uint32_t InitialOffset)
 | |
|     : PDBSymDumper(true), Printer(P), RecursionLevel(RecurseLevel),
 | |
|       ClassOffsetZero(InitialOffset), CurrentAbsoluteOffset(InitialOffset) {}
 | |
| 
 | |
| bool PrettyClassLayoutGraphicalDumper::start(const UDTLayoutBase &Layout) {
 | |
| 
 | |
|   if (RecursionLevel == 1 &&
 | |
|       opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::All) {
 | |
|     for (auto &Other : Layout.other_items())
 | |
|       Other->dump(*this);
 | |
|     for (auto &Func : Layout.funcs())
 | |
|       Func->dump(*this);
 | |
|   }
 | |
| 
 | |
|   const BitVector &UseMap = Layout.usedBytes();
 | |
|   int NextPaddingByte = UseMap.find_first_unset();
 | |
| 
 | |
|   for (auto &Item : Layout.layout_items()) {
 | |
|     // Calculate the absolute offset of the first byte of the next field.
 | |
|     uint32_t RelativeOffset = Item->getOffsetInParent();
 | |
|     CurrentAbsoluteOffset = ClassOffsetZero + RelativeOffset;
 | |
| 
 | |
|     // This might be an empty base, in which case it could extend outside the
 | |
|     // bounds of the parent class.
 | |
|     if (RelativeOffset < UseMap.size() && (Item->getSize() > 0)) {
 | |
|       // If there is any remaining padding in this class, and the offset of the
 | |
|       // new item is after the padding, then we must have just jumped over some
 | |
|       // padding.  Print a padding row and then look for where the next block
 | |
|       // of padding begins.
 | |
|       if ((NextPaddingByte >= 0) &&
 | |
|           (RelativeOffset > uint32_t(NextPaddingByte))) {
 | |
|         printPaddingRow(RelativeOffset - NextPaddingByte);
 | |
|         NextPaddingByte = UseMap.find_next_unset(RelativeOffset);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     CurrentItem = Item;
 | |
|     if (Item->isVBPtr()) {
 | |
|       VTableLayoutItem &Layout = static_cast<VTableLayoutItem &>(*CurrentItem);
 | |
| 
 | |
|       VariableDumper VarDumper(Printer);
 | |
|       VarDumper.startVbptr(CurrentAbsoluteOffset, Layout.getSize());
 | |
|     } else {
 | |
|       if (auto Sym = Item->getSymbol())
 | |
|         Sym->dump(*this);
 | |
|     }
 | |
| 
 | |
|     if (Item->getLayoutSize() > 0) {
 | |
|       uint32_t Prev = RelativeOffset + Item->getLayoutSize() - 1;
 | |
|       if (Prev < UseMap.size())
 | |
|         NextPaddingByte = UseMap.find_next_unset(Prev);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   auto TailPadding = Layout.tailPadding();
 | |
|   if (TailPadding > 0) {
 | |
|     if (TailPadding != 1 || Layout.getSize() != 1) {
 | |
|       Printer.NewLine();
 | |
|       WithColor(Printer, PDB_ColorItem::Padding).get()
 | |
|           << "<padding> (" << TailPadding << " bytes)";
 | |
|       DumpedAnything = true;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return DumpedAnything;
 | |
| }
 | |
| 
 | |
| void PrettyClassLayoutGraphicalDumper::printPaddingRow(uint32_t Amount) {
 | |
|   if (Amount == 0)
 | |
|     return;
 | |
| 
 | |
|   Printer.NewLine();
 | |
|   WithColor(Printer, PDB_ColorItem::Padding).get() << "<padding> (" << Amount
 | |
|                                                    << " bytes)";
 | |
|   DumpedAnything = true;
 | |
| }
 | |
| 
 | |
| void PrettyClassLayoutGraphicalDumper::dump(
 | |
|     const PDBSymbolTypeBaseClass &Symbol) {
 | |
|   assert(CurrentItem != nullptr);
 | |
| 
 | |
|   Printer.NewLine();
 | |
|   BaseClassLayout &Layout = static_cast<BaseClassLayout &>(*CurrentItem);
 | |
| 
 | |
|   std::string Label = "base";
 | |
|   if (Layout.isVirtualBase()) {
 | |
|     Label.insert(Label.begin(), 'v');
 | |
|     if (Layout.getBase().isIndirectVirtualBaseClass())
 | |
|       Label.insert(Label.begin(), 'i');
 | |
|   }
 | |
|   Printer << Label << " ";
 | |
| 
 | |
|   uint32_t Size = Layout.isEmptyBase() ? 1 : Layout.getLayoutSize();
 | |
| 
 | |
|   WithColor(Printer, PDB_ColorItem::Offset).get()
 | |
|       << "+" << format_hex(CurrentAbsoluteOffset, 4) << " [sizeof=" << Size
 | |
|       << "] ";
 | |
| 
 | |
|   WithColor(Printer, PDB_ColorItem::Identifier).get() << Layout.getName();
 | |
| 
 | |
|   if (shouldRecurse()) {
 | |
|     Printer.Indent();
 | |
|     uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
 | |
|     PrettyClassLayoutGraphicalDumper BaseDumper(Printer, RecursionLevel + 1,
 | |
|                                                 ChildOffsetZero);
 | |
|     DumpedAnything |= BaseDumper.start(Layout);
 | |
|     Printer.Unindent();
 | |
|   }
 | |
| 
 | |
|   DumpedAnything = true;
 | |
| }
 | |
| 
 | |
| bool PrettyClassLayoutGraphicalDumper::shouldRecurse() const {
 | |
|   uint32_t Limit = opts::pretty::ClassRecursionDepth;
 | |
|   if (Limit == 0)
 | |
|     return true;
 | |
|   return RecursionLevel < Limit;
 | |
| }
 | |
| 
 | |
| void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {
 | |
|   VariableDumper VarDumper(Printer);
 | |
|   VarDumper.start(Symbol, ClassOffsetZero);
 | |
| 
 | |
|   if (CurrentItem != nullptr) {
 | |
|     DataMemberLayoutItem &Layout =
 | |
|         static_cast<DataMemberLayoutItem &>(*CurrentItem);
 | |
| 
 | |
|     if (Layout.hasUDTLayout() && shouldRecurse()) {
 | |
|       uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
 | |
|       Printer.Indent();
 | |
|       PrettyClassLayoutGraphicalDumper TypeDumper(Printer, RecursionLevel + 1,
 | |
|                                                   ChildOffsetZero);
 | |
|       TypeDumper.start(Layout.getUDTLayout());
 | |
|       Printer.Unindent();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   DumpedAnything = true;
 | |
| }
 | |
| 
 | |
| void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeVTable &Symbol) {
 | |
|   assert(CurrentItem != nullptr);
 | |
| 
 | |
|   VariableDumper VarDumper(Printer);
 | |
|   VarDumper.start(Symbol, ClassOffsetZero);
 | |
| 
 | |
|   DumpedAnything = true;
 | |
| }
 | |
| 
 | |
| void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeEnum &Symbol) {
 | |
|   DumpedAnything = true;
 | |
|   Printer.NewLine();
 | |
|   EnumDumper Dumper(Printer);
 | |
|   Dumper.start(Symbol);
 | |
| }
 | |
| 
 | |
| void PrettyClassLayoutGraphicalDumper::dump(
 | |
|     const PDBSymbolTypeTypedef &Symbol) {
 | |
|   DumpedAnything = true;
 | |
|   Printer.NewLine();
 | |
|   TypedefDumper Dumper(Printer);
 | |
|   Dumper.start(Symbol);
 | |
| }
 | |
| 
 | |
| void PrettyClassLayoutGraphicalDumper::dump(
 | |
|     const PDBSymbolTypeBuiltin &Symbol) {}
 | |
| 
 | |
| void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolTypeUDT &Symbol) {}
 | |
| 
 | |
| void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolFunc &Symbol) {
 | |
|   if (Printer.IsSymbolExcluded(Symbol.getName()))
 | |
|     return;
 | |
|   if (Symbol.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
 | |
|     return;
 | |
|   if (Symbol.getLength() == 0 && !Symbol.isPureVirtual() &&
 | |
|       !Symbol.isIntroVirtualFunction())
 | |
|     return;
 | |
| 
 | |
|   DumpedAnything = true;
 | |
|   Printer.NewLine();
 | |
|   FunctionDumper Dumper(Printer);
 | |
|   Dumper.start(Symbol, FunctionDumper::PointerType::None);
 | |
| }
 |