From 4c0a8b3025868a9eac77e1262b7cacefb15cbff2 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Fri, 13 Feb 2015 17:57:09 +0000 Subject: [PATCH] llvm-pdbdump: Improve printing of functions and signatures. This correctly prints the function pointers, and also prints function signatures for symbols as opposed to just types. So actual functions in your program will now be printed with full name and signature, as opposed to just name as before. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229129 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/DebugInfo/PDB/PDBSymbolFunc.h | 2 + .../DebugInfo/PDB/PDBSymbolTypeFunctionSig.h | 5 + lib/DebugInfo/PDB/PDBSymbolExe.cpp | 20 ++++ lib/DebugInfo/PDB/PDBSymbolFunc.cpp | 43 +++++--- .../PDB/PDBSymbolTypeFunctionSig.cpp | 104 ++++++++++++++---- lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp | 18 ++- 6 files changed, 154 insertions(+), 38 deletions(-) diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h index 6b7af0c87fe..a521acff547 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolFunc.h @@ -24,6 +24,8 @@ public: void dump(raw_ostream &OS, int Indent, PDB_DumpLevel Level) const override; + std::unique_ptr getSignature() const; + DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function) FORWARD_SYMBOL_METHOD(getAccess) diff --git a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h index 3737eccd5db..e81afcbd75e 100644 --- a/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h +++ b/include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h @@ -24,7 +24,12 @@ public: DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionSig) + std::unique_ptr getReturnType() const; + std::unique_ptr getArguments() const; + std::unique_ptr getClassParent() const; + void dump(raw_ostream &OS, int Indent, PDB_DumpLevel Level) const override; + void dumpArgList(raw_ostream &OS) const; FORWARD_SYMBOL_METHOD(getCallingConvention) FORWARD_SYMBOL_METHOD(getClassParentId) diff --git a/lib/DebugInfo/PDB/PDBSymbolExe.cpp b/lib/DebugInfo/PDB/PDBSymbolExe.cpp index 69f928415f1..366c748ca20 100644 --- a/lib/DebugInfo/PDB/PDBSymbolExe.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolExe.cpp @@ -47,6 +47,26 @@ void PDBSymbolExe::dump(raw_ostream &OS, int Indent, auto ChildrenEnum = getChildStats(Stats); OS << stream_indent(Indent + 2) << "Children: " << Stats << "\n"; while (auto Child = ChildrenEnum->getNext()) { + // Skip uninteresting types. These are useful to print as part of type + // hierarchies, but as general children of the global scope, they are + // not very interesting. + switch (Child->getSymTag()) { + case PDB_SymType::ArrayType: + case PDB_SymType::BaseClass: + case PDB_SymType::BuiltinType: + case PDB_SymType::CompilandEnv: + case PDB_SymType::CustomType: + case PDB_SymType::Dimension: + case PDB_SymType::Friend: + case PDB_SymType::ManagedType: + case PDB_SymType::VTableShape: + case PDB_SymType::PointerType: + case PDB_SymType::FunctionSig: + case PDB_SymType::FunctionArg: + continue; + default: + break; + } Child->dump(OS, Indent + 4, PDB_DumpLevel::Normal); OS << "\n"; } diff --git a/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp index 1b52a2670b1..0195ce35ab0 100644 --- a/lib/DebugInfo/PDB/PDBSymbolFunc.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp @@ -23,6 +23,10 @@ PDBSymbolFunc::PDBSymbolFunc(const IPDBSession &PDBSession, std::unique_ptr Symbol) : PDBSymbol(PDBSession, std::move(Symbol)) {} +std::unique_ptr PDBSymbolFunc::getSignature() const { + return Session.getConcreteSymbolById(getTypeId()); +} + void PDBSymbolFunc::dump(raw_ostream &OS, int Indent, PDB_DumpLevel Level) const { OS << stream_indent(Indent); @@ -30,7 +34,7 @@ void PDBSymbolFunc::dump(raw_ostream &OS, int Indent, uint32_t FuncStart = getRelativeVirtualAddress(); uint32_t FuncEnd = FuncStart + getLength(); if (FuncStart == 0 && FuncEnd == 0) { - OS << "func [???]"; + OS << "func [???] "; } else { OS << "func "; OS << "[" << format_hex(FuncStart, 8); @@ -52,21 +56,34 @@ void PDBSymbolFunc::dump(raw_ostream &OS, int Indent, OS << " "; uint32_t FuncSigId = getTypeId(); - if (auto FuncSig = Session.getConcreteSymbolById( - FuncSigId)) { - OS << "(" << FuncSig->getCallingConvention() << ") "; - } + if (auto FuncSig = getSignature()) { + // If we have a signature, dump the name with the signature. + if (auto ReturnType = FuncSig->getReturnType()) { + ReturnType->dump(OS, 0, PDB_DumpLevel::Compact); + OS << " "; + } + + OS << FuncSig->getCallingConvention() << " "; - uint32_t ClassId = getClassParentId(); - if (ClassId != 0) { - if (auto Class = Session.getSymbolById(ClassId)) { - if (auto UDT = dyn_cast(Class.get())) - OS << UDT->getName() << "::"; - else - OS << "{class " << Class->getSymTag() << "}::"; + if (auto ClassParent = FuncSig->getClassParent()) { + ClassParent->dump(OS, 0, PDB_DumpLevel::Compact); + OS << "::"; } + + OS << getName(); + FuncSig->dumpArgList(OS); + } else { + uint32_t ClassId = getClassParentId(); + if (ClassId != 0) { + if (auto Class = Session.getSymbolById(ClassId)) { + if (auto UDT = dyn_cast(Class.get())) + OS << UDT->getName() << "::"; + else + OS << "{class " << Class->getSymTag() << "}::"; + } + } + OS << getName(); } - OS << getName(); } else { OS << getName(); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp index 24497ed9890..db821d3db38 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp @@ -17,35 +17,72 @@ using namespace llvm; +namespace { +class FunctionArgEnumerator : public IPDBEnumSymbols { +public: + typedef ConcreteSymbolEnumerator ArgEnumeratorType; + + FunctionArgEnumerator(const IPDBSession &PDBSession, + const PDBSymbolTypeFunctionSig &Sig) + : Session(PDBSession), + Enumerator(Sig.findAllChildren()) {} + + FunctionArgEnumerator(const IPDBSession &PDBSession, + std::unique_ptr ArgEnumerator) + : Session(PDBSession), Enumerator(std::move(ArgEnumerator)) {} + + uint32_t getChildCount() const { return Enumerator->getChildCount(); } + + std::unique_ptr getChildAtIndex(uint32_t Index) const { + auto FunctionArgSymbol = Enumerator->getChildAtIndex(Index); + if (!FunctionArgSymbol) + return nullptr; + return Session.getSymbolById(FunctionArgSymbol->getTypeId()); + } + + std::unique_ptr getNext() { + auto FunctionArgSymbol = Enumerator->getNext(); + if (!FunctionArgSymbol) + return nullptr; + return Session.getSymbolById(FunctionArgSymbol->getTypeId()); + } + + void reset() { Enumerator->reset(); } + + MyType *clone() const { + std::unique_ptr Clone(Enumerator->clone()); + return new FunctionArgEnumerator(Session, std::move(Clone)); + } + +private: + const IPDBSession &Session; + std::unique_ptr Enumerator; +}; +} + PDBSymbolTypeFunctionSig::PDBSymbolTypeFunctionSig( const IPDBSession &PDBSession, std::unique_ptr Symbol) : PDBSymbol(PDBSession, std::move(Symbol)) {} -void PDBSymbolTypeFunctionSig::dump(raw_ostream &OS, int Indent, - PDB_DumpLevel Level) const { - OS << stream_indent(Indent); +std::unique_ptr PDBSymbolTypeFunctionSig::getReturnType() const { + return Session.getSymbolById(getTypeId()); +} - uint32_t ReturnTypeId = getTypeId(); - if (auto ReturnType = Session.getSymbolById(ReturnTypeId)) { - ReturnType->dump(OS, 0, PDB_DumpLevel::Compact); - OS << " "; - } - // TODO: We need a way to detect if this is a pointer to function so that we - // can print the * between the return type and the argument list. The only - // way to do this is to pass the parent into this function, but that will - // require a larger interface change. - OS << getCallingConvention() << " "; +std::unique_ptr +PDBSymbolTypeFunctionSig::getArguments() const { + return llvm::make_unique(Session, *this); +} + +std::unique_ptr PDBSymbolTypeFunctionSig::getClassParent() const { uint32_t ClassId = getClassParentId(); - if (ClassId != 0) { - if (auto ClassParent = Session.getSymbolById(ClassId)) { - OS << "("; - ClassParent->dump(OS, 0, PDB_DumpLevel::Compact); - OS << "::*)"; - } - } - OS.flush(); + if (ClassId == 0) + return nullptr; + return Session.getSymbolById(ClassId); +} + +void PDBSymbolTypeFunctionSig::dumpArgList(raw_ostream &OS) const { OS << "("; - if (auto ChildEnum = findAllChildren()) { + if (auto ChildEnum = getArguments()) { uint32_t Index = 0; while (auto Arg = ChildEnum->getNext()) { Arg->dump(OS, 0, PDB_DumpLevel::Compact); @@ -54,4 +91,27 @@ void PDBSymbolTypeFunctionSig::dump(raw_ostream &OS, int Indent, } } OS << ")"; + if (isConstType()) + OS << " const"; + if (isVolatileType()) + OS << " volatile"; +} + +void PDBSymbolTypeFunctionSig::dump(raw_ostream &OS, int Indent, + PDB_DumpLevel Level) const { + OS << stream_indent(Indent); + + if (auto ReturnType = getReturnType()) { + ReturnType->dump(OS, 0, PDB_DumpLevel::Compact); + OS << " "; + } + + OS << getCallingConvention() << " "; + if (auto ClassParent = getClassParent()) { + OS << "("; + ClassParent->dump(OS, 0, PDB_DumpLevel::Compact); + OS << "::*)"; + } + + dumpArgList(OS); } diff --git a/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp b/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp index 05abb675fb6..dbad00696d6 100644 --- a/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp +++ b/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp @@ -10,6 +10,7 @@ #include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" #include @@ -27,7 +28,18 @@ void PDBSymbolTypePointer::dump(raw_ostream &OS, int Indent, if (isVolatileType()) OS << "volatile "; uint32_t PointeeId = getTypeId(); - if (auto PointeeType = Session.getSymbolById(PointeeId)) - PointeeType->dump(OS, 0, PDB_DumpLevel::Compact); - OS << ((isReference()) ? "&" : "*"); + if (auto PointeeType = Session.getSymbolById(PointeeId)) { + // Function pointers get special treatment, since we need to print the * in + // the middle of the signature. + if (auto FuncSig = dyn_cast(PointeeType.get())) { + if (auto ReturnType = FuncSig->getReturnType()) + ReturnType->dump(OS, 0, PDB_DumpLevel::Compact); + OS << " (" << FuncSig->getCallingConvention() << " "; + OS << ((isReference()) ? "&" : "*") << ")"; + FuncSig->dumpArgList(OS); + } else { + PointeeType->dump(OS, 0, PDB_DumpLevel::Compact); + OS << ((isReference()) ? "&" : "*"); + } + } } -- 2.34.1