1 //===- PrettyVariableDumper.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 "PrettyVariableDumper.h"
10 
11 #include "PrettyBuiltinDumper.h"
12 #include "PrettyFunctionDumper.h"
13 #include "llvm-pdbutil.h"
14 
15 #include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
16 #include "llvm/DebugInfo/PDB/IPDBSession.h"
17 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
18 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
19 #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
20 #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
21 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.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/DebugInfo/PDB/PDBSymbolTypeVTable.h"
27 #include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
28 #include "llvm/DebugInfo/PDB/PDBTypes.h"
29 
30 #include "llvm/Support/Format.h"
31 
32 using namespace llvm;
33 using namespace llvm::codeview;
34 using namespace llvm::pdb;
35 
36 VariableDumper::VariableDumper(LinePrinter &P)
37     : PDBSymDumper(true), Printer(P) {}
38 
39 void VariableDumper::start(const PDBSymbolData &Var, uint32_t Offset) {
40   if (Var.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
41     return;
42   if (Printer.IsSymbolExcluded(Var.getName()))
43     return;
44 
45   auto VarType = Var.getType();
46 
47   uint64_t Length = VarType->getRawSymbol().getLength();
48 
49   switch (auto LocType = Var.getLocationType()) {
50   case PDB_LocType::Static:
51     Printer.NewLine();
52     Printer << "data [";
53     WithColor(Printer, PDB_ColorItem::Address).get()
54         << format_hex(Var.getVirtualAddress(), 10);
55     Printer << ", sizeof=" << Length << "] ";
56     WithColor(Printer, PDB_ColorItem::Keyword).get() << "static ";
57     dumpSymbolTypeAndName(*VarType, Var.getName());
58     break;
59   case PDB_LocType::Constant:
60     if (isa<PDBSymbolTypeEnum>(*VarType))
61       break;
62     Printer.NewLine();
63     Printer << "data [sizeof=" << Length << "] ";
64     dumpSymbolTypeAndName(*VarType, Var.getName());
65     Printer << " = ";
66     WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue();
67     break;
68   case PDB_LocType::ThisRel:
69     Printer.NewLine();
70     Printer << "data ";
71     WithColor(Printer, PDB_ColorItem::Offset).get()
72         << "+" << format_hex(Offset + Var.getOffset(), 4)
73         << " [sizeof=" << Length << "] ";
74     dumpSymbolTypeAndName(*VarType, Var.getName());
75     break;
76   case PDB_LocType::BitField:
77     Printer.NewLine();
78     Printer << "data ";
79     WithColor(Printer, PDB_ColorItem::Offset).get()
80         << "+" << format_hex(Offset + Var.getOffset(), 4)
81         << " [sizeof=" << Length << "] ";
82     dumpSymbolTypeAndName(*VarType, Var.getName());
83     Printer << " : ";
84     WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getLength();
85     break;
86   default:
87     Printer.NewLine();
88     Printer << "data [sizeof=" << Length << "] ";
89     Printer << "unknown(" << LocType << ") ";
90     WithColor(Printer, PDB_ColorItem::Identifier).get() << Var.getName();
91     break;
92   }
93 }
94 
95 void VariableDumper::startVbptr(uint32_t Offset, uint32_t Size) {
96   Printer.NewLine();
97   Printer << "vbptr ";
98 
99   WithColor(Printer, PDB_ColorItem::Offset).get()
100       << "+" << format_hex(Offset, 4) << " [sizeof=" << Size << "] ";
101 }
102 
103 void VariableDumper::start(const PDBSymbolTypeVTable &Var, uint32_t Offset) {
104   Printer.NewLine();
105   Printer << "vfptr ";
106   auto VTableType = cast<PDBSymbolTypePointer>(Var.getType());
107   uint32_t PointerSize = VTableType->getLength();
108 
109   WithColor(Printer, PDB_ColorItem::Offset).get()
110       << "+" << format_hex(Offset + Var.getOffset(), 4)
111       << " [sizeof=" << PointerSize << "] ";
112 }
113 
114 void VariableDumper::dump(const PDBSymbolTypeArray &Symbol) {
115   auto ElementType = Symbol.getElementType();
116   assert(ElementType);
117   if (!ElementType)
118     return;
119   ElementType->dump(*this);
120 }
121 
122 void VariableDumper::dumpRight(const PDBSymbolTypeArray &Symbol) {
123   auto ElementType = Symbol.getElementType();
124   assert(ElementType);
125   if (!ElementType)
126     return;
127   Printer << '[' << Symbol.getCount() << ']';
128   ElementType->dumpRight(*this);
129 }
130 
131 void VariableDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
132   BuiltinDumper Dumper(Printer);
133   Dumper.start(Symbol);
134 }
135 
136 void VariableDumper::dump(const PDBSymbolTypeEnum &Symbol) {
137   WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
138 }
139 
140 void VariableDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
141   auto ReturnType = Symbol.getReturnType();
142   ReturnType->dump(*this);
143   Printer << " ";
144 
145   uint32_t ClassParentId = Symbol.getClassParentId();
146   auto ClassParent =
147       Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(
148           ClassParentId);
149 
150   if (ClassParent) {
151     WithColor(Printer, PDB_ColorItem::Identifier).get()
152       << ClassParent->getName();
153     Printer << "::";
154   }
155 }
156 
157 void VariableDumper::dumpRight(const PDBSymbolTypeFunctionSig &Symbol) {
158   Printer << "(";
159   if (auto Arguments = Symbol.getArguments()) {
160     uint32_t Index = 0;
161     while (auto Arg = Arguments->getNext()) {
162       Arg->dump(*this);
163       if (++Index < Arguments->getChildCount())
164         Printer << ", ";
165     }
166   }
167   Printer << ")";
168 
169   if (Symbol.isConstType())
170     WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";
171   if (Symbol.isVolatileType())
172     WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";
173 
174   if (Symbol.getRawSymbol().isRestrictedType())
175     WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict";
176 }
177 
178 void VariableDumper::dump(const PDBSymbolTypePointer &Symbol) {
179   auto PointeeType = Symbol.getPointeeType();
180   if (!PointeeType)
181     return;
182   PointeeType->dump(*this);
183   if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) {
184     // A hack to get the calling convention in the right spot.
185     Printer << " (";
186     PDB_CallingConv CC = FuncSig->getCallingConvention();
187     WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";
188   } else if (isa<PDBSymbolTypeArray>(PointeeType)) {
189     Printer << " (";
190   }
191   Printer << (Symbol.isReference() ? "&" : "*");
192   if (Symbol.isConstType())
193     WithColor(Printer, PDB_ColorItem::Keyword).get() << " const ";
194   if (Symbol.isVolatileType())
195     WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile ";
196 
197   if (Symbol.getRawSymbol().isRestrictedType())
198     WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict ";
199 }
200 
201 void VariableDumper::dumpRight(const PDBSymbolTypePointer &Symbol) {
202   auto PointeeType = Symbol.getPointeeType();
203   assert(PointeeType);
204   if (!PointeeType)
205     return;
206   if (isa<PDBSymbolTypeFunctionSig>(PointeeType) ||
207       isa<PDBSymbolTypeArray>(PointeeType)) {
208     Printer << ")";
209   }
210   PointeeType->dumpRight(*this);
211 }
212 
213 void VariableDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
214   WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef ";
215   WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
216 }
217 
218 void VariableDumper::dump(const PDBSymbolTypeUDT &Symbol) {
219   WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
220 }
221 
222 void VariableDumper::dumpSymbolTypeAndName(const PDBSymbol &Type,
223                                            StringRef Name) {
224   Type.dump(*this);
225   WithColor(Printer, PDB_ColorItem::Identifier).get() << " " << Name;
226   Type.dumpRight(*this);
227 }
228