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 << CPURegister{Symbol.getRawSymbol().getPlatform(), 142 Symbol.getLocalBasePointerRegisterId()}; 143 } else { 144 WithColor(Printer, PDB_ColorItem::Register).get() << "FPO"; 145 } 146 Printer << ") "; 147 148 if (Symbol.isVirtual() || Symbol.isPureVirtual()) 149 WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual "; 150 151 auto Signature = Symbol.getSignature(); 152 if (!Signature) { 153 WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); 154 if (Pointer == PointerType::Pointer) 155 Printer << "*"; 156 else if (Pointer == FunctionDumper::PointerType::Reference) 157 Printer << "&"; 158 return; 159 } 160 161 auto ReturnType = Signature->getReturnType(); 162 ReturnType->dump(*this); 163 Printer << " "; 164 165 auto ClassParent = Symbol.getClassParent(); 166 CallingConvention CC = Signature->getCallingConvention(); 167 if (Pointer != FunctionDumper::PointerType::None) 168 Printer << "("; 169 170 if ((ClassParent && CC != CallingConvention::ThisCall) || 171 (!ClassParent && CC != CallingConvention::NearStdCall)) { 172 WithColor(Printer, PDB_ColorItem::Keyword).get() 173 << Signature->getCallingConvention() << " "; 174 } 175 WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName(); 176 if (Pointer != FunctionDumper::PointerType::None) { 177 if (Pointer == PointerType::Pointer) 178 Printer << "*"; 179 else if (Pointer == FunctionDumper::PointerType::Reference) 180 Printer << "&"; 181 Printer << ")"; 182 } 183 184 Printer << "("; 185 if (auto Arguments = Symbol.getArguments()) { 186 uint32_t Index = 0; 187 while (auto Arg = Arguments->getNext()) { 188 auto ArgType = Arg->getType(); 189 ArgType->dump(*this); 190 WithColor(Printer, PDB_ColorItem::Identifier).get() << " " 191 << Arg->getName(); 192 if (++Index < Arguments->getChildCount()) 193 Printer << ", "; 194 } 195 if (Signature->isCVarArgs()) 196 Printer << ", ..."; 197 } 198 Printer << ")"; 199 if (Symbol.isConstType()) 200 WithColor(Printer, PDB_ColorItem::Keyword).get() << " const"; 201 if (Symbol.isVolatileType()) 202 WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile"; 203 if (Symbol.isPureVirtual()) 204 Printer << " = 0"; 205 } 206 207 void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol) { 208 auto ElementType = Symbol.getElementType(); 209 210 ElementType->dump(*this); 211 Printer << "["; 212 WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getLength(); 213 Printer << "]"; 214 } 215 216 void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol) { 217 BuiltinDumper Dumper(Printer); 218 Dumper.start(Symbol); 219 } 220 221 void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol) { 222 dumpClassParentWithScopeOperator(Symbol, Printer, *this); 223 WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); 224 } 225 226 void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) { 227 // PDBSymbolTypeFunctionArg is just a shim over the real argument. Just drill 228 // through to the real thing and dump it. 229 uint32_t TypeId = Symbol.getTypeId(); 230 auto Type = Symbol.getSession().getSymbolById(TypeId); 231 if (Type) 232 Type->dump(*this); 233 else 234 Printer << "<unknown-type>"; 235 } 236 237 void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol) { 238 dumpClassParentWithScopeOperator(Symbol, Printer, *this); 239 WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); 240 } 241 242 void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol) { 243 auto PointeeType = Symbol.getPointeeType(); 244 if (!PointeeType) 245 return; 246 247 if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) { 248 FunctionDumper NestedDumper(Printer); 249 PointerType Pointer = 250 Symbol.isReference() ? PointerType::Reference : PointerType::Pointer; 251 NestedDumper.start(*FuncSig, nullptr, Pointer); 252 } else { 253 if (Symbol.isConstType()) 254 WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; 255 if (Symbol.isVolatileType()) 256 WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; 257 PointeeType->dump(*this); 258 Printer << (Symbol.isReference() ? "&" : "*"); 259 260 if (Symbol.getRawSymbol().isRestrictedType()) 261 WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict"; 262 } 263 } 264 265 void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol) { 266 WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); 267 } 268