1*307f5ae8SZachary Turner //===-- SymbolFileNativePDB.cpp ---------------------------------*- C++ -*-===// 2*307f5ae8SZachary Turner // 3*307f5ae8SZachary Turner // The LLVM Compiler Infrastructure 4*307f5ae8SZachary Turner // 5*307f5ae8SZachary Turner // This file is distributed under the University of Illinois Open Source 6*307f5ae8SZachary Turner // License. See LICENSE.TXT for details. 7*307f5ae8SZachary Turner // 8*307f5ae8SZachary Turner //===----------------------------------------------------------------------===// 9*307f5ae8SZachary Turner 10*307f5ae8SZachary Turner #include "SymbolFileNativePDB.h" 11*307f5ae8SZachary Turner 12*307f5ae8SZachary Turner #include "clang/Lex/Lexer.h" 13*307f5ae8SZachary Turner 14*307f5ae8SZachary Turner #include "lldb/Core/Module.h" 15*307f5ae8SZachary Turner #include "lldb/Core/PluginManager.h" 16*307f5ae8SZachary Turner #include "lldb/Symbol/CompileUnit.h" 17*307f5ae8SZachary Turner #include "lldb/Symbol/LineTable.h" 18*307f5ae8SZachary Turner #include "lldb/Symbol/ObjectFile.h" 19*307f5ae8SZachary Turner #include "lldb/Symbol/SymbolContext.h" 20*307f5ae8SZachary Turner #include "lldb/Symbol/SymbolVendor.h" 21*307f5ae8SZachary Turner 22*307f5ae8SZachary Turner #include "llvm/DebugInfo/CodeView/CVRecord.h" 23*307f5ae8SZachary Turner #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" 24*307f5ae8SZachary Turner #include "llvm/DebugInfo/CodeView/RecordName.h" 25*307f5ae8SZachary Turner #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" 26*307f5ae8SZachary Turner #include "llvm/DebugInfo/PDB/Native/DbiStream.h" 27*307f5ae8SZachary Turner #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" 28*307f5ae8SZachary Turner #include "llvm/DebugInfo/PDB/Native/InfoStream.h" 29*307f5ae8SZachary Turner #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" 30*307f5ae8SZachary Turner #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 31*307f5ae8SZachary Turner #include "llvm/DebugInfo/PDB/Native/SymbolStream.h" 32*307f5ae8SZachary Turner #include "llvm/DebugInfo/PDB/PDBTypes.h" 33*307f5ae8SZachary Turner #include "llvm/Object/COFF.h" 34*307f5ae8SZachary Turner #include "llvm/Support/Allocator.h" 35*307f5ae8SZachary Turner #include "llvm/Support/BinaryStreamReader.h" 36*307f5ae8SZachary Turner #include "llvm/Support/ErrorOr.h" 37*307f5ae8SZachary Turner #include "llvm/Support/MemoryBuffer.h" 38*307f5ae8SZachary Turner 39*307f5ae8SZachary Turner #include "PdbSymUid.h" 40*307f5ae8SZachary Turner #include "PdbUtil.h" 41*307f5ae8SZachary Turner 42*307f5ae8SZachary Turner using namespace lldb; 43*307f5ae8SZachary Turner using namespace lldb_private; 44*307f5ae8SZachary Turner using namespace lldb_private::npdb; 45*307f5ae8SZachary Turner using namespace llvm::codeview; 46*307f5ae8SZachary Turner using namespace llvm::pdb; 47*307f5ae8SZachary Turner 48*307f5ae8SZachary Turner static lldb::LanguageType TranslateLanguage(PDB_Lang lang) { 49*307f5ae8SZachary Turner switch (lang) { 50*307f5ae8SZachary Turner case PDB_Lang::Cpp: 51*307f5ae8SZachary Turner return lldb::LanguageType::eLanguageTypeC_plus_plus; 52*307f5ae8SZachary Turner case PDB_Lang::C: 53*307f5ae8SZachary Turner return lldb::LanguageType::eLanguageTypeC; 54*307f5ae8SZachary Turner default: 55*307f5ae8SZachary Turner return lldb::LanguageType::eLanguageTypeUnknown; 56*307f5ae8SZachary Turner } 57*307f5ae8SZachary Turner } 58*307f5ae8SZachary Turner 59*307f5ae8SZachary Turner static std::unique_ptr<PDBFile> loadPDBFile(std::string PdbPath, 60*307f5ae8SZachary Turner llvm::BumpPtrAllocator &Allocator) { 61*307f5ae8SZachary Turner llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer = 62*307f5ae8SZachary Turner llvm::MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1, 63*307f5ae8SZachary Turner /*RequiresNullTerminator=*/false); 64*307f5ae8SZachary Turner if (!ErrorOrBuffer) 65*307f5ae8SZachary Turner return nullptr; 66*307f5ae8SZachary Turner std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer); 67*307f5ae8SZachary Turner 68*307f5ae8SZachary Turner llvm::StringRef Path = Buffer->getBufferIdentifier(); 69*307f5ae8SZachary Turner auto Stream = llvm::make_unique<llvm::MemoryBufferByteStream>( 70*307f5ae8SZachary Turner std::move(Buffer), llvm::support::little); 71*307f5ae8SZachary Turner 72*307f5ae8SZachary Turner auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), Allocator); 73*307f5ae8SZachary Turner if (auto EC = File->parseFileHeaders()) 74*307f5ae8SZachary Turner return nullptr; 75*307f5ae8SZachary Turner if (auto EC = File->parseStreamData()) 76*307f5ae8SZachary Turner return nullptr; 77*307f5ae8SZachary Turner 78*307f5ae8SZachary Turner return File; 79*307f5ae8SZachary Turner } 80*307f5ae8SZachary Turner 81*307f5ae8SZachary Turner static std::unique_ptr<PDBFile> 82*307f5ae8SZachary Turner loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) { 83*307f5ae8SZachary Turner // Try to find a matching PDB for an EXE. 84*307f5ae8SZachary Turner using namespace llvm::object; 85*307f5ae8SZachary Turner auto expected_binary = createBinary(exe_path); 86*307f5ae8SZachary Turner 87*307f5ae8SZachary Turner // If the file isn't a PE/COFF executable, fail. 88*307f5ae8SZachary Turner if (!expected_binary) { 89*307f5ae8SZachary Turner llvm::consumeError(expected_binary.takeError()); 90*307f5ae8SZachary Turner return nullptr; 91*307f5ae8SZachary Turner } 92*307f5ae8SZachary Turner OwningBinary<Binary> binary = std::move(*expected_binary); 93*307f5ae8SZachary Turner 94*307f5ae8SZachary Turner auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary()); 95*307f5ae8SZachary Turner if (!obj) 96*307f5ae8SZachary Turner return nullptr; 97*307f5ae8SZachary Turner const llvm::codeview::DebugInfo *pdb_info = nullptr; 98*307f5ae8SZachary Turner 99*307f5ae8SZachary Turner // If it doesn't have a debug directory, fail. 100*307f5ae8SZachary Turner llvm::StringRef pdb_file; 101*307f5ae8SZachary Turner auto ec = obj->getDebugPDBInfo(pdb_info, pdb_file); 102*307f5ae8SZachary Turner if (ec) 103*307f5ae8SZachary Turner return nullptr; 104*307f5ae8SZachary Turner 105*307f5ae8SZachary Turner // if the file doesn't exist, is not a pdb, or doesn't have a matching guid, 106*307f5ae8SZachary Turner // fail. 107*307f5ae8SZachary Turner llvm::file_magic magic; 108*307f5ae8SZachary Turner ec = llvm::identify_magic(pdb_file, magic); 109*307f5ae8SZachary Turner if (ec || magic != llvm::file_magic::pdb) 110*307f5ae8SZachary Turner return nullptr; 111*307f5ae8SZachary Turner std::unique_ptr<PDBFile> pdb = loadPDBFile(pdb_file, allocator); 112*307f5ae8SZachary Turner auto expected_info = pdb->getPDBInfoStream(); 113*307f5ae8SZachary Turner if (!expected_info) { 114*307f5ae8SZachary Turner llvm::consumeError(expected_info.takeError()); 115*307f5ae8SZachary Turner return nullptr; 116*307f5ae8SZachary Turner } 117*307f5ae8SZachary Turner llvm::codeview::GUID guid; 118*307f5ae8SZachary Turner memcpy(&guid, pdb_info->PDB70.Signature, 16); 119*307f5ae8SZachary Turner 120*307f5ae8SZachary Turner if (expected_info->getGuid() != guid) 121*307f5ae8SZachary Turner return nullptr; 122*307f5ae8SZachary Turner return pdb; 123*307f5ae8SZachary Turner } 124*307f5ae8SZachary Turner 125*307f5ae8SZachary Turner static bool IsFunctionPrologue(const CompilandIndexItem &cci, 126*307f5ae8SZachary Turner lldb::addr_t addr) { 127*307f5ae8SZachary Turner // FIXME: Implement this. 128*307f5ae8SZachary Turner return false; 129*307f5ae8SZachary Turner } 130*307f5ae8SZachary Turner 131*307f5ae8SZachary Turner static bool IsFunctionEpilogue(const CompilandIndexItem &cci, 132*307f5ae8SZachary Turner lldb::addr_t addr) { 133*307f5ae8SZachary Turner // FIXME: Implement this. 134*307f5ae8SZachary Turner return false; 135*307f5ae8SZachary Turner } 136*307f5ae8SZachary Turner 137*307f5ae8SZachary Turner void SymbolFileNativePDB::Initialize() { 138*307f5ae8SZachary Turner PluginManager::RegisterPlugin(GetPluginNameStatic(), 139*307f5ae8SZachary Turner GetPluginDescriptionStatic(), CreateInstance, 140*307f5ae8SZachary Turner DebuggerInitialize); 141*307f5ae8SZachary Turner } 142*307f5ae8SZachary Turner 143*307f5ae8SZachary Turner void SymbolFileNativePDB::Terminate() { 144*307f5ae8SZachary Turner PluginManager::UnregisterPlugin(CreateInstance); 145*307f5ae8SZachary Turner } 146*307f5ae8SZachary Turner 147*307f5ae8SZachary Turner void SymbolFileNativePDB::DebuggerInitialize(lldb_private::Debugger &debugger) { 148*307f5ae8SZachary Turner } 149*307f5ae8SZachary Turner 150*307f5ae8SZachary Turner lldb_private::ConstString SymbolFileNativePDB::GetPluginNameStatic() { 151*307f5ae8SZachary Turner static ConstString g_name("native-pdb"); 152*307f5ae8SZachary Turner return g_name; 153*307f5ae8SZachary Turner } 154*307f5ae8SZachary Turner 155*307f5ae8SZachary Turner const char *SymbolFileNativePDB::GetPluginDescriptionStatic() { 156*307f5ae8SZachary Turner return "Microsoft PDB debug symbol cross-platform file reader."; 157*307f5ae8SZachary Turner } 158*307f5ae8SZachary Turner 159*307f5ae8SZachary Turner lldb_private::SymbolFile * 160*307f5ae8SZachary Turner SymbolFileNativePDB::CreateInstance(lldb_private::ObjectFile *obj_file) { 161*307f5ae8SZachary Turner return new SymbolFileNativePDB(obj_file); 162*307f5ae8SZachary Turner } 163*307f5ae8SZachary Turner 164*307f5ae8SZachary Turner SymbolFileNativePDB::SymbolFileNativePDB(lldb_private::ObjectFile *object_file) 165*307f5ae8SZachary Turner : SymbolFile(object_file) {} 166*307f5ae8SZachary Turner 167*307f5ae8SZachary Turner SymbolFileNativePDB::~SymbolFileNativePDB() {} 168*307f5ae8SZachary Turner 169*307f5ae8SZachary Turner uint32_t SymbolFileNativePDB::CalculateAbilities() { 170*307f5ae8SZachary Turner uint32_t abilities = 0; 171*307f5ae8SZachary Turner if (!m_obj_file) 172*307f5ae8SZachary Turner return 0; 173*307f5ae8SZachary Turner 174*307f5ae8SZachary Turner if (!m_index) { 175*307f5ae8SZachary Turner // Lazily load and match the PDB file, but only do this once. 176*307f5ae8SZachary Turner std::unique_ptr<PDBFile> file_up = 177*307f5ae8SZachary Turner loadMatchingPDBFile(m_obj_file->GetFileSpec().GetPath(), m_allocator); 178*307f5ae8SZachary Turner 179*307f5ae8SZachary Turner if (!file_up) { 180*307f5ae8SZachary Turner auto module_sp = m_obj_file->GetModule(); 181*307f5ae8SZachary Turner if (!module_sp) 182*307f5ae8SZachary Turner return 0; 183*307f5ae8SZachary Turner // See if any symbol file is specified through `--symfile` option. 184*307f5ae8SZachary Turner FileSpec symfile = module_sp->GetSymbolFileFileSpec(); 185*307f5ae8SZachary Turner if (!symfile) 186*307f5ae8SZachary Turner return 0; 187*307f5ae8SZachary Turner file_up = loadPDBFile(symfile.GetPath(), m_allocator); 188*307f5ae8SZachary Turner } 189*307f5ae8SZachary Turner 190*307f5ae8SZachary Turner if (!file_up) 191*307f5ae8SZachary Turner return 0; 192*307f5ae8SZachary Turner 193*307f5ae8SZachary Turner auto expected_index = PdbIndex::create(std::move(file_up)); 194*307f5ae8SZachary Turner if (!expected_index) { 195*307f5ae8SZachary Turner llvm::consumeError(expected_index.takeError()); 196*307f5ae8SZachary Turner return 0; 197*307f5ae8SZachary Turner } 198*307f5ae8SZachary Turner m_index = std::move(*expected_index); 199*307f5ae8SZachary Turner } 200*307f5ae8SZachary Turner if (!m_index) 201*307f5ae8SZachary Turner return 0; 202*307f5ae8SZachary Turner 203*307f5ae8SZachary Turner // We don't especially have to be precise here. We only distinguish between 204*307f5ae8SZachary Turner // stripped and not stripped. 205*307f5ae8SZachary Turner abilities = kAllAbilities; 206*307f5ae8SZachary Turner 207*307f5ae8SZachary Turner if (m_index->dbi().isStripped()) 208*307f5ae8SZachary Turner abilities &= ~(Blocks | LocalVariables); 209*307f5ae8SZachary Turner return abilities; 210*307f5ae8SZachary Turner } 211*307f5ae8SZachary Turner 212*307f5ae8SZachary Turner void SymbolFileNativePDB::InitializeObject() { 213*307f5ae8SZachary Turner m_obj_load_address = m_obj_file->GetFileOffset(); 214*307f5ae8SZachary Turner m_index->SetLoadAddress(m_obj_load_address); 215*307f5ae8SZachary Turner m_index->ParseSectionContribs(); 216*307f5ae8SZachary Turner } 217*307f5ae8SZachary Turner 218*307f5ae8SZachary Turner uint32_t SymbolFileNativePDB::GetNumCompileUnits() { 219*307f5ae8SZachary Turner const DbiModuleList &modules = m_index->dbi().modules(); 220*307f5ae8SZachary Turner uint32_t count = modules.getModuleCount(); 221*307f5ae8SZachary Turner if (count == 0) 222*307f5ae8SZachary Turner return count; 223*307f5ae8SZachary Turner 224*307f5ae8SZachary Turner // The linker can inject an additional "dummy" compilation unit into the 225*307f5ae8SZachary Turner // PDB. Ignore this special compile unit for our purposes, if it is there. 226*307f5ae8SZachary Turner // It is always the last one. 227*307f5ae8SZachary Turner DbiModuleDescriptor last = modules.getModuleDescriptor(count - 1); 228*307f5ae8SZachary Turner if (last.getModuleName() == "* Linker *") 229*307f5ae8SZachary Turner --count; 230*307f5ae8SZachary Turner return count; 231*307f5ae8SZachary Turner } 232*307f5ae8SZachary Turner 233*307f5ae8SZachary Turner lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbSymUid func_uid, 234*307f5ae8SZachary Turner const SymbolContext &sc) { 235*307f5ae8SZachary Turner lldbassert(func_uid.tag() == PDB_SymType::Function); 236*307f5ae8SZachary Turner 237*307f5ae8SZachary Turner PdbSymUid cuid = PdbSymUid::makeCompilandId(func_uid.asCuSym().modi); 238*307f5ae8SZachary Turner 239*307f5ae8SZachary Turner const CompilandIndexItem *cci = m_index->compilands().GetCompiland(cuid); 240*307f5ae8SZachary Turner lldbassert(cci); 241*307f5ae8SZachary Turner CVSymbol sym_record = 242*307f5ae8SZachary Turner cci->m_debug_stream.readSymbolAtOffset(func_uid.asCuSym().offset); 243*307f5ae8SZachary Turner 244*307f5ae8SZachary Turner lldbassert(sym_record.kind() == S_LPROC32 || sym_record.kind() == S_GPROC32); 245*307f5ae8SZachary Turner SegmentOffsetLength sol = GetSegmentOffsetAndLength(sym_record); 246*307f5ae8SZachary Turner 247*307f5ae8SZachary Turner auto file_vm_addr = m_index->MakeVirtualAddress(sol.so); 248*307f5ae8SZachary Turner if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0) 249*307f5ae8SZachary Turner return nullptr; 250*307f5ae8SZachary Turner 251*307f5ae8SZachary Turner AddressRange func_range(file_vm_addr, sol.length, 252*307f5ae8SZachary Turner sc.module_sp->GetSectionList()); 253*307f5ae8SZachary Turner if (!func_range.GetBaseAddress().IsValid()) 254*307f5ae8SZachary Turner return nullptr; 255*307f5ae8SZachary Turner 256*307f5ae8SZachary Turner lldb_private::Type *func_type = nullptr; 257*307f5ae8SZachary Turner 258*307f5ae8SZachary Turner // FIXME: Resolve types and mangled names. 259*307f5ae8SZachary Turner PdbSymUid sig_uid = 260*307f5ae8SZachary Turner PdbSymUid::makeTypeSymId(PDB_SymType::FunctionSig, TypeIndex{0}, false); 261*307f5ae8SZachary Turner Mangled mangled(getSymbolName(sym_record)); 262*307f5ae8SZachary Turner 263*307f5ae8SZachary Turner FunctionSP func_sp = std::make_shared<Function>( 264*307f5ae8SZachary Turner sc.comp_unit, func_uid.toOpaqueId(), sig_uid.toOpaqueId(), mangled, 265*307f5ae8SZachary Turner func_type, func_range); 266*307f5ae8SZachary Turner 267*307f5ae8SZachary Turner sc.comp_unit->AddFunction(func_sp); 268*307f5ae8SZachary Turner return func_sp; 269*307f5ae8SZachary Turner } 270*307f5ae8SZachary Turner 271*307f5ae8SZachary Turner CompUnitSP 272*307f5ae8SZachary Turner SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) { 273*307f5ae8SZachary Turner lldb::LanguageType lang = 274*307f5ae8SZachary Turner cci.m_compile_opts ? TranslateLanguage(cci.m_compile_opts->getLanguage()) 275*307f5ae8SZachary Turner : lldb::eLanguageTypeUnknown; 276*307f5ae8SZachary Turner 277*307f5ae8SZachary Turner LazyBool optimized = eLazyBoolNo; 278*307f5ae8SZachary Turner if (cci.m_compile_opts && cci.m_compile_opts->hasOptimizations()) 279*307f5ae8SZachary Turner optimized = eLazyBoolYes; 280*307f5ae8SZachary Turner 281*307f5ae8SZachary Turner llvm::StringRef source_file_name = 282*307f5ae8SZachary Turner m_index->compilands().GetMainSourceFile(cci); 283*307f5ae8SZachary Turner lldb_private::FileSpec fs(source_file_name, false); 284*307f5ae8SZachary Turner 285*307f5ae8SZachary Turner CompUnitSP cu_sp = 286*307f5ae8SZachary Turner std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr, fs, 287*307f5ae8SZachary Turner cci.m_uid.toOpaqueId(), lang, optimized); 288*307f5ae8SZachary Turner 289*307f5ae8SZachary Turner const PdbCompilandId &cuid = cci.m_uid.asCompiland(); 290*307f5ae8SZachary Turner m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(cuid.modi, 291*307f5ae8SZachary Turner cu_sp); 292*307f5ae8SZachary Turner return cu_sp; 293*307f5ae8SZachary Turner } 294*307f5ae8SZachary Turner 295*307f5ae8SZachary Turner FunctionSP SymbolFileNativePDB::GetOrCreateFunction(PdbSymUid func_uid, 296*307f5ae8SZachary Turner const SymbolContext &sc) { 297*307f5ae8SZachary Turner lldbassert(func_uid.tag() == PDB_SymType::Function); 298*307f5ae8SZachary Turner auto emplace_result = m_functions.try_emplace(func_uid.toOpaqueId(), nullptr); 299*307f5ae8SZachary Turner if (emplace_result.second) 300*307f5ae8SZachary Turner emplace_result.first->second = CreateFunction(func_uid, sc); 301*307f5ae8SZachary Turner 302*307f5ae8SZachary Turner lldbassert(emplace_result.first->second); 303*307f5ae8SZachary Turner return emplace_result.first->second; 304*307f5ae8SZachary Turner } 305*307f5ae8SZachary Turner 306*307f5ae8SZachary Turner CompUnitSP 307*307f5ae8SZachary Turner SymbolFileNativePDB::GetOrCreateCompileUnit(const CompilandIndexItem &cci) { 308*307f5ae8SZachary Turner auto emplace_result = 309*307f5ae8SZachary Turner m_compilands.try_emplace(cci.m_uid.toOpaqueId(), nullptr); 310*307f5ae8SZachary Turner if (emplace_result.second) 311*307f5ae8SZachary Turner emplace_result.first->second = CreateCompileUnit(cci); 312*307f5ae8SZachary Turner 313*307f5ae8SZachary Turner lldbassert(emplace_result.first->second); 314*307f5ae8SZachary Turner return emplace_result.first->second; 315*307f5ae8SZachary Turner } 316*307f5ae8SZachary Turner 317*307f5ae8SZachary Turner lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) { 318*307f5ae8SZachary Turner if (index >= GetNumCompileUnits()) 319*307f5ae8SZachary Turner return CompUnitSP(); 320*307f5ae8SZachary Turner lldbassert(index < UINT16_MAX); 321*307f5ae8SZachary Turner if (index >= UINT16_MAX) 322*307f5ae8SZachary Turner return nullptr; 323*307f5ae8SZachary Turner 324*307f5ae8SZachary Turner CompilandIndexItem &item = m_index->compilands().GetOrCreateCompiland(index); 325*307f5ae8SZachary Turner 326*307f5ae8SZachary Turner return GetOrCreateCompileUnit(item); 327*307f5ae8SZachary Turner } 328*307f5ae8SZachary Turner 329*307f5ae8SZachary Turner lldb::LanguageType SymbolFileNativePDB::ParseCompileUnitLanguage( 330*307f5ae8SZachary Turner const lldb_private::SymbolContext &sc) { 331*307f5ae8SZachary Turner // What fields should I expect to be filled out on the SymbolContext? Is it 332*307f5ae8SZachary Turner // safe to assume that `sc.comp_unit` is valid? 333*307f5ae8SZachary Turner if (!sc.comp_unit) 334*307f5ae8SZachary Turner return lldb::eLanguageTypeUnknown; 335*307f5ae8SZachary Turner PdbSymUid uid = PdbSymUid::fromOpaqueId(sc.comp_unit->GetID()); 336*307f5ae8SZachary Turner lldbassert(uid.tag() == PDB_SymType::Compiland); 337*307f5ae8SZachary Turner 338*307f5ae8SZachary Turner CompilandIndexItem *item = m_index->compilands().GetCompiland(uid); 339*307f5ae8SZachary Turner lldbassert(item); 340*307f5ae8SZachary Turner if (!item->m_compile_opts) 341*307f5ae8SZachary Turner return lldb::eLanguageTypeUnknown; 342*307f5ae8SZachary Turner 343*307f5ae8SZachary Turner return TranslateLanguage(item->m_compile_opts->getLanguage()); 344*307f5ae8SZachary Turner } 345*307f5ae8SZachary Turner 346*307f5ae8SZachary Turner size_t SymbolFileNativePDB::ParseCompileUnitFunctions( 347*307f5ae8SZachary Turner const lldb_private::SymbolContext &sc) { 348*307f5ae8SZachary Turner lldbassert(sc.comp_unit); 349*307f5ae8SZachary Turner return false; 350*307f5ae8SZachary Turner } 351*307f5ae8SZachary Turner 352*307f5ae8SZachary Turner static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) { 353*307f5ae8SZachary Turner // If any of these flags are set, we need to resolve the compile unit. 354*307f5ae8SZachary Turner uint32_t flags = eSymbolContextCompUnit; 355*307f5ae8SZachary Turner flags |= eSymbolContextVariable; 356*307f5ae8SZachary Turner flags |= eSymbolContextFunction; 357*307f5ae8SZachary Turner flags |= eSymbolContextBlock; 358*307f5ae8SZachary Turner flags |= eSymbolContextLineEntry; 359*307f5ae8SZachary Turner return (resolve_scope & flags) != 0; 360*307f5ae8SZachary Turner } 361*307f5ae8SZachary Turner 362*307f5ae8SZachary Turner uint32_t 363*307f5ae8SZachary Turner SymbolFileNativePDB::ResolveSymbolContext(const lldb_private::Address &addr, 364*307f5ae8SZachary Turner uint32_t resolve_scope, 365*307f5ae8SZachary Turner lldb_private::SymbolContext &sc) { 366*307f5ae8SZachary Turner uint32_t resolved_flags = 0; 367*307f5ae8SZachary Turner lldb::addr_t file_addr = addr.GetFileAddress(); 368*307f5ae8SZachary Turner 369*307f5ae8SZachary Turner if (NeedsResolvedCompileUnit(resolve_scope)) { 370*307f5ae8SZachary Turner llvm::Optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr); 371*307f5ae8SZachary Turner if (!modi) 372*307f5ae8SZachary Turner return 0; 373*307f5ae8SZachary Turner PdbSymUid cuid = PdbSymUid::makeCompilandId(*modi); 374*307f5ae8SZachary Turner CompilandIndexItem *cci = m_index->compilands().GetCompiland(cuid); 375*307f5ae8SZachary Turner if (!cci) 376*307f5ae8SZachary Turner return 0; 377*307f5ae8SZachary Turner 378*307f5ae8SZachary Turner sc.comp_unit = GetOrCreateCompileUnit(*cci).get(); 379*307f5ae8SZachary Turner resolved_flags |= eSymbolContextCompUnit; 380*307f5ae8SZachary Turner } 381*307f5ae8SZachary Turner 382*307f5ae8SZachary Turner if (resolve_scope & eSymbolContextFunction) { 383*307f5ae8SZachary Turner lldbassert(sc.comp_unit); 384*307f5ae8SZachary Turner std::vector<SymbolAndUid> matches = m_index->FindSymbolsByVa(file_addr); 385*307f5ae8SZachary Turner for (const auto &match : matches) { 386*307f5ae8SZachary Turner if (match.uid.tag() != PDB_SymType::Function) 387*307f5ae8SZachary Turner continue; 388*307f5ae8SZachary Turner sc.function = GetOrCreateFunction(match.uid, sc).get(); 389*307f5ae8SZachary Turner } 390*307f5ae8SZachary Turner resolved_flags |= eSymbolContextFunction; 391*307f5ae8SZachary Turner } 392*307f5ae8SZachary Turner 393*307f5ae8SZachary Turner if (resolve_scope & eSymbolContextLineEntry) { 394*307f5ae8SZachary Turner lldbassert(sc.comp_unit); 395*307f5ae8SZachary Turner if (auto *line_table = sc.comp_unit->GetLineTable()) { 396*307f5ae8SZachary Turner if (line_table->FindLineEntryByAddress(addr, sc.line_entry)) 397*307f5ae8SZachary Turner resolved_flags |= eSymbolContextLineEntry; 398*307f5ae8SZachary Turner } 399*307f5ae8SZachary Turner } 400*307f5ae8SZachary Turner 401*307f5ae8SZachary Turner return resolved_flags; 402*307f5ae8SZachary Turner } 403*307f5ae8SZachary Turner 404*307f5ae8SZachary Turner static void AppendLineEntryToSequence(LineTable &table, LineSequence &sequence, 405*307f5ae8SZachary Turner const CompilandIndexItem &cci, 406*307f5ae8SZachary Turner lldb::addr_t base_addr, 407*307f5ae8SZachary Turner uint32_t file_number, 408*307f5ae8SZachary Turner const LineFragmentHeader &block, 409*307f5ae8SZachary Turner const LineNumberEntry &cur) { 410*307f5ae8SZachary Turner LineInfo cur_info(cur.Flags); 411*307f5ae8SZachary Turner 412*307f5ae8SZachary Turner if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto()) 413*307f5ae8SZachary Turner return; 414*307f5ae8SZachary Turner 415*307f5ae8SZachary Turner uint64_t addr = base_addr + cur.Offset; 416*307f5ae8SZachary Turner 417*307f5ae8SZachary Turner bool is_statement = cur_info.isStatement(); 418*307f5ae8SZachary Turner bool is_prologue = IsFunctionPrologue(cci, addr); 419*307f5ae8SZachary Turner bool is_epilogue = IsFunctionEpilogue(cci, addr); 420*307f5ae8SZachary Turner 421*307f5ae8SZachary Turner uint32_t lno = cur_info.getStartLine(); 422*307f5ae8SZachary Turner 423*307f5ae8SZachary Turner table.AppendLineEntryToSequence(&sequence, addr, lno, 0, file_number, 424*307f5ae8SZachary Turner is_statement, false, is_prologue, is_epilogue, 425*307f5ae8SZachary Turner false); 426*307f5ae8SZachary Turner } 427*307f5ae8SZachary Turner 428*307f5ae8SZachary Turner static void TerminateLineSequence(LineTable &table, 429*307f5ae8SZachary Turner const LineFragmentHeader &block, 430*307f5ae8SZachary Turner lldb::addr_t base_addr, uint32_t file_number, 431*307f5ae8SZachary Turner uint32_t last_line, 432*307f5ae8SZachary Turner std::unique_ptr<LineSequence> seq) { 433*307f5ae8SZachary Turner // The end is always a terminal entry, so insert it regardless. 434*307f5ae8SZachary Turner table.AppendLineEntryToSequence(seq.get(), base_addr + block.CodeSize, 435*307f5ae8SZachary Turner last_line, 0, file_number, false, false, 436*307f5ae8SZachary Turner false, false, true); 437*307f5ae8SZachary Turner table.InsertSequence(seq.release()); 438*307f5ae8SZachary Turner } 439*307f5ae8SZachary Turner 440*307f5ae8SZachary Turner bool SymbolFileNativePDB::ParseCompileUnitLineTable( 441*307f5ae8SZachary Turner const lldb_private::SymbolContext &sc) { 442*307f5ae8SZachary Turner // Unfortunately LLDB is set up to parse the entire compile unit line table 443*307f5ae8SZachary Turner // all at once, even if all it really needs is line info for a specific 444*307f5ae8SZachary Turner // function. In the future it would be nice if it could set the sc.m_function 445*307f5ae8SZachary Turner // member, and we could only get the line info for the function in question. 446*307f5ae8SZachary Turner lldbassert(sc.comp_unit); 447*307f5ae8SZachary Turner PdbSymUid cu_id = PdbSymUid::fromOpaqueId(sc.comp_unit->GetID()); 448*307f5ae8SZachary Turner lldbassert(cu_id.isCompiland()); 449*307f5ae8SZachary Turner CompilandIndexItem *cci = m_index->compilands().GetCompiland(cu_id); 450*307f5ae8SZachary Turner lldbassert(cci); 451*307f5ae8SZachary Turner auto line_table = llvm::make_unique<LineTable>(sc.comp_unit); 452*307f5ae8SZachary Turner 453*307f5ae8SZachary Turner // This is basically a copy of the .debug$S subsections from all original COFF 454*307f5ae8SZachary Turner // object files merged together with address relocations applied. We are 455*307f5ae8SZachary Turner // looking for all DEBUG_S_LINES subsections. 456*307f5ae8SZachary Turner for (const DebugSubsectionRecord &dssr : 457*307f5ae8SZachary Turner cci->m_debug_stream.getSubsectionsArray()) { 458*307f5ae8SZachary Turner if (dssr.kind() != DebugSubsectionKind::Lines) 459*307f5ae8SZachary Turner continue; 460*307f5ae8SZachary Turner 461*307f5ae8SZachary Turner DebugLinesSubsectionRef lines; 462*307f5ae8SZachary Turner llvm::BinaryStreamReader reader(dssr.getRecordData()); 463*307f5ae8SZachary Turner if (auto EC = lines.initialize(reader)) { 464*307f5ae8SZachary Turner llvm::consumeError(std::move(EC)); 465*307f5ae8SZachary Turner return false; 466*307f5ae8SZachary Turner } 467*307f5ae8SZachary Turner 468*307f5ae8SZachary Turner const LineFragmentHeader *lfh = lines.header(); 469*307f5ae8SZachary Turner uint64_t virtual_addr = 470*307f5ae8SZachary Turner m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset); 471*307f5ae8SZachary Turner 472*307f5ae8SZachary Turner const auto &checksums = cci->m_strings.checksums().getArray(); 473*307f5ae8SZachary Turner const auto &strings = cci->m_strings.strings(); 474*307f5ae8SZachary Turner for (const LineColumnEntry &group : lines) { 475*307f5ae8SZachary Turner // Indices in this structure are actually offsets of records in the 476*307f5ae8SZachary Turner // DEBUG_S_FILECHECKSUMS subsection. Those entries then have an index 477*307f5ae8SZachary Turner // into the global PDB string table. 478*307f5ae8SZachary Turner auto iter = checksums.at(group.NameIndex); 479*307f5ae8SZachary Turner if (iter == checksums.end()) 480*307f5ae8SZachary Turner continue; 481*307f5ae8SZachary Turner 482*307f5ae8SZachary Turner llvm::Expected<llvm::StringRef> efn = 483*307f5ae8SZachary Turner strings.getString(iter->FileNameOffset); 484*307f5ae8SZachary Turner if (!efn) { 485*307f5ae8SZachary Turner llvm::consumeError(efn.takeError()); 486*307f5ae8SZachary Turner continue; 487*307f5ae8SZachary Turner } 488*307f5ae8SZachary Turner 489*307f5ae8SZachary Turner // LLDB wants the index of the file in the list of support files. 490*307f5ae8SZachary Turner auto fn_iter = llvm::find(cci->m_file_list, *efn); 491*307f5ae8SZachary Turner lldbassert(fn_iter != cci->m_file_list.end()); 492*307f5ae8SZachary Turner uint32_t file_index = std::distance(cci->m_file_list.begin(), fn_iter); 493*307f5ae8SZachary Turner 494*307f5ae8SZachary Turner std::unique_ptr<LineSequence> sequence( 495*307f5ae8SZachary Turner line_table->CreateLineSequenceContainer()); 496*307f5ae8SZachary Turner lldbassert(!group.LineNumbers.empty()); 497*307f5ae8SZachary Turner 498*307f5ae8SZachary Turner for (const LineNumberEntry &entry : group.LineNumbers) { 499*307f5ae8SZachary Turner AppendLineEntryToSequence(*line_table, *sequence, *cci, virtual_addr, 500*307f5ae8SZachary Turner file_index, *lfh, entry); 501*307f5ae8SZachary Turner } 502*307f5ae8SZachary Turner LineInfo last_line(group.LineNumbers.back().Flags); 503*307f5ae8SZachary Turner TerminateLineSequence(*line_table, *lfh, virtual_addr, file_index, 504*307f5ae8SZachary Turner last_line.getEndLine(), std::move(sequence)); 505*307f5ae8SZachary Turner } 506*307f5ae8SZachary Turner } 507*307f5ae8SZachary Turner 508*307f5ae8SZachary Turner if (line_table->GetSize() == 0) 509*307f5ae8SZachary Turner return false; 510*307f5ae8SZachary Turner 511*307f5ae8SZachary Turner sc.comp_unit->SetLineTable(line_table.release()); 512*307f5ae8SZachary Turner return true; 513*307f5ae8SZachary Turner } 514*307f5ae8SZachary Turner 515*307f5ae8SZachary Turner bool SymbolFileNativePDB::ParseCompileUnitDebugMacros( 516*307f5ae8SZachary Turner const lldb_private::SymbolContext &sc) { 517*307f5ae8SZachary Turner // PDB doesn't contain information about macros 518*307f5ae8SZachary Turner return false; 519*307f5ae8SZachary Turner } 520*307f5ae8SZachary Turner 521*307f5ae8SZachary Turner bool SymbolFileNativePDB::ParseCompileUnitSupportFiles( 522*307f5ae8SZachary Turner const lldb_private::SymbolContext &sc, 523*307f5ae8SZachary Turner lldb_private::FileSpecList &support_files) { 524*307f5ae8SZachary Turner lldbassert(sc.comp_unit); 525*307f5ae8SZachary Turner 526*307f5ae8SZachary Turner PdbSymUid comp_uid = PdbSymUid::fromOpaqueId(sc.comp_unit->GetID()); 527*307f5ae8SZachary Turner lldbassert(comp_uid.tag() == PDB_SymType::Compiland); 528*307f5ae8SZachary Turner 529*307f5ae8SZachary Turner const CompilandIndexItem *cci = m_index->compilands().GetCompiland(comp_uid); 530*307f5ae8SZachary Turner lldbassert(cci); 531*307f5ae8SZachary Turner 532*307f5ae8SZachary Turner for (llvm::StringRef f : cci->m_file_list) { 533*307f5ae8SZachary Turner FileSpec::Style style = 534*307f5ae8SZachary Turner f.startswith("/") ? FileSpec::Style::posix : FileSpec::Style::windows; 535*307f5ae8SZachary Turner FileSpec spec(f, false, style); 536*307f5ae8SZachary Turner support_files.Append(spec); 537*307f5ae8SZachary Turner } 538*307f5ae8SZachary Turner 539*307f5ae8SZachary Turner return true; 540*307f5ae8SZachary Turner } 541*307f5ae8SZachary Turner 542*307f5ae8SZachary Turner bool SymbolFileNativePDB::ParseImportedModules( 543*307f5ae8SZachary Turner const lldb_private::SymbolContext &sc, 544*307f5ae8SZachary Turner std::vector<lldb_private::ConstString> &imported_modules) { 545*307f5ae8SZachary Turner // PDB does not yet support module debug info 546*307f5ae8SZachary Turner return false; 547*307f5ae8SZachary Turner } 548*307f5ae8SZachary Turner 549*307f5ae8SZachary Turner size_t SymbolFileNativePDB::ParseFunctionBlocks( 550*307f5ae8SZachary Turner const lldb_private::SymbolContext &sc) { 551*307f5ae8SZachary Turner lldbassert(sc.comp_unit && sc.function); 552*307f5ae8SZachary Turner return 0; 553*307f5ae8SZachary Turner } 554*307f5ae8SZachary Turner 555*307f5ae8SZachary Turner uint32_t SymbolFileNativePDB::FindFunctions( 556*307f5ae8SZachary Turner const lldb_private::ConstString &name, 557*307f5ae8SZachary Turner const lldb_private::CompilerDeclContext *parent_decl_ctx, 558*307f5ae8SZachary Turner uint32_t name_type_mask, bool include_inlines, bool append, 559*307f5ae8SZachary Turner lldb_private::SymbolContextList &sc_list) { 560*307f5ae8SZachary Turner // For now we only support lookup by method name. 561*307f5ae8SZachary Turner if (!(name_type_mask & eFunctionNameTypeMethod)) 562*307f5ae8SZachary Turner return 0; 563*307f5ae8SZachary Turner 564*307f5ae8SZachary Turner using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; 565*307f5ae8SZachary Turner 566*307f5ae8SZachary Turner std::vector<SymbolAndOffset> matches = m_index->globals().findRecordsByName( 567*307f5ae8SZachary Turner name.GetStringRef(), m_index->symrecords()); 568*307f5ae8SZachary Turner for (const SymbolAndOffset &match : matches) { 569*307f5ae8SZachary Turner if (match.second.kind() != S_PROCREF && match.second.kind() != S_LPROCREF) 570*307f5ae8SZachary Turner continue; 571*307f5ae8SZachary Turner ProcRefSym proc(match.second.kind()); 572*307f5ae8SZachary Turner cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(match.second, proc)); 573*307f5ae8SZachary Turner 574*307f5ae8SZachary Turner if (!IsValidRecord(proc)) 575*307f5ae8SZachary Turner continue; 576*307f5ae8SZachary Turner 577*307f5ae8SZachary Turner PdbSymUid cuid = PdbSymUid::makeCompilandId(proc); 578*307f5ae8SZachary Turner CompilandIndexItem &cci = m_index->compilands().GetOrCreateCompiland(cuid); 579*307f5ae8SZachary Turner lldb_private::SymbolContext sc; 580*307f5ae8SZachary Turner 581*307f5ae8SZachary Turner sc.comp_unit = GetOrCreateCompileUnit(cci).get(); 582*307f5ae8SZachary Turner sc.module_sp = sc.comp_unit->GetModule(); 583*307f5ae8SZachary Turner PdbSymUid func_uid = PdbSymUid::makeCuSymId(proc); 584*307f5ae8SZachary Turner sc.function = GetOrCreateFunction(func_uid, sc).get(); 585*307f5ae8SZachary Turner 586*307f5ae8SZachary Turner sc_list.Append(sc); 587*307f5ae8SZachary Turner } 588*307f5ae8SZachary Turner 589*307f5ae8SZachary Turner return sc_list.GetSize(); 590*307f5ae8SZachary Turner } 591*307f5ae8SZachary Turner 592*307f5ae8SZachary Turner uint32_t 593*307f5ae8SZachary Turner SymbolFileNativePDB::FindFunctions(const lldb_private::RegularExpression ®ex, 594*307f5ae8SZachary Turner bool include_inlines, bool append, 595*307f5ae8SZachary Turner lldb_private::SymbolContextList &sc_list) { 596*307f5ae8SZachary Turner return 0; 597*307f5ae8SZachary Turner } 598*307f5ae8SZachary Turner 599*307f5ae8SZachary Turner lldb_private::CompilerDeclContext SymbolFileNativePDB::FindNamespace( 600*307f5ae8SZachary Turner const lldb_private::SymbolContext &sc, 601*307f5ae8SZachary Turner const lldb_private::ConstString &name, 602*307f5ae8SZachary Turner const lldb_private::CompilerDeclContext *parent_decl_ctx) { 603*307f5ae8SZachary Turner return {}; 604*307f5ae8SZachary Turner } 605*307f5ae8SZachary Turner 606*307f5ae8SZachary Turner lldb_private::TypeSystem * 607*307f5ae8SZachary Turner SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) { 608*307f5ae8SZachary Turner auto type_system = 609*307f5ae8SZachary Turner m_obj_file->GetModule()->GetTypeSystemForLanguage(language); 610*307f5ae8SZachary Turner if (type_system) 611*307f5ae8SZachary Turner type_system->SetSymbolFile(this); 612*307f5ae8SZachary Turner return type_system; 613*307f5ae8SZachary Turner } 614*307f5ae8SZachary Turner 615*307f5ae8SZachary Turner lldb_private::ConstString SymbolFileNativePDB::GetPluginName() { 616*307f5ae8SZachary Turner static ConstString g_name("pdb"); 617*307f5ae8SZachary Turner return g_name; 618*307f5ae8SZachary Turner } 619*307f5ae8SZachary Turner 620*307f5ae8SZachary Turner uint32_t SymbolFileNativePDB::GetPluginVersion() { return 1; } 621