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