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