1242e1e99SZequan Wu //===-- ObjectFilePDB.cpp -------------------------------------------------===// 2242e1e99SZequan Wu // 3242e1e99SZequan Wu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4242e1e99SZequan Wu // See https://llvm.org/LICENSE.txt for license information. 5242e1e99SZequan Wu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6242e1e99SZequan Wu // 7242e1e99SZequan Wu //===----------------------------------------------------------------------===// 8242e1e99SZequan Wu 9242e1e99SZequan Wu #include "ObjectFilePDB.h" 10242e1e99SZequan Wu #include "lldb/Core/Module.h" 11242e1e99SZequan Wu #include "lldb/Core/ModuleSpec.h" 12242e1e99SZequan Wu #include "lldb/Core/PluginManager.h" 13242e1e99SZequan Wu #include "lldb/Core/Section.h" 14242e1e99SZequan Wu #include "lldb/Utility/StreamString.h" 15242e1e99SZequan Wu #include "llvm/BinaryFormat/Magic.h" 16242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/Native/DbiStream.h" 17242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/Native/InfoStream.h" 18242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 19242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 20242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/PDB.h" 21242e1e99SZequan Wu #include "llvm/Support/BinaryByteStream.h" 22242e1e99SZequan Wu 23242e1e99SZequan Wu using namespace lldb; 24242e1e99SZequan Wu using namespace lldb_private; 25242e1e99SZequan Wu using namespace llvm::pdb; 26242e1e99SZequan Wu using namespace llvm::codeview; 27242e1e99SZequan Wu 28242e1e99SZequan Wu LLDB_PLUGIN_DEFINE(ObjectFilePDB) 29242e1e99SZequan Wu 30242e1e99SZequan Wu static UUID GetPDBUUID(InfoStream &IS) { 314348e0eeSZequan Wu UUID::CvRecordPdb70 debug_info; 324348e0eeSZequan Wu memcpy(&debug_info.Uuid, IS.getGuid().Guid, sizeof(debug_info.Uuid)); 334348e0eeSZequan Wu debug_info.Age = IS.getAge(); 344348e0eeSZequan Wu return UUID::fromCvRecord(debug_info); 35242e1e99SZequan Wu } 36242e1e99SZequan Wu 37242e1e99SZequan Wu char ObjectFilePDB::ID; 38242e1e99SZequan Wu 39242e1e99SZequan Wu void ObjectFilePDB::Initialize() { 40242e1e99SZequan Wu PluginManager::RegisterPlugin(GetPluginNameStatic(), 41242e1e99SZequan Wu GetPluginDescriptionStatic(), CreateInstance, 42242e1e99SZequan Wu CreateMemoryInstance, GetModuleSpecifications); 43242e1e99SZequan Wu } 44242e1e99SZequan Wu 45242e1e99SZequan Wu void ObjectFilePDB::Terminate() { 46242e1e99SZequan Wu PluginManager::UnregisterPlugin(CreateInstance); 47242e1e99SZequan Wu } 48242e1e99SZequan Wu 49242e1e99SZequan Wu ConstString ObjectFilePDB::GetPluginNameStatic() { 50242e1e99SZequan Wu static ConstString g_name("pdb"); 51242e1e99SZequan Wu return g_name; 52242e1e99SZequan Wu } 53242e1e99SZequan Wu 54242e1e99SZequan Wu ArchSpec ObjectFilePDB::GetArchitecture() { 55242e1e99SZequan Wu auto dbi_stream = m_file_up->getPDBDbiStream(); 56242e1e99SZequan Wu if (!dbi_stream) { 57242e1e99SZequan Wu llvm::consumeError(dbi_stream.takeError()); 58242e1e99SZequan Wu return ArchSpec(); 59242e1e99SZequan Wu } 60242e1e99SZequan Wu 61242e1e99SZequan Wu PDB_Machine machine = dbi_stream->getMachineType(); 62242e1e99SZequan Wu switch (machine) { 63242e1e99SZequan Wu default: 64242e1e99SZequan Wu break; 65242e1e99SZequan Wu case PDB_Machine::Amd64: 66242e1e99SZequan Wu case PDB_Machine::x86: 67242e1e99SZequan Wu case PDB_Machine::PowerPC: 68242e1e99SZequan Wu case PDB_Machine::PowerPCFP: 69242e1e99SZequan Wu case PDB_Machine::Arm: 70242e1e99SZequan Wu case PDB_Machine::ArmNT: 71242e1e99SZequan Wu case PDB_Machine::Thumb: 72242e1e99SZequan Wu case PDB_Machine::Arm64: 73242e1e99SZequan Wu ArchSpec arch; 74242e1e99SZequan Wu arch.SetArchitecture(eArchTypeCOFF, static_cast<int>(machine), 75242e1e99SZequan Wu LLDB_INVALID_CPUTYPE); 76242e1e99SZequan Wu return arch; 77242e1e99SZequan Wu } 78242e1e99SZequan Wu return ArchSpec(); 79242e1e99SZequan Wu } 80242e1e99SZequan Wu 81242e1e99SZequan Wu bool ObjectFilePDB::initPDBFile() { 82242e1e99SZequan Wu m_file_up = loadPDBFile(m_file.GetPath(), m_allocator); 83242e1e99SZequan Wu if (!m_file_up) 84242e1e99SZequan Wu return false; 85242e1e99SZequan Wu auto info_stream = m_file_up->getPDBInfoStream(); 86242e1e99SZequan Wu if (!info_stream) { 87242e1e99SZequan Wu llvm::consumeError(info_stream.takeError()); 88242e1e99SZequan Wu return false; 89242e1e99SZequan Wu } 90242e1e99SZequan Wu m_uuid = GetPDBUUID(*info_stream); 91242e1e99SZequan Wu return true; 92242e1e99SZequan Wu } 93242e1e99SZequan Wu 94242e1e99SZequan Wu ObjectFile * 95242e1e99SZequan Wu ObjectFilePDB::CreateInstance(const ModuleSP &module_sp, DataBufferSP &data_sp, 96242e1e99SZequan Wu offset_t data_offset, const FileSpec *file, 97242e1e99SZequan Wu offset_t file_offset, offset_t length) { 98242e1e99SZequan Wu auto objfile_up = std::make_unique<ObjectFilePDB>( 99242e1e99SZequan Wu module_sp, data_sp, data_offset, file, file_offset, length); 100242e1e99SZequan Wu if (!objfile_up->initPDBFile()) 101242e1e99SZequan Wu return nullptr; 102242e1e99SZequan Wu return objfile_up.release(); 103242e1e99SZequan Wu } 104242e1e99SZequan Wu 105242e1e99SZequan Wu ObjectFile *ObjectFilePDB::CreateMemoryInstance(const ModuleSP &module_sp, 106242e1e99SZequan Wu DataBufferSP &data_sp, 107242e1e99SZequan Wu const ProcessSP &process_sp, 108242e1e99SZequan Wu addr_t header_addr) { 109242e1e99SZequan Wu return nullptr; 110242e1e99SZequan Wu } 111242e1e99SZequan Wu 112242e1e99SZequan Wu size_t ObjectFilePDB::GetModuleSpecifications( 113242e1e99SZequan Wu const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset, 114242e1e99SZequan Wu offset_t file_offset, offset_t length, ModuleSpecList &specs) { 115242e1e99SZequan Wu const size_t initial_count = specs.GetSize(); 116242e1e99SZequan Wu ModuleSpec module_spec(file); 117242e1e99SZequan Wu llvm::BumpPtrAllocator allocator; 118242e1e99SZequan Wu std::unique_ptr<PDBFile> pdb_file = loadPDBFile(file.GetPath(), allocator); 119242e1e99SZequan Wu if (!pdb_file) 120242e1e99SZequan Wu return initial_count; 121242e1e99SZequan Wu 122242e1e99SZequan Wu auto info_stream = pdb_file->getPDBInfoStream(); 123242e1e99SZequan Wu if (!info_stream) { 124242e1e99SZequan Wu llvm::consumeError(info_stream.takeError()); 125242e1e99SZequan Wu return initial_count; 126242e1e99SZequan Wu } 127242e1e99SZequan Wu auto dbi_stream = pdb_file->getPDBDbiStream(); 128242e1e99SZequan Wu if (!dbi_stream) { 129242e1e99SZequan Wu llvm::consumeError(dbi_stream.takeError()); 130242e1e99SZequan Wu return initial_count; 131242e1e99SZequan Wu } 132242e1e99SZequan Wu 133242e1e99SZequan Wu lldb_private::UUID &uuid = module_spec.GetUUID(); 134242e1e99SZequan Wu uuid = GetPDBUUID(*info_stream); 135242e1e99SZequan Wu 136242e1e99SZequan Wu ArchSpec &module_arch = module_spec.GetArchitecture(); 137242e1e99SZequan Wu switch (dbi_stream->getMachineType()) { 138242e1e99SZequan Wu case PDB_Machine::Amd64: 139242e1e99SZequan Wu module_arch.SetTriple("x86_64-pc-windows"); 140242e1e99SZequan Wu specs.Append(module_spec); 141242e1e99SZequan Wu break; 142242e1e99SZequan Wu case PDB_Machine::x86: 143242e1e99SZequan Wu module_arch.SetTriple("i386-pc-windows"); 144242e1e99SZequan Wu specs.Append(module_spec); 145242e1e99SZequan Wu module_arch.SetTriple("i686-pc-windows"); 146242e1e99SZequan Wu specs.Append(module_spec); 147242e1e99SZequan Wu break; 148242e1e99SZequan Wu case PDB_Machine::ArmNT: 149242e1e99SZequan Wu module_arch.SetTriple("armv7-pc-windows"); 150242e1e99SZequan Wu specs.Append(module_spec); 151242e1e99SZequan Wu break; 152242e1e99SZequan Wu case PDB_Machine::Arm64: 153242e1e99SZequan Wu module_arch.SetTriple("aarch64-pc-windows"); 154242e1e99SZequan Wu specs.Append(module_spec); 155242e1e99SZequan Wu break; 156242e1e99SZequan Wu default: 157242e1e99SZequan Wu break; 158242e1e99SZequan Wu } 159242e1e99SZequan Wu 160242e1e99SZequan Wu return specs.GetSize() - initial_count; 161242e1e99SZequan Wu } 162242e1e99SZequan Wu 163242e1e99SZequan Wu ObjectFilePDB::ObjectFilePDB(const ModuleSP &module_sp, DataBufferSP &data_sp, 164242e1e99SZequan Wu offset_t data_offset, const FileSpec *file, 165242e1e99SZequan Wu offset_t offset, offset_t length) 166242e1e99SZequan Wu : ObjectFile(module_sp, file, offset, length, data_sp, data_offset) {} 167242e1e99SZequan Wu 168242e1e99SZequan Wu std::unique_ptr<PDBFile> 169242e1e99SZequan Wu ObjectFilePDB::loadPDBFile(std::string PdbPath, 170242e1e99SZequan Wu llvm::BumpPtrAllocator &Allocator) { 171242e1e99SZequan Wu llvm::file_magic magic; 172242e1e99SZequan Wu auto ec = llvm::identify_magic(PdbPath, magic); 173242e1e99SZequan Wu if (ec || magic != llvm::file_magic::pdb) 174242e1e99SZequan Wu return nullptr; 175242e1e99SZequan Wu llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer = 176*c83cd8feSAbhina Sreeskantharajan llvm::MemoryBuffer::getFile(PdbPath, /*IsText=*/false, 177242e1e99SZequan Wu /*RequiresNullTerminator=*/false); 178242e1e99SZequan Wu if (!ErrorOrBuffer) 179242e1e99SZequan Wu return nullptr; 180242e1e99SZequan Wu std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer); 181242e1e99SZequan Wu 182242e1e99SZequan Wu llvm::StringRef Path = Buffer->getBufferIdentifier(); 183242e1e99SZequan Wu auto Stream = std::make_unique<llvm::MemoryBufferByteStream>( 184242e1e99SZequan Wu std::move(Buffer), llvm::support::little); 185242e1e99SZequan Wu 186242e1e99SZequan Wu auto File = std::make_unique<PDBFile>(Path, std::move(Stream), Allocator); 187242e1e99SZequan Wu if (auto EC = File->parseFileHeaders()) { 188242e1e99SZequan Wu llvm::consumeError(std::move(EC)); 189242e1e99SZequan Wu return nullptr; 190242e1e99SZequan Wu } 191242e1e99SZequan Wu if (auto EC = File->parseStreamData()) { 192242e1e99SZequan Wu llvm::consumeError(std::move(EC)); 193242e1e99SZequan Wu return nullptr; 194242e1e99SZequan Wu } 195242e1e99SZequan Wu 196242e1e99SZequan Wu return File; 197242e1e99SZequan Wu } 198