|  | //===- PrettyCompilandDumper.cpp - llvm-pdbutil compiland dumper -*- 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 "PrettyCompilandDumper.h" | 
|  |  | 
|  | #include "LinePrinter.h" | 
|  | #include "PrettyFunctionDumper.h" | 
|  | #include "llvm-pdbutil.h" | 
|  |  | 
|  | #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" | 
|  | #include "llvm/DebugInfo/PDB/IPDBLineNumber.h" | 
|  | #include "llvm/DebugInfo/PDB/IPDBSession.h" | 
|  | #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" | 
|  | #include "llvm/DebugInfo/PDB/PDBExtras.h" | 
|  | #include "llvm/DebugInfo/PDB/PDBSymbol.h" | 
|  | #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" | 
|  | #include "llvm/DebugInfo/PDB/PDBSymbolData.h" | 
|  | #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" | 
|  | #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" | 
|  | #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" | 
|  | #include "llvm/DebugInfo/PDB/PDBSymbolLabel.h" | 
|  | #include "llvm/DebugInfo/PDB/PDBSymbolThunk.h" | 
|  | #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" | 
|  | #include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h" | 
|  | #include "llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h" | 
|  | #include "llvm/Support/Format.h" | 
|  | #include "llvm/Support/Path.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  |  | 
|  | #include <utility> | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace llvm::pdb; | 
|  |  | 
|  | CompilandDumper::CompilandDumper(LinePrinter &P) | 
|  | : PDBSymDumper(true), Printer(P) {} | 
|  |  | 
|  | void CompilandDumper::dump(const PDBSymbolCompilandDetails &Symbol) {} | 
|  |  | 
|  | void CompilandDumper::dump(const PDBSymbolCompilandEnv &Symbol) {} | 
|  |  | 
|  | void CompilandDumper::start(const PDBSymbolCompiland &Symbol, | 
|  | CompilandDumpFlags opts) { | 
|  | std::string FullName = Symbol.getName(); | 
|  | if (Printer.IsCompilandExcluded(FullName)) | 
|  | return; | 
|  |  | 
|  | Printer.NewLine(); | 
|  | WithColor(Printer, PDB_ColorItem::Path).get() << FullName; | 
|  |  | 
|  | if (opts & Flags::Lines) { | 
|  | const IPDBSession &Session = Symbol.getSession(); | 
|  | if (auto Files = Session.getSourceFilesForCompiland(Symbol)) { | 
|  | Printer.Indent(); | 
|  | while (auto File = Files->getNext()) { | 
|  | Printer.NewLine(); | 
|  | WithColor(Printer, PDB_ColorItem::Path).get() << File->getFileName(); | 
|  | if (File->getChecksumType() != PDB_Checksum::None) { | 
|  | auto ChecksumType = File->getChecksumType(); | 
|  | auto ChecksumHexString = toHex(File->getChecksum()); | 
|  | WithColor(Printer, PDB_ColorItem::Comment).get() | 
|  | << " (" << ChecksumType << ": " << ChecksumHexString << ")"; | 
|  | } | 
|  |  | 
|  | auto Lines = Session.findLineNumbers(Symbol, *File); | 
|  | if (!Lines) | 
|  | continue; | 
|  |  | 
|  | Printer.Indent(); | 
|  | while (auto Line = Lines->getNext()) { | 
|  | Printer.NewLine(); | 
|  | uint32_t LineStart = Line->getLineNumber(); | 
|  | uint32_t LineEnd = Line->getLineNumberEnd(); | 
|  |  | 
|  | Printer << "Line "; | 
|  | PDB_ColorItem StatementColor = Line->isStatement() | 
|  | ? PDB_ColorItem::Keyword | 
|  | : PDB_ColorItem::LiteralValue; | 
|  | WithColor(Printer, StatementColor).get() << LineStart; | 
|  | if (LineStart != LineEnd) | 
|  | WithColor(Printer, StatementColor).get() << " - " << LineEnd; | 
|  |  | 
|  | uint32_t ColumnStart = Line->getColumnNumber(); | 
|  | uint32_t ColumnEnd = Line->getColumnNumberEnd(); | 
|  | if (ColumnStart != 0 || ColumnEnd != 0) { | 
|  | Printer << ", Column: "; | 
|  | WithColor(Printer, StatementColor).get() << ColumnStart; | 
|  | if (ColumnEnd != ColumnStart) | 
|  | WithColor(Printer, StatementColor).get() << " - " << ColumnEnd; | 
|  | } | 
|  |  | 
|  | Printer << ", Address: "; | 
|  | if (Line->getLength() > 0) { | 
|  | uint64_t AddrStart = Line->getVirtualAddress(); | 
|  | uint64_t AddrEnd = AddrStart + Line->getLength() - 1; | 
|  | WithColor(Printer, PDB_ColorItem::Address).get() | 
|  | << "[" << format_hex(AddrStart, 10) << " - " | 
|  | << format_hex(AddrEnd, 10) << "]"; | 
|  | Printer << " (" << Line->getLength() << " bytes)"; | 
|  | } else { | 
|  | uint64_t AddrStart = Line->getVirtualAddress(); | 
|  | WithColor(Printer, PDB_ColorItem::Address).get() | 
|  | << "[" << format_hex(AddrStart, 10) << "] "; | 
|  | Printer << "(0 bytes)"; | 
|  | } | 
|  | } | 
|  | Printer.Unindent(); | 
|  | } | 
|  | Printer.Unindent(); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (opts & Flags::Children) { | 
|  | if (auto ChildrenEnum = Symbol.findAllChildren()) { | 
|  | Printer.Indent(); | 
|  | while (auto Child = ChildrenEnum->getNext()) | 
|  | Child->dump(*this); | 
|  | Printer.Unindent(); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void CompilandDumper::dump(const PDBSymbolData &Symbol) { | 
|  | if (!shouldDumpSymLevel(opts::pretty::SymLevel::Data)) | 
|  | return; | 
|  | if (Printer.IsSymbolExcluded(Symbol.getName())) | 
|  | return; | 
|  |  | 
|  | Printer.NewLine(); | 
|  |  | 
|  | switch (auto LocType = Symbol.getLocationType()) { | 
|  | case PDB_LocType::Static: | 
|  | Printer << "data: "; | 
|  | WithColor(Printer, PDB_ColorItem::Address).get() | 
|  | << "[" << format_hex(Symbol.getVirtualAddress(), 10) << "]"; | 
|  |  | 
|  | WithColor(Printer, PDB_ColorItem::Comment).get() | 
|  | << " [sizeof = " << getTypeLength(Symbol) << "]"; | 
|  |  | 
|  | break; | 
|  | case PDB_LocType::Constant: | 
|  | Printer << "constant: "; | 
|  | WithColor(Printer, PDB_ColorItem::LiteralValue).get() | 
|  | << "[" << Symbol.getValue() << "]"; | 
|  | WithColor(Printer, PDB_ColorItem::Comment).get() | 
|  | << " [sizeof = " << getTypeLength(Symbol) << "]"; | 
|  | break; | 
|  | default: | 
|  | Printer << "data(unexpected type=" << LocType << ")"; | 
|  | } | 
|  |  | 
|  | Printer << " "; | 
|  | WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); | 
|  | } | 
|  |  | 
|  | void CompilandDumper::dump(const PDBSymbolFunc &Symbol) { | 
|  | if (!shouldDumpSymLevel(opts::pretty::SymLevel::Functions)) | 
|  | return; | 
|  | if (Symbol.getLength() == 0) | 
|  | return; | 
|  | if (Printer.IsSymbolExcluded(Symbol.getName())) | 
|  | return; | 
|  |  | 
|  | Printer.NewLine(); | 
|  | FunctionDumper Dumper(Printer); | 
|  | Dumper.start(Symbol, FunctionDumper::PointerType::None); | 
|  | } | 
|  |  | 
|  | void CompilandDumper::dump(const PDBSymbolLabel &Symbol) { | 
|  | if (Printer.IsSymbolExcluded(Symbol.getName())) | 
|  | return; | 
|  |  | 
|  | Printer.NewLine(); | 
|  | Printer << "label "; | 
|  | WithColor(Printer, PDB_ColorItem::Address).get() | 
|  | << "[" << format_hex(Symbol.getVirtualAddress(), 10) << "] "; | 
|  | WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); | 
|  | } | 
|  |  | 
|  | void CompilandDumper::dump(const PDBSymbolThunk &Symbol) { | 
|  | if (!shouldDumpSymLevel(opts::pretty::SymLevel::Thunks)) | 
|  | return; | 
|  | if (Printer.IsSymbolExcluded(Symbol.getName())) | 
|  | return; | 
|  |  | 
|  | Printer.NewLine(); | 
|  | Printer << "thunk "; | 
|  | codeview::ThunkOrdinal Ordinal = Symbol.getThunkOrdinal(); | 
|  | uint64_t VA = Symbol.getVirtualAddress(); | 
|  | if (Ordinal == codeview::ThunkOrdinal::TrampIncremental) { | 
|  | uint64_t Target = Symbol.getTargetVirtualAddress(); | 
|  | WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(VA, 10); | 
|  | Printer << " -> "; | 
|  | WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Target, 10); | 
|  | } else { | 
|  | WithColor(Printer, PDB_ColorItem::Address).get() | 
|  | << "[" << format_hex(VA, 10) << " - " | 
|  | << format_hex(VA + Symbol.getLength(), 10) << "]"; | 
|  | } | 
|  | Printer << " ("; | 
|  | WithColor(Printer, PDB_ColorItem::Register).get() << Ordinal; | 
|  | Printer << ") "; | 
|  | std::string Name = Symbol.getName(); | 
|  | if (!Name.empty()) | 
|  | WithColor(Printer, PDB_ColorItem::Identifier).get() << Name; | 
|  | } | 
|  |  | 
|  | void CompilandDumper::dump(const PDBSymbolTypeTypedef &Symbol) {} | 
|  |  | 
|  | void CompilandDumper::dump(const PDBSymbolUnknown &Symbol) { | 
|  | Printer.NewLine(); | 
|  | Printer << "unknown (" << Symbol.getSymTag() << ")"; | 
|  | } | 
|  |  | 
|  | void CompilandDumper::dump(const PDBSymbolUsingNamespace &Symbol) { | 
|  | if (Printer.IsSymbolExcluded(Symbol.getName())) | 
|  | return; | 
|  |  | 
|  | Printer.NewLine(); | 
|  | Printer << "using namespace "; | 
|  | std::string Name = Symbol.getName(); | 
|  | WithColor(Printer, PDB_ColorItem::Identifier).get() << Name; | 
|  | } |