[NativeSession] Implement findLineNumbersByAddress in NativeSession,
authorAmy Huang <akhuang@google.com>
Mon, 16 Mar 2020 16:53:49 +0000 (09:53 -0700)
committerAmy Huang <akhuang@google.com>
Tue, 16 Jun 2020 00:05:39 +0000 (17:05 -0700)
which takes an address and a length and returns all lines within that
address range.

13 files changed:
llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h [new file with mode: 0644]
llvm/include/llvm/DebugInfo/PDB/Native/NativeLineNumber.h [new file with mode: 0644]
llvm/include/llvm/DebugInfo/PDB/Native/NativeSourceFile.h [new file with mode: 0644]
llvm/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
llvm/lib/DebugInfo/PDB/CMakeLists.txt
llvm/lib/DebugInfo/PDB/Native/NativeEnumLineNumbers.cpp [new file with mode: 0644]
llvm/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp [new file with mode: 0644]
llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp
llvm/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp [new file with mode: 0644]
llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp
llvm/lib/DebugInfo/PDB/PDB.cpp
llvm/test/tools/llvm-symbolizer/pdb/pdb-native.test
llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn

diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h
new file mode 100644 (file)
index 0000000..32a4515
--- /dev/null
@@ -0,0 +1,39 @@
+//==- NativeEnumLineNumbers.h - Native Line Number Enumerator ------------*-==//
+//
+// 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_NATIVEENUMLINENUMBERS_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMLINENUMBERS_H
+
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h"
+
+namespace llvm {
+namespace pdb {
+class IPDBLineNumber;
+
+class NativeEnumLineNumbers : public IPDBEnumChildren<IPDBLineNumber> {
+public:
+  explicit NativeEnumLineNumbers(std::vector<NativeLineNumber> LineNums);
+
+  uint32_t getChildCount() const override;
+  ChildTypePtr getChildAtIndex(uint32_t Index) const override;
+  ChildTypePtr getNext() override;
+  void reset() override;
+
+private:
+  std::vector<NativeLineNumber> Lines;
+  uint32_t Index;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeLineNumber.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeLineNumber.h
new file mode 100644 (file)
index 0000000..f105526
--- /dev/null
@@ -0,0 +1,49 @@
+//===- NativeLineNumber.h - Native line number implementation ---*- 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_NATIVELINENUMBER_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVELINENUMBER_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+namespace llvm {
+namespace pdb {
+class NativeLineNumber : public IPDBLineNumber {
+public:
+  explicit NativeLineNumber(const NativeSession &Session,
+                            const codeview::LineInfo Line, uint32_t Length,
+                            uint32_t Section, uint32_t Offset,
+                            uint32_t SrcFileId);
+
+  uint32_t getLineNumber() const override;
+  uint32_t getLineNumberEnd() const override;
+  uint32_t getColumnNumber() const override;
+  uint32_t getColumnNumberEnd() const override;
+  uint32_t getAddressSection() const override;
+  uint32_t getAddressOffset() const override;
+  uint32_t getRelativeVirtualAddress() const override;
+  uint64_t getVirtualAddress() const override;
+  uint32_t getLength() const override;
+  uint32_t getSourceFileId() const override;
+  uint32_t getCompilandId() const override;
+  bool isStatement() const override;
+
+private:
+  const NativeSession &Session;
+  const codeview::LineInfo Line;
+  uint32_t Section;
+  uint32_t Offset;
+  uint32_t Length;
+  uint32_t SrcFileId;
+};
+} // namespace pdb
+} // namespace llvm
+#endif
diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/NativeSourceFile.h b/llvm/include/llvm/DebugInfo/PDB/Native/NativeSourceFile.h
new file mode 100644 (file)
index 0000000..eb6336f
--- /dev/null
@@ -0,0 +1,40 @@
+//===- NativeSourceFile.h - Native source file implementation ---*- 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_NATIVESOURCEFILE_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVESOURCEFILE_H
+
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
+
+namespace llvm {
+namespace pdb {
+class NativeSession;
+
+class NativeSourceFile : public IPDBSourceFile {
+public:
+  explicit NativeSourceFile(NativeSession &Session, uint32_t FileId,
+                            const codeview::FileChecksumEntry &Checksum);
+
+  std::string getFileName() const override;
+  uint32_t getUniqueId() const override;
+  std::string getChecksum() const override;
+  PDB_Checksum getChecksumType() const override;
+  std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
+  getCompilands() const override;
+
+private:
+  NativeSession &Session;
+  uint32_t FileId;
+  const codeview::FileChecksumEntry Checksum;
+};
+} // namespace pdb
+} // namespace llvm
+#endif
index 33428bf..e14ef32 100644 (file)
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/IntervalMap.h"
+#include "llvm/DebugInfo/CodeView/Line.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"
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
 #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSourceFile.h"
 
 #include <memory>
 #include <vector>
@@ -50,6 +53,10 @@ class SymbolCache {
   /// appear in the PDB file.
   std::vector<SymIndexId> Compilands;
 
+  /// List of source files, indexed by unique source file index.
+  mutable std::vector<std::unique_ptr<NativeSourceFile>> SourceFiles;
+  mutable DenseMap<uint32_t, SymIndexId> FileNameOffsetToId;
+
   /// Map from global symbol offset to SymIndexId.
   DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
 
@@ -63,6 +70,18 @@ class SymbolCache {
   IMap::Allocator IMapAllocator;
   IMap AddrToModuleIndex;
 
+  Expected<ModuleDebugStreamRef> getModuleDebugStream(uint32_t Index) const;
+
+  struct LineTableEntry {
+    uint64_t Addr;
+    codeview::LineInfo Line;
+    uint32_t FileNameIndex;
+    bool IsTerminalEntry;
+  };
+
+  std::vector<LineTableEntry> findLineTable(uint16_t Modi) const;
+  mutable DenseMap<uint16_t, std::vector<LineTableEntry>> LineTable;
+
   SymIndexId createSymbolPlaceholder() {
     SymIndexId Id = Cache.size();
     Cache.push_back(nullptr);
@@ -94,10 +113,6 @@ class SymbolCache {
   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);
 
@@ -151,6 +166,9 @@ public:
   std::unique_ptr<PDBSymbol>
   findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type);
 
+  std::unique_ptr<IPDBEnumLineNumbers>
+  findLineNumbersByVA(uint64_t VA, uint32_t Length) const;
+
   std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index);
   uint32_t getNumCompilands() const;
 
@@ -162,6 +180,13 @@ public:
   ConcreteT &getNativeSymbolById(SymIndexId SymbolId) const {
     return static_cast<ConcreteT &>(getNativeSymbolById(SymbolId));
   }
+
+  std::unique_ptr<IPDBSourceFile> getSourceFileById(SymIndexId FileId) const;
+  SymIndexId
+  getOrCreateSourceFile(const codeview::FileChecksumEntry &Checksum) const;
+
+  void parseSectionContribs();
+  Optional<uint16_t> getModuleIndexForAddr(uint64_t Addr) const;
 };
 
 } // namespace pdb
index 1eda97a..9088bc8 100644 (file)
@@ -52,12 +52,15 @@ add_pdb_impl_folder(Native
   Native/NativeCompilandSymbol.cpp
   Native/NativeEnumGlobals.cpp
   Native/NativeEnumInjectedSources.cpp
+  Native/NativeEnumLineNumbers.cpp
   Native/NativeEnumModules.cpp
   Native/NativeEnumTypes.cpp
   Native/NativeExeSymbol.cpp
   Native/NativeFunctionSymbol.cpp
+  Native/NativeLineNumber.cpp
   Native/NativePublicSymbol.cpp
   Native/NativeRawSymbol.cpp
+  Native/NativeSourceFile.cpp
   Native/NativeSymbolEnumerator.cpp
   Native/NativeTypeArray.cpp
   Native/NativeTypeBuiltin.cpp
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeEnumLineNumbers.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeEnumLineNumbers.cpp
new file mode 100644 (file)
index 0000000..1e4b076
--- /dev/null
@@ -0,0 +1,42 @@
+//==- NativeEnumLineNumbers.cpp - Native Type Enumerator impl ----*- 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/NativeEnumLineNumbers.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSourceFile.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+NativeEnumLineNumbers::NativeEnumLineNumbers(
+    std::vector<NativeLineNumber> LineNums)
+    : Lines(std::move(LineNums)), Index(0) {}
+
+uint32_t NativeEnumLineNumbers::getChildCount() const {
+  return static_cast<uint32_t>(Lines.size());
+}
+
+std::unique_ptr<IPDBLineNumber>
+NativeEnumLineNumbers::getChildAtIndex(uint32_t N) const {
+  if (N >= getChildCount())
+    return nullptr;
+  return std::make_unique<NativeLineNumber>(Lines[N]);
+}
+
+std::unique_ptr<IPDBLineNumber> NativeEnumLineNumbers::getNext() {
+  return getChildAtIndex(Index++);
+}
+
+void NativeEnumLineNumbers::reset() { Index = 0; }
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeLineNumber.cpp
new file mode 100644 (file)
index 0000000..f493c18
--- /dev/null
@@ -0,0 +1,49 @@
+//===- NativeLineNumber.cpp - Native line number implementation -*- 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/NativeLineNumber.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+NativeLineNumber::NativeLineNumber(const NativeSession &Session,
+                                   const codeview::LineInfo Line,
+                                   uint32_t Section, uint32_t Offset,
+                                   uint32_t Length, uint32_t SrcFileId)
+    : Session(Session), Line(Line), Section(Section), Offset(Offset),
+      Length(Length), SrcFileId(SrcFileId) {}
+
+uint32_t NativeLineNumber::getLineNumber() const { return Line.getStartLine(); }
+
+uint32_t NativeLineNumber::getLineNumberEnd() const {
+  return Line.getEndLine();
+}
+
+uint32_t NativeLineNumber::getColumnNumber() const { return 0; }
+
+uint32_t NativeLineNumber::getColumnNumberEnd() const { return 0; }
+
+uint32_t NativeLineNumber::getAddressSection() const { return Section; }
+
+uint32_t NativeLineNumber::getAddressOffset() const { return Offset; }
+
+uint32_t NativeLineNumber::getRelativeVirtualAddress() const {
+  return Session.getRVAFromSectOffset(Section, Offset);
+}
+
+uint64_t NativeLineNumber::getVirtualAddress() const {
+  return Session.getVAFromSectOffset(Section, Offset);
+}
+
+uint32_t NativeLineNumber::getLength() const { return Length; }
+
+uint32_t NativeLineNumber::getSourceFileId() const { return SrcFileId; }
+
+uint32_t NativeLineNumber::getCompilandId() const { return 0; }
+
+bool NativeLineNumber::isStatement() const { return Line.isStatement(); }
index dcae2e9..ac8449d 100644 (file)
@@ -43,7 +43,6 @@
 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();
