| //===- 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 "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; |
| } |