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