@@ -182,6 +181,12 @@ NativeSession::searchForPdb(const PdbSearchOptions &Opts) {
   if (auto File = loadPdbFile(PdbPath, Allocator))
     return std::string(PdbPath);
   else
+    consumeError(File.takeError());
+
+  // Check path that was in the executable.
+  if (auto File = loadPdbFile(PathFromExe, Allocator))
+    return std::string(PathFromExe);
+  else
     return File.takeError();
 
   return make_error<RawError>("PDB not found");
@@ -262,18 +267,19 @@ NativeSession::findLineNumbers(const PDBSymbolCompiland &Compiland,
 std::unique_ptr<IPDBEnumLineNumbers>
 NativeSession::findLineNumbersByAddress(uint64_t Address,
                                         uint32_t Length) const {
-  return nullptr;
+  return Cache.findLineNumbersByVA(Address, Length);
 }
 
 std::unique_ptr<IPDBEnumLineNumbers>
 NativeSession::findLineNumbersByRVA(uint32_t RVA, uint32_t Length) const {
-  return nullptr;
+  return findLineNumbersByAddress(getLoadAddress() + RVA, Length);
 }
 
 std::unique_ptr<IPDBEnumLineNumbers>
 NativeSession::findLineNumbersBySectOffset(uint32_t Section, uint32_t Offset,
                                            uint32_t Length) const {
-  return nullptr;
+  uint64_t VA = getVAFromSectOffset(Section, Offset);
+  return findLineNumbersByAddress(VA, Length);
 }
 
 std::unique_ptr<IPDBEnumSourceFiles>
@@ -313,7 +319,7 @@ std::unique_ptr<IPDBEnumSourceFiles> NativeSession::getSourceFilesForCompiland(
 
 std::unique_ptr<IPDBSourceFile>
 NativeSession::getSourceFileById(uint32_t FileId) const {
-  return nullptr;
+  return Cache.getSourceFileById(FileId);
 }
 
 std::unique_ptr<IPDBEnumDataStreams> NativeSession::getDebugStreams() const {
diff --git a/llvm/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp b/llvm/lib/DebugInfo/PDB/Native/NativeSourceFile.cpp
new file mode 100644 (file)
index 0000000..6473207
--- /dev/null
@@ -0,0 +1,47 @@
+//===- NativeSourceFile.cpp - Native line number implementaiton -*- 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/NativeSourceFile.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+NativeSourceFile::NativeSourceFile(NativeSession &Session, uint32_t FileId,
+                                   const codeview::FileChecksumEntry &Checksum)
+    : Session(Session), FileId(FileId), Checksum(Checksum) {}
+
+std::string NativeSourceFile::getFileName() const {
+  auto ST = Session.getPDBFile().getStringTable();
+  if (!ST) {
+    consumeError(ST.takeError());
+    return "";
+  }
+  auto FileName = ST->getStringTable().getString(Checksum.FileNameOffset);
+  if (!FileName) {
+    consumeError(FileName.takeError());
+    return "";
+  }
+
+  return std::string(FileName.get());
+}
+
+uint32_t NativeSourceFile::getUniqueId() const { return FileId; }
+
+std::string NativeSourceFile::getChecksum() const {
+  return toStringRef(Checksum.Checksum).str();
+}
+
+PDB_Checksum NativeSourceFile::getChecksumType() const {
+  return static_cast<PDB_Checksum>(Checksum.Kind);
+}
+
+std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
+NativeSourceFile::getCompilands() const {
+  return nullptr;
+}
index 554eea0..83cf77a 100644 (file)
@@ -7,9 +7,9 @@
 #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/NativeEnumLineNumbers.h"
 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
 #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
 #include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h"
@@ -71,6 +71,7 @@ SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
     : Session(Session), Dbi(Dbi), AddrToModuleIndex(IMapAllocator) {
   // Id 0 is reserved for the invalid symbol.
   Cache.push_back(nullptr);
+  SourceFiles.push_back(nullptr);
 
   if (Dbi)
     Compilands.resize(Dbi->modules().getModuleCount());
@@ -287,6 +288,26 @@ SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
   return Id;
 }
 
+Expected<ModuleDebugStreamRef>
+SymbolCache::getModuleDebugStream(uint32_t Index) const {
+  assert(Dbi && "Dbi stream not present");
+
+  DbiModuleDescriptor Modi = Dbi->modules().getModuleDescriptor(Index);
+
+  uint16_t ModiStream = Modi.getModuleStreamIndex();
+  if (ModiStream == kInvalidStreamIndex)
+    return make_error<RawError>("Module stream not present");
+
+  std::unique_ptr<msf::MappedBlockStream> ModStreamData =
+      Session.getPDBFile().createIndexedStream(ModiStream);
+
+  ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
+  if (auto EC = ModS.reload())
+    return std::move(EC);
+
+  return std::move(ModS);
+}
+
 std::unique_ptr<PDBSymbol>
 SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
                                     PDB_SymType Type) {
@@ -318,23 +339,18 @@ SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
   if (!Dbi)
     return nullptr;
 
-  auto Modi = getModuleIndexForAddr(Sect, Offset);
+  auto Modi = getModuleIndexForAddr(Session.getVAFromSectOffset(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));
+  auto ExpectedModS = getModuleDebugStream(*Modi);
+  if (!ExpectedModS) {
+    consumeError(ExpectedModS.takeError());
     return nullptr;
   }
+  CVSymbolArray Syms = ExpectedModS->getSymbolArray();
 
   // 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;
@@ -342,6 +358,7 @@ SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
     if (Sect == PS.Segment && Offset >= PS.CodeOffset &&
         Offset < PS.CodeOffset + PS.CodeSize) {
       SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS);
+      AddressToFunctionSymId.insert({{Sect, Offset}, Id});
       return getSymbolById(Id);
     }
 
@@ -392,6 +409,8 @@ SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
     } else
       Count = Half;
   }
