[Lldb-commits] [lldb] 242e1e9 - [lldb][PDB] Add ObjectFile PDB plugin

Zequan Wu via lldb-commits lldb-commits at lists.llvm.org
Mon Oct 26 10:29:02 PDT 2020


Author: Zequan Wu
Date: 2020-10-26T10:28:48-07:00
New Revision: 242e1e9910441ad00118e580e4cbd5743c77ea5e

URL: https://github.com/llvm/llvm-project/commit/242e1e9910441ad00118e580e4cbd5743c77ea5e
DIFF: https://github.com/llvm/llvm-project/commit/242e1e9910441ad00118e580e4cbd5743c77ea5e.diff

LOG: [lldb][PDB] Add ObjectFile PDB plugin

To allow loading PDB file with `target symbols add` command.

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

Added: 
    lldb/source/Plugins/ObjectFile/PDB/CMakeLists.txt
    lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
    lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h
    lldb/test/Shell/ObjectFile/PDB/object.test
    lldb/test/Shell/SymbolFile/NativePDB/load-pdb.cpp

Modified: 
    lldb/source/Plugins/ObjectFile/CMakeLists.txt
    lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
    lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
    lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp
    lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h
    lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
    lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/ObjectFile/CMakeLists.txt b/lldb/source/Plugins/ObjectFile/CMakeLists.txt
index 77ca511bd7cf1..3b2cc6177d313 100644
--- a/lldb/source/Plugins/ObjectFile/CMakeLists.txt
+++ b/lldb/source/Plugins/ObjectFile/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_subdirectory(Breakpad)
 add_subdirectory(ELF)
 add_subdirectory(Mach-O)
+add_subdirectory(PDB)
 add_subdirectory(PECOFF)
 add_subdirectory(JIT)
 add_subdirectory(wasm)

diff  --git a/lldb/source/Plugins/ObjectFile/PDB/CMakeLists.txt b/lldb/source/Plugins/ObjectFile/PDB/CMakeLists.txt
new file mode 100644
index 0000000000000..d5ade2b93ad86
--- /dev/null
+++ b/lldb/source/Plugins/ObjectFile/PDB/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_lldb_library(lldbPluginObjectFilePDB PLUGIN
+  ObjectFilePDB.cpp
+
+  LINK_LIBS
+    lldbCore
+    lldbSymbol
+    lldbUtility
+  LINK_COMPONENTS
+    Support
+  )

