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