+  if (It == AddrMap.begin())
+    return nullptr;
   --It;
 
   Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
@@ -401,9 +420,165 @@ SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
   }
   auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
   SymIndexId Id = createSymbol<NativePublicSymbol>(PS);
+  AddressToPublicSymId.insert({{Sect, Offset}, Id});
   return getSymbolById(Id);
 }
 
+std::vector<SymbolCache::LineTableEntry>
+SymbolCache::findLineTable(uint16_t Modi) const {
+  // Check if this module has already been added.
+  auto LineTableIter = LineTable.find(Modi);
+  if (LineTableIter != LineTable.end())
+    return LineTableIter->second;
+
+  std::vector<LineTableEntry> &ModuleLineTable = LineTable[Modi];
+
+  // If there is an error or there are no lines, just return the
+  // empty vector.
+  Expected<ModuleDebugStreamRef> ExpectedModS = getModuleDebugStream(Modi);
+  if (!ExpectedModS) {
+    consumeError(ExpectedModS.takeError());
+    return ModuleLineTable;
+  }
+
+  std::vector<std::vector<LineTableEntry>> EntryList;
+  for (const auto &SS : ExpectedModS->getSubsectionsArray()) {
+    if (SS.kind() != DebugSubsectionKind::Lines)
+      continue;
+
+    DebugLinesSubsectionRef Lines;
+    BinaryStreamReader Reader(SS.getRecordData());
+    if (auto EC = Lines.initialize(Reader)) {
+      consumeError(std::move(EC));
+      continue;
+    }
+
+    uint32_t RelocSegment = Lines.header()->RelocSegment;
+    uint32_t RelocOffset = Lines.header()->RelocOffset;
+    for (const LineColumnEntry &Group : Lines) {
+      if (Group.LineNumbers.empty())
+        continue;
+
+      std::vector<LineTableEntry> Entries;
+      for (const LineNumberEntry &LN : Group.LineNumbers) {
+        LineInfo Line(LN.Flags);
+        uint64_t VA =
+            Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.Offset);
+        Entries.push_back({VA, Line, Group.NameIndex, false});
+      }
+
+      // Add a terminal entry line to mark the end of this subsection.
+      LineInfo LastLine(Group.LineNumbers.back().Flags);
+      uint64_t VA = Session.getVAFromSectOffset(
+          RelocSegment, RelocOffset + Lines.header()->CodeSize);
+      Entries.push_back({VA, LastLine, Group.NameIndex, true});
+      EntryList.push_back(Entries);
+    }
+  }
+
+  // Sort EntryList, and add flattened contents to the line table.
+  std::sort(EntryList.begin(), EntryList.end(),
+            [](const std::vector<LineTableEntry> &LHS,
+               const std::vector<LineTableEntry> &RHS) {
+              return LHS[0].Addr < RHS[0].Addr;
+            });
+  for (size_t I = 0; I < EntryList.size(); ++I)
+    ModuleLineTable.insert(ModuleLineTable.end(), EntryList[I].begin(),
+                           EntryList[I].end());
+
+  return ModuleLineTable;
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
+  Optional<uint16_t> MaybeModi = getModuleIndexForAddr(VA);
+  if (!MaybeModi)
+    return nullptr;
+  uint16_t Modi = *MaybeModi;
+
+  std::vector<LineTableEntry> Lines = findLineTable(Modi);
+  if (Lines.empty())
+    return nullptr;
+
+  // Find the first line in the line table whose address is not greater than
+  // the one we are searching for.
+  auto LineIter = llvm::partition_point(Lines, [&](const LineTableEntry &E) {
+    return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));
+  });
+
+  // Try to back up if we've gone too far.
+  if (LineIter == Lines.end() || LineIter->Addr > VA) {
+    if (LineIter == Lines.begin() || std::prev(LineIter)->IsTerminalEntry)
+      return nullptr;
+    --LineIter;
+  }
+
+  Expected<ModuleDebugStreamRef> ExpectedModS = getModuleDebugStream(Modi);
+  if (!ExpectedModS) {
+    consumeError(ExpectedModS.takeError());
+    return nullptr;
+  }
+  Expected<DebugChecksumsSubsectionRef> ExpectedChecksums =
+      ExpectedModS->findChecksumsSubsection();
+  if (!ExpectedChecksums) {
+    consumeError(ExpectedChecksums.takeError());
+    return nullptr;
+  }
+
+  // Populate a vector of NativeLineNumbers that have addresses in the given
+  // address range.
+  Optional<uint16_t> EndModi = getModuleIndexForAddr(VA + Length);
+  if (!EndModi)
+    return nullptr;
+  std::vector<NativeLineNumber> LineNumbers;
+  while (Modi <= *EndModi) {
+    // If we reached the end of the current module, increment Modi and get the
+    // new line table and checksums array.
+    if (LineIter == Lines.end()) {
+      ++Modi;
+
+      ExpectedModS = getModuleDebugStream(Modi);
+      if (!ExpectedModS) {
+        consumeError(ExpectedModS.takeError());
+        break;
+      }
+      ExpectedChecksums = ExpectedModS->findChecksumsSubsection();
+      if (!ExpectedChecksums) {
+        consumeError(ExpectedChecksums.takeError());
+        break;
+      }
+
+      Lines = findLineTable(Modi);
+      LineIter = Lines.begin();
+
+      if (Lines.empty())
+        continue;
+    }
+
+    if (LineIter->IsTerminalEntry) {
+      ++LineIter;
+      continue;
+    }
+
+    // If the line is still within the address range, create a NativeLineNumber
+    // and add to the list.
+    if (LineIter->Addr > VA + Length)
+      break;
+
+    uint32_t LineSect, LineOff;
+    Session.addressForVA(LineIter->Addr, LineSect, LineOff);
+    uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr;
+    auto ChecksumIter =
+        ExpectedChecksums->getArray().at(LineIter->FileNameIndex);
+    uint32_t SrcFileId = getOrCreateSourceFile(*ChecksumIter);
+    NativeLineNumber LineNum(Session, LineIter->Line, LineSect, LineOff,
+                             LineLength, SrcFileId);
+    LineNumbers.push_back(LineNum);
+    ++LineIter;
+  }
+  return std::make_unique<NativeEnumLineNumbers>(std::move(LineNumbers));
+}
+
 std::unique_ptr<PDBSymbolCompiland>
 SymbolCache::getOrCreateCompiland(uint32_t Index) {
   if (!Dbi)
@@ -421,6 +596,31 @@ SymbolCache::getOrCreateCompiland(uint32_t Index) {
   return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
 }
 
+std::unique_ptr<IPDBSourceFile>
+SymbolCache::getSourceFileById(SymIndexId FileId) const {
+  assert(FileId < SourceFiles.size());
+
+  // Id 0 is reserved.
+  if (FileId == 0)
+    return nullptr;
+
+  return std::unique_ptr<NativeSourceFile>(
+      new NativeSourceFile(*SourceFiles[FileId].get()));
+}
+
+SymIndexId
+SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const {
+  auto Iter = FileNameOffsetToId.find(Checksums.FileNameOffset);
+  if (Iter != FileNameOffsetToId.end())
+    return Iter->second;
+
+  SymIndexId Id = SourceFiles.size();
+  auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums);
+  SourceFiles.push_back(std::move(SrcFile));
+  FileNameOffsetToId[Checksums.FileNameOffset] = Id;
+  return Id;
+}
+
 void SymbolCache::parseSectionContribs() {
   if (!Dbi)
     return;
@@ -451,9 +651,8 @@ void SymbolCache::parseSectionContribs() {
   Dbi->visitSectionContributions(V);
 }
 
-Optional<uint16_t> SymbolCache::getModuleIndexForAddr(uint32_t Sect,
-                                                      uint32_t Offset) const {
-  auto Iter = AddrToModuleIndex.find(Session.getVAFromSectOffset(Sect, Offset));
+Optional<uint16_t> SymbolCache::getModuleIndexForAddr(uint64_t Addr) const {
+  auto Iter = AddrToModuleIndex.find(Addr);
   if (Iter == AddrToModuleIndex.end())
     return None;
   return Iter.value();
index a0d015c..e5b7731 100644 (file)
@@ -37,15 +37,10 @@ Error llvm::pdb::loadDataForEXE(PDB_ReaderType Type, StringRef Path,
                                 std::unique_ptr<IPDBSession> &Session) {
   // Create the correct concrete instance type based on the value of Type.
   if (Type == PDB_ReaderType::Native) {
-    if (auto Err = NativeSession::createFromExe(Path, Session)) {
-      consumeError(std::move(Err));
-
-      Expected<std::string> PdbPath = NativeSession::searchForPdb({Path});
-      if (!PdbPath)
-        return PdbPath.takeError();
-      return NativeSession::createFromPdbPath(PdbPath.get(), Session);
-    }
-    return Error::success();
+    Expected<std::string> PdbPath = NativeSession::searchForPdb({Path});
+    if (!PdbPath)
+      return PdbPath.takeError();
+    return NativeSession::createFromPdbPath(PdbPath.get(), Session);
   }
 
 #if LLVM_ENABLE_DIA_SDK
index 29a770e..d132dbf 100644 (file)
@@ -21,19 +21,27 @@ RUN:    | FileCheck %s --check-prefix=CHECK-NO-DEMANGLE
 Currently only finding function/public symbol names is implemented.
 
 CHECK: foo(void)
+CHECK-NEXT: test.cpp:10
 CHECK: {{^private_symbol$}}
+CHECK-NEXT: test.cpp:13:0
 CHECK: {{^main}}
+CHECK-NEXT: test.cpp:16:0
 CHECK: {{^foo_cdecl$}}
 CHECK: {{^foo_stdcall$}}
 CHECK: {{^foo_fastcall$}}
 CHECK: {{^foo_vectorcall$}}
 CHECK: NS::Foo::bar(void)
+CHECK-NEXT: test.cpp:6:0
 
 CHECK-NO-DEMANGLE: ?foo@@YAXXZ
+CHECK-NO-DEMANGLE-NEXT: test.cpp:10
 CHECK-NO-DEMANGLE: private_symbol
+CHECK-NO-DEMANGLE-NEXT: test.cpp:13
 CHECK-NO-DEMANGLE: _main
+CHECK-NO-DEMANGLE-NEXT: test.cpp:16
 CHECK-NO-DEMANGLE: _foo_cdecl
 CHECK-NO-DEMANGLE: _foo_stdcall@0
 CHECK-NO-DEMANGLE: @foo_fastcall@0
 CHECK-NO-DEMANGLE: foo_vectorcall@@0
 CHECK-NO-DEMANGLE: ?bar@Foo@NS@@QAEXXZ
+CHECK-NO-DEMANGLE-NEXT: test.cpp:6
index a11ace5..8d8990b 100644 (file)
@@ -30,13 +30,16 @@ static_library("PDB") {
     "Native/NativeCompilandSymbol.cpp",
     "Native/NativeEnumGlobals.cpp",
     "Native/NativeEnumInjectedSources.cpp",
+    "Native/NativeEnumLineNumbers.cpp",
     "Native/NativeEnumModules.cpp",
     "Native/NativeEnumTypes.cpp",
     "Native/NativeExeSymbol.cpp",
     "Native/NativeFunctionSymbol.cpp",
+    "Native/NativeLineNumber.cpp",
     "Native/NativePublicSymbol.cpp",
     "Native/NativeRawSymbol.cpp",
     "Native/NativeSession.cpp",
+    "Native/NativeSourceFile.cpp",
     "Native/NativeSymbolEnumerator.cpp",
     "Native/NativeTypeArray.cpp",
     "Native/NativeTypeBuiltin.cpp",