1//===- VariableDumper.cpp - -------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "VariableDumper.h" 11 12#include "BuiltinDumper.h" 13#include "LinePrinter.h" 14#include "llvm-pdbdump.h" 15#include "FunctionDumper.h" 16 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/PDBSymbolTypeFunctionSig.h" 22#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" 23#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" 24#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" 25#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" 26 27#include "llvm/Support/Format.h" 28 29using namespace llvm; 30using namespace llvm::pdb; 31 32VariableDumper::VariableDumper(LinePrinter &P) 33 : PDBSymDumper(true), Printer(P) {} 34 35void VariableDumper::start(const PDBSymbolData &Var) { 36 if (Var.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated) 37 return; 38 if (Printer.IsSymbolExcluded(Var.getName())) 39 return; 40 41 auto VarType = Var.getType(); 42 43 switch (auto LocType = Var.getLocationType()) { 44 case PDB_LocType::Static: 45 Printer.NewLine(); 46 Printer << "data ["; 47 WithColor(Printer, PDB_ColorItem::Address).get() 48 << format_hex(Var.getVirtualAddress(), 10); 49 Printer << "] "; 50 WithColor(Printer, PDB_ColorItem::Keyword).get() << "static "; 51 dumpSymbolTypeAndName(*VarType, Var.getName()); 52 break; 53 case PDB_LocType::Constant: 54 if (isa<PDBSymbolTypeEnum>(*VarType)) 55 break; 56 Printer.NewLine(); 57 Printer << "data "; 58 WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; 59 dumpSymbolTypeAndName(*VarType, Var.getName()); 60 Printer << " = "; 61 WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getValue(); 62 break; 63 case PDB_LocType::ThisRel: 64 Printer.NewLine(); 65 Printer << "data "; 66 WithColor(Printer, PDB_ColorItem::Offset).get() 67 << "+" << format_hex(Var.getOffset(), 4) << " "; 68 dumpSymbolTypeAndName(*VarType, Var.getName()); 69 break; 70 case PDB_LocType::BitField: 71 Printer.NewLine(); 72 Printer << "data "; 73 WithColor(Printer, PDB_ColorItem::Offset).get() 74 << "+" << format_hex(Var.getOffset(), 4) << " "; 75 dumpSymbolTypeAndName(*VarType, Var.getName()); 76 Printer << " : "; 77 WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Var.getLength(); 78 break; 79 default: 80 Printer.NewLine(); 81 Printer << "data "; 82 Printer << "unknown(" << LocType << ") "; 83 WithColor(Printer, PDB_ColorItem::Identifier).get() << Var.getName(); 84 break; 85 } 86} 87 88void VariableDumper::dump(const PDBSymbolTypeBuiltin &Symbol) { 89 BuiltinDumper Dumper(Printer); 90 Dumper.start(Symbol); 91} 92 93void VariableDumper::dump(const PDBSymbolTypeEnum &Symbol) { 94 WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); 95} 96 97void VariableDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {} 98 99void VariableDumper::dump(const PDBSymbolTypePointer &Symbol) { 100 auto PointeeType = Symbol.getPointeeType(); 101 if (!PointeeType) 102 return; 103 104 if (auto Func = dyn_cast<PDBSymbolFunc>(PointeeType.get())) { 105 FunctionDumper NestedDumper(Printer); 106 FunctionDumper::PointerType Pointer = 107 Symbol.isReference() ? FunctionDumper::PointerType::Reference 108 : FunctionDumper::PointerType::Pointer; 109 NestedDumper.start(*Func, Pointer); 110 } else { 111 if (Symbol.isConstType()) 112 WithColor(Printer, PDB_ColorItem::Keyword).get() << "const "; 113 if (Symbol.isVolatileType()) 114 WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile "; 115 PointeeType->dump(*this); 116 Printer << (Symbol.isReference() ? "&" : "*"); 117 } 118} 119 120void VariableDumper::dump(const PDBSymbolTypeTypedef &Symbol) { 121 WithColor(Printer, PDB_ColorItem::Keyword).get() << "typedef "; 122 WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); 123} 124 125void VariableDumper::dump(const PDBSymbolTypeUDT &Symbol) { 126 WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName(); 127} 128 129void VariableDumper::dumpSymbolTypeAndName(const PDBSymbol &Type, 130 StringRef Name) { 131 if (auto *ArrayType = dyn_cast<PDBSymbolTypeArray>(&Type)) { 132 std::string IndexSpec; 133 raw_string_ostream IndexStream(IndexSpec); 134 std::unique_ptr<PDBSymbol> ElementType = ArrayType->getElementType(); 135 while (auto NestedArray = dyn_cast<PDBSymbolTypeArray>(ElementType.get())) { 136 IndexStream << "["; 137 IndexStream << NestedArray->getCount(); 138 IndexStream << "]"; 139 ElementType = NestedArray->getElementType(); 140 } 141 IndexStream << "[" << ArrayType->getCount() << "]"; 142 ElementType->dump(*this); 143 WithColor(Printer, PDB_ColorItem::Identifier).get() << " " << Name; 144 Printer << IndexStream.str(); 145 } else { 146 if (!tryDumpFunctionPointer(Type, Name)) { 147 Type.dump(*this); 148 WithColor(Printer, PDB_ColorItem::Identifier).get() << " " << Name; 149 } 150 } 151} 152 153bool VariableDumper::tryDumpFunctionPointer(const PDBSymbol &Type, 154 StringRef Name) { 155 // Function pointers come across as pointers to function signatures. But the 156 // signature carries no name, so we have to handle this case separately. 157 if (auto *PointerType = dyn_cast<PDBSymbolTypePointer>(&Type)) { 158 auto PointeeType = PointerType->getPointeeType(); 159 if (auto *FunctionSig = 160 dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) { 161 FunctionDumper Dumper(Printer); 162 FunctionDumper::PointerType PT = FunctionDumper::PointerType::Pointer; 163 if (PointerType->isReference()) 164 PT = FunctionDumper::PointerType::Reference; 165 std::string NameStr(Name.begin(), Name.end()); 166 Dumper.start(*FunctionSig, NameStr.c_str(), PT); 167 return true; 168 } 169 } 170 return false; 171} 172