diff --git a/lldb/source/Plugins/ObjectFile/CMakeLists.txt b/lldb/source/Plugins/ObjectFile/CMakeLists.txt --- 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 --- /dev/null +++ b/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 + ) diff --git a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.h new file mode 100644 --- /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 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_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; + llvm::pdb::PDBFile *m_pdb_file; + + bool initPDBFile(); +}; + +} // namespace lldb_private +#endif // LLDB_PLUGINS_OBJECTFILE_PDB_OBJECTFILEPDB_H diff --git a/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp new file mode 100644 --- /dev/null +++ b/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp @@ -0,0 +1,228 @@ +//===-- 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(machine), + LLDB_INVALID_CPUTYPE); + return arch; + } + return ArchSpec(); +} + +bool ObjectFilePDB::initPDBFile() { + m_pdb_file = loadPDBFile(m_file.GetPath(), m_allocator); + if (!m_pdb_file) + return false; + auto info_stream = m_pdb_file->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( + 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; + 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) {} + +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> ErrorOrBuffer = + llvm::MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1, + /*RequiresNullTerminator=*/false); + if (!ErrorOrBuffer) + return nullptr; + std::unique_ptr Buffer = std::move(*ErrorOrBuffer); + + llvm::StringRef Path = Buffer->getBufferIdentifier(); + auto Stream = std::make_unique( + std::move(Buffer), llvm::support::little); + + auto File = std::make_unique(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.release(); +} diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/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(); - ModuleSP module_sp(GetModule()); if (module_sp) { std::lock_guard guard(module_sp->GetMutex()); diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt --- a/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt @@ -15,6 +15,7 @@ lldbSymbol lldbUtility lldbPluginTypeSystemClang + lldbPluginObjectFilePDB CLANG_LIBS clangAST clangLex diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h @@ -48,7 +48,7 @@ class PdbIndex { /// The underlying PDB file. - std::unique_ptr 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 @@ -111,7 +111,7 @@ public: static llvm::Expected> - create(std::unique_ptr); + 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/PdbIndex.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp @@ -39,7 +39,7 @@ } llvm::Expected> -PdbIndex::create(std::unique_ptr file) { +PdbIndex::create(llvm::pdb::PDBFile *&file) { lldbassert(file); std::unique_ptr result(new PdbIndex()); @@ -53,7 +53,7 @@ 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/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp --- 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,34 +84,8 @@ } } -static std::unique_ptr loadPDBFile(std::string PdbPath, - llvm::BumpPtrAllocator &Allocator) { - llvm::ErrorOr> ErrorOrBuffer = - llvm::MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1, - /*RequiresNullTerminator=*/false); - if (!ErrorOrBuffer) - return nullptr; - std::unique_ptr Buffer = std::move(*ErrorOrBuffer); - - llvm::StringRef Path = Buffer->getBufferIdentifier(); - auto Stream = std::make_unique( - std::move(Buffer), llvm::support::little); - - auto File = std::make_unique(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 -loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) { +static PDBFile *loadMatchingPDBFile(std::string exe_path, + llvm::BumpPtrAllocator &allocator) { // Try to find a matching PDB for an EXE. using namespace llvm::object; auto expected_binary = createBinary(exe_path); @@ -144,11 +121,7 @@ } // 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 pdb = loadPDBFile(std::string(pdb_file), allocator); + PDBFile *pdb = ObjectFilePDB::loadPDBFile(std::string(pdb_file), allocator); if (!pdb) return nullptr; @@ -292,24 +265,17 @@ if (!m_index) { // Lazily load and match the PDB file, but only do this once. - std::unique_ptr 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 *file_up = nullptr; + if (auto *pdb = llvm::dyn_cast(m_objfile_sp.get())) { + file_up = pdb->GetPDBFile(); + } else + file_up = loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(), + m_allocator); if (!file_up) return 0; - auto expected_index = PdbIndex::create(std::move(file_up)); + auto expected_index = PdbIndex::create(file_up); if (!expected_index) { llvm::consumeError(expected_index.takeError()); return 0; @@ -329,7 +295,10 @@ } 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/test/Shell/ObjectFile/PDB/Inputs/pdb.yaml b/lldb/test/Shell/ObjectFile/PDB/Inputs/pdb.yaml new file mode 100644 --- /dev/null +++ b/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 (git@github.com: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 +... diff --git a/lldb/test/Shell/ObjectFile/PDB/object.test b/lldb/test/Shell/ObjectFile/PDB/object.test new file mode 100644 --- /dev/null +++ b/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: AB70D9A0-FB42-B92C-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 diff --git a/lldb/test/Shell/ObjectFile/PDB/symbol.test b/lldb/test/Shell/ObjectFile/PDB/symbol.test new file mode 100644 --- /dev/null +++ b/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 diff --git a/lldb/test/Shell/SymbolFile/NativePDB/load-pdb.cpp b/lldb/test/Shell/SymbolFile/NativePDB/load-pdb.cpp new file mode 100644 --- /dev/null +++ b/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'