diff  --git a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
new file mode 100644
index 0000000000000..f467f926128a1
--- /dev/null
+++ b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
@@ -0,0 +1,229 @@
+//===-- ObjectFilePDB.cpp -------------------------------------------------===//
+//
+// 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 "ObjectFilePDB.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Utility/StreamString.h"
+#include "llvm/BinaryFormat/Magic.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/PDB.h"
+#include "llvm/Support/BinaryByteStream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm::pdb;
+using namespace llvm::codeview;
+
+LLDB_PLUGIN_DEFINE(ObjectFilePDB)
+
+struct CVInfoPdb70 {
+  // 16-byte GUID
+  struct _Guid {
+    llvm::support::ulittle32_t Data1;
+    llvm::support::ulittle16_t Data2;
+    llvm::support::ulittle16_t Data3;
+    uint8_t Data4[8];
+  } Guid;
+
+  llvm::support::ulittle32_t Age;
+};
+
+static UUID GetPDBUUID(InfoStream &IS) {
+  // This part is similar with what has done in ObjectFilePECOFF.
+  using llvm::support::endian::read16be;
+  using llvm::support::endian::read32;
+  using llvm::support::endian::read32be;
+
+  GUID guid = IS.getGuid();
+  const uint8_t *guid_p = guid.Guid;
+  struct CVInfoPdb70 info;
+  info.Guid.Data1 = read32be(guid_p);
+  guid_p += 4;
+  info.Guid.Data2 = read16be(guid_p);
+  guid_p += 2;
+  info.Guid.Data3 = read16be(guid_p);
+  guid_p += 2;
+  memcpy(info.Guid.Data4, guid_p, 8);
+
+  // Return 20-byte UUID if the Age is not zero
+  uint32_t age = IS.getAge();
+  if (age) {
+    info.Age = read32(&age, llvm::support::big);
+    return UUID::fromOptionalData(&info, sizeof(info));
+  }
+  // Otherwise return 16-byte GUID
+  return UUID::fromOptionalData(&info.Guid, sizeof(info.Guid));
+}
+
+char ObjectFilePDB::ID;
+
+void ObjectFilePDB::Initialize() {
+  PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                GetPluginDescriptionStatic(), CreateInstance,
+                                CreateMemoryInstance, GetModuleSpecifications);
+}
+
+void ObjectFilePDB::Terminate() {
+  PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+ConstString ObjectFilePDB::GetPluginNameStatic() {
+  static ConstString g_name("pdb");
+  return g_name;
+}
+
+ArchSpec ObjectFilePDB::GetArchitecture() {
+  auto dbi_stream = m_file_up->getPDBDbiStream();
+  if (!dbi_stream) {
+    llvm::consumeError(dbi_stream.takeError());
+    return ArchSpec();
+  }
+
+  PDB_Machine machine = dbi_stream->getMachineType();
+  switch (machine) {
+  default:
+    break;
+  case PDB_Machine::Amd64:
+  case PDB_Machine::x86:
+  case PDB_Machine::PowerPC:
+  case PDB_Machine::PowerPCFP:
+  case PDB_Machine::Arm:
+  case PDB_Machine::ArmNT:
+  case PDB_Machine::Thumb:
+  case PDB_Machine::Arm64:
+    ArchSpec arch;
+    arch.SetArchitecture(eArchTypeCOFF, static_cast<int>(machine),
+                         LLDB_INVALID_CPUTYPE);
+    return arch;
+  }
+  return ArchSpec();
+}
+
+bool ObjectFilePDB::initPDBFile() {
+  m_file_up = loadPDBFile(m_file.GetPath(), m_allocator);
+  if (!m_file_up)
+    return false;
+  auto info_stream = m_file_up->getPDBInfoStream();
+  if (!info_stream) {
+    llvm::consumeError(info_stream.takeError());
+    return false;
+  }
+  m_uuid = GetPDBUUID(*info_stream);
+  return true;
+}
+
+ObjectFile *
+ObjectFilePDB::CreateInstance(const ModuleSP &module_sp, DataBufferSP &data_sp,
+                              offset_t data_offset, const FileSpec *file,
+                              offset_t file_offset, offset_t length) {
+  auto objfile_up = std::make_unique<ObjectFilePDB>(
+      module_sp, data_sp, data_offset, file, file_offset, length);
+  if (!objfile_up->initPDBFile())
+    return nullptr;
+  return objfile_up.release();
+}
+
+ObjectFile *ObjectFilePDB::CreateMemoryInstance(const ModuleSP &module_sp,
+                                                DataBufferSP &data_sp,
+                                                const ProcessSP &process_sp,
+                                                addr_t header_addr) {
+  return nullptr;
+}
+
+size_t ObjectFilePDB::GetModuleSpecifications(
+    const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
+    offset_t file_offset, offset_t length, ModuleSpecList &specs) {
+  const size_t initial_count = specs.GetSize();
+  ModuleSpec module_spec(file);
+  llvm::BumpPtrAllocator allocator;
+  std::unique_ptr<PDBFile> pdb_file = loadPDBFile(file.GetPath(), allocator);
+  if (!pdb_file)
+    return initial_count;
+
+  auto info_stream = pdb_file->getPDBInfoStream();
+  if (!info_stream) {
+    llvm::consumeError(info_stream.takeError());
+    return initial_count;
+  }
+  auto dbi_stream = pdb_file->getPDBDbiStream();
+  if (!dbi_stream) {
+    llvm::consumeError(dbi_stream.takeError());
+    return initial_count;
+  }
+
+  lldb_private::UUID &uuid = module_spec.GetUUID();
+  uuid = GetPDBUUID(*info_stream);
+
+  ArchSpec &module_arch = module_spec.GetArchitecture();
+  switch (dbi_stream->getMachineType()) {
+  case PDB_Machine::Amd64:
+    module_arch.SetTriple("x86_64-pc-windows");
+    specs.Append(module_spec);
+    break;
+  case PDB_Machine::x86:
+    module_arch.SetTriple("i386-pc-windows");
+    specs.Append(module_spec);
+    module_arch.SetTriple("i686-pc-windows");
+    specs.Append(module_spec);
+    break;
+  case PDB_Machine::ArmNT:
+    module_arch.SetTriple("armv7-pc-windows");
+    specs.Append(module_spec);
+    break;
+  case PDB_Machine::Arm64:
+    module_arch.SetTriple("aarch64-pc-windows");
+    specs.Append(module_spec);
+    break;
+  default:
+    break;
+  }
+
+  return specs.GetSize() - initial_count;
+}
+
+ObjectFilePDB::ObjectFilePDB(const ModuleSP &module_sp, DataBufferSP &data_sp,
+                             offset_t data_offset, const FileSpec *file,
+                             offset_t offset, offset_t length)
+    : ObjectFile(module_sp, file, offset, length, data_sp, data_offset) {}
+
+std::unique_ptr<PDBFile>
+ObjectFilePDB::loadPDBFile(std::string PdbPath,
+                           llvm::BumpPtrAllocator &Allocator) {
+  llvm::file_magic magic;
+  auto ec = llvm::identify_magic(PdbPath, magic);
+  if (ec || magic != llvm::file_magic::pdb)
+    return nullptr;
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer =
+      llvm::MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1,
+                                  /*RequiresNullTerminator=*/false);
+  if (!ErrorOrBuffer)
+    return nullptr;
+  std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
+
+  llvm::StringRef Path = Buffer->getBufferIdentifier();
+  auto Stream = std::make_unique<llvm::MemoryBufferByteStream>(
+      std::move(Buffer), llvm::support::little);
+
+  auto File = std::make_unique<PDBFile>(Path, std::move(Stream), Allocator);
+  if (auto EC = File->parseFileHeaders()) {
+    llvm::consumeError(std::move(EC));
+    return nullptr;
+  }
+  if (auto EC = File->parseStreamData()) {
+    llvm::consumeError(std::move(EC));
+    return nullptr;
+  }
+
+  return File;
+}

