Path: blob/main/contrib/llvm-project/lldb/source/Plugins/ObjectFile/PDB/ObjectFilePDB.cpp
39642 views
//===-- ObjectFilePDB.cpp -------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "ObjectFilePDB.h"9#include "lldb/Core/Module.h"10#include "lldb/Core/ModuleSpec.h"11#include "lldb/Core/PluginManager.h"12#include "lldb/Core/Section.h"13#include "lldb/Utility/StreamString.h"14#include "llvm/BinaryFormat/Magic.h"15#include "llvm/DebugInfo/PDB/Native/DbiStream.h"16#include "llvm/DebugInfo/PDB/Native/InfoStream.h"17#include "llvm/DebugInfo/PDB/Native/NativeSession.h"18#include "llvm/DebugInfo/PDB/Native/PDBFile.h"19#include "llvm/DebugInfo/PDB/PDB.h"20#include "llvm/Support/BinaryByteStream.h"2122using namespace lldb;23using namespace lldb_private;24using namespace llvm::pdb;25using namespace llvm::codeview;2627LLDB_PLUGIN_DEFINE(ObjectFilePDB)2829static UUID GetPDBUUID(InfoStream &IS, DbiStream &DS) {30UUID::CvRecordPdb70 debug_info;31memcpy(&debug_info.Uuid, IS.getGuid().Guid, sizeof(debug_info.Uuid));32debug_info.Age = DS.getAge();33return UUID(debug_info);34}3536char ObjectFilePDB::ID;3738void ObjectFilePDB::Initialize() {39PluginManager::RegisterPlugin(GetPluginNameStatic(),40GetPluginDescriptionStatic(), CreateInstance,41CreateMemoryInstance, GetModuleSpecifications);42}4344void ObjectFilePDB::Terminate() {45PluginManager::UnregisterPlugin(CreateInstance);46}4748ArchSpec ObjectFilePDB::GetArchitecture() {49auto dbi_stream = m_file_up->getPDBDbiStream();50if (!dbi_stream) {51llvm::consumeError(dbi_stream.takeError());52return ArchSpec();53}5455PDB_Machine machine = dbi_stream->getMachineType();56switch (machine) {57default:58break;59case PDB_Machine::Amd64:60case PDB_Machine::x86:61case PDB_Machine::PowerPC:62case PDB_Machine::PowerPCFP:63case PDB_Machine::Arm:64case PDB_Machine::ArmNT:65case PDB_Machine::Thumb:66case PDB_Machine::Arm64:67ArchSpec arch;68arch.SetArchitecture(eArchTypeCOFF, static_cast<int>(machine),69LLDB_INVALID_CPUTYPE);70return arch;71}72return ArchSpec();73}7475bool ObjectFilePDB::initPDBFile() {76m_file_up = loadPDBFile(m_file.GetPath(), m_allocator);77if (!m_file_up)78return false;79auto info_stream = m_file_up->getPDBInfoStream();80if (!info_stream) {81llvm::consumeError(info_stream.takeError());82return false;83}84auto dbi_stream = m_file_up->getPDBDbiStream();85if (!dbi_stream) {86llvm::consumeError(dbi_stream.takeError());87return false;88}89m_uuid = GetPDBUUID(*info_stream, *dbi_stream);90return true;91}9293ObjectFile *94ObjectFilePDB::CreateInstance(const ModuleSP &module_sp, DataBufferSP data_sp,95offset_t data_offset, const FileSpec *file,96offset_t file_offset, offset_t length) {97auto objfile_up = std::make_unique<ObjectFilePDB>(98module_sp, data_sp, data_offset, file, file_offset, length);99if (!objfile_up->initPDBFile())100return nullptr;101return objfile_up.release();102}103104ObjectFile *ObjectFilePDB::CreateMemoryInstance(const ModuleSP &module_sp,105WritableDataBufferSP data_sp,106const ProcessSP &process_sp,107addr_t header_addr) {108return nullptr;109}110111size_t ObjectFilePDB::GetModuleSpecifications(112const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,113offset_t file_offset, offset_t length, ModuleSpecList &specs) {114const size_t initial_count = specs.GetSize();115ModuleSpec module_spec(file);116llvm::BumpPtrAllocator allocator;117std::unique_ptr<PDBFile> pdb_file = loadPDBFile(file.GetPath(), allocator);118if (!pdb_file)119return initial_count;120121auto info_stream = pdb_file->getPDBInfoStream();122if (!info_stream) {123llvm::consumeError(info_stream.takeError());124return initial_count;125}126auto dbi_stream = pdb_file->getPDBDbiStream();127if (!dbi_stream) {128llvm::consumeError(dbi_stream.takeError());129return initial_count;130}131132lldb_private::UUID &uuid = module_spec.GetUUID();133uuid = GetPDBUUID(*info_stream, *dbi_stream);134135ArchSpec &module_arch = module_spec.GetArchitecture();136switch (dbi_stream->getMachineType()) {137case PDB_Machine::Amd64:138module_arch.SetTriple("x86_64-pc-windows");139specs.Append(module_spec);140break;141case PDB_Machine::x86:142module_arch.SetTriple("i386-pc-windows");143specs.Append(module_spec);144break;145case PDB_Machine::ArmNT:146module_arch.SetTriple("armv7-pc-windows");147specs.Append(module_spec);148break;149case PDB_Machine::Arm64:150module_arch.SetTriple("aarch64-pc-windows");151specs.Append(module_spec);152break;153default:154break;155}156157return specs.GetSize() - initial_count;158}159160ObjectFilePDB::ObjectFilePDB(const ModuleSP &module_sp, DataBufferSP &data_sp,161offset_t data_offset, const FileSpec *file,162offset_t offset, offset_t length)163: ObjectFile(module_sp, file, offset, length, data_sp, data_offset) {}164165std::unique_ptr<PDBFile>166ObjectFilePDB::loadPDBFile(std::string PdbPath,167llvm::BumpPtrAllocator &Allocator) {168llvm::file_magic magic;169auto ec = llvm::identify_magic(PdbPath, magic);170if (ec || magic != llvm::file_magic::pdb)171return nullptr;172llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer =173llvm::MemoryBuffer::getFile(PdbPath, /*IsText=*/false,174/*RequiresNullTerminator=*/false);175if (!ErrorOrBuffer)176return nullptr;177std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);178179llvm::StringRef Path = Buffer->getBufferIdentifier();180auto Stream = std::make_unique<llvm::MemoryBufferByteStream>(181std::move(Buffer), llvm::endianness::little);182183auto File = std::make_unique<PDBFile>(Path, std::move(Stream), Allocator);184if (auto EC = File->parseFileHeaders()) {185llvm::consumeError(std::move(EC));186return nullptr;187}188if (auto EC = File->parseStreamData()) {189llvm::consumeError(std::move(EC));190return nullptr;191}192193return File;194}195196197