[llvm] 641ae73 - [NativeSession] Implement NativeSession::findSymbolByAddress.

Amy Huang via llvm-commits llvm-commits at lists.llvm.org
Wed May 13 09:39:59 PDT 2020


Author: Amy Huang
Date: 2020-05-13T09:39:25-07:00
New Revision: 641ae73f2eba1a4c52d8ddeefad44f26cc7530f3

URL: https://github.com/llvm/llvm-project/commit/641ae73f2eba1a4c52d8ddeefad44f26cc7530f3
DIFF: https://github.com/llvm/llvm-project/commit/641ae73f2eba1a4c52d8ddeefad44f26cc7530f3.diff

LOG: [NativeSession] Implement NativeSession::findSymbolByAddress.

Summary: This implements searching for function symbols and public symbols by address.

More specifically,
-Implements NativeSession::findSymbolByAddress for function symbols and
public symbols. I think data symbols are also searched for, but isn't
implemented in this patch.
-Adds classes for NativeFunctionSymbol and NativePublicSymbol
-Adds a '-use-native-pdb-reader' option to llvm-symbolizer, for testing
purposes.

Reviewers: rnk, amccarth, labath

Subscribers: mgorny, hiraditya, MaskRay, rupprecht, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D79269

Added: 
    llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
    llvm/include/llvm/DebugInfo/PDB/Native/NativePublicSymbol.h
    llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
    llvm/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp
    llvm/test/tools/llvm-symbolizer/pdb/pdb-native.test

Modified: 
    llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h
    llvm/include/llvm/DebugInfo/PDB/IPDBSession.h
    llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
    llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
    llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
    llvm/lib/DebugInfo/PDB/CMakeLists.txt
    llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp
    llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
    llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
    llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
    llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
    llvm/unittests/DebugInfo/PDB/NativeSessionTest.cpp
    llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp
    llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h
index 6f62e6061f56..09ab9e2861cd 100644
--- a/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h
+++ b/llvm/include/llvm/DebugInfo/PDB/DIA/DIASession.h
@@ -38,13 +38,13 @@ class DIASession : public IPDBSession {
   bool addressForRVA(uint32_t RVA, uint32_t &Section,
                      uint32_t &Offset) const override;
 
-  std::unique_ptr<PDBSymbol>
-  findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override;
+  std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address,
+                                                 PDB_SymType Type) override;
   std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
-                                             PDB_SymType Type) const override;
-  std::unique_ptr<PDBSymbol>
-  findSymbolBySectOffset(uint32_t Section, uint32_t Offset,
-                         PDB_SymType Type) const override;
+                                             PDB_SymType Type) override;
+  std::unique_ptr<PDBSymbol> findSymbolBySectOffset(uint32_t Section,
+                                                    uint32_t Offset,
+                                                    PDB_SymType Type) override;
 
   std::unique_ptr<IPDBEnumLineNumbers>
   findLineNumbers(const PDBSymbolCompiland &Compiland,

diff  --git a/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h b/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h
index aa8d9c76d63e..7e38654c6550 100644
--- a/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h
+++ b/llvm/include/llvm/DebugInfo/PDB/IPDBSession.h
@@ -42,13 +42,12 @@ class IPDBSession {
     return unique_dyn_cast_or_null<T>(getSymbolById(SymbolId));
   }
 
+  virtual std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address,
+                                                         PDB_SymType Type) = 0;
+  virtual std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
+                                                     PDB_SymType Type) = 0;
   virtual std::unique_ptr<PDBSymbol>
