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 if (!ReturnType) 57 Printer << "<unknown-type>"; 58 else 59 ReturnType->dump(*this); 60 Printer << " "; 61 uint32_t ClassParentId = Symbol.getClassParentId(); 62 auto ClassParent = 63 Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>( 64 ClassParentId); 65 66 PDB_CallingConv CC = Symbol.getCallingConvention(); 67 bool ShouldDumpCallingConvention = true; 68 if ((ClassParent && CC == CallingConvention::ThisCall) || 69 (!ClassParent && CC == CallingConvention::NearStdCall)) { 70 ShouldDumpCallingConvention = false; 71 } 72 73 if (Pointer == PointerType::None) { 74 if (ShouldDumpCallingConvention) 75 WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " "; 76 if (ClassParent) { 77 Printer << "("; 78 WithColor(Printer, PDB_ColorItem::Identifier).get() 79 << ClassParent->getName(); 80 Printer << "::)"; 81 } 82 } else { 83 Printer << "("; 84 if (ShouldDumpCallingConvention) 85 WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " "; 86 if (ClassParent) { 87 WithColor(Printer, PDB_ColorItem::Identifier).get() 88 << ClassParent->getName(); 89 Printer << "::"; 90 } 91 if (Pointer == PointerType::Reference) 92 Printer << "&"; 93 else 94 Printer << "*"; 95 if (Name) 96 WithColor(Printer, PDB_ColorItem::Identifier).get() << Name; 97 Printer << ")"; 98 } 99 100 Printer << "("; 101 if (auto ChildEnum = Symbol.getArguments()) { 102 uint32_t Index = 0; 103 while (auto Arg = ChildEnum->getNext()) { 104 Arg->dump(*this); 105 if (++Index < ChildEnum->getChildCount()) 106 Printer << ", "; 107 } 108 } 109 Printer << ")"; 110 111 if (Symbol.isConstType()) 112 WithColor(Printer, PDB_ColorItem::Keyword).get() << " const"; 113 if (Symbol.isVolatileType()) 114 WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile"; 115 } 116 117 void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) { 118 uint64_t FuncStart = Symbol.getVirtualAddress(); 119 uint64_t FuncEnd = FuncStart + Symbol.getLength(); 120 121 Printer << "func ["; 122 WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10); 123 if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) { 124 uint64_t Prologue = DebugStart->getVirtualAddress() - FuncStart; 125 WithColor(Printer, PDB_ColorItem::Offset).get() 126 << formatv("+{0,2}", Prologue); 127 } 128 Printer << " - "; 129 WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10); 130 if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) { 131 uint64_t Epilogue = FuncEnd - DebugEnd->getVirtualAddress(); 132 WithColor(Printer, PDB_ColorItem::Offset).get() 133 << formatv("-{0,2}", Epilogue); 134 } 135 136 WithColor(Printer, PDB_ColorItem::Comment).get() 137 << formatv(" | sizeof={0,3}", Symbol.getLength()); 138 Printer << "] ("; 139 140 if (Symbol.hasFramePointer()) { 141 WithColor(Printer, PDB_ColorItem::Register).get() 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 Printer << "<unknown-type>"; 233 else 234 Type->dump(*this); 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