]> granicus.if.org Git - llvm/commitdiff
[llvm-pdbdump] Support dynamic load address and external symbols.
authorZachary Turner <zturner@google.com>
Fri, 1 May 2015 20:24:26 +0000 (20:24 +0000)
committerZachary Turner <zturner@google.com>
Fri, 1 May 2015 20:24:26 +0000 (20:24 +0000)
This patch adds the --load-address command line option to
llvm-pdbdump, which dumps all addresses assuming the module has
loaded at the specified address.

Additionally, this patch adds an option to llvm-pdbdump to support
dumping of public symbols (i.e. symbols with external linkage).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236342 91177308-0d34-0410-b5e6-96231b3b80d8

14 files changed:
include/llvm/DebugInfo/PDB/DIA/DIASession.h
include/llvm/DebugInfo/PDB/IPDBSession.h
include/llvm/DebugInfo/PDB/PDBContext.h
lib/DebugInfo/PDB/DIA/DIASession.cpp
test/tools/llvm-pdbdump/Inputs/LoadAddressTest.cpp [new file with mode: 0644]
test/tools/llvm-pdbdump/Inputs/LoadAddressTest.pdb [new file with mode: 0644]
test/tools/llvm-pdbdump/load-address.test [new file with mode: 0644]
tools/llvm-pdbdump/CMakeLists.txt
tools/llvm-pdbdump/CompilandDumper.cpp
tools/llvm-pdbdump/ExternalSymbolDumper.cpp [new file with mode: 0644]
tools/llvm-pdbdump/ExternalSymbolDumper.h [new file with mode: 0644]
tools/llvm-pdbdump/FunctionDumper.cpp
tools/llvm-pdbdump/VariableDumper.cpp
tools/llvm-pdbdump/llvm-pdbdump.cpp

index b8d1f1ca5bf92fbbd0f02f69ce9c448573fe6996..9a8600fb85ec8446ef395d5eec9643fcc1bd812c 100644 (file)
@@ -30,7 +30,8 @@ public:
   std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override;
 
   std::unique_ptr<PDBSymbol>
-  findSymbolByAddress(uint64_t Address) const override;
+  findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override;
+
   std::unique_ptr<IPDBEnumLineNumbers>
   findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override;
 
index f1debc02bc602b4b3e9db2258646519746733289..a130a38a653844272aac0a857ff1b65aeee9da86 100644 (file)
@@ -44,7 +44,7 @@ public:
   }
 
   virtual std::unique_ptr<PDBSymbol>
-  findSymbolByAddress(uint64_t Address) const = 0;
+  findSymbolByAddress(uint64_t Address, PDB_SymType Type) const = 0;
   virtual std::unique_ptr<IPDBEnumLineNumbers>
   findLineNumbersByAddress(uint64_t Address, uint32_t Length) const = 0;
 
index 88a11c13caafb4e5c9ca345e266ee3b405958efe..2454a7c19212bb79535e7ff54d0ac0ffe86fb276 100644 (file)
@@ -32,7 +32,7 @@ class PDBContext : public DIContext {
 
 public:
   PDBContext(const object::COFFObjectFile &Object,
-             std::unique_ptr<IPDBSession> PDBSession);
+             std::unique_ptr<IPDBSession> PDBSession, bool RelativeAddress);
 
   static bool classof(const DIContext *DICtx) {
     return DICtx->getKind() == CK_PDB;
index e3e3fc05ab30adc7cc6ef1715ad8f0d11f5071b9..99fe750ebac635c456a3ab72ccf5da9655c58239 100644 (file)
@@ -141,10 +141,18 @@ std::unique_ptr<PDBSymbol> DIASession::getSymbolById(uint32_t SymbolId) const {
 }
 
 std::unique_ptr<PDBSymbol>
-DIASession::findSymbolByAddress(uint64_t Address) const {
+DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
+  enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+
   CComPtr<IDiaSymbol> Symbol;
-  if (S_OK != Session->findSymbolByVA(Address, SymTagNull, &Symbol))
-    return nullptr;
+  if (S_OK != Session->findSymbolByVA(Address, EnumVal, &Symbol)) {
+    ULONGLONG LoadAddr = 0;
+    if (S_OK != Session->get_loadAddress(&LoadAddr))
+      return nullptr;
+    DWORD RVA = static_cast<DWORD>(Address - LoadAddr);
+    if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol))
+      return nullptr;
+  }
   auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
   return PDBSymbol::create(*this, std::move(RawSymbol));
 }
