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