zequanwu created this revision.
zequanwu added reviewers: labath, amccarth.
Herald added subscribers: lldb-commits, mgorny.
Herald added a project: LLDB.
zequanwu requested review of this revision.
Herald added a subscriber: JDevlieghere.
To allow loading PDB file with `target symbols add` command.
Repository:
rG LLVM Github Monorepo
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/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
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/PDB/ObjectFilePDB.h
===================================================================
--- /dev/null
+++ 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_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 { return m_arch; }
+
+ 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:
+ ArchSpec m_arch;
+ 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,159 @@
+//===-- 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/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;
+}
+
+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 stream = pdb_file.getPDBInfoStream();
+ if (!stream)
+ return initial_count;
+ lldb_private::UUID &uuid = module_spec.GetUUID();
+ if (!uuid.IsValid()) {
+ uuid = GetPDBUUID(*stream);
+ }
+
+ specs.Append(module_spec);
+ 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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits