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 ArchSpec ObjectFilePDB::GetArchitecture() { 50242e1e99SZequan Wu auto dbi_stream = m_file_up->getPDBDbiStream(); 51242e1e99SZequan Wu if (!dbi_stream) { 52242e1e99SZequan Wu llvm::consumeError(dbi_stream.takeError()); 53242e1e99SZequan Wu return ArchSpec(); 54242e1e99SZequan Wu } 55242e1e99SZequan Wu 56242e1e99SZequan Wu PDB_Machine machine = dbi_stream->getMachineType(); 57242e1e99SZequan Wu switch (machine) { 58242e1e99SZequan Wu default: 59242e1e99SZequan Wu break; 60242e1e99SZequan Wu case PDB_Machine::Amd64: 61242e1e99SZequan Wu case PDB_Machine::x86: 62242e1e99SZequan Wu case PDB_Machine::PowerPC: 63242e1e99SZequan Wu case PDB_Machine::PowerPCFP: 64242e1e99SZequan Wu case PDB_Machine::Arm: 65242e1e99SZequan Wu case PDB_Machine::ArmNT: 66242e1e99SZequan Wu case PDB_Machine::Thumb: 67242e1e99SZequan Wu case PDB_Machine::Arm64: 68242e1e99SZequan Wu ArchSpec arch; 69242e1e99SZequan Wu arch.SetArchitecture(eArchTypeCOFF, static_cast<int>(machine), 70242e1e99SZequan Wu LLDB_INVALID_CPUTYPE); 71242e1e99SZequan Wu return arch; 72242e1e99SZequan Wu } 73242e1e99SZequan Wu return ArchSpec(); 74242e1e99SZequan Wu } 75242e1e99SZequan Wu 76242e1e99SZequan Wu bool ObjectFilePDB::initPDBFile() { 77242e1e99SZequan Wu m_file_up = loadPDBFile(m_file.GetPath(), m_allocator); 78242e1e99SZequan Wu if (!m_file_up) 79242e1e99SZequan Wu return false; 80242e1e99SZequan Wu auto info_stream = m_file_up->getPDBInfoStream(); 81242e1e99SZequan Wu if (!info_stream) { 82242e1e99SZequan Wu llvm::consumeError(info_stream.takeError()); 83242e1e99SZequan Wu return false; 84242e1e99SZequan Wu } 85242e1e99SZequan Wu m_uuid = GetPDBUUID(*info_stream); 86242e1e99SZequan Wu return true; 87242e1e99SZequan Wu } 88242e1e99SZequan Wu 89242e1e99SZequan Wu ObjectFile * 90c69307e5SJonas Devlieghere ObjectFilePDB::CreateInstance(const ModuleSP &module_sp, DataBufferSP data_sp, 91242e1e99SZequan Wu offset_t data_offset, const FileSpec *file, 92242e1e99SZequan Wu offset_t file_offset, offset_t length) { 93242e1e99SZequan Wu auto objfile_up = std::make_unique<ObjectFilePDB>( 94242e1e99SZequan Wu module_sp, data_sp, data_offset, file, file_offset, length); 95242e1e99SZequan Wu if (!objfile_up->initPDBFile()) 96242e1e99SZequan Wu return nullptr; 97242e1e99SZequan Wu return objfile_up.release(); 98242e1e99SZequan Wu } 99242e1e99SZequan Wu 100242e1e99SZequan Wu ObjectFile *ObjectFilePDB::CreateMemoryInstance(const ModuleSP &module_sp, 101*f2ea125eSJonas Devlieghere WritableDataBufferSP data_sp, 102242e1e99SZequan Wu const ProcessSP &process_sp, 103242e1e99SZequan Wu addr_t header_addr) { 104242e1e99SZequan Wu return nullptr; 105242e1e99SZequan Wu } 106242e1e99SZequan Wu 107242e1e99SZequan Wu size_t ObjectFilePDB::GetModuleSpecifications( 108242e1e99SZequan Wu const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset, 109242e1e99SZequan Wu offset_t file_offset, offset_t length, ModuleSpecList &specs) { 110242e1e99SZequan Wu const size_t initial_count = specs.GetSize(); 111242e1e99SZequan Wu ModuleSpec module_spec(file); 112242e1e99SZequan Wu llvm::BumpPtrAllocator allocator; 113242e1e99SZequan Wu std::unique_ptr<PDBFile> pdb_file = loadPDBFile(file.GetPath(), allocator); 114242e1e99SZequan Wu if (!pdb_file) 115242e1e99SZequan Wu return initial_count; 116242e1e99SZequan Wu 117242e1e99SZequan Wu auto info_stream = pdb_file->getPDBInfoStream(); 118242e1e99SZequan Wu if (!info_stream) { 119242e1e99SZequan Wu llvm::consumeError(info_stream.takeError()); 120242e1e99SZequan Wu return initial_count; 121242e1e99SZequan Wu } 122242e1e99SZequan Wu auto dbi_stream = pdb_file->getPDBDbiStream(); 123242e1e99SZequan Wu if (!dbi_stream) { 124242e1e99SZequan Wu llvm::consumeError(dbi_stream.takeError()); 125242e1e99SZequan Wu return initial_count; 126242e1e99SZequan Wu } 127242e1e99SZequan Wu 128242e1e99SZequan Wu lldb_private::UUID &uuid = module_spec.GetUUID(); 129242e1e99SZequan Wu uuid = GetPDBUUID(*info_stream); 130242e1e99SZequan Wu 131242e1e99SZequan Wu ArchSpec &module_arch = module_spec.GetArchitecture(); 132242e1e99SZequan Wu switch (dbi_stream->getMachineType()) { 133242e1e99SZequan Wu case PDB_Machine::Amd64: 134242e1e99SZequan Wu module_arch.SetTriple("x86_64-pc-windows"); 135242e1e99SZequan Wu specs.Append(module_spec); 136242e1e99SZequan Wu break; 137242e1e99SZequan Wu case PDB_Machine::x86: 138242e1e99SZequan Wu module_arch.SetTriple("i386-pc-windows"); 139242e1e99SZequan Wu specs.Append(module_spec); 140242e1e99SZequan Wu module_arch.SetTriple("i686-pc-windows"); 141242e1e99SZequan Wu specs.Append(module_spec); 142242e1e99SZequan Wu break; 143242e1e99SZequan Wu case PDB_Machine::ArmNT: 144242e1e99SZequan Wu module_arch.SetTriple("armv7-pc-windows"); 145242e1e99SZequan Wu specs.Append(module_spec); 146242e1e99SZequan Wu break; 147242e1e99SZequan Wu case PDB_Machine::Arm64: 148242e1e99SZequan Wu module_arch.SetTriple("aarch64-pc-windows"); 149242e1e99SZequan Wu specs.Append(module_spec); 150242e1e99SZequan Wu break; 151242e1e99SZequan Wu default: 152242e1e99SZequan Wu break; 153242e1e99SZequan Wu } 154242e1e99SZequan Wu 155242e1e99SZequan Wu return specs.GetSize() - initial_count; 156242e1e99SZequan Wu } 157242e1e99SZequan Wu 158242e1e99SZequan Wu ObjectFilePDB::ObjectFilePDB(const ModuleSP &module_sp, DataBufferSP &data_sp, 159242e1e99SZequan Wu offset_t data_offset, const FileSpec *file, 160242e1e99SZequan Wu offset_t offset, offset_t length) 161242e1e99SZequan Wu : ObjectFile(module_sp, file, offset, length, data_sp, data_offset) {} 162242e1e99SZequan Wu 163242e1e99SZequan Wu std::unique_ptr<PDBFile> 164242e1e99SZequan Wu ObjectFilePDB::loadPDBFile(std::string PdbPath, 165242e1e99SZequan Wu llvm::BumpPtrAllocator &Allocator) { 166242e1e99SZequan Wu llvm::file_magic magic; 167242e1e99SZequan Wu auto ec = llvm::identify_magic(PdbPath, magic); 168242e1e99SZequan Wu if (ec || magic != llvm::file_magic::pdb) 169242e1e99SZequan Wu return nullptr; 170242e1e99SZequan Wu llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer = 171c83cd8feSAbhina Sreeskantharajan llvm::MemoryBuffer::getFile(PdbPath, /*IsText=*/false, 172242e1e99SZequan Wu /*RequiresNullTerminator=*/false); 173242e1e99SZequan Wu if (!ErrorOrBuffer) 174242e1e99SZequan Wu return nullptr; 175242e1e99SZequan Wu std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer); 176242e1e99SZequan Wu 177242e1e99SZequan Wu llvm::StringRef Path = Buffer->getBufferIdentifier(); 178242e1e99SZequan Wu auto Stream = std::make_unique<llvm::MemoryBufferByteStream>( 179242e1e99SZequan Wu std::move(Buffer), llvm::support::little); 180242e1e99SZequan Wu 181242e1e99SZequan Wu auto File = std::make_unique<PDBFile>(Path, std::move(Stream), Allocator); 182242e1e99SZequan Wu if (auto EC = File->parseFileHeaders()) { 183242e1e99SZequan Wu llvm::consumeError(std::move(EC)); 184242e1e99SZequan Wu return nullptr; 185242e1e99SZequan Wu } 186242e1e99SZequan Wu if (auto EC = File->parseStreamData()) { 187242e1e99SZequan Wu llvm::consumeError(std::move(EC)); 188242e1e99SZequan Wu return nullptr; 189242e1e99SZequan Wu } 190242e1e99SZequan Wu 191242e1e99SZequan Wu return File; 192242e1e99SZequan Wu } 193