diff  --git a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h
new file mode 100644
index 0000000000000..19dd46b31406c
--- /dev/null
+++ b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h
@@ -0,0 +1,107 @@
+//===-- ObjectFilePDB.h --------------------------------------- -*- 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 LLDB_SOURCE_PLUGINS_OBJECTFILE_PDB_OBJECTFILEPDB_H
+#define LLDB_SOURCE_PLUGINS_OBJECTFILE_PDB_OBJECTFILEPDB_H
+
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+namespace lldb_private {
+
+class ObjectFilePDB : public ObjectFile {
+public:
+  // Static Functions
+  static void Initialize();
+  static void Terminate();
+
+  static ConstString GetPluginNameStatic();
+  static const char *GetPluginDescriptionStatic() {
+    return "PDB object file reader.";
+  }
+
+  static std::unique_ptr<llvm::pdb::PDBFile>
+  loadPDBFile(std::string PdbPath, llvm::BumpPtrAllocator &Allocator);
+
+  static ObjectFile *
+  CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
+                 lldb::offset_t data_offset, const FileSpec *file,
+                 lldb::offset_t file_offset, lldb::offset_t length);
+
+  static ObjectFile *CreateMemoryInstance(const lldb::ModuleSP &module_sp,
+                                          lldb::DataBufferSP &data_sp,
+                                          const lldb::ProcessSP &process_sp,
+                                          lldb::addr_t header_addr);
+
+  static size_t GetModuleSpecifications(const FileSpec &file,
+                                        lldb::DataBufferSP &data_sp,
+                                        lldb::offset_t data_offset,
+                                        lldb::offset_t file_offset,
+                                        lldb::offset_t length,
+                                        ModuleSpecList &specs);
+
+  // PluginInterface protocol
+  ConstString GetPluginName() override { return GetPluginNameStatic(); }
+
+  uint32_t GetPluginVersion() override { return 1; }
+
+  // LLVM RTTI support
+  static char ID;
+  bool isA(const void *ClassID) const override {
+    return ClassID == &ID || ObjectFile::isA(ClassID);
+  }
+  static bool classof(const ObjectFile *obj) { return obj->isA(&ID); }
+
+  // ObjectFile Protocol.
+  uint32_t GetAddressByteSize() const override { return 8; }
+
+  lldb::ByteOrder GetByteOrder() const override {
+    return lldb::eByteOrderLittle;
+  }
+
+  bool ParseHeader() override { return true; }
+
+  bool IsExecutable() const override { return false; }
+
+  Symtab *GetSymtab() override { return nullptr; }
+
+  bool IsStripped() override { return false; }
+
+  // No section in PDB file.
+  void CreateSections(SectionList &unified_section_list) override {}
+
+  void Dump(Stream *s) override {}
+
+  ArchSpec GetArchitecture() override;
+
+  UUID GetUUID() override { return m_uuid; }
+
+  uint32_t GetDependentModules(FileSpecList &files) override { return 0; }
+
+  Type CalculateType() override { return eTypeDebugInfo; }
+
+  Strata CalculateStrata() override { return eStrataUser; }
+
+  llvm::pdb::PDBFile &GetPDBFile() { return *m_file_up; }
+
+  ObjectFilePDB(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
+                lldb::offset_t data_offset, const FileSpec *file,
+                lldb::offset_t offset, lldb::offset_t length);
+
+private:
+  UUID m_uuid;
+  llvm::BumpPtrAllocator m_allocator;
+  std::unique_ptr<llvm::pdb::PDBFile> m_file_up;
+
+  bool initPDBFile();
+};
+
+} // namespace lldb_private
+#endif // LLDB_PLUGINS_OBJECTFILE_PDB_OBJECTFILEPDB_H

