[llvm-pdbdump] Support dynamic load address and external symbols.
[oota-llvm.git] / tools / llvm-pdbdump / FunctionDumper.cpp
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>
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
47 FunctionDumper::FunctionDumper(LinePrinter &P)
48     : PDBSymDumper(true), Printer(P) {}
49
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
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
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
206 void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
207   BuiltinDumper Dumper(Printer);
208   Dumper.start(Symbol);
209 }
210
211 void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol) {
212   dumpClassParentWithScopeOperator(Symbol, Printer, *this);
213   WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
214 }
215
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
226 void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
227   dumpClassParentWithScopeOperator(Symbol, Printer, *this);
228   WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
229 }
230
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
252 void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol) {
253   WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
254 }