aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
diff options
context:
space:
mode:
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.cpp195
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;
+}