llvm-pdbdump: Improve printing of functions and signatures.
authorZachary Turner <zturner@google.com>
Fri, 13 Feb 2015 17:57:09 +0000 (17:57 +0000)
committerZachary Turner <zturner@google.com>
Fri, 13 Feb 2015 17:57:09 +0000 (17:57 +0000)
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
include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h
lib/DebugInfo/PDB/PDBSymbolExe.cpp
lib/DebugInfo/PDB/PDBSymbolFunc.cpp
lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp
lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp

index 6b7af0c87fe879c3b2fbc44e9c56a3fe5cc2281a..a521acff547fc03c06415bb262ff7688c082ef94 100644 (file)
@@ -24,6 +24,8 @@ public:
 
   void dump(raw_ostream &OS, int Indent, PDB_DumpLevel Level) const override;
 
+  std::unique_ptr<PDBSymbolTypeFunctionSig> getSignature() const;
+
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::Function)
 
   FORWARD_SYMBOL_METHOD(getAccess)
index 3737eccd5dbf473f440b09fd491b0245ddde087c..e81afcbd75e14674c4668cfe36bd20fd2b3987cf 100644 (file)
@@ -24,7 +24,12 @@ public:
 
   DECLARE_PDB_SYMBOL_CONCRETE_TYPE(PDB_SymType::FunctionSig)
 
+  std::unique_ptr<PDBSymbol> getReturnType() const;
+  std::unique_ptr<IPDBEnumSymbols> getArguments() const;
+  std::unique_ptr<PDBSymbol> 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)
index 69f928415f1c52ce525136dc23610b3d393a7e5e..366c748ca200b0e98957b86be93ae28a77765654 100644 (file)
@@ -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";
   }
index 1b52a2670b1821fc72bf95a1067bb1d4af71d451..0195ce35ab03a7fbb51fbf839f53e33cc666ce7c 100644 (file)
@@ -23,6 +23,10 @@ PDBSymbolFunc::PDBSymbolFunc(const IPDBSession &PDBSession,
                              std::unique_ptr<IPDBRawSymbol> Symbol)
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
+std::unique_ptr<PDBSymbolTypeFunctionSig> PDBSymbolFunc::getSignature() const {
+  return Session.getConcreteSymbolById<PDBSymbolTypeFunctionSig>(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<PDBSymbolTypeFunctionSig>(
-            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<PDBSymbolTypeUDT>(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<PDBSymbolTypeUDT>(Class.get()))
+            OS << UDT->getName() << "::";
+          else
+            OS << "{class " << Class->getSymTag() << "}::";
+        }
+      }
+      OS << getName();
     }
-    OS << getName();
   } else {
     OS << getName();
   }
index 24497ed98900556ca2e11e7f73cb4b3b7fbb4362..db821d3db385369bf30e53a1f63ed08f0a6847e2 100644 (file)
 
 using namespace llvm;
 
+namespace {
+class FunctionArgEnumerator : public IPDBEnumSymbols {
+public:
+  typedef ConcreteSymbolEnumerator<PDBSymbolTypeFunctionArg> ArgEnumeratorType;
+
+  FunctionArgEnumerator(const IPDBSession &PDBSession,
+                        const PDBSymbolTypeFunctionSig &Sig)
+      : Session(PDBSession),
+        Enumerator(Sig.findAllChildren<PDBSymbolTypeFunctionArg>()) {}
+
+  FunctionArgEnumerator(const IPDBSession &PDBSession,
+                        std::unique_ptr<ArgEnumeratorType> ArgEnumerator)
+      : Session(PDBSession), Enumerator(std::move(ArgEnumerator)) {}
+
+  uint32_t getChildCount() const { return Enumerator->getChildCount(); }
+
+  std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const {
+    auto FunctionArgSymbol = Enumerator->getChildAtIndex(Index);
+    if (!FunctionArgSymbol)
+      return nullptr;
+    return Session.getSymbolById(FunctionArgSymbol->getTypeId());
+  }
+
+  std::unique_ptr<PDBSymbol> getNext() {
+    auto FunctionArgSymbol = Enumerator->getNext();
+    if (!FunctionArgSymbol)
+      return nullptr;
+    return Session.getSymbolById(FunctionArgSymbol->getTypeId());
+  }
+
+  void reset() { Enumerator->reset(); }
+
+  MyType *clone() const {
+    std::unique_ptr<ArgEnumeratorType> Clone(Enumerator->clone());
+    return new FunctionArgEnumerator(Session, std::move(Clone));
+  }
+
+private:
+  const IPDBSession &Session;
+  std::unique_ptr<ArgEnumeratorType> Enumerator;
+};
+}
+
 PDBSymbolTypeFunctionSig::PDBSymbolTypeFunctionSig(
     const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> 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<PDBSymbol> 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<IPDBEnumSymbols>
+PDBSymbolTypeFunctionSig::getArguments() const {
+  return llvm::make_unique<FunctionArgEnumerator>(Session, *this);
+}
+
+std::unique_ptr<PDBSymbol> 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<PDBSymbolTypeFunctionArg>()) {
+  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);
 }
index 05abb675fb646d20ba31edd159faad602d10d7f0..dbad00696d66758b9a1eb49a1e5db32d683c3b6a 100644 (file)
@@ -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 <utility>
 
@@ -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<PDBSymbolTypeFunctionSig>(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()) ? "&" : "*");
+    }
+  }
 }