xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-pdbutil/PrettyFunctionDumper.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
10b57cec5SDimitry Andric //===- PrettyFunctionDumper.cpp --------------------------------- *- C++ *-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "PrettyFunctionDumper.h"
100b57cec5SDimitry Andric #include "PrettyBuiltinDumper.h"
110b57cec5SDimitry Andric 
12*81ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
13*81ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
140b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBSession.h"
15*81ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
160b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBExtras.h"
170b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
180b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
190b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
200b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
210b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
22*81ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
230b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
240b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
250b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
260b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
270b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
280b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
290b57cec5SDimitry Andric #include "llvm/Support/Format.h"
300b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h"
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric using namespace llvm;
330b57cec5SDimitry Andric using namespace llvm::codeview;
340b57cec5SDimitry Andric using namespace llvm::pdb;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric namespace {
370b57cec5SDimitry Andric template <class T>
dumpClassParentWithScopeOperator(const T & Symbol,LinePrinter & Printer,FunctionDumper & Dumper)380b57cec5SDimitry Andric void dumpClassParentWithScopeOperator(const T &Symbol, LinePrinter &Printer,
390b57cec5SDimitry Andric                                       FunctionDumper &Dumper) {
400b57cec5SDimitry Andric   uint32_t ClassParentId = Symbol.getClassParentId();
410b57cec5SDimitry Andric   auto ClassParent =
420b57cec5SDimitry Andric       Symbol.getSession().template getConcreteSymbolById<PDBSymbolTypeUDT>(
430b57cec5SDimitry Andric           ClassParentId);
440b57cec5SDimitry Andric   if (!ClassParent)
450b57cec5SDimitry Andric     return;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Type).get() << ClassParent->getName();
480b57cec5SDimitry Andric   Printer << "::";
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
FunctionDumper(LinePrinter & P)520b57cec5SDimitry Andric FunctionDumper::FunctionDumper(LinePrinter &P)
530b57cec5SDimitry Andric     : PDBSymDumper(true), Printer(P) {}
540b57cec5SDimitry Andric 
start(const PDBSymbolTypeFunctionSig & Symbol,const char * Name,PointerType Pointer)550b57cec5SDimitry Andric void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol,
560b57cec5SDimitry Andric                            const char *Name, PointerType Pointer) {
570b57cec5SDimitry Andric   auto ReturnType = Symbol.getReturnType();
580b57cec5SDimitry Andric   if (!ReturnType)
590b57cec5SDimitry Andric     Printer << "<unknown-type>";
600b57cec5SDimitry Andric   else
610b57cec5SDimitry Andric     ReturnType->dump(*this);
620b57cec5SDimitry Andric   Printer << " ";
630b57cec5SDimitry Andric   uint32_t ClassParentId = Symbol.getClassParentId();
640b57cec5SDimitry Andric   auto ClassParent =
650b57cec5SDimitry Andric       Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
660b57cec5SDimitry Andric           ClassParentId);
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   PDB_CallingConv CC = Symbol.getCallingConvention();
690b57cec5SDimitry Andric   bool ShouldDumpCallingConvention = true;
700b57cec5SDimitry Andric   if ((ClassParent && CC == CallingConvention::ThisCall) ||
710b57cec5SDimitry Andric       (!ClassParent && CC == CallingConvention::NearStdCall)) {
720b57cec5SDimitry Andric     ShouldDumpCallingConvention = false;
730b57cec5SDimitry Andric   }
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   if (Pointer == PointerType::None) {
760b57cec5SDimitry Andric     if (ShouldDumpCallingConvention)
770b57cec5SDimitry Andric       WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
780b57cec5SDimitry Andric     if (ClassParent) {
790b57cec5SDimitry Andric       Printer << "(";
800b57cec5SDimitry Andric       WithColor(Printer, PDB_ColorItem::Identifier).get()
810b57cec5SDimitry Andric           << ClassParent->getName();
820b57cec5SDimitry Andric       Printer << "::)";
830b57cec5SDimitry Andric     }
840b57cec5SDimitry Andric   } else {
850b57cec5SDimitry Andric     Printer << "(";
860b57cec5SDimitry Andric     if (ShouldDumpCallingConvention)
870b57cec5SDimitry Andric       WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
880b57cec5SDimitry Andric     if (ClassParent) {
890b57cec5SDimitry Andric       WithColor(Printer, PDB_ColorItem::Identifier).get()
900b57cec5SDimitry Andric           << ClassParent->getName();
910b57cec5SDimitry Andric       Printer << "::";
920b57cec5SDimitry Andric     }
930b57cec5SDimitry Andric     if (Pointer == PointerType::Reference)
940b57cec5SDimitry Andric       Printer << "&";
950b57cec5SDimitry Andric     else
960b57cec5SDimitry Andric       Printer << "*";
970b57cec5SDimitry Andric     if (Name)
980b57cec5SDimitry Andric       WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;
990b57cec5SDimitry Andric     Printer << ")";
1000b57cec5SDimitry Andric   }
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   Printer << "(";
1030b57cec5SDimitry Andric   if (auto ChildEnum = Symbol.getArguments()) {
1040b57cec5SDimitry Andric     uint32_t Index = 0;
1050b57cec5SDimitry Andric     while (auto Arg = ChildEnum->getNext()) {
1060b57cec5SDimitry Andric       Arg->dump(*this);
1070b57cec5SDimitry Andric       if (++Index < ChildEnum->getChildCount())
1080b57cec5SDimitry Andric         Printer << ", ";
1090b57cec5SDimitry Andric     }
1100b57cec5SDimitry Andric   }
1110b57cec5SDimitry Andric   Printer << ")";
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   if (Symbol.isConstType())
1140b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
1150b57cec5SDimitry Andric   if (Symbol.isVolatileType())
1160b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
start(const PDBSymbolFunc & Symbol,PointerType Pointer)1190b57cec5SDimitry Andric void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) {
1200b57cec5SDimitry Andric   uint64_t FuncStart = Symbol.getVirtualAddress();
1210b57cec5SDimitry Andric   uint64_t FuncEnd = FuncStart + Symbol.getLength();
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   Printer << "func [";
1240b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10);
1250b57cec5SDimitry Andric   if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) {
1260b57cec5SDimitry Andric     uint64_t Prologue = DebugStart->getVirtualAddress() - FuncStart;
1270b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Offset).get()
1280b57cec5SDimitry Andric         << formatv("+{0,2}", Prologue);
1290b57cec5SDimitry Andric   }
1300b57cec5SDimitry Andric   Printer << " - ";
1310b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10);
1320b57cec5SDimitry Andric   if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) {
1330b57cec5SDimitry Andric     uint64_t Epilogue = FuncEnd - DebugEnd->getVirtualAddress();
1340b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Offset).get()
1350b57cec5SDimitry Andric         << formatv("-{0,2}", Epilogue);
1360b57cec5SDimitry Andric   }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Comment).get()
1390b57cec5SDimitry Andric       << formatv(" | sizeof={0,3}", Symbol.getLength());
1400b57cec5SDimitry Andric   Printer << "] (";
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   if (Symbol.hasFramePointer()) {
1430b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Register).get()
1440b57cec5SDimitry Andric         << CPURegister{Symbol.getRawSymbol().getPlatform(),
1450b57cec5SDimitry Andric                        Symbol.getLocalBasePointerRegisterId()};
1460b57cec5SDimitry Andric   } else {
1470b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Register).get() << "FPO";
1480b57cec5SDimitry Andric   }
1490b57cec5SDimitry Andric   Printer << ") ";
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   if (Symbol.isVirtual() || Symbol.isPureVirtual())
1520b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual ";
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   auto Signature = Symbol.getSignature();
1550b57cec5SDimitry Andric   if (!Signature) {
1560b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
1570b57cec5SDimitry Andric     if (Pointer == PointerType::Pointer)
1580b57cec5SDimitry Andric       Printer << "*";
1590b57cec5SDimitry Andric     else if (Pointer == FunctionDumper::PointerType::Reference)
1600b57cec5SDimitry Andric       Printer << "&";
1610b57cec5SDimitry Andric     return;
1620b57cec5SDimitry Andric   }
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   auto ReturnType = Signature->getReturnType();
1650b57cec5SDimitry Andric   ReturnType->dump(*this);
1660b57cec5SDimitry Andric   Printer << " ";
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   auto ClassParent = Symbol.getClassParent();
1690b57cec5SDimitry Andric   CallingConvention CC = Signature->getCallingConvention();
1700b57cec5SDimitry Andric   if (Pointer != FunctionDumper::PointerType::None)
1710b57cec5SDimitry Andric     Printer << "(";
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   if ((ClassParent && CC != CallingConvention::ThisCall) ||
1740b57cec5SDimitry Andric       (!ClassParent && CC != CallingConvention::NearStdCall)) {
1750b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get()
1760b57cec5SDimitry Andric         << Signature->getCallingConvention() << " ";
1770b57cec5SDimitry Andric   }
1780b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
1790b57cec5SDimitry Andric   if (Pointer != FunctionDumper::PointerType::None) {
1800b57cec5SDimitry Andric     if (Pointer == PointerType::Pointer)
1810b57cec5SDimitry Andric       Printer << "*";
1820b57cec5SDimitry Andric     else if (Pointer == FunctionDumper::PointerType::Reference)
1830b57cec5SDimitry Andric       Printer << "&";
1840b57cec5SDimitry Andric     Printer << ")";
1850b57cec5SDimitry Andric   }
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   Printer << "(";
1880b57cec5SDimitry Andric   if (auto Arguments = Symbol.getArguments()) {
1890b57cec5SDimitry Andric     uint32_t Index = 0;
1900b57cec5SDimitry Andric     while (auto Arg = Arguments->getNext()) {
1910b57cec5SDimitry Andric       auto ArgType = Arg->getType();
1920b57cec5SDimitry Andric       ArgType->dump(*this);
1930b57cec5SDimitry Andric       WithColor(Printer, PDB_ColorItem::Identifier).get() << " "
1940b57cec5SDimitry Andric                                                           << Arg->getName();
1950b57cec5SDimitry Andric       if (++Index < Arguments->getChildCount())
1960b57cec5SDimitry Andric         Printer << ", ";
1970b57cec5SDimitry Andric     }
1980b57cec5SDimitry Andric     if (Signature->isCVarArgs())
1990b57cec5SDimitry Andric       Printer << ", ...";
2000b57cec5SDimitry Andric   }
2010b57cec5SDimitry Andric   Printer << ")";
2020b57cec5SDimitry Andric   if (Symbol.isConstType())
2030b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
2040b57cec5SDimitry Andric   if (Symbol.isVolatileType())
2050b57cec5SDimitry Andric     WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
2060b57cec5SDimitry Andric   if (Symbol.isPureVirtual())
2070b57cec5SDimitry Andric     Printer << " = 0";
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
dump(const PDBSymbolTypeArray & Symbol)2100b57cec5SDimitry Andric void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol) {
2110b57cec5SDimitry Andric   auto ElementType = Symbol.getElementType();
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   ElementType->dump(*this);
2140b57cec5SDimitry Andric   Printer << "[";
2150b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getLength();
2160b57cec5SDimitry Andric   Printer << "]";
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric 
dump(const PDBSymbolTypeBuiltin & Symbol)2190b57cec5SDimitry Andric void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
2200b57cec5SDimitry Andric   BuiltinDumper Dumper(Printer);
2210b57cec5SDimitry Andric   Dumper.start(Symbol);
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric 
dump(const PDBSymbolTypeEnum & Symbol)2240b57cec5SDimitry Andric void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol) {
2250b57cec5SDimitry Andric   dumpClassParentWithScopeOperator(Symbol, Printer, *this);
2260b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric 
dump(const PDBSymbolTypeFunctionArg & Symbol)2290b57cec5SDimitry Andric void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) {
2300b57cec5SDimitry Andric   // PDBSymbolTypeFunctionArg is just a shim over the real argument.  Just drill
2310b57cec5SDimitry Andric   // through to the real thing and dump it.
2320b57cec5SDimitry Andric   uint32_t TypeId = Symbol.getTypeId();
2330b57cec5SDimitry Andric   auto Type = Symbol.getSession().getSymbolById(TypeId);
2340b57cec5SDimitry Andric   if (Type)
2350b57cec5SDimitry Andric     Type->dump(*this);
2360b57cec5SDimitry Andric   else
2370b57cec5SDimitry Andric     Printer << "<unknown-type>";
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric 
dump(const PDBSymbolTypeTypedef & Symbol)2400b57cec5SDimitry Andric void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
2410b57cec5SDimitry Andric   dumpClassParentWithScopeOperator(Symbol, Printer, *this);
2420b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
dump(const PDBSymbolTypePointer & Symbol)2450b57cec5SDimitry Andric void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol) {
2460b57cec5SDimitry Andric   auto PointeeType = Symbol.getPointeeType();
2470b57cec5SDimitry Andric   if (!PointeeType)
2480b57cec5SDimitry Andric     return;
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) {
2510b57cec5SDimitry Andric     FunctionDumper NestedDumper(Printer);
2520b57cec5SDimitry Andric     PointerType Pointer =
2530b57cec5SDimitry Andric         Symbol.isReference() ? PointerType::Reference : PointerType::Pointer;
2540b57cec5SDimitry Andric     NestedDumper.start(*FuncSig, nullptr, Pointer);
2550b57cec5SDimitry Andric   } else {
2560b57cec5SDimitry Andric     if (Symbol.isConstType())
2570b57cec5SDimitry Andric       WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";
2580b57cec5SDimitry Andric     if (Symbol.isVolatileType())
2590b57cec5SDimitry Andric       WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";
2600b57cec5SDimitry Andric     PointeeType->dump(*this);
2610b57cec5SDimitry Andric     Printer << (Symbol.isReference() ? "&" : "*");
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric     if (Symbol.getRawSymbol().isRestrictedType())
2640b57cec5SDimitry Andric       WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict";
2650b57cec5SDimitry Andric   }
2660b57cec5SDimitry Andric }
2670b57cec5SDimitry Andric 
dump(const PDBSymbolTypeUDT & Symbol)2680b57cec5SDimitry Andric void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol) {
2690b57cec5SDimitry Andric   WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
2700b57cec5SDimitry Andric }
271