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