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