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