diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp')
-rw-r--r-- | contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp new file mode 100644 index 000000000000..f0832dbf0734 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp @@ -0,0 +1,195 @@ +//===-- 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) + +static UUID GetPDBUUID(InfoStream &IS, DbiStream &DS) { + UUID::CvRecordPdb70 debug_info; + memcpy(&debug_info.Uuid, IS.getGuid().Guid, sizeof(debug_info.Uuid)); + debug_info.Age = DS.getAge(); + return UUID(debug_info); +} + +char ObjectFilePDB::ID; + +void ObjectFilePDB::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance, + CreateMemoryInstance, GetModuleSpecifications); +} + +void ObjectFilePDB::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +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; + } + auto dbi_stream = m_file_up->getPDBDbiStream(); + if (!dbi_stream) { + llvm::consumeError(dbi_stream.takeError()); + return false; + } + m_uuid = GetPDBUUID(*info_stream, *dbi_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, + WritableDataBufferSP 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, *dbi_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); + 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, /*IsText=*/false, + /*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::endianness::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; +} |