zequanwu updated this revision to Diff 299527.
zequanwu added a comment.

elaborate CHECK


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D89812/new/

https://reviews.llvm.org/D89812

Files:
  lldb/source/Plugins/ObjectFile/CMakeLists.txt
  lldb/source/Plugins/ObjectFile/PDB/CMakeLists.txt
  lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
  lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h
  lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
  lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
  lldb/test/Shell/SymbolFile/NativePDB/load-pdb.cpp

Index: lldb/test/Shell/SymbolFile/NativePDB/load-pdb.cpp
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/NativePDB/load-pdb.cpp
@@ -0,0 +1,23 @@
+// 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 different from the name inside the executable (foo.exe).
+// RUN: mv %t/executable/foo.pdb %t/executable/bar.pdb
+// Create lldbinit
+// RUN: echo -e "target symbols add %t/executable/bar.pdb\nquit" > %t/load-pdb.lldbinit
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t/executable/foo.exe -s \
+// RUN:     %t/load-pdb.lldbinit | 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'
Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -42,9 +42,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"
@@ -113,10 +115,11 @@
   using namespace llvm::object;
   auto expected_binary = createBinary(exe_path);
 
-  // If the file isn't a PE/COFF executable, fail.
+  // If the file isn't a PE/COFF executable, it might be pdb file.
   if (!expected_binary) {
     llvm::consumeError(expected_binary.takeError());
-    return nullptr;
+    std::unique_ptr<PDBFile> pdb = loadPDBFile(exe_path, allocator);
+    return pdb;
   }
   OwningBinary<Binary> binary = std::move(*expected_binary);
 
Index: lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
===================================================================
--- lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -142,7 +142,6 @@
   // Cache coff binary.
   if (!objfile_up->CreateBinary())
     return nullptr;
-
   return objfile_up.release();
 }
 
@@ -852,7 +851,6 @@
   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());
Index: lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h
@@ -0,0 +1,106 @@
+//===-- 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_PLUGINS_OBJECTFILE_PDB_OBJECTFILEPDB_H
+#define LLDB_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 {
+namespace pdb {
+
+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 bool MagicBytesMatch(lldb::DataBufferSP &data_sp);
+
+  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; }
+
+  Address GetBaseAddress() override;
+
+  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; }
+
+  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; }
+
+  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;
+  std::unique_ptr<llvm::pdb::NativeSession> m_session;
+
+  bool CreateSession();
+};
+
+} // namespace pdb
+} // namespace lldb_private
+#endif // LLDB_PLUGINS_OBJECTFILE_PDB_OBJECTFILEPDB_H
Index: lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
@@ -0,0 +1,217 @@
+//===-- 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 lldb_private::pdb;
+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));
+}
+
+static std::unique_ptr<NativeSession> GetNativeSession(const FileSpec *file) {
+  std::unique_ptr<IPDBSession> session;
+  if (auto E =
+          loadDataForPDB(PDB_ReaderType::Native, file->GetPath(), session)) {
+    llvm::consumeError(std::move(E));
+    return nullptr;
+  }
+  return std::unique_ptr<NativeSession>(
+      static_cast<NativeSession *>(session.release()));
+}
+
+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_session->getPDBFile().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::CreateSession() {
+  m_session = GetNativeSession(&m_file);
+  return (bool)m_session;
+}
+
+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->CreateSession())
+    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);
+
+  std::unique_ptr<NativeSession> NS = GetNativeSession(&file);
+  if (!NS)
+    return initial_count;
+
+  PDBFile &pdb_file = NS->getPDBFile();
+  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();
+  if (!uuid.IsValid())
+    uuid = GetPDBUUID(*info_stream);
+
+  ArchSpec &spec = module_spec.GetArchitecture();
+  switch (dbi_stream->getMachineType()) {
+  case PDB_Machine::Amd64:
+    spec.SetTriple("x86_64-pc-windows");
+    specs.Append(module_spec);
+    break;
+  case PDB_Machine::x86:
+    spec.SetTriple("i386-pc-windows");
+    specs.Append(module_spec);
+    spec.SetTriple("i686-pc-windows");
+    specs.Append(module_spec);
+    break;
+  case PDB_Machine::ArmNT:
+    spec.SetTriple("armv7-pc-windows");
+    specs.Append(module_spec);
+    break;
+  case PDB_Machine::Arm64:
+    spec.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) {}
+
+Address ObjectFilePDB::GetBaseAddress() {
+  return Address(GetSectionList()->GetSectionAtIndex(0), 0);
+}
+
+void ObjectFilePDB::CreateSections(SectionList &unified_section_list) {
+  if (m_sections_up)
+    return;
+  m_sections_up = std::make_unique<SectionList>();
+  for (auto s : unified_section_list)
+    m_sections_up->AddSection(s);
+}
Index: lldb/source/Plugins/ObjectFile/PDB/CMakeLists.txt
===================================================================
--- /dev/null
+++ lldb/source/Plugins/ObjectFile/PDB/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_lldb_library(lldbPluginObjectFilePDB PLUGIN
+  ObjectFilePDB.cpp
+
+  LINK_LIBS
+    lldbCore
+    lldbHost
+    lldbSymbol
+    lldbUtility
+  LINK_COMPONENTS
+    Support
+  )
\ No newline at end of file
Index: lldb/source/Plugins/ObjectFile/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/ObjectFile/CMakeLists.txt
+++ 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)
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to