271 lines · cpp
1//===- PrettyFunctionDumper.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "PrettyFunctionDumper.h"10#include "PrettyBuiltinDumper.h"11 12#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"13#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"14#include "llvm/DebugInfo/PDB/IPDBSession.h"15#include "llvm/DebugInfo/PDB/Native/LinePrinter.h"16#include "llvm/DebugInfo/PDB/PDBExtras.h"17#include "llvm/DebugInfo/PDB/PDBSymbolData.h"18#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"19#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"20#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"21#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"22#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"23#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"24#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"25#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"26#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"27#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"28#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"29#include "llvm/Support/Format.h"30#include "llvm/Support/FormatVariadic.h"31 32using namespace llvm;33using namespace llvm::codeview;34using namespace llvm::pdb;35 36namespace {37template <class T>38void dumpClassParentWithScopeOperator(const T &Symbol, LinePrinter &Printer,39 FunctionDumper &Dumper) {40 uint32_t ClassParentId = Symbol.getClassParentId();41 auto ClassParent =42 Symbol.getSession().template getConcreteSymbolById<PDBSymbolTypeUDT>(43 ClassParentId);44 if (!ClassParent)45 return;46 47 WithColor(Printer, PDB_ColorItem::Type).get() << ClassParent->getName();48 Printer << "::";49}50}51 52FunctionDumper::FunctionDumper(LinePrinter &P)53 : PDBSymDumper(true), Printer(P) {}54 55void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol,56 const char *Name, PointerType Pointer) {57 auto ReturnType = Symbol.getReturnType();58 if (!ReturnType)59 Printer << "<unknown-type>";60 else61 ReturnType->dump(*this);62 Printer << " ";63 uint32_t ClassParentId = Symbol.getClassParentId();64 auto ClassParent =65 Symbol.getSession().getConcreteSymbolById<PDBSymbolTypeUDT>(66 ClassParentId);67 68 PDB_CallingConv CC = Symbol.getCallingConvention();69 bool ShouldDumpCallingConvention = true;70 if ((ClassParent && CC == CallingConvention::ThisCall) ||71 (!ClassParent && CC == CallingConvention::NearStdCall)) {72 ShouldDumpCallingConvention = false;73 }74 75 if (Pointer == PointerType::None) {76 if (ShouldDumpCallingConvention)77 WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";78 if (ClassParent) {79 Printer << "(";80 WithColor(Printer, PDB_ColorItem::Identifier).get()81 << ClassParent->getName();82 Printer << "::)";83 }84 } else {85 Printer << "(";86 if (ShouldDumpCallingConvention)87 WithColor(Printer, PDB_ColorItem::Keyword).get() << CC << " ";88 if (ClassParent) {89 WithColor(Printer, PDB_ColorItem::Identifier).get()90 << ClassParent->getName();91 Printer << "::";92 }93 if (Pointer == PointerType::Reference)94 Printer << "&";95 else96 Printer << "*";97 if (Name)98 WithColor(Printer, PDB_ColorItem::Identifier).get() << Name;99 Printer << ")";100 }101 102 Printer << "(";103 if (auto ChildEnum = Symbol.getArguments()) {104 uint32_t Index = 0;105 while (auto Arg = ChildEnum->getNext()) {106 Arg->dump(*this);107 if (++Index < ChildEnum->getChildCount())108 Printer << ", ";109 }110 }111 Printer << ")";112 113 if (Symbol.isConstType())114 WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";115 if (Symbol.isVolatileType())116 WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";117}118 119void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) {120 uint64_t FuncStart = Symbol.getVirtualAddress();121 uint64_t FuncEnd = FuncStart + Symbol.getLength();122 123 Printer << "func [";124 WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10);125 if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) {126 uint64_t Prologue = DebugStart->getVirtualAddress() - FuncStart;127 WithColor(Printer, PDB_ColorItem::Offset).get()128 << formatv("+{0,2}", Prologue);129 }130 Printer << " - ";131 WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10);132 if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) {133 uint64_t Epilogue = FuncEnd - DebugEnd->getVirtualAddress();134 WithColor(Printer, PDB_ColorItem::Offset).get()135 << formatv("-{0,2}", Epilogue);136 }137 138 WithColor(Printer, PDB_ColorItem::Comment).get()139 << formatv(" | sizeof={0,3}", Symbol.getLength());140 Printer << "] (";141 142 if (Symbol.hasFramePointer()) {143 WithColor(Printer, PDB_ColorItem::Register).get()144 << CPURegister{Symbol.getRawSymbol().getPlatform(),145 Symbol.getLocalBasePointerRegisterId()};146 } else {147 WithColor(Printer, PDB_ColorItem::Register).get() << "FPO";148 }149 Printer << ") ";150 151 if (Symbol.isVirtual() || Symbol.isPureVirtual())152 WithColor(Printer, PDB_ColorItem::Keyword).get() << "virtual ";153 154 auto Signature = Symbol.getSignature();155 if (!Signature) {156 WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();157 if (Pointer == PointerType::Pointer)158 Printer << "*";159 else if (Pointer == FunctionDumper::PointerType::Reference)160 Printer << "&";161 return;162 }163 164 auto ReturnType = Signature->getReturnType();165 ReturnType->dump(*this);166 Printer << " ";167 168 auto ClassParent = Symbol.getClassParent();169 CallingConvention CC = Signature->getCallingConvention();170 if (Pointer != FunctionDumper::PointerType::None)171 Printer << "(";172 173 if ((ClassParent && CC != CallingConvention::ThisCall) ||174 (!ClassParent && CC != CallingConvention::NearStdCall)) {175 WithColor(Printer, PDB_ColorItem::Keyword).get()176 << Signature->getCallingConvention() << " ";177 }178 WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();179 if (Pointer != FunctionDumper::PointerType::None) {180 if (Pointer == PointerType::Pointer)181 Printer << "*";182 else if (Pointer == FunctionDumper::PointerType::Reference)183 Printer << "&";184 Printer << ")";185 }186 187 Printer << "(";188 if (auto Arguments = Symbol.getArguments()) {189 uint32_t Index = 0;190 while (auto Arg = Arguments->getNext()) {191 auto ArgType = Arg->getType();192 ArgType->dump(*this);193 WithColor(Printer, PDB_ColorItem::Identifier).get() << " "194 << Arg->getName();195 if (++Index < Arguments->getChildCount())196 Printer << ", ";197 }198 if (Signature->isCVarArgs())199 Printer << ", ...";200 }201 Printer << ")";202 if (Symbol.isConstType())203 WithColor(Printer, PDB_ColorItem::Keyword).get() << " const";204 if (Symbol.isVolatileType())205 WithColor(Printer, PDB_ColorItem::Keyword).get() << " volatile";206 if (Symbol.isPureVirtual())207 Printer << " = 0";208}209 210void FunctionDumper::dump(const PDBSymbolTypeArray &Symbol) {211 auto ElementType = Symbol.getElementType();212 213 ElementType->dump(*this);214 Printer << "[";215 WithColor(Printer, PDB_ColorItem::LiteralValue).get() << Symbol.getLength();216 Printer << "]";217}218 219void FunctionDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {220 BuiltinDumper Dumper(Printer);221 Dumper.start(Symbol);222}223 224void FunctionDumper::dump(const PDBSymbolTypeEnum &Symbol) {225 dumpClassParentWithScopeOperator(Symbol, Printer, *this);226 WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();227}228 229void FunctionDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) {230 // PDBSymbolTypeFunctionArg is just a shim over the real argument. Just drill231 // through to the real thing and dump it.232 uint32_t TypeId = Symbol.getTypeId();233 auto Type = Symbol.getSession().getSymbolById(TypeId);234 if (Type)235 Type->dump(*this);236 else237 Printer << "<unknown-type>";238}239 240void FunctionDumper::dump(const PDBSymbolTypeTypedef &Symbol) {241 dumpClassParentWithScopeOperator(Symbol, Printer, *this);242 WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();243}244 245void FunctionDumper::dump(const PDBSymbolTypePointer &Symbol) {246 auto PointeeType = Symbol.getPointeeType();247 if (!PointeeType)248 return;249 250 if (auto FuncSig = unique_dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType)) {251 FunctionDumper NestedDumper(Printer);252 PointerType Pointer =253 Symbol.isReference() ? PointerType::Reference : PointerType::Pointer;254 NestedDumper.start(*FuncSig, nullptr, Pointer);255 } else {256 if (Symbol.isConstType())257 WithColor(Printer, PDB_ColorItem::Keyword).get() << "const ";258 if (Symbol.isVolatileType())259 WithColor(Printer, PDB_ColorItem::Keyword).get() << "volatile ";260 PointeeType->dump(*this);261 Printer << (Symbol.isReference() ? "&" : "*");262 263 if (Symbol.getRawSymbol().isRestrictedType())264 WithColor(Printer, PDB_ColorItem::Keyword).get() << " __restrict";265 }266}267 268void FunctionDumper::dump(const PDBSymbolTypeUDT &Symbol) {269 WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();270}271