-  findSymbolByAddress(uint64_t Address, PDB_SymType Type) const = 0;
-  virtual std::unique_ptr<PDBSymbol>
-  findSymbolByRVA(uint32_t RVA, PDB_SymType Type) const = 0;
-  virtual std::unique_ptr<PDBSymbol>
-  findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
-                         PDB_SymType Type) const = 0;
+  findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type) = 0;
 
   virtual std::unique_ptr<IPDBEnumLineNumbers>
   findLineNumbers(const PDBSymbolCompiland &Compiland,

diff  --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
new file mode 100644
index 000000000000..4adf89f0d69a
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
@@ -0,0 +1,45 @@
+//===- NativeFunctionSymbol.h - info about function symbols -----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEFUNCTIONSYMBOL_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEFUNCTIONSYMBOL_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+namespace llvm {
+namespace pdb {
+
+class NativeFunctionSymbol : public NativeRawSymbol {
+public:
+  NativeFunctionSymbol(NativeSession &Session, SymIndexId Id,
+                       const codeview::ProcSym &Sym);
+
+  ~NativeFunctionSymbol() override;
+
+  void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
+            PdbSymbolIdField RecurseIdFields) const override;
+
+  uint32_t getAddressOffset() const override;
+  uint32_t getAddressSection() const override;
+  std::string getName() const override;
+  PDB_SymType getSymTag() const override;
+  uint64_t getLength() const override;
+  uint32_t getRelativeVirtualAddress() const override;
+  uint64_t getVirtualAddress() const override;
+
+protected:
+  const codeview::ProcSym Sym;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEFUNCTIONSYMBOL_H

diff  --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativePublicSymbol.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativePublicSymbol.h
new file mode 100644
index 000000000000..0a1451530f18
--- /dev/null
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativePublicSymbol.h
@@ -0,0 +1,44 @@
+//===- NativePublicSymbol.h - info about public symbols ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEPUBLICSYMBOL_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEPUBLICSYMBOL_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+namespace llvm {
+namespace pdb {
+
+class NativePublicSymbol : public NativeRawSymbol {
+public:
+  NativePublicSymbol(NativeSession &Session, SymIndexId Id,
+                     const codeview::PublicSym32 &Sym);
+
+  ~NativePublicSymbol() override;
+
+  void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
+            PdbSymbolIdField RecurseIdFields) const override;
+
+  uint32_t getAddressOffset() const override;
+  uint32_t getAddressSection() const override;
+  std::string getName() const override;
+  PDB_SymType getSymTag() const override;
+  uint32_t getRelativeVirtualAddress() const override;
+  uint64_t getVirtualAddress() const override;
+
+protected:
+  const codeview::PublicSym32 Sym;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEPUBLICSYMBOL_H

diff  --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
index 26b1992a03d7..342e63599e66 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSession.h
@@ -54,13 +54,13 @@ class NativeSession : public IPDBSession {
   bool addressForRVA(uint32_t RVA, uint32_t &Section,
                      uint32_t &Offset) const override;
 
-  std::unique_ptr<PDBSymbol>
-  findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override;
+  std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address,
+                                                 PDB_SymType Type) override;
   std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
-                                             PDB_SymType Type) const override;
-  std::unique_ptr<PDBSymbol>
-  findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
-                         PDB_SymType Type) const override;
+                                             PDB_SymType Type) override;
+  std::unique_ptr<PDBSymbol> findSymbolBySectOffset(uint32_t Sect,
+                                                    uint32_t Offset,
+                                                    PDB_SymType Type) override;
 
   std::unique_ptr<IPDBEnumLineNumbers>
   findLineNumbers(const PDBSymbolCompiland &Compiland,
@@ -108,6 +108,8 @@ class NativeSession : public IPDBSession {
   NativeExeSymbol &getNativeGlobalScope() const;
   SymbolCache &getSymbolCache() { return Cache; }
   const SymbolCache &getSymbolCache() const { return Cache; }
+  uint32_t getRVAFromSectOffset(uint32_t Section, uint32_t Offset) const;
+  uint64_t getVAFromSectOffset(uint32_t Section, uint32_t Offset) const;
 
 private:
   void initializeExeSymbol();

diff  --git a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
index bf9eb717f980..33428bfbf427 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
@@ -10,6 +10,8 @@
 #define LLVM_DEBUGINFO_PDB_NATIVE_SYMBOLCACHE_H
 
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntervalMap.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
@@ -51,6 +53,16 @@ class SymbolCache {
   /// Map from global symbol offset to SymIndexId.
   DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
 
+  /// Map from segment and code offset to SymIndexId.
+  DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> AddressToFunctionSymId;
+  DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> AddressToPublicSymId;
+
+  /// Map from virtual address to module index.
+  using IMap =
+      IntervalMap<uint64_t, uint16_t, 8, IntervalMapHalfOpenInfo<uint64_t>>;
+  IMap::Allocator IMapAllocator;
+  IMap AddrToModuleIndex;
+
   SymIndexId createSymbolPlaceholder() {
     SymIndexId Id = Cache.size();
     Cache.push_back(nullptr);
@@ -77,6 +89,15 @@ class SymbolCache {
   SymIndexId createSimpleType(codeview::TypeIndex TI,
                               codeview::ModifierOptions Mods);
 
+  std::unique_ptr<PDBSymbol> findFunctionSymbolBySectOffset(uint32_t Sect,
+                                                            uint32_t Offset);
+  std::unique_ptr<PDBSymbol> findPublicSymbolBySectOffset(uint32_t Sect,
+                                                          uint32_t Offset);
+
+  void parseSectionContribs();
+  Optional<uint16_t> getModuleIndexForAddr(uint32_t Sect,
+                                           uint32_t Offset) const;
+
 public:
   SymbolCache(NativeSession &Session, DbiStream *Dbi);
 
@@ -127,6 +148,9 @@ class SymbolCache {
 
   SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset);
 
+  std::unique_ptr<PDBSymbol>
+  findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type);
+
   std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index);
   uint32_t getNumCompilands() const;
 

diff  --git a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
index b0972ed11581..085e4bb4ccb8 100644
--- a/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
+++ b/llvm/include/llvm/DebugInfo/Symbolize/Symbolize.h
@@ -43,6 +43,7 @@ class LLVMSymbolizer {
     bool Demangle = true;
     bool RelativeAddresses = false;
     bool UntagAddresses = false;
+    bool UseNativePDBReader = false;
     std::string DefaultArch;
     std::vector<std::string> DsymHints;
     std::string FallbackDebugPath;

diff  --git a/llvm/lib/DebugInfo/PDB/CMakeLists.txt b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
index 320ca78b5255..1eda97a06a53 100644
--- a/llvm/lib/DebugInfo/PDB/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/PDB/CMakeLists.txt
@@ -55,6 +55,8 @@ add_pdb_impl_folder(Native
   Native/NativeEnumModules.cpp
   Native/NativeEnumTypes.cpp
   Native/NativeExeSymbol.cpp
+  Native/NativeFunctionSymbol.cpp
+  Native/NativePublicSymbol.cpp
   Native/NativeRawSymbol.cpp
   Native/NativeSymbolEnumerator.cpp
   Native/NativeTypeArray.cpp

diff  --git a/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp b/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp
index 64ffa776bbd6..2729e3236965 100644
--- a/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp
+++ b/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp
@@ -189,8 +189,8 @@ DIASession::getSymbolById(SymIndexId SymbolId) const {
   return PDBSymbol::create(*this, std::move(RawSymbol));
 }
 
-std::unique_ptr<PDBSymbol>
-DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
+std::unique_ptr<PDBSymbol> DIASession::findSymbolByAddress(uint64_t Address,
+                                                           PDB_SymType Type) {
   enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
 
   CComPtr<IDiaSymbol> Symbol;
@@ -207,7 +207,7 @@ DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
 }
 
 std::unique_ptr<PDBSymbol> DIASession::findSymbolByRVA(uint32_t RVA,
-                                                       PDB_SymType Type) const {
+                                                       PDB_SymType Type) {
   enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
 
   CComPtr<IDiaSymbol> Symbol;
@@ -220,7 +220,7 @@ std::unique_ptr<PDBSymbol> DIASession::findSymbolByRVA(uint32_t RVA,
 
 std::unique_ptr<PDBSymbol>
 DIASession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
-                                   PDB_SymType Type) const {
+                                   PDB_SymType Type) {
   enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
 
   CComPtr<IDiaSymbol> Symbol;

diff  --git a/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
new file mode 100644
index 000000000000..2537daa7493c
--- /dev/null
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeFunctionSymbol.cpp
@@ -0,0 +1,57 @@
+//===- NativeFunctionSymbol.cpp - info about function symbols----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeFunctionSymbol::NativeFunctionSymbol(NativeSession &Session,
+                                           SymIndexId Id,
+                                           const codeview::ProcSym &Sym)
+    : NativeRawSymbol(Session, PDB_SymType::Data, Id), Sym(Sym) {}
+
+NativeFunctionSymbol::~NativeFunctionSymbol() {}
+
+void NativeFunctionSymbol::dump(raw_ostream &OS, int Indent,
+                                PdbSymbolIdField ShowIdFields,
+                                PdbSymbolIdField RecurseIdFields) const {
+  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+  dumpSymbolField(OS, "name", getName(), Indent);
+  dumpSymbolField(OS, "length", getLength(), Indent);
+  dumpSymbolField(OS, "offset", getAddressOffset(), Indent);
+  dumpSymbolField(OS, "section", getAddressSection(), Indent);
+}
+
+uint32_t NativeFunctionSymbol::getAddressOffset() const {
+  return Sym.CodeOffset;
+}
+
+uint32_t NativeFunctionSymbol::getAddressSection() const { return Sym.Segment; }
+std::string NativeFunctionSymbol::getName() const {
+  return std::string(Sym.Name);
+}
+
+PDB_SymType NativeFunctionSymbol::getSymTag() const {
+  return PDB_SymType::Function;
+}
+
+uint64_t NativeFunctionSymbol::getLength() const { return Sym.CodeSize; }
+
+uint32_t NativeFunctionSymbol::getRelativeVirtualAddress() const {
+  return Session.getRVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
+}
+
+uint64_t NativeFunctionSymbol::getVirtualAddress() const {
+  return Session.getVAFromSectOffset(Sym.Segment, Sym.CodeOffset);
+}

diff  --git a/llvm/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp b/llvm/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp
new file mode 100644
index 000000000000..7086af7e67a2
--- /dev/null
+++ b/llvm/lib/DebugInfo/PDB/Native/NativePublicSymbol.cpp
@@ -0,0 +1,52 @@
+//===- NativePublicSymbol.cpp - info about public symbols -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativePublicSymbol::NativePublicSymbol(NativeSession &Session, SymIndexId Id,
+                                       const codeview::PublicSym32 &Sym)
+    : NativeRawSymbol(Session, PDB_SymType::Data, Id), Sym(Sym) {}
+
+NativePublicSymbol::~NativePublicSymbol() {}
+
+void NativePublicSymbol::dump(raw_ostream &OS, int Indent,
+                              PdbSymbolIdField ShowIdFields,
+                              PdbSymbolIdField RecurseIdFields) const {
+  NativeRawSymbol::dump(OS, Indent, ShowIdFields, RecurseIdFields);
+  dumpSymbolField(OS, "name", getName(), Indent);
+  dumpSymbolField(OS, "offset", getAddressOffset(), Indent);
+  dumpSymbolField(OS, "section", getAddressSection(), Indent);
+}
+
+uint32_t NativePublicSymbol::getAddressOffset() const { return Sym.Offset; }
+
+uint32_t NativePublicSymbol::getAddressSection() const { return Sym.Segment; }
+
+std::string NativePublicSymbol::getName() const {
+  return std::string(Sym.Name);
+}
+
+PDB_SymType NativePublicSymbol::getSymTag() const {
+  return PDB_SymType::PublicSymbol;
+}
+
+uint32_t NativePublicSymbol::getRelativeVirtualAddress() const {
+  return Session.getRVAFromSectOffset(Sym.Segment, Sym.Offset);
+}
+
+uint64_t NativePublicSymbol::getVirtualAddress() const {
+  return Session.getVAFromSectOffset(Sym.Segment, Sym.Offset);
+}

diff  --git a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
index 9a9254f4302d..043d2361af50 100644
--- a/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
@@ -43,6 +43,7 @@
 using namespace llvm;
 using namespace llvm::msf;
 using namespace llvm::pdb;
+using namespace llvm::codeview;
 
 static DbiStream *getDbiStreamPtr(PDBFile &File) {
   Expected<DbiStream &> DbiS = File.getPDBDbiStream();
@@ -210,13 +211,13 @@ bool NativeSession::addressForVA(uint64_t VA, uint32_t &Section,
 
 bool NativeSession::addressForRVA(uint32_t RVA, uint32_t &Section,
                                   uint32_t &Offset) const {
+  Section = 0;
+  Offset = 0;
+
   auto Dbi = Pdb->getPDBDbiStream();
   if (!Dbi)
     return false;
 
-  Section = 0;
-  Offset = 0;
-
   if ((int32_t)RVA < 0)
     return true;
 
@@ -231,19 +232,25 @@ bool NativeSession::addressForRVA(uint32_t RVA, uint32_t &Section,
 }
 
 std::unique_ptr<PDBSymbol>
-NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
-  return nullptr;
+NativeSession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) {
+  uint32_t Section;
+  uint32_t Offset;
+  addressForVA(Address, Section, Offset);
+  return findSymbolBySectOffset(Section, Offset, Type);
 }
 
-std::unique_ptr<PDBSymbol>
-NativeSession::findSymbolByRVA(uint32_t RVA, PDB_SymType Type) const {
-  return nullptr;
+std::unique_ptr<PDBSymbol> NativeSession::findSymbolByRVA(uint32_t RVA,
+                                                          PDB_SymType Type) {
+  uint32_t Section;
+  uint32_t Offset;
+  addressForRVA(RVA, Section, Offset);
+  return findSymbolBySectOffset(Section, Offset, Type);
 }
 
 std::unique_ptr<PDBSymbol>
 NativeSession::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
-                                      PDB_SymType Type) const {
-  return nullptr;
+                                      PDB_SymType Type) {
+  return Cache.findSymbolBySectOffset(Sect, Offset, Type);
 }
 
 std::unique_ptr<IPDBEnumLineNumbers>
@@ -352,3 +359,24 @@ NativeExeSymbol &NativeSession::getNativeGlobalScope() const {
 
   return Cache.getNativeSymbolById<NativeExeSymbol>(ExeSymbol);
 }
+
+uint32_t NativeSession::getRVAFromSectOffset(uint32_t Section,
+                                             uint32_t Offset) const {
+  if (Section <= 0)
+    return 0;
+
+  auto Dbi = getDbiStreamPtr(*Pdb);
+  if (!Dbi)
+    return 0;
+
+  uint32_t MaxSection = Dbi->getSectionHeaders().size();
+  if (Section > MaxSection + 1)
+    Section = MaxSection + 1;
+  auto &Sec = Dbi->getSectionHeaders()[Section - 1];
+  return Sec.VirtualAddress + Offset;
+}
+
+uint64_t NativeSession::getVAFromSectOffset(uint32_t Section,
+                                            uint32_t Offset) const {
+  return LoadAddress + getRVAFromSectOffset(Section, Offset);
+}

diff  --git a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
index 5cdd628312fe..554eea06dc68 100644
--- a/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
@@ -1,13 +1,18 @@
 #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
 
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
 #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
+#include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
 #include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"
@@ -19,6 +24,7 @@
 #include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
 #include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"
 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
 #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
@@ -62,7 +68,7 @@ static const struct BuiltinTypeEntry {
 };
 
 SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
-    : Session(Session), Dbi(Dbi) {
+    : Session(Session), Dbi(Dbi), AddrToModuleIndex(IMapAllocator) {
   // Id 0 is reserved for the invalid symbol.
   Cache.push_back(nullptr);
 
@@ -281,6 +287,123 @@ SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
   return Id;
 }
 
+std::unique_ptr<PDBSymbol>
+SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
+                                    PDB_SymType Type) {
+  if (AddrToModuleIndex.empty())
+    parseSectionContribs();
+
+  switch (Type) {
+  case PDB_SymType::Function:
+    return findFunctionSymbolBySectOffset(Sect, Offset);
+  case PDB_SymType::PublicSymbol:
+    return findPublicSymbolBySectOffset(Sect, Offset);
+  case PDB_SymType::None: {
+    // FIXME: Implement for PDB_SymType::Data.
+    if (auto Sym = findFunctionSymbolBySectOffset(Sect, Offset))
+      return Sym;
+    return nullptr;
+  }
+  default:
+    return nullptr;
+  }
+}
+
+std::unique_ptr<PDBSymbol>
+SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
+  auto Iter = AddressToFunctionSymId.find({Sect, Offset});
+  if (Iter != AddressToFunctionSymId.end())
+    return getSymbolById(Iter->second);
+
+  if (!Dbi)
+    return nullptr;
+
+  auto Modi = getModuleIndexForAddr(Sect, Offset);
+  if (!Modi)
+    return nullptr;
+
+  DbiModuleDescriptor ModDesc = Dbi->modules().getModuleDescriptor(*Modi);
+  uint16_t StreamIndex = ModDesc.getModuleStreamIndex();
+  if (StreamIndex == kInvalidStreamIndex)
+    return nullptr;
+  auto ModStreamData = Session.getPDBFile().createIndexedStream(StreamIndex);
+  ModuleDebugStreamRef ModS(ModDesc, std::move(ModStreamData));
+  if (auto EC = ModS.reload()) {
+    consumeError(std::move(EC));
+    return nullptr;
+  }
+
+  // Search for the symbol in this module.
+  CVSymbolArray Syms = ModS.getSymbolArray();
+  for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) {
+    if (I->kind() != S_LPROC32 && I->kind() != S_GPROC32)
+      continue;
+    auto PS = cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*I));
+    if (Sect == PS.Segment && Offset >= PS.CodeOffset &&
+        Offset < PS.CodeOffset + PS.CodeSize) {
+      SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS);
+      return getSymbolById(Id);
+    }
+
+    // Jump to the end of this ProcSym.
+    I = Syms.at(PS.End);
+  }
+  return nullptr;
+}
+
+std::unique_ptr<PDBSymbol>
+SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
+  auto Iter = AddressToPublicSymId.find({Sect, Offset});
+  if (Iter != AddressToPublicSymId.end())
+    return getSymbolById(Iter->second);
+
+  auto Publics = Session.getPDBFile().getPDBPublicsStream();
+  if (!Publics)
+    return nullptr;
+
+  auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream();
+  if (!ExpectedSyms)
+    return nullptr;
+  BinaryStreamRef SymStream =
+      ExpectedSyms->getSymbolArray().getUnderlyingStream();
+
+  // Use binary search to find the first public symbol with an address greater
+  // than or equal to Sect, Offset.
+  auto AddrMap = Publics->getAddressMap();
+  auto First = AddrMap.begin();
+  auto It = AddrMap.begin();
+  size_t Count = AddrMap.size();
+  size_t Half;
+  while (Count > 0) {
+    It = First;
+    Half = Count / 2;
+    It += Half;
+    Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
+    if (!Sym) {
+      consumeError(Sym.takeError());
+      return nullptr;
+    }
+
+    auto PS =
+        cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
+    if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <= Offset)) {
+      First = ++It;
+      Count -= Half + 1;
+    } else
+      Count = Half;
+  }
+  --It;
+
+  Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
+  if (!Sym) {
+    consumeError(Sym.takeError());
+    return nullptr;
+  }
+  auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
+  SymIndexId Id = createSymbol<NativePublicSymbol>(PS);
+  return getSymbolById(Id);
+}
+
 std::unique_ptr<PDBSymbolCompiland>
 SymbolCache::getOrCreateCompiland(uint32_t Index) {
   if (!Dbi)
@@ -297,3 +420,41 @@ SymbolCache::getOrCreateCompiland(uint32_t Index) {
 
   return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
 }
+
+void SymbolCache::parseSectionContribs() {
+  if (!Dbi)
+    return;
+
+  class Visitor : public ISectionContribVisitor {
+    NativeSession &Session;
+    IMap &AddrMap;
+
+  public:
+    Visitor(NativeSession &Session, IMap &AddrMap)
+        : Session(Session), AddrMap(AddrMap) {}
+    void visit(const SectionContrib &C) override {
+      if (C.Size == 0)
+        return;
+
+      uint64_t VA = Session.getVAFromSectOffset(C.ISect, C.Off);
+      uint64_t End = VA + C.Size;
+
+      // Ignore overlapping sections based on the assumption that a valid
+      // PDB file should not have overlaps.
+      if (!AddrMap.overlaps(VA, End))
+        AddrMap.insert(VA, End, C.Imod);
+    }
+    void visit(const SectionContrib2 &C) override { visit(C.Base); }
+  };
+
+  Visitor V(Session, AddrToModuleIndex);
+  Dbi->visitSectionContributions(V);
+}
+
+Optional<uint16_t> SymbolCache::getModuleIndexForAddr(uint32_t Sect,
+                                                      uint32_t Offset) const {
+  auto Iter = AddrToModuleIndex.find(Session.getVAFromSectOffset(Sect, Offset));
+  if (Iter == AddrToModuleIndex.end())
+    return None;
+  return Iter.value();
+}

diff  --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
index 768c306dfe38..ff017b078019 100644
--- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
+++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
@@ -555,8 +555,11 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
     if (!EC && DebugInfo != nullptr && !PDBFileName.empty()) {
       using namespace pdb;
       std::unique_ptr<IPDBSession> Session;
-      if (auto Err = loadDataForEXE(PDB_ReaderType::DIA,
-                                    Objects.first->getFileName(), Session)) {
+      PDB_ReaderType ReaderType = Opts.UseNativePDBReader
+                                      ? PDB_ReaderType::Native
+                                      : PDB_ReaderType::DIA;
+      if (auto Err = loadDataForEXE(ReaderType, Objects.first->getFileName(),
+                                    Session)) {
         Modules.emplace(ModuleName, std::unique_ptr<SymbolizableModule>());
         // Return along the PDB filename to provide more context
         return createFileError(PDBFileName, std::move(Err));

diff  --git a/llvm/test/tools/llvm-symbolizer/pdb/pdb-native.test b/llvm/test/tools/llvm-symbolizer/pdb/pdb-native.test
new file mode 100644
index 000000000000..29a770e402ee
--- /dev/null
+++ b/llvm/test/tools/llvm-symbolizer/pdb/pdb-native.test
@@ -0,0 +1,39 @@
+RUN: echo 0x401380 > %t.input
+RUN: echo 0x401390 >> %t.input
+RUN: echo 0x4013A0 >> %t.input
+RUN: echo 0x4013C0 >> %t.input
+RUN: echo 0x4013D0 >> %t.input
+RUN: echo 0x4013E0 >> %t.input
+RUN: echo 0x4013F0 >> %t.input
+RUN: echo 0x401420 >> %t.input
+RUN: llvm-symbolizer -obj="%p/Inputs/test.exe" -use-native-pdb-reader < %t.input \
+RUN:    | FileCheck %s
+RUN: llvm-symbolizer -obj="%p/Inputs/test.exe" -demangle=false -use-native-pdb-reader < %t.input \
+RUN:    | FileCheck %s --check-prefix=CHECK-NO-DEMANGLE
+
+Subtract ImageBase from all the offsets and run the test again with
+--relative-address.
+
+RUN: %python -c 'import sys;print("\n".join([hex(int(x, 16) - 0x400000) for x in sys.stdin]))' < %t.input \
+RUN:    | llvm-symbolizer -obj="%p/Inputs/test.exe" -use-native-pdb-reader -demangle=false --relative-address \
+RUN:    | FileCheck %s --check-prefix=CHECK-NO-DEMANGLE
+
+Currently only finding function/public symbol names is implemented.
+
+CHECK: foo(void)
+CHECK: {{^private_symbol$}}
+CHECK: {{^main}}
+CHECK: {{^foo_cdecl$}}
+CHECK: {{^foo_stdcall$}}
+CHECK: {{^foo_fastcall$}}
+CHECK: {{^foo_vectorcall$}}
+CHECK: NS::Foo::bar(void)
+
+CHECK-NO-DEMANGLE: ?foo@@YAXXZ
+CHECK-NO-DEMANGLE: private_symbol
+CHECK-NO-DEMANGLE: _main
+CHECK-NO-DEMANGLE: _foo_cdecl
+CHECK-NO-DEMANGLE: _foo_stdcall at 0
+CHECK-NO-DEMANGLE: @foo_fastcall at 0
+CHECK-NO-DEMANGLE: foo_vectorcall@@0
+CHECK-NO-DEMANGLE: ?bar at Foo@NS@@QAEXXZ

diff  --git a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
index bb282a52b331..6a702c64a105 100644
--- a/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -163,6 +163,10 @@ static cl::opt<DIPrinter::OutputStyle>
                              clEnumValN(DIPrinter::OutputStyle::GNU, "GNU",
                                         "GNU addr2line style")));
 
+static cl::opt<bool>
+    ClUseNativePDBReader("use-native-pdb-reader", cl::init(0),
+                         cl::desc("Use native PDB functionality"));
+
 static cl::extrahelp
     HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
 
@@ -313,6 +317,7 @@ int main(int argc, char **argv) {
   Opts.FallbackDebugPath = ClFallbackDebugPath;
   Opts.DWPName = ClDwpName;
   Opts.DebugFileDirectory = ClDebugFileDirectory;
+  Opts.UseNativePDBReader = ClUseNativePDBReader;
   Opts.PathStyle = DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath;
   // If both --basenames and --relativenames are specified then pick the last
   // one.

diff  --git a/llvm/unittests/DebugInfo/PDB/NativeSessionTest.cpp b/llvm/unittests/DebugInfo/PDB/NativeSessionTest.cpp
index c0606315c963..002dd6579a46 100644
--- a/llvm/unittests/DebugInfo/PDB/NativeSessionTest.cpp
+++ b/llvm/unittests/DebugInfo/PDB/NativeSessionTest.cpp
@@ -9,6 +9,8 @@
 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
 #include "llvm/DebugInfo/PDB/IPDBSession.h"
 #include "llvm/DebugInfo/PDB/PDB.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
 #include "llvm/Support/Path.h"
 
 #include "llvm/Testing/Support/Error.h"
@@ -30,9 +32,11 @@ static std::string getExePath() {
 
 TEST(NativeSessionTest, TestCreateFromExe) {
   std::unique_ptr<IPDBSession> S;
-  // Tests that the PDB file can be found if it is in the same directory as the
-  // executable.
-  Error E = pdb::loadDataForEXE(PDB_ReaderType::Native, getExePath(), S);
+  std::string ExePath = getExePath();
+  Expected<std::string> PdbPath = NativeSession::searchForPdb({ExePath});
+  ASSERT_TRUE((bool)PdbPath);
+
+  Error E = NativeSession::createFromPdbPath(PdbPath.get(), S);
   ASSERT_THAT_ERROR(std::move(E), Succeeded());
 }
 

diff  --git a/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp b/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp
index f48e8379046f..eb3b696acde7 100644
--- a/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp
+++ b/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp
@@ -82,17 +82,17 @@ class MockSession : public IPDBSession {
                      uint32_t &Offset) const override {
     return false;
   }
-  std::unique_ptr<PDBSymbol>
-  findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override {
+  std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address,
+                                                 PDB_SymType Type) override {
     return nullptr;
   }
   std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
-                                             PDB_SymType Type) const override {
+                                             PDB_SymType Type) override {
     return nullptr;
   }
-  std::unique_ptr<PDBSymbol>
-  findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
-                         PDB_SymType Type) const override {
+  std::unique_ptr<PDBSymbol> findSymbolBySectOffset(uint32_t Sect,
+                                                    uint32_t Offset,
+                                                    PDB_SymType Type) override {
     return nullptr;
   }
   std::unique_ptr<IPDBEnumLineNumbers>

diff  --git a/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn
index d38b2bb214cc..a11ace501518 100644
--- a/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn
@@ -33,6 +33,8 @@ static_library("PDB") {
     "Native/NativeEnumModules.cpp",
     "Native/NativeEnumTypes.cpp",
     "Native/NativeExeSymbol.cpp",
+    "Native/NativeFunctionSymbol.cpp",
+    "Native/NativePublicSymbol.cpp",
     "Native/NativeRawSymbol.cpp",
     "Native/NativeSession.cpp",
     "Native/NativeSymbolEnumerator.cpp",


        


More information about the llvm-commits mailing list