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