2944 lines · cpp
1//===-- SymbolFileNativePDB.cpp -------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "SymbolFileNativePDB.h"10 11#include "Plugins/ExpressionParser/Clang/ClangUtil.h"12#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"13#include "Plugins/ObjectFile/PDB/ObjectFilePDB.h"14#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"15#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"16#include "lldb/Core/Module.h"17#include "lldb/Core/PluginManager.h"18#include "lldb/Symbol/CompileUnit.h"19#include "lldb/Symbol/LineTable.h"20#include "lldb/Symbol/ObjectFile.h"21#include "lldb/Symbol/SymbolContext.h"22#include "lldb/Symbol/SymbolVendor.h"23#include "lldb/Symbol/Variable.h"24#include "lldb/Symbol/VariableList.h"25#include "lldb/Utility/LLDBLog.h"26#include "lldb/Utility/Log.h"27 28#include "llvm/DebugInfo/CodeView/CVRecord.h"29#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"30#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"31#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"32#include "llvm/DebugInfo/CodeView/RecordName.h"33#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"34#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"35#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"36#include "llvm/DebugInfo/PDB/Native/DbiStream.h"37#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"38#include "llvm/DebugInfo/PDB/Native/InfoStream.h"39#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"40#include "llvm/DebugInfo/PDB/Native/NativeSession.h"41#include "llvm/DebugInfo/PDB/Native/PDBFile.h"42#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"43#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"44#include "llvm/DebugInfo/PDB/Native/TpiStream.h"45#include "llvm/DebugInfo/PDB/PDB.h"46#include "llvm/DebugInfo/PDB/PDBTypes.h"47#include "llvm/Demangle/MicrosoftDemangle.h"48#include "llvm/Object/COFF.h"49#include "llvm/Support/Allocator.h"50#include "llvm/Support/BinaryStreamReader.h"51#include "llvm/Support/Error.h"52#include "llvm/Support/ErrorOr.h"53#include "llvm/Support/MemoryBuffer.h"54 55#include "DWARFLocationExpression.h"56#include "PdbSymUid.h"57#include "PdbUtil.h"58#include "UdtRecordCompleter.h"59#include <optional>60#include <string_view>61 62using namespace lldb;63using namespace lldb_private;64using namespace npdb;65using namespace llvm::codeview;66using namespace llvm::pdb;67 68char SymbolFileNativePDB::ID;69 70static lldb::LanguageType TranslateLanguage(PDB_Lang lang) {71 switch (lang) {72 case PDB_Lang::Cpp:73 return lldb::LanguageType::eLanguageTypeC_plus_plus;74 case PDB_Lang::C:75 return lldb::LanguageType::eLanguageTypeC;76 case PDB_Lang::Swift:77 return lldb::LanguageType::eLanguageTypeSwift;78 case PDB_Lang::Rust:79 return lldb::LanguageType::eLanguageTypeRust;80 case PDB_Lang::ObjC:81 return lldb::LanguageType::eLanguageTypeObjC;82 case PDB_Lang::ObjCpp:83 return lldb::LanguageType::eLanguageTypeObjC_plus_plus;84 default:85 return lldb::LanguageType::eLanguageTypeUnknown;86 }87}88 89static std::optional<std::string>90findMatchingPDBFilePath(llvm::StringRef original_pdb_path,91 llvm::StringRef exe_path) {92 const FileSystem &fs = FileSystem::Instance();93 94 if (fs.Exists(original_pdb_path))95 return std::string(original_pdb_path);96 97 const auto exe_dir = FileSpec(exe_path).CopyByRemovingLastPathComponent();98 // While the exe_path uses the native style, the exe might be compiled on a99 // different OS, so try to guess the style used.100 const FileSpec original_pdb_spec(original_pdb_path,101 FileSpec::GuessPathStyle(original_pdb_path)102 .value_or(FileSpec::Style::native));103 const llvm::StringRef pdb_filename = original_pdb_spec.GetFilename();104 105 // If the file doesn't exist, perhaps the path specified at build time106 // doesn't match the PDB's current location, so check the location of the107 // executable.108 const FileSpec local_pdb = exe_dir.CopyByAppendingPathComponent(pdb_filename);109 if (fs.Exists(local_pdb))110 return local_pdb.GetPath();111 112 // Otherwise, search for one in target.debug-file-search-paths113 FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();114 for (const FileSpec &search_dir : search_paths) {115 FileSpec pdb_path = search_dir.CopyByAppendingPathComponent(pdb_filename);116 if (fs.Exists(pdb_path))117 return pdb_path.GetPath();118 }119 120 return std::nullopt;121}122 123static std::unique_ptr<PDBFile>124loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {125 // Try to find a matching PDB for an EXE.126 using namespace llvm::object;127 auto expected_binary = createBinary(exe_path);128 129 // If the file isn't a PE/COFF executable, fail.130 if (!expected_binary) {131 llvm::consumeError(expected_binary.takeError());132 return nullptr;133 }134 OwningBinary<Binary> binary = std::move(*expected_binary);135 136 // TODO: Avoid opening the PE/COFF binary twice by reading this information137 // directly from the lldb_private::ObjectFile.138 auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary());139 if (!obj)140 return nullptr;141 const llvm::codeview::DebugInfo *pdb_info = nullptr;142 143 // If it doesn't have a debug directory, fail.144 llvm::StringRef pdb_file;145 if (llvm::Error e = obj->getDebugPDBInfo(pdb_info, pdb_file)) {146 consumeError(std::move(e));147 return nullptr;148 }149 150 std::optional<std::string> resolved_pdb_path =151 findMatchingPDBFilePath(pdb_file, exe_path);152 if (!resolved_pdb_path)153 return nullptr;154 155 // If the file is not a PDB or if it doesn't have a matching GUID, fail.156 auto pdb =157 ObjectFilePDB::loadPDBFile(*std::move(resolved_pdb_path), allocator);158 if (!pdb)159 return nullptr;160 161 auto expected_info = pdb->getPDBInfoStream();162 if (!expected_info) {163 llvm::consumeError(expected_info.takeError());164 return nullptr;165 }166 llvm::codeview::GUID guid;167 memcpy(&guid, pdb_info->PDB70.Signature, 16);168 169 if (expected_info->getGuid() != guid)170 return nullptr;171 172 LLDB_LOG(GetLog(LLDBLog::Symbols), "Loading {0} for {1}", pdb->getFilePath(),173 exe_path);174 return pdb;175}176 177static bool IsFunctionPrologue(const CompilandIndexItem &cci,178 lldb::addr_t addr) {179 // FIXME: Implement this.180 return false;181}182 183static bool IsFunctionEpilogue(const CompilandIndexItem &cci,184 lldb::addr_t addr) {185 // FIXME: Implement this.186 return false;187}188 189// See llvm::codeview::TypeIndex::simpleTypeName as well as strForPrimitiveTi190// from the original pdbdump:191// https://github.com/microsoft/microsoft-pdb/blob/805655a28bd8198004be2ac27e6e0290121a5e89/pdbdump/pdbdump.cpp#L1896-L1974192//193// For 64bit integers we use "long long" like DIA instead of "__int64".194static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) {195 switch (kind) {196 case SimpleTypeKind::Boolean128:197 return "__bool128";198 case SimpleTypeKind::Boolean64:199 return "__bool64";200 case SimpleTypeKind::Boolean32:201 return "__bool32";202 case SimpleTypeKind::Boolean16:203 return "__bool16";204 case SimpleTypeKind::Boolean8:205 return "bool";206 207 case SimpleTypeKind::Byte:208 case SimpleTypeKind::UnsignedCharacter:209 return "unsigned char";210 case SimpleTypeKind::NarrowCharacter:211 return "char";212 case SimpleTypeKind::SignedCharacter:213 case SimpleTypeKind::SByte:214 return "signed char";215 case SimpleTypeKind::Character32:216 return "char32_t";217 case SimpleTypeKind::Character16:218 return "char16_t";219 case SimpleTypeKind::Character8:220 return "char8_t";221 222 case SimpleTypeKind::Complex128:223 return "_Complex __float128";224 case SimpleTypeKind::Complex80:225 return "_Complex long double";226 case SimpleTypeKind::Complex64:227 return "_Complex double";228 case SimpleTypeKind::Complex48:229 return "_Complex __float48";230 case SimpleTypeKind::Complex32:231 case SimpleTypeKind::Complex32PartialPrecision:232 return "_Complex float";233 case SimpleTypeKind::Complex16:234 return "_Complex _Float16";235 236 case SimpleTypeKind::Float128:237 return "__float128";238 case SimpleTypeKind::Float80:239 return "long double";240 case SimpleTypeKind::Float64:241 return "double";242 case SimpleTypeKind::Float48:243 return "__float48";244 case SimpleTypeKind::Float32:245 case SimpleTypeKind::Float32PartialPrecision:246 return "float";247 case SimpleTypeKind::Float16:248 return "_Float16";249 250 case SimpleTypeKind::Int128Oct:251 case SimpleTypeKind::Int128:252 return "__int128";253 case SimpleTypeKind::Int64:254 case SimpleTypeKind::Int64Quad:255 return "long long";256 case SimpleTypeKind::Int32Long:257 return "long";258 case SimpleTypeKind::Int32:259 return "int";260 case SimpleTypeKind::Int16:261 case SimpleTypeKind::Int16Short:262 return "short";263 264 case SimpleTypeKind::UInt128Oct:265 case SimpleTypeKind::UInt128:266 return "unsigned __int128";267 case SimpleTypeKind::UInt64:268 case SimpleTypeKind::UInt64Quad:269 return "unsigned long long";270 case SimpleTypeKind::UInt32:271 return "unsigned";272 case SimpleTypeKind::UInt16:273 case SimpleTypeKind::UInt16Short:274 return "unsigned short";275 case SimpleTypeKind::UInt32Long:276 return "unsigned long";277 278 case SimpleTypeKind::HResult:279 return "HRESULT";280 case SimpleTypeKind::Void:281 return "void";282 case SimpleTypeKind::WideCharacter:283 return "wchar_t";284 285 case SimpleTypeKind::None:286 case SimpleTypeKind::NotTranslated:287 return "";288 }289 return "";290}291 292static bool IsClassRecord(TypeLeafKind kind) {293 switch (kind) {294 case LF_STRUCTURE:295 case LF_CLASS:296 case LF_INTERFACE:297 return true;298 default:299 return false;300 }301}302 303static std::optional<CVTagRecord>304GetNestedTagDefinition(const NestedTypeRecord &Record,305 const CVTagRecord &parent, TpiStream &tpi) {306 // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it307 // is also used to indicate the primary definition of a nested class. That is308 // to say, if you have:309 // struct A {310 // struct B {};311 // using C = B;312 // };313 // Then in the debug info, this will appear as:314 // LF_STRUCTURE `A::B` [type index = N]315 // LF_STRUCTURE `A`316 // LF_NESTTYPE [name = `B`, index = N]317 // LF_NESTTYPE [name = `C`, index = N]318 // In order to accurately reconstruct the decl context hierarchy, we need to319 // know which ones are actual definitions and which ones are just aliases.320 321 // If it's a simple type, then this is something like `using foo = int`.322 if (Record.Type.isSimple())323 return std::nullopt;324 325 CVType cvt = tpi.getType(Record.Type);326 327 if (!IsTagRecord(cvt))328 return std::nullopt;329 330 // If it's an inner definition, then treat whatever name we have here as a331 // single component of a mangled name. So we can inject it into the parent's332 // mangled name to see if it matches.333 CVTagRecord child = CVTagRecord::create(cvt);334 std::string qname = std::string(parent.asTag().getUniqueName());335 if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4)336 return std::nullopt;337 338 // qname[3] is the tag type identifier (struct, class, union, etc). Since the339 // inner tag type is not necessarily the same as the outer tag type, re-write340 // it to match the inner tag type.341 qname[3] = child.asTag().getUniqueName()[3];342 std::string piece;343 if (qname[3] == 'W')344 piece = "4";345 piece += Record.Name;346 piece.push_back('@');347 qname.insert(4, std::move(piece));348 if (qname != child.asTag().UniqueName)349 return std::nullopt;350 351 return std::move(child);352}353 354void SymbolFileNativePDB::Initialize() {355 PluginManager::RegisterPlugin(GetPluginNameStatic(),356 GetPluginDescriptionStatic(), CreateInstance,357 DebuggerInitialize);358}359 360void SymbolFileNativePDB::Terminate() {361 PluginManager::UnregisterPlugin(CreateInstance);362}363 364void SymbolFileNativePDB::DebuggerInitialize(Debugger &debugger) {}365 366llvm::StringRef SymbolFileNativePDB::GetPluginDescriptionStatic() {367 return "Microsoft PDB debug symbol cross-platform file reader.";368}369 370SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFileSP objfile_sp) {371 if (!SymbolFilePDB::UseNativePDB())372 return nullptr;373 374 return new SymbolFileNativePDB(std::move(objfile_sp));375}376 377SymbolFileNativePDB::SymbolFileNativePDB(ObjectFileSP objfile_sp)378 : SymbolFileCommon(std::move(objfile_sp)) {}379 380SymbolFileNativePDB::~SymbolFileNativePDB() = default;381 382uint32_t SymbolFileNativePDB::CalculateAbilities() {383 uint32_t abilities = 0;384 if (!m_objfile_sp)385 return 0;386 387 if (!m_index) {388 // Lazily load and match the PDB file, but only do this once.389 PDBFile *pdb_file;390 if (auto *pdb = llvm::dyn_cast<ObjectFilePDB>(m_objfile_sp.get())) {391 pdb_file = &pdb->GetPDBFile();392 } else {393 m_file_up = loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(),394 m_allocator);395 pdb_file = m_file_up.get();396 }397 398 if (!pdb_file)399 return 0;400 401 auto expected_index = PdbIndex::create(pdb_file);402 if (!expected_index) {403 llvm::consumeError(expected_index.takeError());404 return 0;405 }406 m_index = std::move(*expected_index);407 }408 if (!m_index)409 return 0;410 411 // We don't especially have to be precise here. We only distinguish between412 // stripped and not stripped.413 abilities = kAllAbilities;414 415 if (m_index->dbi().isStripped())416 abilities &= ~(Blocks | LocalVariables);417 return abilities;418}419 420void SymbolFileNativePDB::InitializeObject() {421 m_obj_load_address = m_objfile_sp->GetModule()422 ->GetObjectFile()423 ->GetBaseAddress()424 .GetFileAddress();425 m_index->SetLoadAddress(m_obj_load_address);426 m_index->ParseSectionContribs();427 428 auto ts_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage(429 lldb::eLanguageTypeC_plus_plus);430 if (auto err = ts_or_err.takeError()) {431 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err),432 "Failed to initialize: {0}");433 } else {434 if (auto ts = *ts_or_err)435 ts->SetSymbolFile(this);436 BuildParentMap();437 }438}439 440uint32_t SymbolFileNativePDB::CalculateNumCompileUnits() {441 const DbiModuleList &modules = m_index->dbi().modules();442 uint32_t count = modules.getModuleCount();443 if (count == 0)444 return count;445 446 // The linker can inject an additional "dummy" compilation unit into the447 // PDB. Ignore this special compile unit for our purposes, if it is there.448 // It is always the last one.449 DbiModuleDescriptor last = modules.getModuleDescriptor(count - 1);450 if (last.getModuleName() == "* Linker *")451 --count;452 return count;453}454 455Block *SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {456 CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);457 CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);458 CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);459 lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id);460 auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());461 if (auto err = ts_or_err.takeError())462 return nullptr;463 auto ts = *ts_or_err;464 if (!ts)465 return nullptr;466 PdbAstBuilder* ast_builder = ts->GetNativePDBParser();467 468 switch (sym.kind()) {469 case S_GPROC32:470 case S_LPROC32:471 // This is a function. It must be global. Creating the Function entry472 // for it automatically creates a block for it.473 if (FunctionSP func = GetOrCreateFunction(block_id, *comp_unit))474 return &func->GetBlock(false);475 break;476 case S_BLOCK32: {477 // This is a block. Its parent is either a function or another block. In478 // either case, its parent can be viewed as a block (e.g. a function479 // contains 1 big block. So just get the parent block and add this block480 // to it.481 BlockSym block(static_cast<SymbolRecordKind>(sym.kind()));482 cantFail(SymbolDeserializer::deserializeAs<BlockSym>(sym, block));483 lldbassert(block.Parent != 0);484 PdbCompilandSymId parent_id(block_id.modi, block.Parent);485 Block *parent_block = GetOrCreateBlock(parent_id);486 if (!parent_block)487 return nullptr;488 Function *func = parent_block->CalculateSymbolContextFunction();489 lldbassert(func);490 lldb::addr_t block_base =491 m_index->MakeVirtualAddress(block.Segment, block.CodeOffset);492 lldb::addr_t func_base = func->GetAddress().GetFileAddress();493 BlockSP child_block = parent_block->CreateChild(opaque_block_uid);494 if (block_base >= func_base)495 child_block->AddRange(Block::Range(block_base - func_base, block.CodeSize));496 else {497 GetObjectFile()->GetModule()->ReportError(498 "S_BLOCK32 at modi: {0:d} offset: {1:d}: adding range "499 "[{2:x16}-{3:x16}) which has a base that is less than the "500 "function's "501 "low PC 0x%" PRIx64 ". Please file a bug and attach the file at the "502 "start of this error message",503 block_id.modi, block_id.offset, block_base,504 block_base + block.CodeSize, func_base);505 }506 ast_builder->GetOrCreateBlockDecl(block_id);507 m_blocks.insert({opaque_block_uid, child_block});508 break;509 }510 case S_INLINESITE: {511 // This ensures line table is parsed first so we have inline sites info.512 comp_unit->GetLineTable();513 514 std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid];515 Block *parent_block = GetOrCreateBlock(inline_site->parent_id);516 if (!parent_block)517 return nullptr;518 BlockSP child_block = parent_block->CreateChild(opaque_block_uid);519 ast_builder->GetOrCreateInlinedFunctionDecl(block_id);520 // Copy ranges from InlineSite to Block.521 for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) {522 auto *entry = inline_site->ranges.GetEntryAtIndex(i);523 child_block->AddRange(524 Block::Range(entry->GetRangeBase(), entry->GetByteSize()));525 }526 child_block->FinalizeRanges();527 528 // Get the inlined function callsite info.529 Declaration &decl = inline_site->inline_function_info->GetDeclaration();530 Declaration &callsite = inline_site->inline_function_info->GetCallSite();531 child_block->SetInlinedFunctionInfo(532 inline_site->inline_function_info->GetName().GetCString(), nullptr,533 &decl, &callsite);534 m_blocks.insert({opaque_block_uid, child_block});535 break;536 }537 default:538 lldbassert(false && "Symbol is not a block!");539 }540 541 return nullptr;542}543 544lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,545 CompileUnit &comp_unit) {546 const CompilandIndexItem *cci =547 m_index->compilands().GetCompiland(func_id.modi);548 lldbassert(cci);549 CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset);550 551 lldbassert(sym_record.kind() == S_LPROC32 || sym_record.kind() == S_GPROC32);552 SegmentOffsetLength sol = GetSegmentOffsetAndLength(sym_record);553 554 auto file_vm_addr =555 m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset);556 if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)557 return nullptr;558 559 Address func_addr(file_vm_addr, comp_unit.GetModule()->GetSectionList());560 if (!func_addr.IsValid())561 return nullptr;562 563 ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));564 cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc));565 if (proc.FunctionType == TypeIndex::None())566 return nullptr;567 TypeSP func_type = GetOrCreateType(proc.FunctionType);568 if (!func_type)569 return nullptr;570 571 PdbTypeSymId sig_id(proc.FunctionType, false);572 573 std::optional<llvm::StringRef> mangled_opt = FindMangledSymbol(574 SegmentOffset(proc.Segment, proc.CodeOffset), proc.FunctionType);575 Mangled mangled(mangled_opt.value_or(proc.Name));576 577 FunctionSP func_sp = std::make_shared<Function>(578 &comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled,579 func_type.get(), func_addr,580 AddressRanges{AddressRange(func_addr, sol.length)});581 582 comp_unit.AddFunction(func_sp);583 584 auto ts_or_err = GetTypeSystemForLanguage(comp_unit.GetLanguage());585 if (auto err = ts_or_err.takeError())586 return func_sp;587 auto ts = *ts_or_err;588 if (!ts)589 return func_sp;590 ts->GetNativePDBParser()->GetOrCreateFunctionDecl(func_id);591 592 return func_sp;593}594 595CompUnitSP596SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) {597 lldb::LanguageType lang =598 cci.m_compile_opts ? TranslateLanguage(cci.m_compile_opts->getLanguage())599 : lldb::eLanguageTypeUnknown;600 601 LazyBool optimized = eLazyBoolNo;602 if (cci.m_compile_opts && cci.m_compile_opts->hasOptimizations())603 optimized = eLazyBoolYes;604 605 llvm::SmallString<64> source_file_name =606 m_index->compilands().GetMainSourceFile(cci);607 FileSpec fs(llvm::sys::path::convert_to_slash(608 source_file_name, llvm::sys::path::Style::windows_backslash));609 610 CompUnitSP cu_sp = std::make_shared<CompileUnit>(611 m_objfile_sp->GetModule(), nullptr, std::make_shared<SupportFile>(fs),612 toOpaqueUid(cci.m_id), lang, optimized);613 614 SetCompileUnitAtIndex(cci.m_id.modi, cu_sp);615 return cu_sp;616}617 618lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id,619 const ModifierRecord &mr,620 CompilerType ct) {621 TpiStream &stream = m_index->tpi();622 623 std::string name;624 625 if ((mr.Modifiers & ModifierOptions::Const) != ModifierOptions::None)626 name += "const ";627 if ((mr.Modifiers & ModifierOptions::Volatile) != ModifierOptions::None)628 name += "volatile ";629 if ((mr.Modifiers & ModifierOptions::Unaligned) != ModifierOptions::None)630 name += "__unaligned ";631 632 if (mr.ModifiedType.isSimple())633 name += GetSimpleTypeName(mr.ModifiedType.getSimpleKind());634 else635 name += computeTypeName(stream.typeCollection(), mr.ModifiedType);636 Declaration decl;637 lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType);638 639 return MakeType(toOpaqueUid(type_id), ConstString(name),640 llvm::expectedToOptional(modified_type->GetByteSize(nullptr)),641 nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,642 Type::ResolveState::Full);643}644 645lldb::TypeSP646SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id,647 const llvm::codeview::PointerRecord &pr,648 CompilerType ct) {649 TypeSP pointee = GetOrCreateType(pr.ReferentType);650 if (!pointee)651 return nullptr;652 653 if (pr.isPointerToMember()) {654 MemberPointerInfo mpi = pr.getMemberInfo();655 GetOrCreateType(mpi.ContainingType);656 }657 658 Declaration decl;659 return MakeType(toOpaqueUid(type_id), ConstString(), pr.getSize(), nullptr,660 LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,661 Type::ResolveState::Full);662}663 664lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,665 CompilerType ct) {666 uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false));667 if (ti == TypeIndex::NullptrT()) {668 Declaration decl;669 return MakeType(uid, ConstString("decltype(nullptr)"), std::nullopt,670 nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,671 Type::ResolveState::Full);672 }673 674 if (ti.getSimpleMode() != SimpleTypeMode::Direct) {675 TypeSP direct_sp = GetOrCreateType(ti.makeDirect());676 uint32_t pointer_size = 0;677 switch (ti.getSimpleMode()) {678 case SimpleTypeMode::FarPointer32:679 case SimpleTypeMode::NearPointer32:680 pointer_size = 4;681 break;682 case SimpleTypeMode::NearPointer64:683 pointer_size = 8;684 break;685 default:686 // 128-bit and 16-bit pointers unsupported.687 return nullptr;688 }689 Declaration decl;690 return MakeType(uid, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID,691 Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);692 }693 694 if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)695 return nullptr;696 697 size_t size = GetTypeSizeForSimpleKind(ti.getSimpleKind());698 llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind());699 700 Declaration decl;701 return MakeType(uid, ConstString(type_name), size, nullptr, LLDB_INVALID_UID,702 Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);703}704 705static std::string GetUnqualifiedTypeName(const TagRecord &record) {706 if (!record.hasUniqueName())707 return std::string(MSVCUndecoratedNameParser::DropScope(record.Name));708 709 llvm::ms_demangle::Demangler demangler;710 std::string_view sv(record.UniqueName.begin(), record.UniqueName.size());711 llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);712 if (demangler.Error)713 return std::string(MSVCUndecoratedNameParser::DropScope(record.Name));714 715 llvm::ms_demangle::IdentifierNode *idn =716 ttn->QualifiedName->getUnqualifiedIdentifier();717 return idn->toString();718}719 720lldb::TypeSP721SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id,722 const TagRecord &record,723 size_t size, CompilerType ct) {724 725 std::string uname = GetUnqualifiedTypeName(record);726 727 llvm::Expected<Declaration> maybeDecl = ResolveUdtDeclaration(type_id);728 Declaration decl;729 if (maybeDecl)730 decl = std::move(*maybeDecl);731 else732 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), maybeDecl.takeError(),733 "Failed to resolve declaration for '{1}': {0}", uname);734 735 return MakeType(toOpaqueUid(type_id), ConstString(uname), size, nullptr,736 LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct,737 Type::ResolveState::Forward);738}739 740lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,741 const ClassRecord &cr,742 CompilerType ct) {743 return CreateClassStructUnion(type_id, cr, cr.getSize(), ct);744}745 746lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,747 const UnionRecord &ur,748 CompilerType ct) {749 return CreateClassStructUnion(type_id, ur, ur.getSize(), ct);750}751 752lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,753 const EnumRecord &er,754 CompilerType ct) {755 std::string uname = GetUnqualifiedTypeName(er);756 757 llvm::Expected<Declaration> maybeDecl = ResolveUdtDeclaration(type_id);758 Declaration decl;759 if (maybeDecl)760 decl = std::move(*maybeDecl);761 else762 LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), maybeDecl.takeError(),763 "Failed to resolve declaration for '{1}': {0}", uname);764 765 TypeSP underlying_type = GetOrCreateType(er.UnderlyingType);766 767 return MakeType(768 toOpaqueUid(type_id), ConstString(uname),769 llvm::expectedToOptional(underlying_type->GetByteSize(nullptr)), nullptr,770 LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,771 lldb_private::Type::ResolveState::Forward);772}773 774TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,775 const ArrayRecord &ar,776 CompilerType ct) {777 TypeSP element_type = GetOrCreateType(ar.ElementType);778 779 Declaration decl;780 TypeSP array_sp =781 MakeType(toOpaqueUid(type_id), ConstString(), ar.Size, nullptr,782 LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,783 lldb_private::Type::ResolveState::Full);784 array_sp->SetEncodingType(element_type.get());785 return array_sp;786}787 788TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id,789 const MemberFunctionRecord &mfr,790 CompilerType ct) {791 if (mfr.ReturnType.isSimple())792 GetOrCreateType(mfr.ReturnType);793 CreateSimpleArgumentListTypes(mfr.ArgumentList);794 795 Declaration decl;796 return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,797 LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,798 ct, lldb_private::Type::ResolveState::Full);799}800 801TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id,802 const ProcedureRecord &pr,803 CompilerType ct) {804 if (pr.ReturnType.isSimple())805 GetOrCreateType(pr.ReturnType);806 CreateSimpleArgumentListTypes(pr.ArgumentList);807 808 Declaration decl;809 return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr,810 LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,811 ct, lldb_private::Type::ResolveState::Full);812}813 814void SymbolFileNativePDB::CreateSimpleArgumentListTypes(815 llvm::codeview::TypeIndex arglist_ti) {816 if (arglist_ti.isNoneType())817 return;818 819 CVType arglist_cvt = m_index->tpi().getType(arglist_ti);820 if (arglist_cvt.kind() != LF_ARGLIST)821 return; // invalid debug info822 823 ArgListRecord alr;824 llvm::cantFail(825 TypeDeserializer::deserializeAs<ArgListRecord>(arglist_cvt, alr));826 for (TypeIndex id : alr.getIndices())827 if (!id.isNoneType() && id.isSimple())828 GetOrCreateType(id);829}830 831TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) {832 if (type_id.index.isSimple())833 return CreateSimpleType(type_id.index, ct);834 835 TpiStream &stream = type_id.is_ipi ? m_index->ipi() : m_index->tpi();836 CVType cvt = stream.getType(type_id.index);837 838 if (cvt.kind() == LF_MODIFIER) {839 ModifierRecord modifier;840 llvm::cantFail(841 TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier));842 return CreateModifierType(type_id, modifier, ct);843 }844 845 if (cvt.kind() == LF_POINTER) {846 PointerRecord pointer;847 llvm::cantFail(848 TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer));849 return CreatePointerType(type_id, pointer, ct);850 }851 852 if (IsClassRecord(cvt.kind())) {853 ClassRecord cr;854 llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));855 return CreateTagType(type_id, cr, ct);856 }857 858 if (cvt.kind() == LF_ENUM) {859 EnumRecord er;860 llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));861 return CreateTagType(type_id, er, ct);862 }863 864 if (cvt.kind() == LF_UNION) {865 UnionRecord ur;866 llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));867 return CreateTagType(type_id, ur, ct);868 }869 870 if (cvt.kind() == LF_ARRAY) {871 ArrayRecord ar;872 llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar));873 return CreateArrayType(type_id, ar, ct);874 }875 876 if (cvt.kind() == LF_PROCEDURE) {877 ProcedureRecord pr;878 llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr));879 return CreateProcedureType(type_id, pr, ct);880 }881 if (cvt.kind() == LF_MFUNCTION) {882 MemberFunctionRecord mfr;883 llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr));884 return CreateFunctionType(type_id, mfr, ct);885 }886 887 return nullptr;888}889 890TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) {891 // If they search for a UDT which is a forward ref, try and resolve the full892 // decl and just map the forward ref uid to the full decl record.893 std::optional<PdbTypeSymId> full_decl_uid;894 if (IsForwardRefUdt(type_id, m_index->tpi())) {895 auto expected_full_ti =896 m_index->tpi().findFullDeclForForwardRef(type_id.index);897 if (!expected_full_ti)898 llvm::consumeError(expected_full_ti.takeError());899 else if (*expected_full_ti != type_id.index) {900 full_decl_uid = PdbTypeSymId(*expected_full_ti, false);901 902 // It's possible that a lookup would occur for the full decl causing it903 // to be cached, then a second lookup would occur for the forward decl.904 // We don't want to create a second full decl, so make sure the full905 // decl hasn't already been cached.906 auto full_iter = m_types.find(toOpaqueUid(*full_decl_uid));907 if (full_iter != m_types.end()) {908 TypeSP result = full_iter->second;909 // Map the forward decl to the TypeSP for the full decl so we can take910 // the fast path next time.911 m_types[toOpaqueUid(type_id)] = result;912 return result;913 }914 }915 }916 917 PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id;918 auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);919 if (auto err = ts_or_err.takeError())920 return nullptr;921 auto ts = *ts_or_err;922 if (!ts)923 return nullptr;924 925 PdbAstBuilder* ast_builder = ts->GetNativePDBParser();926 clang::QualType qt = ast_builder->GetOrCreateType(best_decl_id);927 if (qt.isNull())928 return nullptr;929 930 TypeSP result = CreateType(best_decl_id, ast_builder->ToCompilerType(qt));931 if (!result)932 return nullptr;933 934 uint64_t best_uid = toOpaqueUid(best_decl_id);935 m_types[best_uid] = result;936 // If we had both a forward decl and a full decl, make both point to the new937 // type.938 if (full_decl_uid)939 m_types[toOpaqueUid(type_id)] = result;940 941 return result;942}943 944TypeSP SymbolFileNativePDB::GetOrCreateType(PdbTypeSymId type_id) {945 // We can't use try_emplace / overwrite here because the process of creating946 // a type could create nested types, which could invalidate iterators. So947 // we have to do a 2-phase lookup / insert.948 auto iter = m_types.find(toOpaqueUid(type_id));949 if (iter != m_types.end())950 return iter->second;951 952 TypeSP type = CreateAndCacheType(type_id);953 if (type)954 GetTypeList().Insert(type);955 return type;956}957 958VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {959 CVSymbol sym = m_index->symrecords().readRecord(var_id.offset);960 if (sym.kind() == S_CONSTANT)961 return CreateConstantSymbol(var_id, sym);962 963 lldb::ValueType scope = eValueTypeInvalid;964 TypeIndex ti;965 llvm::StringRef name;966 lldb::addr_t addr = 0;967 uint16_t section = 0;968 uint32_t offset = 0;969 bool is_external = false;970 switch (sym.kind()) {971 case S_GDATA32:972 is_external = true;973 [[fallthrough]];974 case S_LDATA32: {975 DataSym ds(sym.kind());976 llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, ds));977 ti = ds.Type;978 scope = (sym.kind() == S_GDATA32) ? eValueTypeVariableGlobal979 : eValueTypeVariableStatic;980 name = ds.Name;981 section = ds.Segment;982 offset = ds.DataOffset;983 addr = m_index->MakeVirtualAddress(ds.Segment, ds.DataOffset);984 break;985 }986 case S_GTHREAD32:987 is_external = true;988 [[fallthrough]];989 case S_LTHREAD32: {990 ThreadLocalDataSym tlds(sym.kind());991 llvm::cantFail(992 SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, tlds));993 ti = tlds.Type;994 name = tlds.Name;995 section = tlds.Segment;996 offset = tlds.DataOffset;997 addr = m_index->MakeVirtualAddress(tlds.Segment, tlds.DataOffset);998 scope = eValueTypeVariableThreadLocal;999 break;1000 }1001 default:1002 llvm_unreachable("unreachable!");1003 }1004 1005 CompUnitSP comp_unit;1006 std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr);1007 // Some globals has modi points to the linker module, ignore them.1008 if (!modi || modi >= GetNumCompileUnits())1009 return nullptr;1010 1011 CompilandIndexItem &cci = m_index->compilands().GetOrCreateCompiland(*modi);1012 comp_unit = GetOrCreateCompileUnit(cci);1013 1014 Declaration decl;1015 PdbTypeSymId tid(ti, false);1016 SymbolFileTypeSP type_sp =1017 std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));1018 Variable::RangeList ranges;1019 auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage());1020 if (auto err = ts_or_err.takeError())1021 return nullptr;1022 auto ts = *ts_or_err;1023 if (!ts)1024 return nullptr;1025 1026 ts->GetNativePDBParser()->GetOrCreateVariableDecl(var_id);1027 1028 ModuleSP module_sp = GetObjectFile()->GetModule();1029 DWARFExpressionList location(1030 module_sp, MakeGlobalLocationExpression(section, offset, module_sp),1031 nullptr);1032 1033 std::string global_name("::");1034 global_name += name;1035 bool artificial = false;1036 bool location_is_constant_data = false;1037 bool static_member = false;1038 VariableSP var_sp = std::make_shared<Variable>(1039 toOpaqueUid(var_id), name.str().c_str(), global_name.c_str(), type_sp,1040 scope, comp_unit.get(), ranges, &decl, location, is_external, artificial,1041 location_is_constant_data, static_member);1042 1043 return var_sp;1044}1045 1046lldb::VariableSP1047SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id,1048 const CVSymbol &cvs) {1049 TpiStream &tpi = m_index->tpi();1050 ConstantSym constant(cvs.kind());1051 1052 llvm::cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(cvs, constant));1053 std::string global_name("::");1054 global_name += constant.Name;1055 PdbTypeSymId tid(constant.Type, false);1056 SymbolFileTypeSP type_sp =1057 std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));1058 1059 Declaration decl;1060 Variable::RangeList ranges;1061 ModuleSP module = GetObjectFile()->GetModule();1062 DWARFExpressionList location(module,1063 MakeConstantLocationExpression(1064 constant.Type, tpi, constant.Value, module),1065 nullptr);1066 1067 bool external = false;1068 bool artificial = false;1069 bool location_is_constant_data = true;1070 bool static_member = false;1071 VariableSP var_sp = std::make_shared<Variable>(1072 toOpaqueUid(var_id), constant.Name.str().c_str(), global_name.c_str(),1073 type_sp, eValueTypeVariableGlobal, module.get(), ranges, &decl, location,1074 external, artificial, location_is_constant_data, static_member);1075 return var_sp;1076}1077 1078VariableSP1079SymbolFileNativePDB::GetOrCreateGlobalVariable(PdbGlobalSymId var_id) {1080 auto emplace_result = m_global_vars.try_emplace(toOpaqueUid(var_id), nullptr);1081 if (emplace_result.second) {1082 if (VariableSP var_sp = CreateGlobalVariable(var_id))1083 emplace_result.first->second = var_sp;1084 else1085 return nullptr;1086 }1087 1088 return emplace_result.first->second;1089}1090 1091lldb::TypeSP SymbolFileNativePDB::GetOrCreateType(TypeIndex ti) {1092 return GetOrCreateType(PdbTypeSymId(ti, false));1093}1094 1095FunctionSP SymbolFileNativePDB::GetOrCreateFunction(PdbCompilandSymId func_id,1096 CompileUnit &comp_unit) {1097 auto emplace_result = m_functions.try_emplace(toOpaqueUid(func_id), nullptr);1098 if (emplace_result.second)1099 emplace_result.first->second = CreateFunction(func_id, comp_unit);1100 1101 return emplace_result.first->second;1102}1103 1104CompUnitSP1105SymbolFileNativePDB::GetOrCreateCompileUnit(const CompilandIndexItem &cci) {1106 1107 auto emplace_result =1108 m_compilands.try_emplace(toOpaqueUid(cci.m_id), nullptr);1109 if (emplace_result.second)1110 emplace_result.first->second = CreateCompileUnit(cci);1111 1112 lldbassert(emplace_result.first->second);1113 return emplace_result.first->second;1114}1115 1116Block *SymbolFileNativePDB::GetOrCreateBlock(PdbCompilandSymId block_id) {1117 auto iter = m_blocks.find(toOpaqueUid(block_id));1118 if (iter != m_blocks.end())1119 return iter->second.get();1120 1121 return CreateBlock(block_id);1122}1123 1124void SymbolFileNativePDB::ParseDeclsForContext(1125 lldb_private::CompilerDeclContext decl_ctx) {1126 TypeSystem* ts_or_err = decl_ctx.GetTypeSystem();1127 if (!ts_or_err)1128 return;1129 PdbAstBuilder* ast_builder = ts_or_err->GetNativePDBParser();1130 clang::DeclContext *context = ast_builder->FromCompilerDeclContext(decl_ctx);1131 if (!context)1132 return;1133 ast_builder->ParseDeclsForContext(*context);1134}1135 1136lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) {1137 if (index >= GetNumCompileUnits())1138 return CompUnitSP();1139 lldbassert(index < UINT16_MAX);1140 if (index >= UINT16_MAX)1141 return nullptr;1142 1143 CompilandIndexItem &item = m_index->compilands().GetOrCreateCompiland(index);1144 1145 return GetOrCreateCompileUnit(item);1146}1147 1148lldb::LanguageType SymbolFileNativePDB::ParseLanguage(CompileUnit &comp_unit) {1149 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());1150 PdbSymUid uid(comp_unit.GetID());1151 lldbassert(uid.kind() == PdbSymUidKind::Compiland);1152 1153 CompilandIndexItem *item =1154 m_index->compilands().GetCompiland(uid.asCompiland().modi);1155 lldbassert(item);1156 if (!item->m_compile_opts)1157 return lldb::eLanguageTypeUnknown;1158 1159 return TranslateLanguage(item->m_compile_opts->getLanguage());1160}1161 1162void SymbolFileNativePDB::AddSymbols(Symtab &symtab) {1163 auto *section_list =1164 m_objfile_sp->GetModule()->GetObjectFile()->GetSectionList();1165 if (!section_list)1166 return;1167 1168 PublicSym32 last_sym;1169 size_t last_sym_idx = 0;1170 lldb::SectionSP section_sp;1171 1172 // To estimate the size of a symbol, we use the difference to the next symbol.1173 // If there's no next symbol or the section/segment changed, the symbol will1174 // take the remaining space. The estimate can be too high in case there's1175 // padding between symbols. This similar to the algorithm used by the DIA1176 // SDK.1177 auto finish_last_symbol = [&](const PublicSym32 *next) {1178 if (!section_sp)1179 return;1180 Symbol *last = symtab.SymbolAtIndex(last_sym_idx);1181 if (!last)1182 return;1183 1184 if (next && last_sym.Segment == next->Segment) {1185 assert(last_sym.Offset <= next->Offset);1186 last->SetByteSize(next->Offset - last_sym.Offset);1187 } else {1188 // the last symbol was the last in its section1189 assert(section_sp->GetByteSize() >= last_sym.Offset);1190 assert(!next || next->Segment > last_sym.Segment);1191 last->SetByteSize(section_sp->GetByteSize() - last_sym.Offset);1192 }1193 };1194 1195 // The address map is sorted by the address of a symbol.1196 for (auto pid : m_index->publics().getAddressMap()) {1197 PdbGlobalSymId global{pid, true};1198 CVSymbol sym = m_index->ReadSymbolRecord(global);1199 auto kind = sym.kind();1200 if (kind != S_PUB32)1201 continue;1202 PublicSym32 pub =1203 llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(sym));1204 finish_last_symbol(&pub);1205 1206 if (!section_sp || last_sym.Segment != pub.Segment)1207 section_sp = section_list->FindSectionByID(pub.Segment);1208 1209 if (!section_sp)1210 continue;1211 1212 lldb::SymbolType type = eSymbolTypeData;1213 if ((pub.Flags & PublicSymFlags::Function) != PublicSymFlags::None ||1214 (pub.Flags & PublicSymFlags::Code) != PublicSymFlags::None)1215 type = eSymbolTypeCode;1216 1217 last_sym_idx =1218 symtab.AddSymbol(Symbol(/*symID=*/pid,1219 /*name=*/pub.Name,1220 /*type=*/type,1221 /*external=*/true,1222 /*is_debug=*/true,1223 /*is_trampoline=*/false,1224 /*is_artificial=*/false,1225 /*section_sp=*/section_sp,1226 /*value=*/pub.Offset,1227 /*size=*/0,1228 /*size_is_valid=*/false,1229 /*contains_linker_annotations=*/false,1230 /*flags=*/0));1231 last_sym = pub;1232 }1233 1234 finish_last_symbol(nullptr);1235}1236 1237size_t SymbolFileNativePDB::ParseFunctions(CompileUnit &comp_unit) {1238 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());1239 PdbSymUid uid{comp_unit.GetID()};1240 lldbassert(uid.kind() == PdbSymUidKind::Compiland);1241 uint16_t modi = uid.asCompiland().modi;1242 CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(modi);1243 1244 size_t count = comp_unit.GetNumFunctions();1245 const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();1246 for (auto iter = syms.begin(); iter != syms.end(); ++iter) {1247 if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32)1248 continue;1249 1250 PdbCompilandSymId sym_id{modi, iter.offset()};1251 1252 FunctionSP func = GetOrCreateFunction(sym_id, comp_unit);1253 }1254 1255 size_t new_count = comp_unit.GetNumFunctions();1256 lldbassert(new_count >= count);1257 return new_count - count;1258}1259 1260static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) {1261 // If any of these flags are set, we need to resolve the compile unit.1262 uint32_t flags = eSymbolContextCompUnit;1263 flags |= eSymbolContextVariable;1264 flags |= eSymbolContextFunction;1265 flags |= eSymbolContextBlock;1266 flags |= eSymbolContextLineEntry;1267 return (resolve_scope & flags) != 0;1268}1269 1270uint32_t SymbolFileNativePDB::ResolveSymbolContext(1271 const Address &addr, SymbolContextItem resolve_scope, SymbolContext &sc) {1272 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());1273 uint32_t resolved_flags = 0;1274 lldb::addr_t file_addr = addr.GetFileAddress();1275 1276 if (NeedsResolvedCompileUnit(resolve_scope)) {1277 std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr);1278 if (!modi)1279 return 0;1280 CompUnitSP cu_sp = GetCompileUnitAtIndex(*modi);1281 if (!cu_sp)1282 return 0;1283 1284 sc.comp_unit = cu_sp.get();1285 resolved_flags |= eSymbolContextCompUnit;1286 }1287 1288 if (resolve_scope & eSymbolContextFunction ||1289 resolve_scope & eSymbolContextBlock) {1290 lldbassert(sc.comp_unit);1291 std::vector<SymbolAndUid> matches = m_index->FindSymbolsByVa(file_addr);1292 // Search the matches in reverse. This way if there are multiple matches1293 // (for example we are 3 levels deep in a nested scope) it will find the1294 // innermost one first.1295 for (const auto &match : llvm::reverse(matches)) {1296 if (match.uid.kind() != PdbSymUidKind::CompilandSym)1297 continue;1298 1299 PdbCompilandSymId csid = match.uid.asCompilandSym();1300 CVSymbol cvs = m_index->ReadSymbolRecord(csid);1301 PDB_SymType type = CVSymToPDBSym(cvs.kind());1302 if (type != PDB_SymType::Function && type != PDB_SymType::Block)1303 continue;1304 if (type == PDB_SymType::Function) {1305 sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get();1306 if (sc.function) {1307 Block &block = sc.function->GetBlock(true);1308 addr_t func_base = sc.function->GetAddress().GetFileAddress();1309 addr_t offset = file_addr - func_base;1310 sc.block = block.FindInnermostBlockByOffset(offset);1311 }1312 }1313 1314 if (type == PDB_SymType::Block) {1315 Block *block = GetOrCreateBlock(csid);1316 if (!block)1317 continue;1318 sc.function = block->CalculateSymbolContextFunction();1319 if (sc.function) {1320 sc.function->GetBlock(true);1321 addr_t func_base = sc.function->GetAddress().GetFileAddress();1322 addr_t offset = file_addr - func_base;1323 sc.block = block->FindInnermostBlockByOffset(offset);1324 }1325 }1326 if (sc.function)1327 resolved_flags |= eSymbolContextFunction;1328 if (sc.block)1329 resolved_flags |= eSymbolContextBlock;1330 break;1331 }1332 }1333 1334 if (resolve_scope & eSymbolContextLineEntry) {1335 lldbassert(sc.comp_unit);1336 if (auto *line_table = sc.comp_unit->GetLineTable()) {1337 if (line_table->FindLineEntryByAddress(addr, sc.line_entry))1338 resolved_flags |= eSymbolContextLineEntry;1339 }1340 }1341 1342 return resolved_flags;1343}1344 1345uint32_t SymbolFileNativePDB::ResolveSymbolContext(1346 const SourceLocationSpec &src_location_spec,1347 lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {1348 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());1349 const uint32_t prev_size = sc_list.GetSize();1350 if (resolve_scope & eSymbolContextCompUnit) {1351 for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus;1352 ++cu_idx) {1353 CompileUnit *cu = ParseCompileUnitAtIndex(cu_idx).get();1354 if (!cu)1355 continue;1356 1357 bool file_spec_matches_cu_file_spec = FileSpec::Match(1358 src_location_spec.GetFileSpec(), cu->GetPrimaryFile());1359 if (file_spec_matches_cu_file_spec) {1360 cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list);1361 break;1362 }1363 }1364 }1365 return sc_list.GetSize() - prev_size;1366}1367 1368bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) {1369 // Unfortunately LLDB is set up to parse the entire compile unit line table1370 // all at once, even if all it really needs is line info for a specific1371 // function. In the future it would be nice if it could set the sc.m_function1372 // member, and we could only get the line info for the function in question.1373 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());1374 PdbSymUid cu_id(comp_unit.GetID());1375 lldbassert(cu_id.kind() == PdbSymUidKind::Compiland);1376 uint16_t modi = cu_id.asCompiland().modi;1377 CompilandIndexItem *cii = m_index->compilands().GetCompiland(modi);1378 lldbassert(cii);1379 1380 // Parse DEBUG_S_LINES subsections first, then parse all S_INLINESITE records1381 // in this CU. Add line entries into the set first so that if there are line1382 // entries with same addres, the later is always more accurate than the1383 // former.1384 std::set<LineTable::Entry, LineTableEntryComparator> line_set;1385 1386 // This is basically a copy of the .debug$S subsections from all original COFF1387 // object files merged together with address relocations applied. We are1388 // looking for all DEBUG_S_LINES subsections.1389 for (const DebugSubsectionRecord &dssr :1390 cii->m_debug_stream.getSubsectionsArray()) {1391 if (dssr.kind() != DebugSubsectionKind::Lines)1392 continue;1393 1394 DebugLinesSubsectionRef lines;1395 llvm::BinaryStreamReader reader(dssr.getRecordData());1396 if (auto EC = lines.initialize(reader)) {1397 llvm::consumeError(std::move(EC));1398 return false;1399 }1400 1401 const LineFragmentHeader *lfh = lines.header();1402 uint64_t virtual_addr =1403 m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset);1404 if (virtual_addr == LLDB_INVALID_ADDRESS)1405 continue;1406 1407 for (const LineColumnEntry &group : lines) {1408 llvm::Expected<uint32_t> file_index_or_err =1409 GetFileIndex(*cii, group.NameIndex);1410 if (!file_index_or_err)1411 continue;1412 uint32_t file_index = file_index_or_err.get();1413 lldbassert(!group.LineNumbers.empty());1414 CompilandIndexItem::GlobalLineTable::Entry line_entry(1415 LLDB_INVALID_ADDRESS, 0);1416 for (const LineNumberEntry &entry : group.LineNumbers) {1417 LineInfo cur_info(entry.Flags);1418 1419 if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto())1420 continue;1421 1422 uint64_t addr = virtual_addr + entry.Offset;1423 1424 bool is_statement = cur_info.isStatement();1425 bool is_prologue = IsFunctionPrologue(*cii, addr);1426 bool is_epilogue = IsFunctionEpilogue(*cii, addr);1427 1428 uint32_t lno = cur_info.getStartLine();1429 1430 LineTable::Entry new_entry(addr, lno, 0, file_index, is_statement, false,1431 is_prologue, is_epilogue, false);1432 // Terminal entry has lower precedence than new entry.1433 auto iter = line_set.find(new_entry);1434 if (iter != line_set.end() && iter->is_terminal_entry)1435 line_set.erase(iter);1436 line_set.insert(new_entry);1437 1438 if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) {1439 line_entry.SetRangeEnd(addr);1440 cii->m_global_line_table.Append(line_entry);1441 }1442 line_entry.SetRangeBase(addr);1443 line_entry.data = {file_index, lno};1444 }1445 LineInfo last_line(group.LineNumbers.back().Flags);1446 line_set.emplace(virtual_addr + lfh->CodeSize, last_line.getEndLine(), 0,1447 file_index, false, false, false, false, true);1448 1449 if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) {1450 line_entry.SetRangeEnd(virtual_addr + lfh->CodeSize);1451 cii->m_global_line_table.Append(line_entry);1452 }1453 }1454 }1455 1456 cii->m_global_line_table.Sort();1457 1458 // Parse all S_INLINESITE in this CU.1459 const CVSymbolArray &syms = cii->m_debug_stream.getSymbolArray();1460 for (auto iter = syms.begin(); iter != syms.end();) {1461 if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32) {1462 ++iter;1463 continue;1464 }1465 1466 uint32_t record_offset = iter.offset();1467 CVSymbol func_record =1468 cii->m_debug_stream.readSymbolAtOffset(record_offset);1469 SegmentOffsetLength sol = GetSegmentOffsetAndLength(func_record);1470 addr_t file_vm_addr =1471 m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset);1472 if (file_vm_addr == LLDB_INVALID_ADDRESS)1473 continue;1474 1475 Address func_base(file_vm_addr, comp_unit.GetModule()->GetSectionList());1476 PdbCompilandSymId func_id{modi, record_offset};1477 1478 // Iterate all S_INLINESITEs in the function.1479 auto parse_inline_sites = [&](SymbolKind kind, PdbCompilandSymId id) {1480 if (kind != S_INLINESITE)1481 return false;1482 1483 ParseInlineSite(id, func_base);1484 1485 for (const auto &line_entry :1486 m_inline_sites[toOpaqueUid(id)]->line_entries) {1487 // If line_entry is not terminal entry, remove previous line entry at1488 // the same address and insert new one. Terminal entry inside an inline1489 // site might not be terminal entry for its parent.1490 if (!line_entry.is_terminal_entry)1491 line_set.erase(line_entry);1492 line_set.insert(line_entry);1493 }1494 // No longer useful after adding to line_set.1495 m_inline_sites[toOpaqueUid(id)]->line_entries.clear();1496 return true;1497 };1498 ParseSymbolArrayInScope(func_id, parse_inline_sites);1499 // Jump to the end of the function record.1500 iter = syms.at(getScopeEndOffset(func_record));1501 }1502 1503 cii->m_global_line_table.Clear();1504 1505 // Add line entries in line_set to line_table.1506 std::vector<LineTable::Sequence> sequence(1);1507 for (const auto &line_entry : line_set) {1508 LineTable::AppendLineEntryToSequence(1509 sequence.back(), line_entry.file_addr, line_entry.line,1510 line_entry.column, line_entry.file_idx,1511 line_entry.is_start_of_statement, line_entry.is_start_of_basic_block,1512 line_entry.is_prologue_end, line_entry.is_epilogue_begin,1513 line_entry.is_terminal_entry);1514 }1515 auto line_table =1516 std::make_unique<LineTable>(&comp_unit, std::move(sequence));1517 1518 if (line_table->GetSize() == 0)1519 return false;1520 1521 comp_unit.SetLineTable(line_table.release());1522 return true;1523}1524 1525bool SymbolFileNativePDB::ParseDebugMacros(CompileUnit &comp_unit) {1526 // PDB doesn't contain information about macros1527 return false;1528}1529 1530llvm::Expected<uint32_t>1531SymbolFileNativePDB::GetFileIndex(const CompilandIndexItem &cii,1532 uint32_t file_id) {1533 if (!cii.m_strings.hasChecksums() || !cii.m_strings.hasStrings())1534 return llvm::make_error<RawError>(raw_error_code::no_entry);1535 1536 const auto &checksums = cii.m_strings.checksums().getArray();1537 const auto &strings = cii.m_strings.strings();1538 // Indices in this structure are actually offsets of records in the1539 // DEBUG_S_FILECHECKSUMS subsection. Those entries then have an index1540 // into the global PDB string table.1541 auto iter = checksums.at(file_id);1542 if (iter == checksums.end())1543 return llvm::make_error<RawError>(raw_error_code::no_entry);1544 1545 llvm::Expected<llvm::StringRef> efn = strings.getString(iter->FileNameOffset);1546 if (!efn) {1547 return efn.takeError();1548 }1549 1550 // LLDB wants the index of the file in the list of support files.1551 auto fn_iter = llvm::find(cii.m_file_list, *efn);1552 if (fn_iter != cii.m_file_list.end())1553 return std::distance(cii.m_file_list.begin(), fn_iter);1554 return llvm::make_error<RawError>(raw_error_code::no_entry);1555}1556 1557bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit,1558 SupportFileList &support_files) {1559 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());1560 PdbSymUid cu_id(comp_unit.GetID());1561 lldbassert(cu_id.kind() == PdbSymUidKind::Compiland);1562 CompilandIndexItem *cci =1563 m_index->compilands().GetCompiland(cu_id.asCompiland().modi);1564 lldbassert(cci);1565 1566 for (llvm::StringRef f : cci->m_file_list) {1567 FileSpec::Style style =1568 f.starts_with("/") ? FileSpec::Style::posix : FileSpec::Style::windows;1569 FileSpec spec(f, style);1570 support_files.Append(spec);1571 }1572 return true;1573}1574 1575bool SymbolFileNativePDB::ParseImportedModules(1576 const SymbolContext &sc, std::vector<SourceModule> &imported_modules) {1577 // PDB does not yet support module debug info1578 return false;1579}1580 1581void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id,1582 Address func_addr) {1583 lldb::user_id_t opaque_uid = toOpaqueUid(id);1584 if (m_inline_sites.contains(opaque_uid))1585 return;1586 1587 addr_t func_base = func_addr.GetFileAddress();1588 CompilandIndexItem *cii = m_index->compilands().GetCompiland(id.modi);1589 CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(id.offset);1590 CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);1591 1592 InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind()));1593 cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site));1594 PdbCompilandSymId parent_id(id.modi, inline_site.Parent);1595 1596 std::shared_ptr<InlineSite> inline_site_sp =1597 std::make_shared<InlineSite>(parent_id);1598 1599 // Get the inlined function declaration info.1600 auto iter = cii->m_inline_map.find(inline_site.Inlinee);1601 if (iter == cii->m_inline_map.end())1602 return;1603 InlineeSourceLine inlinee_line = iter->second;1604 1605 const SupportFileList &files = comp_unit->GetSupportFiles();1606 FileSpec decl_file;1607 llvm::Expected<uint32_t> file_index_or_err =1608 GetFileIndex(*cii, inlinee_line.Header->FileID);1609 if (!file_index_or_err)1610 return;1611 uint32_t file_offset = file_index_or_err.get();1612 decl_file = files.GetFileSpecAtIndex(file_offset);1613 uint32_t decl_line = inlinee_line.Header->SourceLineNum;1614 std::unique_ptr<Declaration> decl_up =1615 std::make_unique<Declaration>(decl_file, decl_line);1616 1617 // Parse range and line info.1618 uint32_t code_offset = 0;1619 int32_t line_offset = 0;1620 std::optional<uint32_t> code_offset_base;1621 std::optional<uint32_t> code_offset_end;1622 std::optional<int32_t> cur_line_offset;1623 std::optional<int32_t> next_line_offset;1624 std::optional<uint32_t> next_file_offset;1625 1626 bool is_terminal_entry = false;1627 bool is_start_of_statement = true;1628 // The first instruction is the prologue end.1629 bool is_prologue_end = true;1630 1631 auto update_code_offset = [&](uint32_t code_delta) {1632 if (!code_offset_base)1633 code_offset_base = code_offset;1634 else if (!code_offset_end)1635 code_offset_end = *code_offset_base + code_delta;1636 };1637 auto update_line_offset = [&](int32_t line_delta) {1638 line_offset += line_delta;1639 if (!code_offset_base || !cur_line_offset)1640 cur_line_offset = line_offset;1641 else1642 next_line_offset = line_offset;1643 ;1644 };1645 auto update_file_offset = [&](uint32_t offset) {1646 if (!code_offset_base)1647 file_offset = offset;1648 else1649 next_file_offset = offset;1650 };1651 1652 for (auto &annot : inline_site.annotations()) {1653 switch (annot.OpCode) {1654 case BinaryAnnotationsOpCode::CodeOffset:1655 case BinaryAnnotationsOpCode::ChangeCodeOffset:1656 case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:1657 code_offset += annot.U1;1658 update_code_offset(annot.U1);1659 break;1660 case BinaryAnnotationsOpCode::ChangeLineOffset:1661 update_line_offset(annot.S1);1662 break;1663 case BinaryAnnotationsOpCode::ChangeCodeLength:1664 update_code_offset(annot.U1);1665 code_offset += annot.U1;1666 is_terminal_entry = true;1667 break;1668 case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset:1669 code_offset += annot.U1;1670 update_code_offset(annot.U1);1671 update_line_offset(annot.S1);1672 break;1673 case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset:1674 code_offset += annot.U2;1675 update_code_offset(annot.U2);1676 update_code_offset(annot.U1);1677 code_offset += annot.U1;1678 is_terminal_entry = true;1679 break;1680 case BinaryAnnotationsOpCode::ChangeFile:1681 update_file_offset(annot.U1);1682 break;1683 default:1684 break;1685 }1686 1687 // Add range if current range is finished.1688 if (code_offset_base && code_offset_end && cur_line_offset) {1689 inline_site_sp->ranges.Append(RangeSourceLineVector::Entry(1690 *code_offset_base, *code_offset_end - *code_offset_base,1691 decl_line + *cur_line_offset));1692 // Set base, end, file offset and line offset for next range.1693 if (next_file_offset)1694 file_offset = *next_file_offset;1695 if (next_line_offset) {1696 cur_line_offset = next_line_offset;1697 next_line_offset = std::nullopt;1698 }1699 code_offset_base = is_terminal_entry ? std::nullopt : code_offset_end;1700 code_offset_end = next_file_offset = std::nullopt;1701 }1702 if (code_offset_base && cur_line_offset) {1703 if (is_terminal_entry) {1704 LineTable::Entry line_entry(1705 func_base + *code_offset_base, decl_line + *cur_line_offset, 0,1706 file_offset, false, false, false, false, true);1707 inline_site_sp->line_entries.push_back(line_entry);1708 } else {1709 LineTable::Entry line_entry(func_base + *code_offset_base,1710 decl_line + *cur_line_offset, 0,1711 file_offset, is_start_of_statement, false,1712 is_prologue_end, false, false);1713 inline_site_sp->line_entries.push_back(line_entry);1714 is_prologue_end = false;1715 is_start_of_statement = false;1716 }1717 }1718 if (is_terminal_entry)1719 is_start_of_statement = true;1720 is_terminal_entry = false;1721 }1722 1723 inline_site_sp->ranges.Sort();1724 1725 // Get the inlined function callsite info.1726 std::unique_ptr<Declaration> callsite_up;1727 if (!inline_site_sp->ranges.IsEmpty()) {1728 auto *entry = inline_site_sp->ranges.GetEntryAtIndex(0);1729 addr_t base_offset = entry->GetRangeBase();1730 if (cii->m_debug_stream.readSymbolAtOffset(parent_id.offset).kind() ==1731 S_INLINESITE) {1732 // Its parent is another inline site, lookup parent site's range vector1733 // for callsite line.1734 ParseInlineSite(parent_id, func_base);1735 std::shared_ptr<InlineSite> parent_site =1736 m_inline_sites[toOpaqueUid(parent_id)];1737 FileSpec &parent_decl_file =1738 parent_site->inline_function_info->GetDeclaration().GetFile();1739 if (auto *parent_entry =1740 parent_site->ranges.FindEntryThatContains(base_offset)) {1741 callsite_up =1742 std::make_unique<Declaration>(parent_decl_file, parent_entry->data);1743 }1744 } else {1745 // Its parent is a function, lookup global line table for callsite.1746 if (auto *entry = cii->m_global_line_table.FindEntryThatContains(1747 func_base + base_offset)) {1748 const FileSpec &callsite_file =1749 files.GetFileSpecAtIndex(entry->data.first);1750 callsite_up =1751 std::make_unique<Declaration>(callsite_file, entry->data.second);1752 }1753 }1754 }1755 1756 // Get the inlined function name.1757 CVType inlinee_cvt = m_index->ipi().getType(inline_site.Inlinee);1758 std::string inlinee_name;1759 if (inlinee_cvt.kind() == LF_MFUNC_ID) {1760 MemberFuncIdRecord mfr;1761 cantFail(1762 TypeDeserializer::deserializeAs<MemberFuncIdRecord>(inlinee_cvt, mfr));1763 LazyRandomTypeCollection &types = m_index->tpi().typeCollection();1764 inlinee_name.append(std::string(types.getTypeName(mfr.ClassType)));1765 inlinee_name.append("::");1766 inlinee_name.append(mfr.getName().str());1767 } else if (inlinee_cvt.kind() == LF_FUNC_ID) {1768 FuncIdRecord fir;1769 cantFail(TypeDeserializer::deserializeAs<FuncIdRecord>(inlinee_cvt, fir));1770 TypeIndex parent_idx = fir.getParentScope();1771 if (!parent_idx.isNoneType()) {1772 LazyRandomTypeCollection &ids = m_index->ipi().typeCollection();1773 inlinee_name.append(std::string(ids.getTypeName(parent_idx)));1774 inlinee_name.append("::");1775 }1776 inlinee_name.append(fir.getName().str());1777 }1778 inline_site_sp->inline_function_info = std::make_shared<InlineFunctionInfo>(1779 inlinee_name.c_str(), llvm::StringRef(), decl_up.get(),1780 callsite_up.get());1781 1782 m_inline_sites[opaque_uid] = inline_site_sp;1783}1784 1785size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) {1786 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());1787 PdbCompilandSymId func_id = PdbSymUid(func.GetID()).asCompilandSym();1788 // After we iterate through inline sites inside the function, we already get1789 // all the info needed, removing from the map to save memory.1790 std::set<uint64_t> remove_uids;1791 auto parse_blocks = [&](SymbolKind kind, PdbCompilandSymId id) {1792 if (kind == S_GPROC32 || kind == S_LPROC32 || kind == S_BLOCK32 ||1793 kind == S_INLINESITE) {1794 GetOrCreateBlock(id);1795 if (kind == S_INLINESITE)1796 remove_uids.insert(toOpaqueUid(id));1797 return true;1798 }1799 return false;1800 };1801 size_t count = ParseSymbolArrayInScope(func_id, parse_blocks);1802 for (uint64_t uid : remove_uids) {1803 m_inline_sites.erase(uid);1804 }1805 1806 func.GetBlock(false).SetBlockInfoHasBeenParsed(true, true);1807 return count;1808}1809 1810size_t SymbolFileNativePDB::ParseSymbolArrayInScope(1811 PdbCompilandSymId parent_id,1812 llvm::function_ref<bool(SymbolKind, PdbCompilandSymId)> fn) {1813 CompilandIndexItem *cii = m_index->compilands().GetCompiland(parent_id.modi);1814 CVSymbolArray syms =1815 cii->m_debug_stream.getSymbolArrayForScope(parent_id.offset);1816 1817 size_t count = 1;1818 for (auto iter = syms.begin(); iter != syms.end(); ++iter) {1819 PdbCompilandSymId child_id(parent_id.modi, iter.offset());1820 if (fn(iter->kind(), child_id))1821 ++count;1822 }1823 1824 return count;1825}1826 1827void SymbolFileNativePDB::DumpClangAST(Stream &s, llvm::StringRef filter,1828 bool show_color) {1829 auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);1830 if (!ts_or_err)1831 return;1832 auto ts = *ts_or_err;1833 TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());1834 if (!clang)1835 return;1836 clang->GetNativePDBParser()->Dump(s, filter, show_color);1837}1838 1839void SymbolFileNativePDB::CacheGlobalBaseNames() {1840 if (!m_func_full_names.IsEmpty() || !m_global_variable_base_names.IsEmpty())1841 return;1842 1843 // (segment, code offset) -> gid1844 std::map<std::pair<uint16_t, uint32_t>, uint32_t> func_addr_ids;1845 1846 // First, look through all items in the globals table.1847 for (const uint32_t gid : m_index->globals().getGlobalsTable()) {1848 CVSymbol sym = m_index->symrecords().readRecord(gid);1849 auto kind = sym.kind();1850 1851 // If this is a global variable, we only need to look at the name1852 llvm::StringRef name;1853 switch (kind) {1854 case SymbolKind::S_GDATA32:1855 case SymbolKind::S_LDATA32: {1856 DataSym data =1857 llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym));1858 name = data.Name;1859 break;1860 }1861 case SymbolKind::S_GTHREAD32:1862 case SymbolKind::S_LTHREAD32: {1863 ThreadLocalDataSym data = llvm::cantFail(1864 SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym));1865 name = data.Name;1866 break;1867 }1868 case SymbolKind::S_CONSTANT: {1869 ConstantSym data =1870 llvm::cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym));1871 name = data.Name;1872 break;1873 }1874 default:1875 break;1876 }1877 1878 if (!name.empty()) {1879 llvm::StringRef base = MSVCUndecoratedNameParser::DropScope(name);1880 if (base.empty())1881 base = name;1882 1883 m_global_variable_base_names.Append(ConstString(base), gid);1884 continue;1885 }1886 1887 if (kind != S_PROCREF && kind != S_LPROCREF)1888 continue;1889 1890 // For functions, we need to follow the reference to the procedure and look1891 // at the type1892 1893 ProcRefSym ref =1894 llvm::cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(sym));1895 if (ref.Name.empty())1896 continue;1897 1898 // Find the function this is referencing.1899 CompilandIndexItem &cci =1900 m_index->compilands().GetOrCreateCompiland(ref.modi());1901 auto iter = cci.m_debug_stream.getSymbolArray().at(ref.SymOffset);1902 if (iter == cci.m_debug_stream.getSymbolArray().end())1903 continue;1904 kind = iter->kind();1905 if (kind != S_GPROC32 && kind != S_LPROC32)1906 continue;1907 1908 ProcSym proc =1909 llvm::cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*iter));1910 if ((proc.Flags & ProcSymFlags::IsUnreachable) != ProcSymFlags::None)1911 continue;1912 if (proc.Name.empty() || proc.FunctionType.isSimple())1913 continue;1914 1915 // The function/procedure symbol only contains the demangled name.1916 // The mangled names are in the publics table. Save the address of this1917 // function to lookup the mangled name later.1918 func_addr_ids.emplace(std::make_pair(proc.Segment, proc.CodeOffset), gid);1919 1920 llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(proc.Name);1921 if (basename.empty())1922 basename = proc.Name;1923 1924 m_func_base_names.Append(ConstString(basename), gid);1925 m_func_full_names.Append(ConstString(proc.Name), gid);1926 1927 // To see if this is a member function, check the type.1928 auto type = m_index->tpi().getType(proc.FunctionType);1929 if (type.kind() == LF_MFUNCTION) {1930 MemberFunctionRecord mfr;1931 llvm::cantFail(1932 TypeDeserializer::deserializeAs<MemberFunctionRecord>(type, mfr));1933 if (!mfr.getThisType().isNoneType())1934 m_func_method_names.Append(ConstString(basename), gid);1935 }1936 }1937 1938 // The publics stream contains all mangled function names and their address.1939 for (auto pid : m_index->publics().getPublicsTable()) {1940 PdbGlobalSymId global{pid, true};1941 CVSymbol sym = m_index->ReadSymbolRecord(global);1942 auto kind = sym.kind();1943 if (kind != S_PUB32)1944 continue;1945 PublicSym32 pub =1946 llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(sym));1947 // We only care about mangled names - if the name isn't mangled, it's1948 // already in the full name map.1949 if (!Mangled::IsMangledName(pub.Name))1950 continue;1951 1952 // Check if this symbol is for one of our functions.1953 auto it = func_addr_ids.find({pub.Segment, pub.Offset});1954 if (it != func_addr_ids.end())1955 m_func_full_names.Append(ConstString(pub.Name), it->second);1956 }1957 1958 // Sort them before value searching is working properly.1959 m_func_full_names.Sort(std::less<uint32_t>());1960 m_func_full_names.SizeToFit();1961 m_func_method_names.Sort(std::less<uint32_t>());1962 m_func_method_names.SizeToFit();1963 m_func_base_names.Sort(std::less<uint32_t>());1964 m_func_base_names.SizeToFit();1965 m_global_variable_base_names.Sort(std::less<uint32_t>());1966 m_global_variable_base_names.SizeToFit();1967}1968 1969void SymbolFileNativePDB::FindGlobalVariables(1970 ConstString name, const CompilerDeclContext &parent_decl_ctx,1971 uint32_t max_matches, VariableList &variables) {1972 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());1973 1974 CacheGlobalBaseNames();1975 1976 std::vector<uint32_t> results;1977 m_global_variable_base_names.GetValues(name, results);1978 1979 size_t n_matches = 0;1980 for (uint32_t gid : results) {1981 PdbGlobalSymId global(gid, false);1982 1983 if (parent_decl_ctx.IsValid() &&1984 GetDeclContextContainingUID(toOpaqueUid(global)) != parent_decl_ctx)1985 continue;1986 1987 VariableSP var = GetOrCreateGlobalVariable(global);1988 if (!var)1989 continue;1990 variables.AddVariable(var);1991 1992 if (++n_matches >= max_matches)1993 break;1994 }1995}1996 1997void SymbolFileNativePDB::FindFunctions(1998 const Module::LookupInfo &lookup_info,1999 const CompilerDeclContext &parent_decl_ctx, bool include_inlines,2000 SymbolContextList &sc_list) {2001 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());2002 ConstString name = lookup_info.GetLookupName();2003 FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();2004 if (name_type_mask & eFunctionNameTypeFull)2005 name = lookup_info.GetName();2006 2007 if (!(name_type_mask & eFunctionNameTypeFull ||2008 name_type_mask & eFunctionNameTypeBase ||2009 name_type_mask & eFunctionNameTypeMethod))2010 return;2011 CacheGlobalBaseNames();2012 2013 std::set<uint32_t> resolved_ids; // avoid duplicate lookups2014 auto resolve_from = [&](UniqueCStringMap<uint32_t> &Names) {2015 std::vector<uint32_t> ids;2016 if (!Names.GetValues(name, ids))2017 return;2018 2019 for (uint32_t id : ids) {2020 if (!resolved_ids.insert(id).second)2021 continue;2022 2023 PdbGlobalSymId global{id, false};2024 if (parent_decl_ctx.IsValid() &&2025 GetDeclContextContainingUID(toOpaqueUid(global)) != parent_decl_ctx)2026 continue;2027 2028 CVSymbol sym = m_index->ReadSymbolRecord(global);2029 auto kind = sym.kind();2030 lldbassert(kind == S_PROCREF || kind == S_LPROCREF);2031 2032 ProcRefSym proc =2033 cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(sym));2034 2035 if (!IsValidRecord(proc))2036 continue;2037 2038 CompilandIndexItem &cci =2039 m_index->compilands().GetOrCreateCompiland(proc.modi());2040 SymbolContext sc;2041 2042 sc.comp_unit = GetOrCreateCompileUnit(cci).get();2043 if (!sc.comp_unit)2044 continue;2045 2046 PdbCompilandSymId func_id(proc.modi(), proc.SymOffset);2047 sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get();2048 if (!sc.function)2049 continue;2050 2051 sc_list.Append(sc);2052 }2053 };2054 2055 if (name_type_mask & eFunctionNameTypeFull)2056 resolve_from(m_func_full_names);2057 if (name_type_mask & eFunctionNameTypeBase)2058 resolve_from(m_func_base_names);2059 if (name_type_mask & eFunctionNameTypeMethod)2060 resolve_from(m_func_method_names);2061}2062 2063void SymbolFileNativePDB::FindFunctions(const RegularExpression ®ex,2064 bool include_inlines,2065 SymbolContextList &sc_list) {}2066 2067void SymbolFileNativePDB::FindTypes(const lldb_private::TypeQuery &query,2068 lldb_private::TypeResults &results) {2069 2070 // Make sure we haven't already searched this SymbolFile before.2071 if (results.AlreadySearched(this))2072 return;2073 2074 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());2075 2076 // We can't query for the full name because the type might reside2077 // in an anonymous namespace. Search for the basename in our map and check the2078 // matching types afterwards.2079 std::vector<uint32_t> matches;2080 m_type_base_names.GetValues(query.GetTypeBasename(), matches);2081 2082 for (uint32_t match_idx : matches) {2083 std::vector context = GetContextForType(TypeIndex(match_idx));2084 if (context.empty())2085 continue;2086 2087 if (query.ContextMatches(context)) {2088 TypeSP type_sp = GetOrCreateType(TypeIndex(match_idx));2089 if (!type_sp)2090 continue;2091 2092 results.InsertUnique(type_sp);2093 if (results.Done(query))2094 return;2095 }2096 }2097}2098 2099void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name,2100 uint32_t max_matches,2101 TypeMap &types) {2102 2103 std::vector<TypeIndex> matches = m_index->tpi().findRecordsByName(name);2104 if (max_matches > 0 && max_matches < matches.size())2105 matches.resize(max_matches);2106 2107 for (TypeIndex ti : matches) {2108 TypeSP type = GetOrCreateType(ti);2109 if (!type)2110 continue;2111 2112 types.Insert(type);2113 }2114}2115 2116size_t SymbolFileNativePDB::ParseTypes(CompileUnit &comp_unit) {2117 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());2118 // Only do the full type scan the first time.2119 if (m_done_full_type_scan)2120 return 0;2121 2122 const size_t old_count = GetTypeList().GetSize();2123 LazyRandomTypeCollection &types = m_index->tpi().typeCollection();2124 2125 // First process the entire TPI stream.2126 for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {2127 TypeSP type = GetOrCreateType(*ti);2128 if (type)2129 (void)type->GetFullCompilerType();2130 }2131 2132 // Next look for S_UDT records in the globals stream.2133 for (const uint32_t gid : m_index->globals().getGlobalsTable()) {2134 PdbGlobalSymId global{gid, false};2135 CVSymbol sym = m_index->ReadSymbolRecord(global);2136 if (sym.kind() != S_UDT)2137 continue;2138 2139 UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));2140 bool is_typedef = true;2141 if (IsTagRecord(PdbTypeSymId{udt.Type, false}, m_index->tpi())) {2142 CVType cvt = m_index->tpi().getType(udt.Type);2143 llvm::StringRef name = CVTagRecord::create(cvt).name();2144 if (name == udt.Name)2145 is_typedef = false;2146 }2147 2148 if (is_typedef)2149 GetOrCreateTypedef(global);2150 }2151 2152 const size_t new_count = GetTypeList().GetSize();2153 2154 m_done_full_type_scan = true;2155 2156 return new_count - old_count;2157}2158 2159size_t2160SymbolFileNativePDB::ParseVariablesForCompileUnit(CompileUnit &comp_unit,2161 VariableList &variables) {2162 PdbSymUid sym_uid(comp_unit.GetID());2163 lldbassert(sym_uid.kind() == PdbSymUidKind::Compiland);2164 for (const uint32_t gid : m_index->globals().getGlobalsTable()) {2165 PdbGlobalSymId global{gid, false};2166 CVSymbol sym = m_index->ReadSymbolRecord(global);2167 // TODO: S_CONSTANT is not handled here to prevent a possible crash in2168 // lldb_private::npdb::MakeConstantLocationExpression when it's a record2169 // type (e.g. std::strong_ordering::equal). That function needs to be2170 // updated to handle this case when we add S_CONSTANT case here.2171 switch (sym.kind()) {2172 case SymbolKind::S_GDATA32:2173 case SymbolKind::S_LDATA32:2174 case SymbolKind::S_GTHREAD32:2175 case SymbolKind::S_LTHREAD32: {2176 if (VariableSP var = GetOrCreateGlobalVariable(global))2177 variables.AddVariable(var);2178 break;2179 }2180 default:2181 break;2182 }2183 }2184 return variables.GetSize();2185}2186 2187VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,2188 PdbCompilandSymId var_id,2189 bool is_param) {2190 ModuleSP module = GetObjectFile()->GetModule();2191 Block *block = GetOrCreateBlock(scope_id);2192 if (!block)2193 return nullptr;2194 2195 // Get function block.2196 Block *func_block = block;2197 while (func_block->GetParent()) {2198 func_block = func_block->GetParent();2199 }2200 2201 Address addr;2202 func_block->GetStartAddress(addr);2203 VariableInfo var_info =2204 GetVariableLocationInfo(*m_index, var_id, *func_block, module);2205 Function *func = func_block->CalculateSymbolContextFunction();2206 if (!func)2207 return nullptr;2208 // Use empty dwarf expr if optimized away so that it won't be filtered out2209 // when lookuping local variables in this scope.2210 if (!var_info.location.IsValid())2211 var_info.location = DWARFExpressionList(module, DWARFExpression(), nullptr);2212 var_info.location.SetFuncFileAddress(func->GetAddress().GetFileAddress());2213 CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);2214 CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);2215 TypeSP type_sp = GetOrCreateType(var_info.type);2216 if (!type_sp)2217 return nullptr;2218 std::string name = var_info.name.str();2219 Declaration decl;2220 SymbolFileTypeSP sftype =2221 std::make_shared<SymbolFileType>(*this, type_sp->GetID());2222 2223 is_param |= var_info.is_param;2224 ValueType var_scope =2225 is_param ? eValueTypeVariableArgument : eValueTypeVariableLocal;2226 bool external = false;2227 bool artificial = false;2228 bool location_is_constant_data = false;2229 bool static_member = false;2230 Variable::RangeList scope_ranges;2231 VariableSP var_sp = std::make_shared<Variable>(2232 toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope, block,2233 scope_ranges, &decl, var_info.location, external, artificial,2234 location_is_constant_data, static_member);2235 if (!is_param) {2236 auto ts_or_err = GetTypeSystemForLanguage(comp_unit_sp->GetLanguage());2237 if (auto err = ts_or_err.takeError())2238 return nullptr;2239 auto ts = *ts_or_err;2240 if (!ts)2241 return nullptr;2242 2243 ts->GetNativePDBParser()->GetOrCreateVariableDecl(scope_id, var_id);2244 }2245 m_local_variables[toOpaqueUid(var_id)] = var_sp;2246 return var_sp;2247}2248 2249VariableSP SymbolFileNativePDB::GetOrCreateLocalVariable(2250 PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param) {2251 auto iter = m_local_variables.find(toOpaqueUid(var_id));2252 if (iter != m_local_variables.end())2253 return iter->second;2254 2255 return CreateLocalVariable(scope_id, var_id, is_param);2256}2257 2258TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {2259 CVSymbol sym = m_index->ReadSymbolRecord(id);2260 lldbassert(sym.kind() == SymbolKind::S_UDT);2261 2262 UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));2263 2264 TypeSP target_type = GetOrCreateType(udt.Type);2265 2266 auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);2267 if (auto err = ts_or_err.takeError())2268 return nullptr;2269 auto ts = *ts_or_err;2270 if (!ts)2271 return nullptr;2272 2273 auto *typedef_decl = ts->GetNativePDBParser()->GetOrCreateTypedefDecl(id);2274 2275 CompilerType ct = target_type->GetForwardCompilerType();2276 if (auto *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()))2277 ct = clang->GetType(clang->getASTContext().getTypeDeclType(typedef_decl));2278 2279 Declaration decl;2280 return MakeType(toOpaqueUid(id), ConstString(udt.Name),2281 llvm::expectedToOptional(target_type->GetByteSize(nullptr)),2282 nullptr, target_type->GetID(),2283 lldb_private::Type::eEncodingIsTypedefUID, decl, ct,2284 lldb_private::Type::ResolveState::Forward);2285}2286 2287TypeSP SymbolFileNativePDB::GetOrCreateTypedef(PdbGlobalSymId id) {2288 auto iter = m_types.find(toOpaqueUid(id));2289 if (iter != m_types.end())2290 return iter->second;2291 2292 return CreateTypedef(id);2293}2294 2295size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) {2296 Block *block = GetOrCreateBlock(block_id);2297 if (!block)2298 return 0;2299 2300 size_t count = 0;2301 2302 CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);2303 CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);2304 uint32_t params_remaining = 0;2305 switch (sym.kind()) {2306 case S_GPROC32:2307 case S_LPROC32: {2308 ProcSym proc(static_cast<SymbolRecordKind>(sym.kind()));2309 cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym, proc));2310 CVType signature = m_index->tpi().getType(proc.FunctionType);2311 if (signature.kind() == LF_PROCEDURE) {2312 ProcedureRecord sig;2313 if (llvm::Error e = TypeDeserializer::deserializeAs<ProcedureRecord>(2314 signature, sig)) {2315 llvm::consumeError(std::move(e));2316 return 0;2317 }2318 params_remaining = sig.getParameterCount();2319 } else if (signature.kind() == LF_MFUNCTION) {2320 MemberFunctionRecord sig;2321 if (llvm::Error e = TypeDeserializer::deserializeAs<MemberFunctionRecord>(2322 signature, sig)) {2323 llvm::consumeError(std::move(e));2324 return 0;2325 }2326 params_remaining = sig.getParameterCount();2327 } else2328 return 0;2329 break;2330 }2331 case S_BLOCK32:2332 break;2333 case S_INLINESITE:2334 break;2335 default:2336 lldbassert(false && "Symbol is not a block!");2337 return 0;2338 }2339 2340 VariableListSP variables = block->GetBlockVariableList(false);2341 if (!variables) {2342 variables = std::make_shared<VariableList>();2343 block->SetVariableList(variables);2344 }2345 2346 CVSymbolArray syms = limitSymbolArrayToScope(2347 cii->m_debug_stream.getSymbolArray(), block_id.offset);2348 2349 // Skip the first record since it's a PROC32 or BLOCK32, and there's2350 // no point examining it since we know it's not a local variable.2351 syms.drop_front();2352 auto iter = syms.begin();2353 auto end = syms.end();2354 2355 while (iter != end) {2356 uint32_t record_offset = iter.offset();2357 CVSymbol variable_cvs = *iter;2358 PdbCompilandSymId child_sym_id(block_id.modi, record_offset);2359 ++iter;2360 2361 // If this is a block or inline site, recurse into its children and then2362 // skip it.2363 if (variable_cvs.kind() == S_BLOCK32 ||2364 variable_cvs.kind() == S_INLINESITE) {2365 uint32_t block_end = getScopeEndOffset(variable_cvs);2366 count += ParseVariablesForBlock(child_sym_id);2367 iter = syms.at(block_end);2368 continue;2369 }2370 2371 bool is_param = params_remaining > 0;2372 VariableSP variable;2373 switch (variable_cvs.kind()) {2374 case S_REGREL32:2375 case S_REGISTER:2376 case S_LOCAL:2377 variable = GetOrCreateLocalVariable(block_id, child_sym_id, is_param);2378 if (is_param)2379 --params_remaining;2380 if (variable)2381 variables->AddVariableIfUnique(variable);2382 break;2383 default:2384 break;2385 }2386 }2387 2388 // Pass false for set_children, since we call this recursively so that the2389 // children will call this for themselves.2390 block->SetDidParseVariables(true, false);2391 2392 return count;2393}2394 2395size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) {2396 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());2397 lldbassert(sc.function || sc.comp_unit);2398 2399 VariableListSP variables;2400 if (sc.block) {2401 PdbSymUid block_id(sc.block->GetID());2402 2403 size_t count = ParseVariablesForBlock(block_id.asCompilandSym());2404 return count;2405 }2406 2407 if (sc.function) {2408 PdbSymUid block_id(sc.function->GetID());2409 2410 size_t count = ParseVariablesForBlock(block_id.asCompilandSym());2411 return count;2412 }2413 2414 if (sc.comp_unit) {2415 variables = sc.comp_unit->GetVariableList(false);2416 if (!variables) {2417 variables = std::make_shared<VariableList>();2418 sc.comp_unit->SetVariableList(variables);2419 }2420 return ParseVariablesForCompileUnit(*sc.comp_unit, *variables);2421 }2422 2423 llvm_unreachable("Unreachable!");2424}2425 2426CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) {2427 auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);2428 if (auto err = ts_or_err.takeError())2429 return CompilerDecl();2430 auto ts = *ts_or_err;2431 if (!ts)2432 return {};2433 2434 if (auto decl = ts->GetNativePDBParser()->GetOrCreateDeclForUid(uid))2435 return *decl;2436 return CompilerDecl();2437}2438 2439CompilerDeclContext2440SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) {2441 auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);2442 if (auto err = ts_or_err.takeError())2443 return {};2444 auto ts = *ts_or_err;2445 if (!ts)2446 return {};2447 2448 PdbAstBuilder *ast_builder = ts->GetNativePDBParser();2449 clang::DeclContext *context =2450 ast_builder->GetOrCreateDeclContextForUid(PdbSymUid(uid));2451 if (!context)2452 return {};2453 2454 return ast_builder->ToCompilerDeclContext(*context);2455}2456 2457CompilerDeclContext2458SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {2459 auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);2460 if (auto err = ts_or_err.takeError())2461 return CompilerDeclContext();2462 auto ts = *ts_or_err;2463 if (!ts)2464 return {};2465 2466 PdbAstBuilder *ast_builder = ts->GetNativePDBParser();2467 clang::DeclContext *context = ast_builder->GetParentDeclContext(PdbSymUid(uid));2468 if (!context)2469 return CompilerDeclContext();2470 return ast_builder->ToCompilerDeclContext(*context);2471}2472 2473Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) {2474 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());2475 auto iter = m_types.find(type_uid);2476 // lldb should not be passing us non-sensical type uids. the only way it2477 // could have a type uid in the first place is if we handed it out, in which2478 // case we should know about the type. However, that doesn't mean we've2479 // instantiated it yet. We can vend out a UID for a future type. So if the2480 // type doesn't exist, let's instantiate it now.2481 if (iter != m_types.end())2482 return &*iter->second;2483 2484 PdbSymUid uid(type_uid);2485 lldbassert(uid.kind() == PdbSymUidKind::Type);2486 PdbTypeSymId type_id = uid.asTypeSym();2487 if (type_id.index.isNoneType())2488 return nullptr;2489 2490 TypeSP type_sp = CreateAndCacheType(type_id);2491 if (!type_sp)2492 return nullptr;2493 return &*type_sp;2494}2495 2496std::optional<SymbolFile::ArrayInfo>2497SymbolFileNativePDB::GetDynamicArrayInfoForUID(2498 lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {2499 return std::nullopt;2500}2501 2502bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) {2503 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());2504 auto clang_type_system = compiler_type.GetTypeSystem<TypeSystemClang>();2505 if (!clang_type_system)2506 return false;2507 2508 PdbAstBuilder *ast_builder =2509 static_cast<PdbAstBuilder *>(clang_type_system->GetNativePDBParser());2510 if (ast_builder &&2511 ast_builder->GetClangASTImporter().CanImport(compiler_type))2512 return ast_builder->GetClangASTImporter().CompleteType(compiler_type);2513 clang::QualType qt =2514 clang::QualType::getFromOpaquePtr(compiler_type.GetOpaqueQualType());2515 2516 return ast_builder->CompleteType(qt);2517}2518 2519void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,2520 TypeClass type_mask,2521 lldb_private::TypeList &type_list) {}2522 2523CompilerDeclContext2524SymbolFileNativePDB::FindNamespace(ConstString name,2525 const CompilerDeclContext &parent_decl_ctx,2526 bool /* only_root_namespaces */) {2527 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());2528 auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);2529 if (auto err = ts_or_err.takeError())2530 return {};2531 auto ts = *ts_or_err;2532 if (!ts)2533 return {};2534 auto *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get());2535 if (!clang)2536 return {};2537 2538 PdbAstBuilder *ast_builder = clang->GetNativePDBParser();2539 if (!ast_builder)2540 return {};2541 2542 clang::DeclContext *decl_context = nullptr;2543 if (parent_decl_ctx)2544 decl_context = static_cast<clang::DeclContext *>(2545 parent_decl_ctx.GetOpaqueDeclContext());2546 2547 auto *namespace_decl =2548 ast_builder->FindNamespaceDecl(decl_context, name.GetStringRef());2549 if (!namespace_decl)2550 return CompilerDeclContext();2551 2552 return clang->CreateDeclContext(namespace_decl);2553}2554 2555llvm::Expected<lldb::TypeSystemSP>2556SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {2557 auto type_system_or_err =2558 m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language);2559 if (type_system_or_err)2560 if (auto ts = *type_system_or_err)2561 ts->SetSymbolFile(this);2562 return type_system_or_err;2563}2564 2565uint64_t SymbolFileNativePDB::GetDebugInfoSize(bool load_all_debug_info) {2566 // PDB files are a separate file that contains all debug info.2567 return m_index->pdb().getFileSize();2568}2569 2570void SymbolFileNativePDB::BuildParentMap() {2571 LazyRandomTypeCollection &types = m_index->tpi().typeCollection();2572 2573 llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full;2574 llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward;2575 2576 struct RecordIndices {2577 TypeIndex forward;2578 TypeIndex full;2579 };2580 2581 llvm::StringMap<RecordIndices> record_indices;2582 2583 for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {2584 CVType type = types.getType(*ti);2585 if (!IsTagRecord(type))2586 continue;2587 2588 CVTagRecord tag = CVTagRecord::create(type);2589 2590 RecordIndices &indices = record_indices[tag.asTag().getUniqueName()];2591 if (tag.asTag().isForwardRef()) {2592 indices.forward = *ti;2593 } else {2594 indices.full = *ti;2595 2596 auto base_name = MSVCUndecoratedNameParser::DropScope(tag.name());2597 m_type_base_names.Append(ConstString(base_name), ti->getIndex());2598 }2599 2600 if (indices.full != TypeIndex::None() &&2601 indices.forward != TypeIndex::None()) {2602 forward_to_full[indices.forward] = indices.full;2603 full_to_forward[indices.full] = indices.forward;2604 }2605 2606 // We're looking for LF_NESTTYPE records in the field list, so ignore2607 // forward references (no field list), and anything without a nested class2608 // (since there won't be any LF_NESTTYPE records).2609 if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass())2610 continue;2611 2612 struct ProcessTpiStream : public TypeVisitorCallbacks {2613 ProcessTpiStream(PdbIndex &index, TypeIndex parent,2614 const CVTagRecord &parent_cvt,2615 llvm::DenseMap<TypeIndex, TypeIndex> &parents)2616 : index(index), parents(parents), parent(parent),2617 parent_cvt(parent_cvt) {}2618 2619 PdbIndex &index;2620 llvm::DenseMap<TypeIndex, TypeIndex> &parents;2621 2622 unsigned unnamed_type_index = 1;2623 TypeIndex parent;2624 const CVTagRecord &parent_cvt;2625 2626 llvm::Error visitKnownMember(CVMemberRecord &CVR,2627 NestedTypeRecord &Record) override {2628 std::string unnamed_type_name;2629 if (Record.Name.empty()) {2630 unnamed_type_name =2631 llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str();2632 Record.Name = unnamed_type_name;2633 ++unnamed_type_index;2634 }2635 std::optional<CVTagRecord> tag =2636 GetNestedTagDefinition(Record, parent_cvt, index.tpi());2637 if (!tag)2638 return llvm::ErrorSuccess();2639 2640 parents[Record.Type] = parent;2641 return llvm::ErrorSuccess();2642 }2643 };2644 2645 CVType field_list_cvt = m_index->tpi().getType(tag.asTag().FieldList);2646 ProcessTpiStream process(*m_index, *ti, tag, m_parent_types);2647 FieldListRecord field_list;2648 if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(2649 field_list_cvt, field_list))2650 llvm::consumeError(std::move(error));2651 if (llvm::Error error = visitMemberRecordStream(field_list.Data, process))2652 llvm::consumeError(std::move(error));2653 }2654 2655 // After calling Append(), the type-name map needs to be sorted again to be2656 // able to look up a type by its name.2657 m_type_base_names.Sort(std::less<uint32_t>());2658 2659 // Now that we know the forward -> full mapping of all type indices, we can2660 // re-write all the indices. At the end of this process, we want a mapping2661 // consisting of fwd -> full and full -> full for all child -> parent indices.2662 // We can re-write the values in place, but for the keys, we must save them2663 // off so that we don't modify the map in place while also iterating it.2664 std::vector<TypeIndex> full_keys;2665 std::vector<TypeIndex> fwd_keys;2666 for (auto &entry : m_parent_types) {2667 TypeIndex key = entry.first;2668 TypeIndex value = entry.second;2669 2670 auto iter = forward_to_full.find(value);2671 if (iter != forward_to_full.end())2672 entry.second = iter->second;2673 2674 iter = forward_to_full.find(key);2675 if (iter != forward_to_full.end())2676 fwd_keys.push_back(key);2677 else2678 full_keys.push_back(key);2679 }2680 for (TypeIndex fwd : fwd_keys) {2681 TypeIndex full = forward_to_full[fwd];2682 TypeIndex parent_idx = m_parent_types[fwd];2683 m_parent_types[full] = parent_idx;2684 }2685 for (TypeIndex full : full_keys) {2686 TypeIndex fwd = full_to_forward[full];2687 m_parent_types[fwd] = m_parent_types[full];2688 }2689}2690 2691std::optional<PdbCompilandSymId>2692SymbolFileNativePDB::FindSymbolScope(PdbCompilandSymId id) {2693 CVSymbol sym = m_index->ReadSymbolRecord(id);2694 if (symbolOpensScope(sym.kind())) {2695 // If this exact symbol opens a scope, we can just directly access its2696 // parent.2697 id.offset = getScopeParentOffset(sym);2698 // Global symbols have parent offset of 0. Return std::nullopt to indicate2699 // this.2700 if (id.offset == 0)2701 return std::nullopt;2702 return id;2703 }2704 2705 // Otherwise we need to start at the beginning and iterate forward until we2706 // reach (or pass) this particular symbol2707 CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(id.modi);2708 const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();2709 2710 auto begin = syms.begin();2711 auto end = syms.at(id.offset);2712 std::vector<PdbCompilandSymId> scope_stack;2713 2714 while (begin != end) {2715 if (begin.offset() > id.offset) {2716 // We passed it. We couldn't even find this symbol record.2717 lldbassert(false && "Invalid compiland symbol id!");2718 return std::nullopt;2719 }2720 2721 // We haven't found the symbol yet. Check if we need to open or close the2722 // scope stack.2723 if (symbolOpensScope(begin->kind())) {2724 // We can use the end offset of the scope to determine whether or not2725 // we can just outright skip this entire scope.2726 uint32_t scope_end = getScopeEndOffset(*begin);2727 if (scope_end < id.offset) {2728 begin = syms.at(scope_end);2729 } else {2730 // The symbol we're looking for is somewhere in this scope.2731 scope_stack.emplace_back(id.modi, begin.offset());2732 }2733 } else if (symbolEndsScope(begin->kind())) {2734 scope_stack.pop_back();2735 }2736 ++begin;2737 }2738 if (scope_stack.empty())2739 return std::nullopt;2740 // We have a match! Return the top of the stack2741 return scope_stack.back();2742}2743 2744std::optional<llvm::codeview::TypeIndex>2745SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) {2746 auto parent_iter = m_parent_types.find(ti);2747 if (parent_iter == m_parent_types.end())2748 return std::nullopt;2749 return parent_iter->second;2750}2751 2752std::vector<CompilerContext>2753SymbolFileNativePDB::GetContextForType(TypeIndex ti) {2754 CVType type = m_index->tpi().getType(ti);2755 if (!IsTagRecord(type))2756 return {};2757 2758 CVTagRecord tag = CVTagRecord::create(type);2759 2760 std::optional<Type::ParsedName> parsed_name =2761 Type::GetTypeScopeAndBasename(tag.name());2762 if (!parsed_name)2763 return {{tag.contextKind(), ConstString(tag.name())}};2764 2765 std::vector<CompilerContext> ctx;2766 // assume everything is a namespace at first2767 for (llvm::StringRef scope : parsed_name->scope) {2768 ctx.emplace_back(CompilerContextKind::Namespace, ConstString(scope));2769 }2770 // we know the kind of our own type2771 ctx.emplace_back(tag.contextKind(), ConstString(parsed_name->basename));2772 2773 // try to find the kind of parents2774 for (auto &el : llvm::reverse(llvm::drop_end(ctx))) {2775 std::optional<TypeIndex> parent = GetParentType(ti);2776 if (!parent)2777 break;2778 2779 ti = *parent;2780 type = m_index->tpi().getType(ti);2781 switch (type.kind()) {2782 case LF_CLASS:2783 case LF_STRUCTURE:2784 case LF_INTERFACE:2785 el.kind = CompilerContextKind::ClassOrStruct;2786 continue;2787 case LF_UNION:2788 el.kind = CompilerContextKind::Union;2789 continue;2790 case LF_ENUM:2791 el.kind = CompilerContextKind::Enum;2792 continue;2793 default:2794 break;2795 }2796 break;2797 }2798 return ctx;2799}2800 2801std::optional<llvm::StringRef>2802SymbolFileNativePDB::FindMangledFunctionName(PdbCompilandSymId func_id) {2803 const CompilandIndexItem *cci =2804 m_index->compilands().GetCompiland(func_id.modi);2805 if (!cci)2806 return std::nullopt;2807 2808 CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset);2809 if (sym_record.kind() != S_LPROC32 && sym_record.kind() != S_GPROC32)2810 return std::nullopt;2811 2812 ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));2813 cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc));2814 2815 return FindMangledSymbol(SegmentOffset(proc.Segment, proc.CodeOffset),2816 proc.FunctionType);2817}2818 2819std::optional<llvm::StringRef>2820SymbolFileNativePDB::FindMangledSymbol(SegmentOffset so,2821 TypeIndex function_type) {2822 auto symbol = m_index->publics().findByAddress(m_index->symrecords(),2823 so.segment, so.offset);2824 if (!symbol)2825 return std::nullopt;2826 2827 llvm::StringRef name = symbol->first.Name;2828 // For functions, we might need to strip the mangled name. See2829 // StripMangledFunctionName for more info.2830 if (!function_type.isNoneType() &&2831 (symbol->first.Flags & PublicSymFlags::Function) != PublicSymFlags::None)2832 name = StripMangledFunctionName(name, function_type);2833 2834 return name;2835}2836 2837llvm::StringRef2838SymbolFileNativePDB::StripMangledFunctionName(const llvm::StringRef mangled,2839 PdbTypeSymId func_ty) {2840 // "In non-64 bit environments" (on x86 in pactice), __cdecl functions get2841 // prefixed with an underscore. For compilers using LLVM, this happens in LLVM2842 // (as opposed to the compiler frontend). Because of this, DWARF doesn't2843 // contain the "full" mangled name in DW_AT_linkage_name for these functions.2844 // We strip the mangling here for compatibility with DWARF. See2845 // llvm.org/pr161676 and2846 // https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names#FormatC2847 2848 if (!mangled.starts_with('_') ||2849 m_index->dbi().getMachineType() != PDB_Machine::x86)2850 return mangled;2851 2852 CVType cvt = m_index->tpi().getType(func_ty.index);2853 PDB_CallingConv cc = PDB_CallingConv::NearC;2854 if (cvt.kind() == LF_PROCEDURE) {2855 ProcedureRecord proc;2856 if (llvm::Error error =2857 TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, proc))2858 llvm::consumeError(std::move(error));2859 cc = proc.CallConv;2860 } else if (cvt.kind() == LF_MFUNCTION) {2861 MemberFunctionRecord mfunc;2862 if (llvm::Error error =2863 TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfunc))2864 llvm::consumeError(std::move(error));2865 cc = mfunc.CallConv;2866 } else {2867 LLDB_LOG(GetLog(LLDBLog::Symbols), "Unexpected function type, got {0}",2868 cvt.kind());2869 return mangled;2870 }2871 2872 if (cc == PDB_CallingConv::NearC || cc == PDB_CallingConv::FarC)2873 return mangled.drop_front();2874 2875 return mangled;2876}2877 2878void SymbolFileNativePDB::CacheUdtDeclarations() {2879 for (CVType cvt : m_index->ipi().typeArray()) {2880 switch (cvt.kind()) {2881 case LF_UDT_SRC_LINE: {2882 UdtSourceLineRecord udt_src;2883 llvm::cantFail(TypeDeserializer::deserializeAs(cvt, udt_src));2884 m_udt_declarations.try_emplace(2885 udt_src.UDT, UdtDeclaration{/*FileNameIndex=*/udt_src.SourceFile,2886 /*IsIpiIndex=*/true,2887 /*Line=*/udt_src.LineNumber});2888 } break;2889 case LF_UDT_MOD_SRC_LINE: {2890 UdtModSourceLineRecord udt_mod_src;2891 llvm::cantFail(TypeDeserializer::deserializeAs(cvt, udt_mod_src));2892 // Some types might be contributed by multiple modules. We assume that2893 // they all point to the same file and line because we can only provide2894 // one location.2895 m_udt_declarations.try_emplace(2896 udt_mod_src.UDT,2897 UdtDeclaration{/*FileNameIndex=*/udt_mod_src.SourceFile,2898 /*IsIpiIndex=*/false,2899 /*Line=*/udt_mod_src.LineNumber});2900 } break;2901 default:2902 break;2903 }2904 }2905}2906 2907llvm::Expected<Declaration>2908SymbolFileNativePDB::ResolveUdtDeclaration(PdbTypeSymId type_id) {2909 std::call_once(m_cached_udt_declarations, [this] { CacheUdtDeclarations(); });2910 2911 auto it = m_udt_declarations.find(type_id.index);2912 if (it == m_udt_declarations.end())2913 return llvm::createStringError("No UDT declaration found");2914 2915 llvm::StringRef file_name;2916 if (it->second.IsIpiIndex) {2917 CVType cvt = m_index->ipi().getType(it->second.FileNameIndex);2918 if (cvt.kind() != LF_STRING_ID)2919 return llvm::createStringError("File name was not a LF_STRING_ID");2920 2921 StringIdRecord sid;2922 llvm::cantFail(TypeDeserializer::deserializeAs(cvt, sid));2923 file_name = sid.String;2924 } else {2925 // The file name index is an index into the string table2926 auto string_table = m_index->pdb().getStringTable();2927 if (!string_table)2928 return string_table.takeError();2929 2930 llvm::Expected<llvm::StringRef> string =2931 string_table->getStringTable().getString(2932 it->second.FileNameIndex.getIndex());2933 if (!string)2934 return string.takeError();2935 file_name = *string;2936 }2937 2938 // rustc sets the filename to "<unknown>" for some files2939 if (file_name == "\\<unknown>")2940 return Declaration();2941 2942 return Declaration(FileSpec(file_name), it->second.Line);2943}2944