1*0b57cec5SDimitry Andric //===- PrettyFunctionDumper.cpp --------------------------------- *- C++ *-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "PrettyFunctionDumper.h" 10*0b57cec5SDimitry Andric #include "LinePrinter.h" 11*0b57cec5SDimitry Andric #include "PrettyBuiltinDumper.h" 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBSession.h" 14*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBExtras.h" 15*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolData.h" 16*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" 17*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" 18*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" 19*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h" 20*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" 21*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h" 22*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" 23*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" 24*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" 25*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" 26*0b57cec5SDimitry Andric #include "llvm/Support/Format.h" 27*0b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h" 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric using namespace llvm; 30*0b57cec5SDimitry Andric using namespace llvm::codeview; 31*0b57cec5SDimitry Andric using namespace llvm::pdb; 32*0b57cec5SDimitry Andric 33*0b57cec5SDimitry Andric namespace { 34*0b57cec5SDimitry Andric template <class T> 35*0b57cec5SDimitry Andric void dumpClassParentWithScopeOperator(const T &Symbol, LinePrinter &Printer, 36*0b57cec5SDimitry Andric FunctionDumper &Dumper) { 37*0b57cec5SDimitry Andric uint32_t ClassParentId = Symbol.getClassParentId(); 38*0b57cec5SDimitry Andric auto ClassParent = 39*0b57cec5SDimitry Andric Symbol.getSession().template getConcreteSymbolById<PDBSymbolTypeUDT>( 40*0b57cec5SDimitry Andric ClassParentId); 41*0b57cec5SDimitry Andric if (!ClassParent) 42*0b57cec5SDimitry Andric return; 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Type).get() << ClassParent->getName(); 45*0b57cec5SDimitry Andric Printer << "::"; 46*0b57cec5SDimitry Andric } 47*0b57cec5SDimitry Andric } 48*0b57cec5SDimitry Andric 49*0b57cec5SDimitry Andric FunctionDumper::FunctionDumper(LinePrinter &P) 50*0b57cec5SDimitry Andric : PDBSymDumper(true), Printer(P) {} 51*0b57cec5SDimitry Andric 52*0b57cec5SDimitry Andric void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol, 53*0b57cec5SDimitry Andric const char *Name, PointerType Pointer) { 54*0b57cec5SDimitry Andric auto ReturnType = Symbol.getReturnType(); 55*0b57cec5SDimitry Andric if (!ReturnType) 56*0b57cec5SDimitry Andric Printer << "<unknown-type>"; 57*0b57cec5SDimitry Andric else 58*0b57cec5SDimitry Andric ReturnType->dump(*this); 59*0b57cec5SDimitry Andric Printer << " "; 60*0b57cec5SDimitry Andric uint32_t ClassParentId = Symbol.getClassParentId(); 61*0b57cec5SDimitry Andric auto ClassParent = 62*0b57cec5SDimitry Andric Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>( 63*0b57cec5SDimitry Andric ClassParentId); 64*0b57cec5SDimitry Andric 65*0b57cec5SDimitry Andric PDB_CallingConv CC = Symbol.getCallingConvention(); 66*0b57cec5SDimitry Andric bool ShouldDumpCallingConvention = true; 67*0b57cec5SDimitry Andric if ((ClassParent && CC == CallingConvention::ThisCall) || 68*0b57cec5SDimitry Andric (!ClassParent && CC == CallingConvention::NearStdCall)) { 69*0b57cec5SDimitry Andric ShouldDumpCallingConvention = false; 70*0b57cec5SDimitry Andric } 71*0b57cec5SDimitry Andric 72*0b57cec5SDimitry Andric if (Pointer == PointerType::None) { 73*0b57cec5SDimitry Andric if (ShouldDumpCallingConvention) 74*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " "; 75*0b57cec5SDimitry Andric if (ClassParent) { 76*0b57cec5SDimitry Andric Printer << "("; 77*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Identifier).get() 78*0b57cec5SDimitry Andric << ClassParent->getName(); 79*0b57cec5SDimitry Andric Printer << "::)"; 80*0b57cec5SDimitry Andric } 81*0b57cec5SDimitry Andric } else { 82*0b57cec5SDimitry Andric Printer << "("; 83*0b57cec5SDimitry Andric if (ShouldDumpCallingConvention) 84*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " "; 85*0b57cec5SDimitry Andric if (ClassParent) { 86*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Identifier).get() 87*0b57cec5SDimitry Andric << ClassParent->getName(); 88*0b57cec5SDimitry Andric Printer << "::"; 89*0b57cec5SDimitry Andric } 90*0b57cec5SDimitry Andric if (Pointer == PointerType::Reference) 91*0b57cec5SDimitry Andric Printer << "&"; 92*0b57cec5SDimitry Andric else 93*0b57cec5SDimitry Andric Printer << "*"; 94*0b57cec5SDimitry Andric if (Name) 95*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Identifier).get() << Name; 96*0b57cec5SDimitry Andric Printer << ")"; 97*0b57cec5SDimitry Andric } 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric Printer << "("; 100*0b57cec5SDimitry Andric if (auto ChildEnum = Symbol.getArguments()) { 101*0b57cec5SDimitry Andric uint32_t Index = 0; 102*0b57cec5SDimitry Andric while (auto Arg = ChildEnum->getNext()) { 103*0b57cec5SDimitry Andric Arg->dump(*this); 104*0b57cec5SDimitry Andric if (++Index < ChildEnum->getChildCount()) 105*0b57cec5SDimitry Andric Printer << ", "; 106*0b57cec5SDimitry Andric } 107*0b57cec5SDimitry Andric } 108*0b57cec5SDimitry Andric Printer << ")"; 109*0b57cec5SDimitry Andric 110*0b57cec5SDimitry Andric if (Symbol.isConstType()) 111*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Keyword).get() << " const"; 112*0b57cec5SDimitry Andric if (Symbol.isVolatileType()) 113*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile"; 114*0b57cec5SDimitry Andric } 115*0b57cec5SDimitry Andric 116*0b57cec5SDimitry Andric void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) { 117*0b57cec5SDimitry Andric uint64_t FuncStart = Symbol.getVirtualAddress(); 118*0b57cec5SDimitry Andric uint64_t FuncEnd = FuncStart + Symbol.getLength(); 119*0b57cec5SDimitry Andric 120*0b57cec5SDimitry Andric Printer << "func ["; 121*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10); 122*0b57cec5SDimitry Andric if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) { 123*0b57cec5SDimitry Andric uint64_t Prologue = DebugStart->getVirtualAddress() - FuncStart; 124*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Offset).get() 125*0b57cec5SDimitry Andric << formatv("+{0,2}", Prologue); 126*0b57cec5SDimitry Andric } 127*0b57cec5SDimitry Andric Printer << " - "; 128*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10); 129*0b57cec5SDimitry Andric if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) { 130*0b57cec5SDimitry Andric uint64_t Epilogue = FuncEnd - DebugEnd->getVirtualAddress(); 131*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Offset).get() 132*0b57cec5SDimitry Andric << formatv("-{0,2}", Epilogue); 133*0b57cec5SDimitry Andric } 134*0b57cec5SDimitry Andric 135*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Comment).get() 136*0b57cec5SDimitry Andric << formatv(" | sizeof={0,3}", Symbol.getLength()); 137*0b57cec5SDimitry Andric Printer << "] ("; 138*0b57cec5SDimitry Andric 139*0b57cec5SDimitry Andric if (Symbol.hasFramePointer()) { 140*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Register).get() 141*0b57cec5SDimitry Andric << CPURegister{Symbol.getRawSymbol().getPlatform(), 142*0b57cec5SDimitry Andric Symbol.getLocalBasePointerRegisterId()}; 143*0b57cec5SDimitry Andric } else { 144*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Register).get() << "FPO"; 145*0b57cec5SDimitry Andric } 146*0b57cec5SDimitry Andric Printer << ") "; 147*0b57cec5SDimitry Andric 148*0b57cec5SDimitry Andric if (Symbol.isVirtual() || Symbol.isPureVirtual()) 149*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual "; 150*0b57cec5SDimitry Andric 151*0b57cec5SDimitry Andric auto Signature = Symbol.getSignature(); 152*0b57cec5SDimitry Andric if (!Signature) { 153*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); 154*0b57cec5SDimitry Andric if (Pointer == PointerType::Pointer) 155*0b57cec5SDimitry Andric Printer << "*"; 156*0b57cec5SDimitry Andric else if (Pointer == FunctionDumper::PointerType::Reference) 157*0b57cec5SDimitry Andric Printer << "&"; 158*0b57cec5SDimitry Andric return; 159*0b57cec5SDimitry Andric } 160*0b57cec5SDimitry Andric 161*0b57cec5SDimitry Andric auto ReturnType = Signature->getReturnType(); 162*0b57cec5SDimitry Andric ReturnType->dump(*this); 163*0b57cec5SDimitry Andric Printer << " "; 164*0b57cec5SDimitry Andric 165*0b57cec5SDimitry Andric auto ClassParent = Symbol.getClassParent(); 166*0b57cec5SDimitry Andric CallingConvention CC = Signature->getCallingConvention(); 167*0b57cec5SDimitry Andric if (Pointer != FunctionDumper::PointerType::None) 168*0b57cec5SDimitry Andric Printer << "("; 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric if ((ClassParent && CC != CallingConvention::ThisCall) || 171*0b57cec5SDimitry Andric (!ClassParent && CC != CallingConvention::NearStdCall)) { 172*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Keyword).get() 173*0b57cec5SDimitry Andric << Signature->getCallingConvention() << " "; 174*0b57cec5SDimitry Andric } 175*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); 176*0b57cec5SDimitry Andric if (Pointer != FunctionDumper::PointerType::None) { 177*0b57cec5SDimitry Andric if (Pointer == PointerType::Pointer) 178*0b57cec5SDimitry Andric Printer << "*"; 179*0b57cec5SDimitry Andric else if (Pointer == FunctionDumper::PointerType::Reference) 180*0b57cec5SDimitry Andric Printer << "&"; 181*0b57cec5SDimitry Andric Printer << ")"; 182*0b57cec5SDimitry Andric } 183*0b57cec5SDimitry Andric 184*0b57cec5SDimitry Andric Printer << "("; 185*0b57cec5SDimitry Andric if (auto Arguments = Symbol.getArguments()) { 186*0b57cec5SDimitry Andric uint32_t Index = 0; 187*0b57cec5SDimitry Andric while (auto Arg = Arguments->getNext()) { 188*0b57cec5SDimitry Andric auto ArgType = Arg->getType(); 189*0b57cec5SDimitry Andric ArgType->dump(*this); 190*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Identifier).get() << " " 191*0b57cec5SDimitry Andric << Arg->getName(); 192*0b57cec5SDimitry Andric if (++Index < Arguments->getChildCount()) 193*0b57cec5SDimitry Andric Printer << ", "; 194*0b57cec5SDimitry Andric } 195*0b57cec5SDimitry Andric if (Signature->isCVarArgs()) 196*0b57cec5SDimitry Andric Printer << ", ..."; 197*0b57cec5SDimitry Andric } 198*0b57cec5SDimitry Andric Printer << ")"; 199*0b57cec5SDimitry Andric if (Symbol.isConstType()) 200*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Keyword).get() << " const"; 201*0b57cec5SDimitry Andric if (Symbol.isVolatileType()) 202*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile"; 203*0b57cec5SDimitry Andric if (Symbol.isPureVirtual()) 204*0b57cec5SDimitry Andric Printer << " = 0"; 205*0b57cec5SDimitry Andric } 206*0b57cec5SDimitry Andric 207*0b57cec5SDimitry Andric void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol) { 208*0b57cec5SDimitry Andric auto ElementType = Symbol.getElementType(); 209*0b57cec5SDimitry Andric 210*0b57cec5SDimitry Andric ElementType->dump(*this); 211*0b57cec5SDimitry Andric Printer << "["; 212*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getLength(); 213*0b57cec5SDimitry Andric Printer << "]"; 214*0b57cec5SDimitry Andric } 215*0b57cec5SDimitry Andric 216*0b57cec5SDimitry Andric void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol) { 217*0b57cec5SDimitry Andric BuiltinDumper Dumper(Printer); 218*0b57cec5SDimitry Andric Dumper.start(Symbol); 219*0b57cec5SDimitry Andric } 220*0b57cec5SDimitry Andric 221*0b57cec5SDimitry Andric void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol) { 222*0b57cec5SDimitry Andric dumpClassParentWithScopeOperator(Symbol, Printer, *this); 223*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); 224*0b57cec5SDimitry Andric } 225*0b57cec5SDimitry Andric 226*0b57cec5SDimitry Andric void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) { 227*0b57cec5SDimitry Andric // PDBSymbolTypeFunctionArg is just a shim over the real argument. Just drill 228*0b57cec5SDimitry Andric // through to the real thing and dump it. 229*0b57cec5SDimitry Andric uint32_t TypeId = Symbol.getTypeId(); 230*0b57cec5SDimitry Andric auto Type = Symbol.getSession().getSymbolById(TypeId); 231*0b57cec5SDimitry Andric if (Type) 232*0b57cec5SDimitry Andric Type->dump(*this); 233*0b57cec5SDimitry Andric else 234*0b57cec5SDimitry Andric Printer << "<unknown-type>"; 235*0b57cec5SDimitry Andric } 236*0b57cec5SDimitry Andric 237*0b57cec5SDimitry Andric void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol) { 238*0b57cec5SDimitry Andric dumpClassParentWithScopeOperator(Symbol, Printer, *this); 239*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); 240*0b57cec5SDimitry Andric } 241*0b57cec5SDimitry Andric 242*0b57cec5SDimitry Andric void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol) { 243*0b57cec5SDimitry Andric auto PointeeType = Symbol.getPointeeType(); 244*0b57cec5SDimitry Andric if (!PointeeType) 245*0b57cec5SDimitry Andric return; 246*0b57cec5SDimitry Andric 247*0b57cec5SDimitry Andric if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) { 248*0b57cec5SDimitry Andric FunctionDumper NestedDumper(Printer); 249*0b57cec5SDimitry Andric PointerType Pointer = 250*0b57cec5SDimitry Andric Symbol.isReference() ? PointerType::Reference : PointerType::Pointer; 251*0b57cec5SDimitry Andric NestedDumper.start(*FuncSig, nullptr, Pointer); 252*0b57cec5SDimitry Andric } else { 253*0b57cec5SDimitry Andric if (Symbol.isConstType()) 254*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; 255*0b57cec5SDimitry Andric if (Symbol.isVolatileType()) 256*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; 257*0b57cec5SDimitry Andric PointeeType->dump(*this); 258*0b57cec5SDimitry Andric Printer << (Symbol.isReference() ? "&" : "*"); 259*0b57cec5SDimitry Andric 260*0b57cec5SDimitry Andric if (Symbol.getRawSymbol().isRestrictedType()) 261*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict"; 262*0b57cec5SDimitry Andric } 263*0b57cec5SDimitry Andric } 264*0b57cec5SDimitry Andric 265*0b57cec5SDimitry Andric void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol) { 266*0b57cec5SDimitry Andric WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); 267*0b57cec5SDimitry Andric } 268