diff --git a/test/tools/llvm-pdbdump/Inputs/LoadAddressTest.cpp b/test/tools/llvm-pdbdump/Inputs/LoadAddressTest.cpp
new file mode 100644 (file)
index 0000000..bb6ed4a
--- /dev/null
@@ -0,0 +1,6 @@
+// Compile with "cl /c /Zi /GR- LoadAddressTest.cpp"\r
+// Link with "link LoadAddressTest.obj /debug /nodefaultlib /entry:main"\r
+\r
+int main(int argc, char **argv) {\r
+  return 0;\r
+}\r
diff --git a/test/tools/llvm-pdbdump/Inputs/LoadAddressTest.pdb b/test/tools/llvm-pdbdump/Inputs/LoadAddressTest.pdb
new file mode 100644 (file)
index 0000000..e302e9b
Binary files /dev/null and b/test/tools/llvm-pdbdump/Inputs/LoadAddressTest.pdb differ
diff --git a/test/tools/llvm-pdbdump/load-address.test b/test/tools/llvm-pdbdump/load-address.test
new file mode 100644 (file)
index 0000000..7a5a4db
--- /dev/null
@@ -0,0 +1,10 @@
+; RUN: llvm-pdbdump -externals %p/Inputs/LoadAddressTest.pdb \\r
+; RUN:    | FileCheck --check-prefix=RVA %s\r
+; RUN: llvm-pdbdump -externals -load-address=0x40000000 \\r
+; RUN: %p/Inputs/LoadAddressTest.pdb | FileCheck --check-prefix=VA %s\r
+\r
+; RVA: ---EXTERNALS---\r
+; RVA: [0x00001010] _main\r
+\r
+; VA: ---EXTERNALS---\r
+; VA: [0x40001010] _main\r
index 4dd339cee57f0ff509c16e552ab86b4874959faa..1907f917079ae6284f6804287297a177301d6bac 100644 (file)
@@ -9,6 +9,7 @@ add_llvm_tool(llvm-pdbdump
   ClassDefinitionDumper.cpp
   CompilandDumper.cpp
   EnumDumper.cpp
+  ExternalSymbolDumper.cpp
   FunctionDumper.cpp
   LinePrinter.cpp
   TypeDumper.cpp
index 86bf32d77d8a2b235bf000cbef277bd8c28cf7cb..68ceb620627b9ff9a0fb24973f56578d3fb00959 100644 (file)
@@ -69,7 +69,7 @@ void CompilandDumper::dump(const PDBSymbolData &Symbol) {
   case PDB_LocType::Static:
     Printer << "data: ";
     WithColor(Printer, PDB_ColorItem::Address).get()
-        << "[" << format_hex(Symbol.getRelativeVirtualAddress(), 10) << "]";
+        << "[" << format_hex(Symbol.getVirtualAddress(), 10) << "]";
     break;
   case PDB_LocType::Constant:
     Printer << "constant: ";
@@ -102,7 +102,7 @@ void CompilandDumper::dump(const PDBSymbolLabel &Symbol) {
   Printer.NewLine();
   Printer << "label ";
   WithColor(Printer, PDB_ColorItem::Address).get()
-      << "[" << format_hex(Symbol.getRelativeVirtualAddress(), 10) << "] ";
+      << "[" << format_hex(Symbol.getVirtualAddress(), 10) << "] ";
   WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
 }
 
@@ -113,16 +113,16 @@ void CompilandDumper::dump(const PDBSymbolThunk &Symbol) {
   Printer.NewLine();
   Printer << "thunk ";
   PDB_ThunkOrdinal Ordinal = Symbol.getThunkOrdinal();
-  uint32_t RVA = Symbol.getRelativeVirtualAddress();
+  uint64_t VA = Symbol.getVirtualAddress();
   if (Ordinal == PDB_ThunkOrdinal::TrampIncremental) {
-    uint32_t Target = Symbol.getTargetRelativeVirtualAddress();
-    WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(RVA, 10);
+    uint64_t Target = Symbol.getTargetVirtualAddress();
+    WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(VA, 10);
     Printer << " -> ";
     WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Target, 10);
   } else {
     WithColor(Printer, PDB_ColorItem::Address).get()
-        << "[" << format_hex(RVA, 10) << " - "
-        << format_hex(RVA + Symbol.getLength(), 10) << "]";
+        << "[" << format_hex(VA, 10) << " - "
+        << format_hex(VA + Symbol.getLength(), 10) << "]";
   }
   Printer << " (";
   WithColor(Printer, PDB_ColorItem::Register).get() << Ordinal;
diff --git a/tools/llvm-pdbdump/ExternalSymbolDumper.cpp b/tools/llvm-pdbdump/ExternalSymbolDumper.cpp
new file mode 100644 (file)
index 0000000..c4e9f47
--- /dev/null
@@ -0,0 +1,40 @@
+//===- ExternalSymbolDumper.cpp -------------------------------- *- C++ *-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ExternalSymbolDumper.h"
+#include "LinePrinter.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
+#include "llvm/Support/Format.h"
+
+using namespace llvm;
+
+ExternalSymbolDumper::ExternalSymbolDumper(LinePrinter &P)
+    : PDBSymDumper(true), Printer(P) {}
+
+void ExternalSymbolDumper::start(const PDBSymbolExe &Symbol) {
+  auto Vars = Symbol.findAllChildren<PDBSymbolPublicSymbol>();
+  while (auto Var = Vars->getNext())
+    Var->dump(*this);
+}
+
+void ExternalSymbolDumper::dump(const PDBSymbolPublicSymbol &Symbol) {
+  std::string LinkageName = Symbol.getName();
+  if (Printer.IsSymbolExcluded(LinkageName))
+    return;
+
+  Printer.NewLine();
+  uint64_t Addr = Symbol.getVirtualAddress();
+
+  Printer << "[";
+  WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(Addr, 10);
+  Printer << "] ";
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << LinkageName;
+}
diff --git a/tools/llvm-pdbdump/ExternalSymbolDumper.h b/tools/llvm-pdbdump/ExternalSymbolDumper.h
new file mode 100644 (file)
index 0000000..d77b09c
--- /dev/null
@@ -0,0 +1,32 @@
+//===- ExternalSymbolDumper.h --------------------------------- *- C++ --*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_EXTERNALSYMBOLDUMPER_H
+#define LLVM_TOOLS_LLVMPDBDUMP_EXTERNALSYMBOLDUMPER_H
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+namespace llvm {
+
+class LinePrinter;
+
+class ExternalSymbolDumper : public PDBSymDumper {
+public:
+  ExternalSymbolDumper(LinePrinter &P);
+
+  void start(const PDBSymbolExe &Symbol);
+
+  void dump(const PDBSymbolPublicSymbol &Symbol) override;
+
+private:
+  LinePrinter &Printer;
+};
+}
+
+#endif
index 419f888ef2f23c50e01cf4fcbb70b5cacb515b3b..9584812e81a945af9f4a8c192f0cebc03e30afcb 100644 (file)
@@ -109,19 +109,19 @@ void FunctionDumper::start(const PDBSymbolTypeFunctionSig &Symbol,
 }
 
 void FunctionDumper::start(const PDBSymbolFunc &Symbol, PointerType Pointer) {
-  uint32_t FuncStart = Symbol.getRelativeVirtualAddress();
-  uint32_t FuncEnd = FuncStart + Symbol.getLength();
+  uint64_t FuncStart = Symbol.getVirtualAddress();
+  uint64_t FuncEnd = FuncStart + Symbol.getLength();
 
   Printer << "func [";
   WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncStart, 10);
   if (auto DebugStart = Symbol.findOneChild<PDBSymbolFuncDebugStart>()) {
-    uint32_t Prologue = DebugStart->getRelativeVirtualAddress() - FuncStart;
+    uint64_t Prologue = DebugStart->getVirtualAddress() - FuncStart;
     WithColor(Printer, PDB_ColorItem::Offset).get() << "+" << Prologue;
   }
   Printer << " - ";
   WithColor(Printer, PDB_ColorItem::Address).get() << format_hex(FuncEnd, 10);
   if (auto DebugEnd = Symbol.findOneChild<PDBSymbolFuncDebugEnd>()) {
-    uint32_t Epilogue = FuncEnd - DebugEnd->getRelativeVirtualAddress();
+    uint64_t Epilogue = FuncEnd - DebugEnd->getVirtualAddress();
     WithColor(Printer, PDB_ColorItem::Offset).get() << "-" << Epilogue;
   }
   Printer << "] (";
index 030610c8c58c23b0828451d613934b0014a652cb..e5665b5fcafa4a42f1c8ad9087a027724dd1248e 100644 (file)
@@ -44,7 +44,7 @@ void VariableDumper::start(const PDBSymbolData &Var) {
     Printer.NewLine();
     Printer << "data [";
     WithColor(Printer, PDB_ColorItem::Address).get()
-        << format_hex(Var.getRelativeVirtualAddress(), 10);
+        << format_hex(Var.getVirtualAddress(), 10);
     Printer << "] ";
     WithColor(Printer, PDB_ColorItem::Keyword).get() << "static ";
     dumpSymbolTypeAndName(*VarType, Var.getName());
index 597683291ffd9a3c7383383031f528219dfac810..4a4c64b80cc18aa0cfe41ab9032cfee4782f14a6 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "llvm-pdbdump.h"
 #include "CompilandDumper.h"
+#include "ExternalSymbolDumper.h"
 #include "FunctionDumper.h"
 #include "LinePrinter.h"
 #include "TypeDumper.h"
@@ -58,6 +59,7 @@ cl::list<std::string> InputFilenames(cl::Positional,
 
 cl::OptionCategory TypeCategory("Symbol Type Options");
 cl::OptionCategory FilterCategory("Filtering Options");
+cl::OptionCategory OtherOptions("Other Options");
 
 cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
                          cl::cat(TypeCategory));
@@ -65,11 +67,18 @@ cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
                       cl::cat(TypeCategory));
 cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
                       cl::cat(TypeCategory));
+cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
+                        cl::cat(TypeCategory));
 cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory));
 cl::opt<bool>
     All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
         cl::cat(TypeCategory));
 
