zequanwu updated this revision to Diff 299826.
zequanwu marked 4 inline comments as done.
zequanwu added a comment.
- address comments.
- add tests.
- move `loadPDBFile` from `SymbolFileNativePDB.cpp` to `ObjectFilePDB.cpp` and
use it to create unique_ptr of `PDBFile` so that we can move it around.
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/CMakeLists.txt
lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
lldb/test/Shell/ObjectFile/PDB/Inputs/pdb.yaml
lldb/test/Shell/ObjectFile/PDB/object.test
lldb/test/Shell/ObjectFile/PDB/symbol.test
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,22 @@
+// 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
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -O \
+// RUN: "target create %t/executable/foo.exe" -o \
+// RUN: "target symbols add %t/executable/bar.pdb" -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'
Index: lldb/test/Shell/ObjectFile/PDB/symbol.test
===================================================================
--- /dev/null
+++ lldb/test/Shell/ObjectFile/PDB/symbol.test
@@ -0,0 +1,10 @@
+# REQUIRES: lld
+# RUN: yaml2obj %p/Inputs/pdb.yaml -o %t.obj
+# RUN: lld-link %t.obj /debug /pdb:%t.pdb /entry:main /nodefaultlib
+# RUN: lldb-test symbols %t.pdb | FileCheck %s
+
+# CHECK: Types:
+# CHECK-NEXT: {{.*}}: Type{0x00010024} , size = 0, compiler_type = {{.*}} int (int, char **)
+# CHECK: Compile units:
+# CHECK-NEXT: {{.*}}: CompileUnit{0x00000000}, language = "c++", file = '/tmp/a.cpp'
+# CHECK-NEXT: {{.*}}: Function{0x08400001}, demangled = main, type = {{.*}}
\ No newline at end of file
Index: lldb/test/Shell/ObjectFile/PDB/object.test
===================================================================
--- /dev/null
+++ lldb/test/Shell/ObjectFile/PDB/object.test
@@ -0,0 +1,14 @@
+# REQUIRES: lld
+# RUN: yaml2obj %p/Inputs/pdb.yaml -o %t.obj
+# RUN: lld-link %t.obj /debug /pdb:%t.pdb /entry:main /nodefaultlib
+# RUN: lldb-test object-file %t.pdb | FileCheck %s
+
+# CHECK: Plugin name: pdb
+# CHECK: Architecture: x86_64-pc-windows-msvc
+# CHECK: UUID:
+# CHECK: Executable: false
+# CHECK: Stripped: false
+# CHECK: Type: debug info
+# CHECK: Strata: user
+# CHECK: Base VM address: 0x0
+# CHECK: There are no sections
\ No newline at end of file
Index: lldb/test/Shell/ObjectFile/PDB/Inputs/pdb.yaml
===================================================================
--- /dev/null
+++ lldb/test/Shell/ObjectFile/PDB/Inputs/pdb.yaml
@@ -0,0 +1,314 @@
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 4883EC1831C0C7442414000000004889542408894C24044883C418C3
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: ''
+ - Name: .bss
+ Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: ''
+ SizeOfRawData: 0
+ - Name: '.debug$S'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 04000000F1000000800000007E003C1101000000D0000C00000000000000E02E000000000000636C616E672076657273696F6E2031322E302E302028676974406769746875622E636F6D3A6C6C766D2F6C6C766D2D70726F6A6563742E6769742038613038653038646236633265346135646234383532353366333138366230663965373339653135290000F1000000900000002A0047110000000000000000000000001C000000000000000000000003100000000000000000006D61696E001E001210180000000000000000000000000000000000000000000040010000000E003E117400000001006172676300000E0042110400000017000000000005000E003E110010000001006172677600000E00421108000000170000000000050002004F11F20000002800000000000000000000001C00000000000000020000001C00000000000000010000001700000002000000F400000018000000010000001001DA1F9D293B90B487ADB2C711137770D30000F30000000C000000002F746D702F612E63707000F10000000800000006004C1106100000
+ Subsections:
+ - !Symbols
+ 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 ([email protected]:llvm/llvm-project.git 8a08e08db6c2e4a5db485253f3186b0f9e739e15)'
+ - !Symbols
+ Records:
+ - Kind: S_GPROC32_ID
+ ProcSym:
+ CodeSize: 28
+ DbgStart: 0
+ DbgEnd: 0
+ FunctionType: 4099
+ 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: 0
+ 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: 0
+ Range: 5
+ Gaps: []
+ - Kind: S_PROC_ID_END
+ ScopeEndSym: {}
+ - !Lines
+ CodeSize: 28
+ Flags: [ ]
+ RelocOffset: 0
+ RelocSegment: 0
+ 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
+ - !StringTable
+ Strings:
+ - '/tmp/a.cpp'
+ - !Symbols
+ Records:
+ - Kind: S_BUILDINFO
+ BuildInfoSym:
+ BuildId: 4102
+ Relocations:
+ - VirtualAddress: 180
+ SymbolName: main
+ Type: IMAGE_REL_AMD64_SECREL
+ - VirtualAddress: 184
+ SymbolName: main
+ Type: IMAGE_REL_AMD64_SECTION
+ - VirtualAddress: 248
+ SymbolName: .text
+ Type: IMAGE_REL_AMD64_SECREL
+ - VirtualAddress: 252
+ SymbolName: .text
+ Type: IMAGE_REL_AMD64_SECTION
+ - VirtualAddress: 280
+ SymbolName: .text
+ Type: IMAGE_REL_AMD64_SECREL
+ - VirtualAddress: 284
+ SymbolName: .text
+ Type: IMAGE_REL_AMD64_SECTION
+ - VirtualAddress: 300
+ SymbolName: main
+ Type: IMAGE_REL_AMD64_SECREL
+ - VirtualAddress: 304
+ SymbolName: main
+ Type: IMAGE_REL_AMD64_SECTION
+ - Name: '.debug$T'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 040000000A000210700600000C0001000E0001120200000074000000001000000E0008107400000000000200011000001200011600000000021000006D61696E00F3F2F10E000516000000002F746D7000F3F2F10E00051600000000612E63707000F2F11A00031605000410000000000000051000000000000000000000F2F1
+ Types:
+ - 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
+ - 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: [ 4100, 0, 4101, 0, 0 ]
+ - Name: .xdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: '0104010004220000'
+ - Name: .pdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 000000001C00000000000000
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: main
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 4
+ SymbolName: main
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 8
+ SymbolName: .xdata
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - Name: .llvm_addrsig
+ Characteristics: [ IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 1
+ SectionData: ''
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 28
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 594448369
+ Number: 1
+ - Name: .data
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 2
+ - Name: .bss
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 3
+ - Name: '.debug$S'
+ Value: 0
+ SectionNumber: 4
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 408
+ NumberOfRelocations: 8
+ NumberOfLinenumbers: 0
+ CheckSum: 1679076592
+ Number: 4
+ - Name: '.debug$T'
+ Value: 0
+ SectionNumber: 5
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 128
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 778204704
+ Number: 5
+ - Name: .xdata
+ Value: 0
+ SectionNumber: 6
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 8
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 1192424177
+ Number: 6
+ - Name: .pdata
+ Value: 0
+ SectionNumber: 7
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 12
+ NumberOfRelocations: 3
+ NumberOfLinenumbers: 0
+ CheckSum: 722740324
+ Number: 7
+ - Name: .llvm_addrsig
+ Value: 0
+ SectionNumber: 8
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 8
+ - Name: '@feat.00'
+ Value: 0
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: .file
+ Value: 0
+ SectionNumber: -2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_FILE
+ File: a.cpp
+...
Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ 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 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,8 @@
}
// 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);
+ std::unique_ptr<PDBFile> pdb =
+ ObjectFilePDB::loadPDBFile(std::string(pdb_file), allocator);
if (!pdb)
return nullptr;
@@ -292,8 +266,12 @@
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);
+ std::unique_ptr<PDBFile> file_up;
+ if (auto *pdb = llvm::dyn_cast<ObjectFilePDB>(m_objfile_sp.get())) {
+ file_up = pdb->giveMeAPDBFile();
+ } else
+ file_up = loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(),
+ m_allocator);
if (!file_up) {
auto module_sp = m_objfile_sp->GetModule();
@@ -303,7 +281,7 @@
FileSpec symfile = module_sp->GetSymbolFileFileSpec();
if (!symfile)
return 0;
- file_up = loadPDBFile(symfile.GetPath(), m_allocator);
+ file_up = ObjectFilePDB::loadPDBFile(symfile.GetPath(), m_allocator);
}
if (!file_up)
Index: lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
+++ lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
@@ -15,6 +15,7 @@
lldbSymbol
lldbUtility
lldbPluginTypeSystemClang
+ lldbPluginObjectFilePDB
CLANG_LIBS
clangAST
clangLex
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,110 @@
+//===-- 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; }
+
+ 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; }
+
+ std::unique_ptr<llvm::pdb::PDBFile> giveMeAPDBFile() {
+ return std::move(m_pdb_file);
+ }
+
+ 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_pdb_file;
+
+ bool initPDBFile();
+};
+
+} // 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,233 @@
+//===-- 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_pdb_file->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_pdb_file = loadPDBFile(m_file.GetPath(), m_allocator);
+ return (bool)m_pdb_file;
+}
+
+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 &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);
+}
+
+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;
+}
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
+ )
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