1 //===- FunctionDumper.cpp ------------------------------------ *- C++ *-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "FunctionDumper.h"
11 #include "llvm-pdbdump.h"
13 #include "llvm/DebugInfo/PDB/IPDBSession.h"
14 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
15 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
16 #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
17 #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
18 #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
19 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
20 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
21 #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
22 #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
23 #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
24 #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
25 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
26 #include "llvm/Support/Format.h"
32 void dumpClassParentWithScopeOperator(const T &Symbol, llvm::raw_ostream &OS,
33 llvm::FunctionDumper &Dumper) {
34 uint32_t ClassParentId = Symbol.getClassParentId();
36 Symbol.getSession().template getConcreteSymbolById<PDBSymbolTypeUDT>(
41 OS << ClassParent->getName() << "::";
45 FunctionDumper::FunctionDumper() : PDBSymDumper(true) {}
47 void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol,
48 PointerType Pointer, raw_ostream &OS) {
49 auto ReturnType = Symbol.getReturnType();
50 ReturnType->dump(OS, 0, *this);
52 uint32_t ClassParentId = Symbol.getClassParentId();
54 Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
57 PDB_CallingConv CC = Symbol.getCallingConvention();
58 bool ShouldDumpCallingConvention = true;
59 if ((ClassParent && CC == PDB_CallingConv::Thiscall) ||
60 (!ClassParent && CC == PDB_CallingConv::NearStdcall)) {
61 ShouldDumpCallingConvention = false;
64 if (Pointer == PointerType::None) {
65 if (ShouldDumpCallingConvention)
68 OS << "(" << ClassParent->getName() << "::)";
71 if (ShouldDumpCallingConvention)
73 OS << Symbol.getCallingConvention() << " ";
75 OS << ClassParent->getName() << "::";
76 if (Pointer == PointerType::Reference)
84 if (auto ChildEnum = Symbol.getArguments()) {
86 while (auto Arg = ChildEnum->getNext()) {
87 Arg->dump(OS, 0, *this);
88 if (++Index < ChildEnum->getChildCount())
94 if (Symbol.isConstType())
96 if (Symbol.isVolatileType())
100 void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer,
101 raw_ostream &OS, int Indent) {
102 uint32_t FuncStart = Symbol.getRelativeVirtualAddress();
103 uint32_t FuncEnd = FuncStart + Symbol.getLength();
105 OS << newline(Indent);
107 OS << "func [" << format_hex(FuncStart, 8);
108 if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>())
109 OS << "+" << DebugStart->getRelativeVirtualAddress() - FuncStart;
110 OS << " - " << format_hex(FuncEnd, 8);
111 if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>())
112 OS << "-" << FuncEnd - DebugEnd->getRelativeVirtualAddress();
115 if (Symbol.hasFramePointer())
116 OS << "(" << Symbol.getLocalBasePointerRegisterId() << ")";
121 if (Symbol.isVirtual() || Symbol.isPureVirtual())
124 auto Signature = Symbol.getSignature();
126 OS << Symbol.getName();
127 if (Pointer == PointerType::Pointer)
129 else if (Pointer == FunctionDumper::PointerType::Reference)
134 auto ReturnType = Signature->getReturnType();
135 ReturnType->dump(OS, 0, *this);
138 auto ClassParent = Symbol.getClassParent();
139 PDB_CallingConv CC = Signature->getCallingConvention();
140 if (Pointer != FunctionDumper::PointerType::None)
143 if ((ClassParent && CC != PDB_CallingConv::Thiscall) ||
144 (!ClassParent && CC != PDB_CallingConv::NearStdcall))
145 OS << Signature->getCallingConvention() << " ";
146 OS << Symbol.getName();
147 if (Pointer != FunctionDumper::PointerType::None) {
148 if (Pointer == PointerType::Pointer)
150 else if (Pointer == FunctionDumper::PointerType::Reference)
156 if (auto Arguments = Symbol.getArguments()) {
158 while (auto Arg = Arguments->getNext()) {
159 auto ArgType = Arg->getType();
160 ArgType->dump(OS, 0, *this);
161 OS << " " << Arg->getName();
162 if (++Index < Arguments->getChildCount())
168 if (Symbol.isConstType())
170 if (Symbol.isVolatileType())
172 if (Symbol.isPureVirtual())
176 void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol, raw_ostream &OS,
178 uint32_t ElementTypeId = Symbol.getTypeId();
179 auto ElementType = Symbol.getSession().getSymbolById(ElementTypeId);
183 ElementType->dump(OS, 0, *this);
184 OS << "[" << Symbol.getLength() << "]";
187 void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol, raw_ostream &OS,
189 PDB_BuiltinType Type = Symbol.getBuiltinType();
191 if (Type == PDB_BuiltinType::UInt || Type == PDB_BuiltinType::Int)
192 OS << (8 * Symbol.getLength()) << "_t";
195 void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS,
197 dumpClassParentWithScopeOperator(Symbol, OS, *this);
198 OS << Symbol.getName();
201 void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol,
202 raw_ostream &OS, int Indent) {
203 // PDBSymbolTypeFunctionArg is just a shim over the real argument. Just drill
204 // through to the real thing and dump it.
205 Symbol.defaultDump(OS, Indent, PDB_DumpLevel::Detailed);
207 uint32_t TypeId = Symbol.getTypeId();
208 auto Type = Symbol.getSession().getSymbolById(TypeId);
211 Type->dump(OS, 0, *this);
214 void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS,
216 dumpClassParentWithScopeOperator(Symbol, OS, *this);
217 OS << Symbol.getName();
220 void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol, raw_ostream &OS,
222 uint32_t PointeeId = Symbol.getTypeId();
223 auto PointeeType = Symbol.getSession().getSymbolById(PointeeId);
227 if (auto FuncSig = dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) {
228 FunctionDumper NestedDumper;
229 PointerType Pointer =
230 Symbol.isReference() ? PointerType::Reference : PointerType::Pointer;
231 NestedDumper.start(*FuncSig, Pointer, OS);
233 if (Symbol.isConstType())
235 if (Symbol.isVolatileType())
237 PointeeType->dump(OS, Indent, *this);
238 OS << (Symbol.isReference() ? "&" : "*");
242 void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS,
244 OS << Symbol.getName();