diff  --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index 9073672740e08..2646ce35d85c4 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -142,7 +142,6 @@ ObjectFile *ObjectFilePECOFF::CreateInstance(const lldb::ModuleSP &module_sp,
   // Cache coff binary.
   if (!objfile_up->CreateBinary())
     return nullptr;
-
   return objfile_up.release();
 }
 
@@ -852,7 +851,6 @@ void ObjectFilePECOFF::CreateSections(SectionList &unified_section_list) {
   if (m_sections_up)
     return;
   m_sections_up = std::make_unique<SectionList>();
-
   ModuleSP module_sp(GetModule());
   if (module_sp) {
     std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
index 7dab9370e512a..38a589d65b184 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
@@ -15,6 +15,7 @@ add_lldb_library(lldbPluginSymbolFileNativePDB
     lldbSymbol
     lldbUtility
     lldbPluginTypeSystemClang
+    lldbPluginObjectFilePDB
   CLANG_LIBS
     clangAST
     clangLex

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp
index 6ac6cc2da29b4..dc964f64a9150 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp
@@ -39,7 +39,7 @@ PdbIndex::PdbIndex() : m_cus(*this), m_va_to_modi(m_allocator) {}
   }
 
 llvm::Expected<std::unique_ptr<PdbIndex>>
-PdbIndex::create(std::unique_ptr<llvm::pdb::PDBFile> file) {
+PdbIndex::create(llvm::pdb::PDBFile *file) {
   lldbassert(file);
 
   std::unique_ptr<PdbIndex> result(new PdbIndex());
@@ -53,7 +53,7 @@ PdbIndex::create(std::unique_ptr<llvm::pdb::PDBFile> file) {
 
   result->m_tpi->buildHashMap();
 
-  result->m_file = std::move(file);
+  result->m_file = file;
 
   return std::move(result);
 }

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h
index ccc3cc2f45382..1b382e5263c12 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h
@@ -48,7 +48,7 @@ struct SegmentOffset;
 class PdbIndex {
 
   /// The underlying PDB file.
-  std::unique_ptr<llvm::pdb::PDBFile> m_file;
+  llvm::pdb::PDBFile *m_file = nullptr;
 
   /// The DBI stream.  This contains general high level information about the
   /// features present in the PDB file, compile units (such as the information
@@ -110,8 +110,7 @@ class PdbIndex {
   void BuildAddrToSymbolMap(CompilandIndexItem &cci);
 
 public:
-  static llvm::Expected<std::unique_ptr<PdbIndex>>
-      create(std::unique_ptr<llvm::pdb::PDBFile>);
+  static llvm::Expected<std::unique_ptr<PdbIndex>> create(llvm::pdb::PDBFile *);
 
   void SetLoadAddress(lldb::addr_t addr) { m_load_address = addr; }
   lldb::addr_t GetLoadAddress() const { return m_load_address; }

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 37d72897e24da..24b4c64a91bcf 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -16,6 +16,7 @@
 
 #include "Plugins/ExpressionParser/Clang/ClangUtil.h"
 #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
+#include "Plugins/ObjectFile/PDB/ObjectFilePDB.h"
 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
@@ -42,9 +43,11 @@
 #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
 #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
 #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
 #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/PDB.h"
 #include "llvm/DebugInfo/PDB/PDBTypes.h"
 #include "llvm/Demangle/MicrosoftDemangle.h"
 #include "llvm/Object/COFF.h"
@@ -81,32 +84,6 @@ static lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
   }
 }
 
-static std::unique_ptr<PDBFile> loadPDBFile(std::string PdbPath,
-                                            llvm::BumpPtrAllocator &Allocator) {
-  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer =
-      llvm::MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1,
-                                  /*RequiresNullTerminator=*/false);
-  if (!ErrorOrBuffer)
-    return nullptr;
-  std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
-
-  llvm::StringRef Path = Buffer->getBufferIdentifier();
-  auto Stream = std::make_unique<llvm::MemoryBufferByteStream>(
-      std::move(Buffer), llvm::support::little);
-
-  auto File = std::make_unique<PDBFile>(Path, std::move(Stream), Allocator);
-  if (auto EC = File->parseFileHeaders()) {
-    llvm::consumeError(std::move(EC));
-    return nullptr;
-  }
-  if (auto EC = File->parseStreamData()) {
-    llvm::consumeError(std::move(EC));
-    return nullptr;
-  }
-
-  return File;
-}
-
 static std::unique_ptr<PDBFile>
 loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
   // Try to find a matching PDB for an EXE.
@@ -144,11 +121,7 @@ loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
   }
 
   // If the file is not a PDB or if it doesn't have a matching GUID, fail.
-  llvm::file_magic magic;
-  auto ec = llvm::identify_magic(pdb_file, magic);
-  if (ec || magic != llvm::file_magic::pdb)
-    return nullptr;
-  std::unique_ptr<PDBFile> pdb = loadPDBFile(std::string(pdb_file), allocator);
+  auto pdb = ObjectFilePDB::loadPDBFile(std::string(pdb_file), allocator);
   if (!pdb)
     return nullptr;
 
@@ -292,24 +265,19 @@ uint32_t SymbolFileNativePDB::CalculateAbilities() {
 
   if (!m_index) {
     // Lazily load and match the PDB file, but only do this once.
-    std::unique_ptr<PDBFile> file_up =
-        loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(), m_allocator);
-
-    if (!file_up) {
-      auto module_sp = m_objfile_sp->GetModule();
-      if (!module_sp)
-        return 0;
-      // See if any symbol file is specified through `--symfile` option.
-      FileSpec symfile = module_sp->GetSymbolFileFileSpec();
-      if (!symfile)
-        return 0;
-      file_up = loadPDBFile(symfile.GetPath(), m_allocator);
+    PDBFile *pdb_file;
+    if (auto *pdb = llvm::dyn_cast<ObjectFilePDB>(m_objfile_sp.get())) {
+      pdb_file = &pdb->GetPDBFile();
+    } else {
+      m_file_up = loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(),
+                                      m_allocator);
+      pdb_file = m_file_up.get();
     }
 
-    if (!file_up)
+    if (!pdb_file)
       return 0;
 
-    auto expected_index = PdbIndex::create(std::move(file_up));
+    auto expected_index = PdbIndex::create(pdb_file);
     if (!expected_index) {
       llvm::consumeError(expected_index.takeError());
       return 0;
@@ -329,7 +297,10 @@ uint32_t SymbolFileNativePDB::CalculateAbilities() {
 }
 
 void SymbolFileNativePDB::InitializeObject() {
-  m_obj_load_address = m_objfile_sp->GetBaseAddress().GetFileAddress();
+  m_obj_load_address = m_objfile_sp->GetModule()
+                           ->GetObjectFile()
+                           ->GetBaseAddress()
+                           .GetFileAddress();
   m_index->SetLoadAddress(m_obj_load_address);
   m_index->ParseSectionContribs();
 

diff  --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
index bf5718e11a19f..61c1d77164b77 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -231,6 +231,7 @@ class SymbolFileNativePDB : public SymbolFile {
   lldb::addr_t m_obj_load_address = 0;
   bool m_done_full_type_scan = false;
 
+  std::unique_ptr<llvm::pdb::PDBFile> m_file_up;
   std::unique_ptr<PdbIndex> m_index;
 
   std::unique_ptr<PdbAstBuilder> m_ast;

diff  --git a/lldb/test/Shell/ObjectFile/PDB/object.test b/lldb/test/Shell/ObjectFile/PDB/object.test
new file mode 100644
index 0000000000000..304872ac30160
--- /dev/null
+++ b/lldb/test/Shell/ObjectFile/PDB/object.test
@@ -0,0 +1,280 @@
+# RUN: llvm-pdbutil yaml2pdb %s -pdb=%t.pdb
+# RUN: lldb-test object-file %t.pdb | FileCheck %s
+
+# CHECK: Plugin name: pdb
+# CHECK: Architecture: x86_64-pc-windows-msvc
+# CHECK: UUID: 3F58AF61-A829-6C7A-4C4C-44205044422E-00000001
+# CHECK: Executable: false
+# CHECK: Stripped: false
+# CHECK: Type: debug info
+# CHECK: Strata: user
+# CHECK: Base VM address: 0xffffffffffffffff
+# CHECK: There are no sections
+
+---
+MSF:
+  SuperBlock:
+    BlockSize:       4096
+    FreeBlockMap:    2
+    NumBlocks:       18
+    NumDirectoryBytes: 116
+    Unknown1:        0
+    BlockMapAddr:    3
+  NumDirectoryBlocks: 1
+  DirectoryBlocks: [ 17 ]
+  NumStreams:      15
+  FileSize:        73728
+StreamSizes:     [ 0, 93, 100, 550, 136, 0, 544, 576, 40, 20, 120, 368, 
+                   336, 49, 24 ]
+StreamMap:
+  - Stream:          [  ]
+  - Stream:          [ 16 ]
+  - Stream:          [ 7 ]
+  - Stream:          [ 12 ]
+  - Stream:          [ 14 ]
+  - Stream:          [  ]
+  - Stream:          [ 4 ]
+  - Stream:          [ 5 ]
+  - Stream:          [ 6 ]
+  - Stream:          [ 8 ]
+  - Stream:          [ 9 ]
+  - Stream:          [ 10 ]
+  - Stream:          [ 11 ]
+  - Stream:          [ 13 ]
+  - Stream:          [ 15 ]
+StringTable:
+  - '/tmp/a.cpp'
+PdbStream:
+  Age:             1
+  Guid:            '{61AF583F-29A8-7A6C-4C4C-44205044422E}'
+  Signature:       1062776673
+  Features:        [ VC140 ]
+  Version:         VC70
+DbiStream:
+  VerHeader:       V70
+  Age:             1
+  BuildNumber:     36363
+  PdbDllVersion:   0
+  PdbDllRbld:      0
+  Flags:           0
+  MachineType:     Amd64
+  Modules:
+    - Module:          '/tmp/pdb.obj'
+      ObjFile:         '/tmp/pdb.obj'
+      SourceFiles:
+        - '/tmp/a.cpp'
+      Subsections:
+        - !Lines
+          CodeSize:        28
+          Flags:           [  ]
+          RelocOffset:     0
+          RelocSegment:    1
+          Blocks:
+            - FileName:        '/tmp/a.cpp'
+              Lines:
+                - Offset:          0
+                  LineStart:       1
+                  IsStatement:     false
+                  EndDelta:        0
+                - Offset:          23
+                  LineStart:       2
+                  IsStatement:     false
+                  EndDelta:        0
+              Columns:         []
+        - !FileChecksums
+          Checksums:
+            - FileName:        '/tmp/a.cpp'
+              Kind:            MD5
+              Checksum:        DA1F9D293B90B487ADB2C711137770D3
+      Modi:
+        Signature:       4
+        Records:
+          - Kind:            S_COMPILE3
+            Compile3Sym:
+              Flags:           [  ]
+              Machine:         X64
+              FrontendMajor:   12
+              FrontendMinor:   0
+              FrontendBuild:   0
+              FrontendQFE:     0
+              BackendMajor:    12000
+              BackendMinor:    0
+              BackendBuild:    0
+              BackendQFE:      0
+              Version:         'clang version 12.0.0 (git at github.com:llvm/llvm-project.git 8a08e08db6c2e4a5db485253f3186b0f9e739e15)'
+          - Kind:            S_GPROC32
+            ProcSym:
+              PtrParent:       0
+              PtrEnd:          272
+              PtrNext:         0
+              CodeSize:        28
+              DbgStart:        0
+              DbgEnd:          0
+              FunctionType:    4098
+              Offset:          0
+              Segment:         1
+              Flags:           [  ]
+              DisplayName:     main
+          - Kind:            S_FRAMEPROC
+            FrameProcSym:
+              TotalFrameBytes: 24
+              PaddingFrameBytes: 0
+              OffsetToPadding: 0
+              BytesOfCalleeSavedRegisters: 0
+              OffsetOfExceptionHandler: 0
+              SectionIdOfExceptionHandler: 0
+              Flags:           [  ]
+          - Kind:            S_LOCAL
+            LocalSym:
+              Type:            116
+              Flags:           [ IsParameter ]
+              VarName:         argc
+          - Kind:            S_DEFRANGE_FRAMEPOINTER_REL
+            DefRangeFramePointerRelSym:
+              Offset:          4
+              Range:
+                OffsetStart:     23
+                ISectStart:      1
+                Range:           5
+              Gaps:            []
+          - Kind:            S_LOCAL
+            LocalSym:
+              Type:            4096
+              Flags:           [ IsParameter ]
+              VarName:         argv
+          - Kind:            S_DEFRANGE_FRAMEPOINTER_REL
+            DefRangeFramePointerRelSym:
+              Offset:          8
+              Range:
+                OffsetStart:     23
+                ISectStart:      1
+                Range:           5
+              Gaps:            []
+          - Kind:            S_END
+            ScopeEndSym:     {}
+          - Kind:            S_BUILDINFO
+            BuildInfoSym:
+              BuildId:         4099
+    - Module:          '* Linker *'
+      ObjFile:         ''
+      Modi:
+        Signature:       4
+        Records:
+          - Kind:            S_OBJNAME
+            ObjNameSym:
+              Signature:       0
+              ObjectName:      '* Linker *'
+          - Kind:            S_COMPILE3
+            Compile3Sym:
+              Flags:           [  ]
+              Machine:         X64
+              FrontendMajor:   0
+              FrontendMinor:   0
+              FrontendBuild:   0
+              FrontendQFE:     0
+              BackendMajor:    14
+              BackendMinor:    10
+              BackendBuild:    25019
+              BackendQFE:      0
+              Version:         LLVM Linker
+          - Kind:            S_ENVBLOCK
+            EnvBlockSym:
+              Entries:
+                - cwd
+                - '/tmp'
+                - exe
+                - '/tmp/lld-link'
+                - pdb
+                - '/tmp/a.pdb'
+                - cmd
+                - '/out:a.exe -debug pdb.obj /nodefaultlib /entry:main'
+          - Kind:            S_SECTION
+            SectionSym:
+              SectionNumber:   1
+              Alignment:       12
+              Rva:             4096
+              Length:          28
+              Characteristics: 1610612768
+              Name:            .text
+          - Kind:            S_COFFGROUP
+            CoffGroupSym:
+              Size:            28
+              Characteristics: 1610612768
+              Offset:          0
+              Segment:         1
+              Name:            .text
+          - Kind:            S_SECTION
+            SectionSym:
+              SectionNumber:   2
+              Alignment:       12
+              Rva:             8192
+              Length:          72
+              Characteristics: 1073741888
+              Name:            .rdata
+          - Kind:            S_COFFGROUP
+            CoffGroupSym:
+              Size:            8
+              Characteristics: 1073741888
+              Offset:          64
+              Segment:         2
+              Name:            .xdata
+          - Kind:            S_SECTION
+            SectionSym:
+              SectionNumber:   3
+              Alignment:       12
+              Rva:             12288
+              Length:          12
+              Characteristics: 1073741888
+              Name:            .pdata
+          - Kind:            S_COFFGROUP
+            CoffGroupSym:
+              Size:            12
+              Characteristics: 1073741888
+              Offset:          0
+              Segment:         3
+              Name:            .pdata
+TpiStream:
+  Version:         VC80
+  Records:
+    - Kind:            LF_POINTER
+      Pointer:
+        ReferentType:    1648
+        Attrs:           65548
+    - Kind:            LF_ARGLIST
+      ArgList:
+        ArgIndices:      [ 116, 4096 ]
+    - Kind:            LF_PROCEDURE
+      Procedure:
+        ReturnType:      116
+        CallConv:        NearC
+        Options:         [ None ]
+        ParameterCount:  2
+        ArgumentList:    4097
+IpiStream:
+  Version:         VC80
+  Records:
+    - Kind:            LF_FUNC_ID
+      FuncId:
+        ParentScope:     0
+        FunctionType:    4098
+        Name:            main
+    - Kind:            LF_STRING_ID
+      StringId:
+        Id:              0
+        String:          '/tmp'
+    - Kind:            LF_STRING_ID
+      StringId:
+        Id:              0
+        String:          a.cpp
+    - Kind:            LF_BUILDINFO
+      BuildInfo:
+        ArgIndices:      [ 4097, 0, 4098, 0, 0 ]
+PublicsStream:
+  Records:
+    - Kind:            S_PUB32
+      PublicSym32:
+        Flags:           [ Function ]
+        Offset:          0
+        Segment:         1
+        Name:            main
+...

diff  --git a/lldb/test/Shell/SymbolFile/NativePDB/load-pdb.cpp b/lldb/test/Shell/SymbolFile/NativePDB/load-pdb.cpp
new file mode 100644
index 0000000000000..b4b9d0f8d22e5
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/NativePDB/load-pdb.cpp
@@ -0,0 +1,32 @@
+// clang-format off
+// REQUIRES: lld, x86
+
+// Test that lldb load PDB file by command `target symbols add`
+
+// RUN: mkdir -p %t/executable
+// RUN: rm -f %t/executable/foo.exe %t/executable/bar.pdb
+// RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 -c /Fo%t/executable/foo.obj -- %s
+// RUN: lld-link -debug:full -nodefaultlib -entry:main %t/executable/foo.obj \
+// RUN:     -out:%t/executable/foo.exe -pdb:%t/executable/foo.pdb
+// Rename the PDB file so that the name is 
diff erent from the name inside the executable (foo.exe).
+// RUN: mv %t/executable/foo.pdb %t/executable/bar.pdb
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb %t/executable/foo.exe \
+// RUN: -o "target symbols add %t/executable/bar.pdb" \
+// RUN: -o "b main" \
+// RUN: -o "image dump symfile" -o "quit" | FileCheck %s
+
+int main(int argc, char** argv) {
+  return 0;
+}
+
+// CHECK: (lldb) target symbols add {{.*}}bar.pdb
+// CHECK: symbol file '{{.*}}/bar.pdb' has been added to '{{.*}}/foo.exe'
+// CHECK: (lldb) b main
+// CHECK: Breakpoint 1: where = foo.exe`main + 23 at load-pdb.cpp:19, address = 0x0000000140001017
+// CHECK: (lldb) image dump symfile
+// CHECK: Types:
+// CHECK: {{.*}}: Type{0x00010024} , size = 0, compiler_type = {{.*}} int (int, char **)
+// CHECK: Compile units:
+// CHECK: {{.*}}: CompileUnit{0x00000000}, language = "c++", file = '{{.*}}/load-pdb.cpp'
+// CHECK: {{.*}}:   Function{0x08400001}, demangled = main, type = {{.*}}
+// CHECK: {{.*}}:   Block{0x08400001}


        


More information about the lldb-commits mailing list