+cl::opt<uint64_t> LoadAddress(
+    "load-address",
+    cl::desc("Assume the module is loaded at the specified address"),
+    cl::cat(OtherOptions));
+
 cl::list<std::string>
     ExcludeTypes("exclude-types",
                  cl::desc("Exclude types by regular expression"),
@@ -121,6 +130,8 @@ static void dumpInput(StringRef Path) {
            << "'.  An unknown error occured.\n";
     return;
   }
+  if (opts::LoadAddress)
+    Session->setLoadAddress(opts::LoadAddress);
 
   LinePrinter Printer(2, outs());
 
@@ -215,6 +226,13 @@ static void dumpInput(StringRef Path) {
     }
     Printer.Unindent();
   }
+  if (opts::Externals) {
+    Printer.NewLine();
+    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
+    Printer.Indent();
+    ExternalSymbolDumper Dumper(Printer);
+    Dumper.start(*GlobalScope);
+  }
   outs().flush();
 }
 
@@ -240,6 +258,7 @@ int main(int argc_, const char *argv_[]) {
     opts::Symbols = true;
     opts::Globals = true;
     opts::Types = true;
+    opts::Externals = true;
   }
   if (opts::ExcludeCompilerGenerated) {
     opts::ExcludeTypes.push_back("__vc_attributes");