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