1*242e1e99SZequan Wu //===-- ObjectFilePDB.cpp -------------------------------------------------===// 2*242e1e99SZequan Wu // 3*242e1e99SZequan Wu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*242e1e99SZequan Wu // See https://llvm.org/LICENSE.txt for license information. 5*242e1e99SZequan Wu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*242e1e99SZequan Wu // 7*242e1e99SZequan Wu //===----------------------------------------------------------------------===// 8*242e1e99SZequan Wu 9*242e1e99SZequan Wu #include "ObjectFilePDB.h" 10*242e1e99SZequan Wu #include "lldb/Core/Module.h" 11*242e1e99SZequan Wu #include "lldb/Core/ModuleSpec.h" 12*242e1e99SZequan Wu #include "lldb/Core/PluginManager.h" 13*242e1e99SZequan Wu #include "lldb/Core/Section.h" 14*242e1e99SZequan Wu #include "lldb/Utility/StreamString.h" 15*242e1e99SZequan Wu #include "llvm/BinaryFormat/Magic.h" 16*242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/Native/DbiStream.h" 17*242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/Native/InfoStream.h" 18*242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 19*242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 20*242e1e99SZequan Wu #include "llvm/DebugInfo/PDB/PDB.h" 21*242e1e99SZequan Wu #include "llvm/Support/BinaryByteStream.h" 22*242e1e99SZequan Wu 23*242e1e99SZequan Wu using namespace lldb; 24*242e1e99SZequan Wu using namespace lldb_private; 25*242e1e99SZequan Wu using namespace llvm::pdb; 26*242e1e99SZequan Wu using namespace llvm::codeview; 27*242e1e99SZequan Wu 28*242e1e99SZequan Wu LLDB_PLUGIN_DEFINE(ObjectFilePDB) 29*242e1e99SZequan Wu 30*242e1e99SZequan Wu struct CVInfoPdb70 { 31*242e1e99SZequan Wu // 16-byte GUID 32*242e1e99SZequan Wu struct _Guid { 33*242e1e99SZequan Wu llvm::support::ulittle32_t Data1; 34*242e1e99SZequan Wu llvm::support::ulittle16_t Data2; 35*242e1e99SZequan Wu llvm::support::ulittle16_t Data3; 36*242e1e99SZequan Wu uint8_t Data4[8]; 37*242e1e99SZequan Wu } Guid; 38*242e1e99SZequan Wu 39*242e1e99SZequan Wu llvm::support::ulittle32_t Age; 40*242e1e99SZequan Wu }; 41*242e1e99SZequan Wu 42*242e1e99SZequan Wu static UUID GetPDBUUID(InfoStream &IS) { 43*242e1e99SZequan Wu // This part is similar with what has done in ObjectFilePECOFF. 44*242e1e99SZequan Wu using llvm::support::endian::read16be; 45*242e1e99SZequan Wu using llvm::support::endian::read32; 46*242e1e99SZequan Wu using llvm::support::endian::read32be; 47*242e1e99SZequan Wu 48*242e1e99SZequan Wu GUID guid = IS.getGuid(); 49*242e1e99SZequan Wu const uint8_t *guid_p = guid.Guid; 50*242e1e99SZequan Wu struct CVInfoPdb70 info; 51*242e1e99SZequan Wu info.Guid.Data1 = read32be(guid_p); 52*242e1e99SZequan Wu guid_p += 4; 53*242e1e99SZequan Wu info.Guid.Data2 = read16be(guid_p); 54*242e1e99SZequan Wu guid_p += 2; 55*242e1e99SZequan Wu info.Guid.Data3 = read16be(guid_p); 56*242e1e99SZequan Wu guid_p += 2; 57*242e1e99SZequan Wu memcpy(info.Guid.Data4, guid_p, 8); 58*242e1e99SZequan Wu 59*242e1e99SZequan Wu // Return 20-byte UUID if the Age is not zero 60*242e1e99SZequan Wu uint32_t age = IS.getAge(); 61*242e1e99SZequan Wu if (age) { 62*242e1e99SZequan Wu info.Age = read32(&age, llvm::support::big); 63*242e1e99SZequan Wu return UUID::fromOptionalData(&info, sizeof(info)); 64*242e1e99SZequan Wu } 65*242e1e99SZequan Wu // Otherwise return 16-byte GUID 66*242e1e99SZequan Wu return UUID::fromOptionalData(&info.Guid, sizeof(info.Guid)); 67*242e1e99SZequan Wu } 68*242e1e99SZequan Wu 69*242e1e99SZequan Wu char ObjectFilePDB::ID; 70*242e1e99SZequan Wu 71*242e1e99SZequan Wu void ObjectFilePDB::Initialize() { 72*242e1e99SZequan Wu PluginManager::RegisterPlugin(GetPluginNameStatic(), 73*242e1e99SZequan Wu GetPluginDescriptionStatic(), CreateInstance, 74*242e1e99SZequan Wu CreateMemoryInstance, GetModuleSpecifications); 75*242e1e99SZequan Wu } 76*242e1e99SZequan Wu 77*242e1e99SZequan Wu void ObjectFilePDB::Terminate() { 78*242e1e99SZequan Wu PluginManager::UnregisterPlugin(CreateInstance); 79*242e1e99SZequan Wu } 80*242e1e99SZequan Wu 81*242e1e99SZequan Wu ConstString ObjectFilePDB::GetPluginNameStatic() { 82*242e1e99SZequan Wu static ConstString g_name("pdb"); 83*242e1e99SZequan Wu return g_name; 84*242e1e99SZequan Wu } 85*242e1e99SZequan Wu 86*242e1e99SZequan Wu ArchSpec ObjectFilePDB::GetArchitecture() { 87*242e1e99SZequan Wu auto dbi_stream = m_file_up->getPDBDbiStream(); 88*242e1e99SZequan Wu if (!dbi_stream) { 89*242e1e99SZequan Wu llvm::consumeError(dbi_stream.takeError()); 90*242e1e99SZequan Wu return ArchSpec(); 91*242e1e99SZequan Wu } 92*242e1e99SZequan Wu 93*242e1e99SZequan Wu PDB_Machine machine = dbi_stream->getMachineType(); 94*242e1e99SZequan Wu switch (machine) { 95*242e1e99SZequan Wu default: 96*242e1e99SZequan Wu break; 97*242e1e99SZequan Wu case PDB_Machine::Amd64: 98*242e1e99SZequan Wu case PDB_Machine::x86: 99*242e1e99SZequan Wu case PDB_Machine::PowerPC: 100*242e1e99SZequan Wu case PDB_Machine::PowerPCFP: 101*242e1e99SZequan Wu case PDB_Machine::Arm: 102*242e1e99SZequan Wu case PDB_Machine::ArmNT: 103*242e1e99SZequan Wu case PDB_Machine::Thumb: 104*242e1e99SZequan Wu case PDB_Machine::Arm64: 105*242e1e99SZequan Wu ArchSpec arch; 106*242e1e99SZequan Wu arch.SetArchitecture(eArchTypeCOFF, static_cast<int>(machine), 107*242e1e99SZequan Wu LLDB_INVALID_CPUTYPE); 108*242e1e99SZequan Wu return arch; 109*242e1e99SZequan Wu } 110*242e1e99SZequan Wu return ArchSpec(); 111*242e1e99SZequan Wu } 112*242e1e99SZequan Wu 113*242e1e99SZequan Wu bool ObjectFilePDB::initPDBFile() { 114*242e1e99SZequan Wu m_file_up = loadPDBFile(m_file.GetPath(), m_allocator); 115*242e1e99SZequan Wu if (!m_file_up) 116*242e1e99SZequan Wu return false; 117*242e1e99SZequan Wu auto info_stream = m_file_up->getPDBInfoStream(); 118*242e1e99SZequan Wu if (!info_stream) { 119*242e1e99SZequan Wu llvm::consumeError(info_stream.takeError()); 120*242e1e99SZequan Wu return false; 121*242e1e99SZequan Wu } 122*242e1e99SZequan Wu m_uuid = GetPDBUUID(*info_stream); 123*242e1e99SZequan Wu return true; 124*242e1e99SZequan Wu } 125*242e1e99SZequan Wu 126*242e1e99SZequan Wu ObjectFile * 127*242e1e99SZequan Wu ObjectFilePDB::CreateInstance(const ModuleSP &module_sp, DataBufferSP &data_sp, 128*242e1e99SZequan Wu offset_t data_offset, const FileSpec *file, 129*242e1e99SZequan Wu offset_t file_offset, offset_t length) { 130*242e1e99SZequan Wu auto objfile_up = std::make_unique<ObjectFilePDB>( 131*242e1e99SZequan Wu module_sp, data_sp, data_offset, file, file_offset, length); 132*242e1e99SZequan Wu if (!objfile_up->initPDBFile()) 133*242e1e99SZequan Wu return nullptr; 134*242e1e99SZequan Wu return objfile_up.release(); 135*242e1e99SZequan Wu } 136*242e1e99SZequan Wu 137*242e1e99SZequan Wu ObjectFile *ObjectFilePDB::CreateMemoryInstance(const ModuleSP &module_sp, 138*242e1e99SZequan Wu DataBufferSP &data_sp, 139*242e1e99SZequan Wu const ProcessSP &process_sp, 140*242e1e99SZequan Wu addr_t header_addr) { 141*242e1e99SZequan Wu return nullptr; 142*242e1e99SZequan Wu } 143*242e1e99SZequan Wu 144*242e1e99SZequan Wu size_t ObjectFilePDB::GetModuleSpecifications( 145*242e1e99SZequan Wu const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset, 146*242e1e99SZequan Wu offset_t file_offset, offset_t length, ModuleSpecList &specs) { 147*242e1e99SZequan Wu const size_t initial_count = specs.GetSize(); 148*242e1e99SZequan Wu ModuleSpec module_spec(file); 149*242e1e99SZequan Wu llvm::BumpPtrAllocator allocator; 150*242e1e99SZequan Wu std::unique_ptr<PDBFile> pdb_file = loadPDBFile(file.GetPath(), allocator); 151*242e1e99SZequan Wu if (!pdb_file) 152*242e1e99SZequan Wu return initial_count; 153*242e1e99SZequan Wu 154*242e1e99SZequan Wu auto info_stream = pdb_file->getPDBInfoStream(); 155*242e1e99SZequan Wu if (!info_stream) { 156*242e1e99SZequan Wu llvm::consumeError(info_stream.takeError()); 157*242e1e99SZequan Wu return initial_count; 158*242e1e99SZequan Wu } 159*242e1e99SZequan Wu auto dbi_stream = pdb_file->getPDBDbiStream(); 160*242e1e99SZequan Wu if (!dbi_stream) { 161*242e1e99SZequan Wu llvm::consumeError(dbi_stream.takeError()); 162*242e1e99SZequan Wu return initial_count; 163*242e1e99SZequan Wu } 164*242e1e99SZequan Wu 165*242e1e99SZequan Wu lldb_private::UUID &uuid = module_spec.GetUUID(); 166*242e1e99SZequan Wu uuid = GetPDBUUID(*info_stream); 167*242e1e99SZequan Wu 168*242e1e99SZequan Wu ArchSpec &module_arch = module_spec.GetArchitecture(); 169*242e1e99SZequan Wu switch (dbi_stream->getMachineType()) { 170*242e1e99SZequan Wu case PDB_Machine::Amd64: 171*242e1e99SZequan Wu module_arch.SetTriple("x86_64-pc-windows"); 172*242e1e99SZequan Wu specs.Append(module_spec); 173*242e1e99SZequan Wu break; 174*242e1e99SZequan Wu case PDB_Machine::x86: 175*242e1e99SZequan Wu module_arch.SetTriple("i386-pc-windows"); 176*242e1e99SZequan Wu specs.Append(module_spec); 177*242e1e99SZequan Wu module_arch.SetTriple("i686-pc-windows"); 178*242e1e99SZequan Wu specs.Append(module_spec); 179*242e1e99SZequan Wu break; 180*242e1e99SZequan Wu case PDB_Machine::ArmNT: 181*242e1e99SZequan Wu module_arch.SetTriple("armv7-pc-windows"); 182*242e1e99SZequan Wu specs.Append(module_spec); 183*242e1e99SZequan Wu break; 184*242e1e99SZequan Wu case PDB_Machine::Arm64: 185*242e1e99SZequan Wu module_arch.SetTriple("aarch64-pc-windows"); 186*242e1e99SZequan Wu specs.Append(module_spec); 187*242e1e99SZequan Wu break; 188*242e1e99SZequan Wu default: 189*242e1e99SZequan Wu break; 190*242e1e99SZequan Wu } 191*242e1e99SZequan Wu 192*242e1e99SZequan Wu return specs.GetSize() - initial_count; 193*242e1e99SZequan Wu } 194*242e1e99SZequan Wu 195*242e1e99SZequan Wu ObjectFilePDB::ObjectFilePDB(const ModuleSP &module_sp, DataBufferSP &data_sp, 196*242e1e99SZequan Wu offset_t data_offset, const FileSpec *file, 197*242e1e99SZequan Wu offset_t offset, offset_t length) 198*242e1e99SZequan Wu : ObjectFile(module_sp, file, offset, length, data_sp, data_offset) {} 199*242e1e99SZequan Wu 200*242e1e99SZequan Wu std::unique_ptr<PDBFile> 201*242e1e99SZequan Wu ObjectFilePDB::loadPDBFile(std::string PdbPath, 202*242e1e99SZequan Wu llvm::BumpPtrAllocator &Allocator) { 203*242e1e99SZequan Wu llvm::file_magic magic; 204*242e1e99SZequan Wu auto ec = llvm::identify_magic(PdbPath, magic); 205*242e1e99SZequan Wu if (ec || magic != llvm::file_magic::pdb) 206*242e1e99SZequan Wu return nullptr; 207*242e1e99SZequan Wu llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer = 208*242e1e99SZequan Wu llvm::MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1, 209*242e1e99SZequan Wu /*RequiresNullTerminator=*/false); 210*242e1e99SZequan Wu if (!ErrorOrBuffer) 211*242e1e99SZequan Wu return nullptr; 212*242e1e99SZequan Wu std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer); 213*242e1e99SZequan Wu 214*242e1e99SZequan Wu llvm::StringRef Path = Buffer->getBufferIdentifier(); 215*242e1e99SZequan Wu auto Stream = std::make_unique<llvm::MemoryBufferByteStream>( 216*242e1e99SZequan Wu std::move(Buffer), llvm::support::little); 217*242e1e99SZequan Wu 218*242e1e99SZequan Wu auto File = std::make_unique<PDBFile>(Path, std::move(Stream), Allocator); 219*242e1e99SZequan Wu if (auto EC = File->parseFileHeaders()) { 220*242e1e99SZequan Wu llvm::consumeError(std::move(EC)); 221*242e1e99SZequan Wu return nullptr; 222*242e1e99SZequan Wu } 223*242e1e99SZequan Wu if (auto EC = File->parseStreamData()) { 224*242e1e99SZequan Wu llvm::consumeError(std::move(EC)); 225*242e1e99SZequan Wu return nullptr; 226*242e1e99SZequan Wu } 227*242e1e99SZequan Wu 228*242e1e99SZequan Wu return File; 229*242e1e99SZequan Wu } 230