diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2022-01-27 22:06:42 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2022-01-27 22:06:42 +0000 |
| commit | 6f8fc217eaa12bf657be1c6468ed9938d10168b3 (patch) | |
| tree | a1fd89b864d9b93e2ad68fe1dcf7afee2e3c8d76 /lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp | |
| parent | 77fc4c146f0870ffb09c1afb823ccbe742c5e6ff (diff) | |
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp')
| -rw-r--r-- | lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp | 521 |
1 files changed, 429 insertions, 92 deletions
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index e859b1d5a86c..a035a791f868 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -330,31 +330,65 @@ uint32_t SymbolFileNativePDB::CalculateNumCompileUnits() { Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) { CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi); CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset); + CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii); + lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id); + BlockSP child_block = std::make_shared<Block>(opaque_block_uid); - if (sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32) { - // This is a function. It must be global. Creating the Function entry for - // it automatically creates a block for it. - CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii); - return GetOrCreateFunction(block_id, *comp_unit)->GetBlock(false); + switch (sym.kind()) { + case S_GPROC32: + case S_LPROC32: { + // This is a function. It must be global. Creating the Function entry + // for it automatically creates a block for it. + FunctionSP func = GetOrCreateFunction(block_id, *comp_unit); + Block &block = func->GetBlock(false); + if (block.GetNumRanges() == 0) + block.AddRange(Block::Range(0, func->GetAddressRange().GetByteSize())); + return block; + } + case S_BLOCK32: { + // This is a block. Its parent is either a function or another block. In + // either case, its parent can be viewed as a block (e.g. a function + // contains 1 big block. So just get the parent block and add this block + // to it. + BlockSym block(static_cast<SymbolRecordKind>(sym.kind())); + cantFail(SymbolDeserializer::deserializeAs<BlockSym>(sym, block)); + lldbassert(block.Parent != 0); + PdbCompilandSymId parent_id(block_id.modi, block.Parent); + Block &parent_block = GetOrCreateBlock(parent_id); + parent_block.AddChild(child_block); + m_ast->GetOrCreateBlockDecl(block_id); + m_blocks.insert({opaque_block_uid, child_block}); + break; } + case S_INLINESITE: { + // This ensures line table is parsed first so we have inline sites info. + comp_unit->GetLineTable(); - lldbassert(sym.kind() == S_BLOCK32); + std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid]; + Block &parent_block = GetOrCreateBlock(inline_site->parent_id); + parent_block.AddChild(child_block); - // This is a block. Its parent is either a function or another block. In - // either case, its parent can be viewed as a block (e.g. a function contains - // 1 big block. So just get the parent block and add this block to it. - BlockSym block(static_cast<SymbolRecordKind>(sym.kind())); - cantFail(SymbolDeserializer::deserializeAs<BlockSym>(sym, block)); - lldbassert(block.Parent != 0); - PdbCompilandSymId parent_id(block_id.modi, block.Parent); - Block &parent_block = GetOrCreateBlock(parent_id); - lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id); - BlockSP child_block = std::make_shared<Block>(opaque_block_uid); - parent_block.AddChild(child_block); + // Copy ranges from InlineSite to Block. + for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) { + auto *entry = inline_site->ranges.GetEntryAtIndex(i); + child_block->AddRange( + Block::Range(entry->GetRangeBase(), entry->GetByteSize())); + } + child_block->FinalizeRanges(); - m_ast->GetOrCreateBlockDecl(block_id); + // Get the inlined function callsite info. + Declaration &decl = inline_site->inline_function_info->GetDeclaration(); + Declaration &callsite = inline_site->inline_function_info->GetCallSite(); + child_block->SetInlinedFunctionInfo( + inline_site->inline_function_info->GetName().GetCString(), nullptr, + &decl, &callsite); + m_blocks.insert({opaque_block_uid, child_block}); + break; + } + default: + lldbassert(false && "Symbol is not a block!"); + } - m_blocks.insert({opaque_block_uid, child_block}); return *child_block; } @@ -971,16 +1005,22 @@ uint32_t SymbolFileNativePDB::ResolveSymbolContext( continue; if (type == PDB_SymType::Function) { sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get(); - sc.block = sc.GetFunctionBlock(); + Block &block = sc.function->GetBlock(true); + addr_t func_base = + sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); + addr_t offset = file_addr - func_base; + sc.block = block.FindInnermostBlockByOffset(offset); } if (type == PDB_SymType::Block) { sc.block = &GetOrCreateBlock(csid); sc.function = sc.block->CalculateSymbolContextFunction(); } - resolved_flags |= eSymbolContextFunction; - resolved_flags |= eSymbolContextBlock; - break; + if (sc.function) + resolved_flags |= eSymbolContextFunction; + if (sc.block) + resolved_flags |= eSymbolContextBlock; + break; } } @@ -998,43 +1038,24 @@ uint32_t SymbolFileNativePDB::ResolveSymbolContext( uint32_t SymbolFileNativePDB::ResolveSymbolContext( const SourceLocationSpec &src_location_spec, lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) { - return 0; -} - -static void AppendLineEntryToSequence(LineTable &table, LineSequence &sequence, - const CompilandIndexItem &cci, - lldb::addr_t base_addr, - uint32_t file_number, - const LineFragmentHeader &block, - const LineNumberEntry &cur) { - LineInfo cur_info(cur.Flags); - - if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto()) - return; - - uint64_t addr = base_addr + cur.Offset; - - bool is_statement = cur_info.isStatement(); - bool is_prologue = IsFunctionPrologue(cci, addr); - bool is_epilogue = IsFunctionEpilogue(cci, addr); - - uint32_t lno = cur_info.getStartLine(); - - table.AppendLineEntryToSequence(&sequence, addr, lno, 0, file_number, - is_statement, false, is_prologue, is_epilogue, - false); -} + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + const uint32_t prev_size = sc_list.GetSize(); + if (resolve_scope & eSymbolContextCompUnit) { + for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus; + ++cu_idx) { + CompileUnit *cu = ParseCompileUnitAtIndex(cu_idx).get(); + if (!cu) + continue; -static void TerminateLineSequence(LineTable &table, - const LineFragmentHeader &block, - lldb::addr_t base_addr, uint32_t file_number, - uint32_t last_line, - std::unique_ptr<LineSequence> seq) { - // The end is always a terminal entry, so insert it regardless. - table.AppendLineEntryToSequence(seq.get(), base_addr + block.CodeSize, - last_line, 0, file_number, false, false, - false, false, true); - table.InsertSequence(seq.get()); + bool file_spec_matches_cu_file_spec = FileSpec::Match( + src_location_spec.GetFileSpec(), cu->GetPrimaryFile()); + if (file_spec_matches_cu_file_spec) { + cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list); + break; + } + } + } + return sc_list.GetSize() - prev_size; } bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) { @@ -1045,16 +1066,21 @@ bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); PdbSymUid cu_id(comp_unit.GetID()); lldbassert(cu_id.kind() == PdbSymUidKind::Compiland); - CompilandIndexItem *cci = - m_index->compilands().GetCompiland(cu_id.asCompiland().modi); - lldbassert(cci); - auto line_table = std::make_unique<LineTable>(&comp_unit); + uint16_t modi = cu_id.asCompiland().modi; + CompilandIndexItem *cii = m_index->compilands().GetCompiland(modi); + lldbassert(cii); + + // Parse DEBUG_S_LINES subsections first, then parse all S_INLINESITE records + // in this CU. Add line entries into the set first so that if there are line + // entries with same addres, the later is always more accurate than the + // former. + std::set<LineTable::Entry, LineTableEntryComparator> line_set; // This is basically a copy of the .debug$S subsections from all original COFF // object files merged together with address relocations applied. We are // looking for all DEBUG_S_LINES subsections. for (const DebugSubsectionRecord &dssr : - cci->m_debug_stream.getSubsectionsArray()) { + cii->m_debug_stream.getSubsectionsArray()) { if (dssr.kind() != DebugSubsectionKind::Lines) continue; @@ -1069,41 +1095,110 @@ bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) { uint64_t virtual_addr = m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset); - const auto &checksums = cci->m_strings.checksums().getArray(); - const auto &strings = cci->m_strings.strings(); for (const LineColumnEntry &group : lines) { - // Indices in this structure are actually offsets of records in the - // DEBUG_S_FILECHECKSUMS subsection. Those entries then have an index - // into the global PDB string table. - auto iter = checksums.at(group.NameIndex); - if (iter == checksums.end()) + llvm::Expected<uint32_t> file_index_or_err = + GetFileIndex(*cii, group.NameIndex); + if (!file_index_or_err) continue; + uint32_t file_index = file_index_or_err.get(); + lldbassert(!group.LineNumbers.empty()); + CompilandIndexItem::GlobalLineTable::Entry line_entry( + LLDB_INVALID_ADDRESS, 0); + for (const LineNumberEntry &entry : group.LineNumbers) { + LineInfo cur_info(entry.Flags); - llvm::Expected<llvm::StringRef> efn = - strings.getString(iter->FileNameOffset); - if (!efn) { - llvm::consumeError(efn.takeError()); - continue; - } + if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto()) + continue; - // LLDB wants the index of the file in the list of support files. - auto fn_iter = llvm::find(cci->m_file_list, *efn); - lldbassert(fn_iter != cci->m_file_list.end()); - uint32_t file_index = std::distance(cci->m_file_list.begin(), fn_iter); + uint64_t addr = virtual_addr + entry.Offset; - std::unique_ptr<LineSequence> sequence( - line_table->CreateLineSequenceContainer()); - lldbassert(!group.LineNumbers.empty()); + bool is_statement = cur_info.isStatement(); + bool is_prologue = IsFunctionPrologue(*cii, addr); + bool is_epilogue = IsFunctionEpilogue(*cii, addr); - for (const LineNumberEntry &entry : group.LineNumbers) { - AppendLineEntryToSequence(*line_table, *sequence, *cci, virtual_addr, - file_index, *lfh, entry); + uint32_t lno = cur_info.getStartLine(); + + line_set.emplace(addr, lno, 0, file_index, is_statement, false, + is_prologue, is_epilogue, false); + + if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) { + line_entry.SetRangeEnd(addr); + cii->m_global_line_table.Append(line_entry); + } + line_entry.SetRangeBase(addr); + line_entry.data = {file_index, lno}; } LineInfo last_line(group.LineNumbers.back().Flags); - TerminateLineSequence(*line_table, *lfh, virtual_addr, file_index, - last_line.getEndLine(), std::move(sequence)); + line_set.emplace(virtual_addr + lfh->CodeSize, last_line.getEndLine(), 0, + file_index, false, false, false, false, true); + + if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) { + line_entry.SetRangeEnd(virtual_addr + lfh->CodeSize); + cii->m_global_line_table.Append(line_entry); + } + } + } + + cii->m_global_line_table.Sort(); + + // Parse all S_INLINESITE in this CU. + const CVSymbolArray &syms = cii->m_debug_stream.getSymbolArray(); + for (auto iter = syms.begin(); iter != syms.end();) { + if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32) { + ++iter; + continue; } + + uint32_t record_offset = iter.offset(); + CVSymbol func_record = + cii->m_debug_stream.readSymbolAtOffset(record_offset); + SegmentOffsetLength sol = GetSegmentOffsetAndLength(func_record); + addr_t file_vm_addr = m_index->MakeVirtualAddress(sol.so); + AddressRange func_range(file_vm_addr, sol.length, + comp_unit.GetModule()->GetSectionList()); + Address func_base = func_range.GetBaseAddress(); + PdbCompilandSymId func_id{modi, record_offset}; + + // Iterate all S_INLINESITEs in the function. + auto parse_inline_sites = [&](SymbolKind kind, PdbCompilandSymId id) { + if (kind != S_INLINESITE) + return false; + + ParseInlineSite(id, func_base); + + for (const auto &line_entry : + m_inline_sites[toOpaqueUid(id)]->line_entries) { + // If line_entry is not terminal entry, remove previous line entry at + // the same address and insert new one. Terminal entry inside an inline + // site might not be terminal entry for its parent. + if (!line_entry.is_terminal_entry) + line_set.erase(line_entry); + line_set.insert(line_entry); + } + // No longer useful after adding to line_set. + m_inline_sites[toOpaqueUid(id)]->line_entries.clear(); + return true; + }; + ParseSymbolArrayInScope(func_id, parse_inline_sites); + // Jump to the end of the function record. + iter = syms.at(getScopeEndOffset(func_record)); + } + + cii->m_global_line_table.Clear(); + + // Add line entries in line_set to line_table. + auto line_table = std::make_unique<LineTable>(&comp_unit); + std::unique_ptr<LineSequence> sequence( + line_table->CreateLineSequenceContainer()); + for (const auto &line_entry : line_set) { + line_table->AppendLineEntryToSequence( + sequence.get(), line_entry.file_addr, line_entry.line, + line_entry.column, line_entry.file_idx, + line_entry.is_start_of_statement, line_entry.is_start_of_basic_block, + line_entry.is_prologue_end, line_entry.is_epilogue_begin, + line_entry.is_terminal_entry); } + line_table->InsertSequence(sequence.get()); if (line_table->GetSize() == 0) return false; @@ -1117,6 +1212,33 @@ bool SymbolFileNativePDB::ParseDebugMacros(CompileUnit &comp_unit) { return false; } +llvm::Expected<uint32_t> +SymbolFileNativePDB::GetFileIndex(const CompilandIndexItem &cii, + uint32_t file_id) { + auto index_iter = m_file_indexes.find(file_id); + if (index_iter != m_file_indexes.end()) + return index_iter->getSecond(); + const auto &checksums = cii.m_strings.checksums().getArray(); + const auto &strings = cii.m_strings.strings(); + // Indices in this structure are actually offsets of records in the + // DEBUG_S_FILECHECKSUMS subsection. Those entries then have an index + // into the global PDB string table. + auto iter = checksums.at(file_id); + if (iter == checksums.end()) + return llvm::make_error<RawError>(raw_error_code::no_entry); + + llvm::Expected<llvm::StringRef> efn = strings.getString(iter->FileNameOffset); + if (!efn) { + return efn.takeError(); + } + + // LLDB wants the index of the file in the list of support files. + auto fn_iter = llvm::find(cii.m_file_list, *efn); + lldbassert(fn_iter != cii.m_file_list.end()); + m_file_indexes[file_id] = std::distance(cii.m_file_list.begin(), fn_iter); + return m_file_indexes[file_id]; +} + bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit, FileSpecList &support_files) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); @@ -1141,11 +1263,223 @@ bool SymbolFileNativePDB::ParseImportedModules( return false; } +void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id, + Address func_addr) { + lldb::user_id_t opaque_uid = toOpaqueUid(id); + if (m_inline_sites.find(opaque_uid) != m_inline_sites.end()) + return; + + addr_t func_base = func_addr.GetFileAddress(); + CompilandIndexItem *cii = m_index->compilands().GetCompiland(id.modi); + CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(id.offset); + CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii); + + InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind())); + cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site)); + PdbCompilandSymId parent_id(id.modi, inline_site.Parent); + + std::shared_ptr<InlineSite> inline_site_sp = + std::make_shared<InlineSite>(parent_id); + + // Get the inlined function declaration info. + auto iter = cii->m_inline_map.find(inline_site.Inlinee); + if (iter == cii->m_inline_map.end()) + return; + InlineeSourceLine inlinee_line = iter->second; + + const FileSpecList &files = comp_unit->GetSupportFiles(); + FileSpec decl_file; + llvm::Expected<uint32_t> file_index_or_err = + GetFileIndex(*cii, inlinee_line.Header->FileID); + if (!file_index_or_err) + return; + uint32_t decl_file_idx = file_index_or_err.get(); + decl_file = files.GetFileSpecAtIndex(decl_file_idx); + uint32_t decl_line = inlinee_line.Header->SourceLineNum; + std::unique_ptr<Declaration> decl_up = + std::make_unique<Declaration>(decl_file, decl_line); + + // Parse range and line info. + uint32_t code_offset = 0; + int32_t line_offset = 0; + bool has_base = false; + bool is_new_line_offset = false; + + bool is_start_of_statement = false; + // The first instruction is the prologue end. + bool is_prologue_end = true; + + auto change_code_offset = [&](uint32_t code_delta) { + if (has_base) { + inline_site_sp->ranges.Append(RangeSourceLineVector::Entry( + code_offset, code_delta, decl_line + line_offset)); + is_prologue_end = false; + is_start_of_statement = false; + } else { + is_start_of_statement = true; + } + has_base = true; + code_offset += code_delta; + + if (is_new_line_offset) { + LineTable::Entry line_entry(func_base + code_offset, + decl_line + line_offset, 0, decl_file_idx, + true, false, is_prologue_end, false, false); + inline_site_sp->line_entries.push_back(line_entry); + is_new_line_offset = false; + } + }; + auto change_code_length = [&](uint32_t length) { + inline_site_sp->ranges.Append(RangeSourceLineVector::Entry( + code_offset, length, decl_line + line_offset)); + has_base = false; + + LineTable::Entry end_line_entry(func_base + code_offset + length, + decl_line + line_offset, 0, decl_file_idx, + false, false, false, false, true); + inline_site_sp->line_entries.push_back(end_line_entry); + }; + auto change_line_offset = [&](int32_t line_delta) { + line_offset += line_delta; + if (has_base) { + LineTable::Entry line_entry( + func_base + code_offset, decl_line + line_offset, 0, decl_file_idx, + is_start_of_statement, false, is_prologue_end, false, false); + inline_site_sp->line_entries.push_back(line_entry); + } else { + // Add line entry in next call to change_code_offset. + is_new_line_offset = true; + } + }; + + for (auto &annot : inline_site.annotations()) { + switch (annot.OpCode) { + case BinaryAnnotationsOpCode::CodeOffset: + case BinaryAnnotationsOpCode::ChangeCodeOffset: + case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: + change_code_offset(annot.U1); + break; + case BinaryAnnotationsOpCode::ChangeLineOffset: + change_line_offset(annot.S1); + break; + case BinaryAnnotationsOpCode::ChangeCodeLength: + change_code_length(annot.U1); + code_offset += annot.U1; + break; + case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: + change_code_offset(annot.U1); + change_line_offset(annot.S1); + break; + case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: + change_code_offset(annot.U2); + change_code_length(annot.U1); + break; + default: + break; + } + } + + inline_site_sp->ranges.Sort(); + inline_site_sp->ranges.CombineConsecutiveEntriesWithEqualData(); + + // Get the inlined function callsite info. + std::unique_ptr<Declaration> callsite_up; + if (!inline_site_sp->ranges.IsEmpty()) { + auto *entry = inline_site_sp->ranges.GetEntryAtIndex(0); + addr_t base_offset = entry->GetRangeBase(); + if (cii->m_debug_stream.readSymbolAtOffset(parent_id.offset).kind() == + S_INLINESITE) { + // Its parent is another inline site, lookup parent site's range vector + // for callsite line. + ParseInlineSite(parent_id, func_base); + std::shared_ptr<InlineSite> parent_site = + m_inline_sites[toOpaqueUid(parent_id)]; + FileSpec &parent_decl_file = + parent_site->inline_function_info->GetDeclaration().GetFile(); + if (auto *parent_entry = + parent_site->ranges.FindEntryThatContains(base_offset)) { + callsite_up = + std::make_unique<Declaration>(parent_decl_file, parent_entry->data); + } + } else { + // Its parent is a function, lookup global line table for callsite. + if (auto *entry = cii->m_global_line_table.FindEntryThatContains( + func_base + base_offset)) { + const FileSpec &callsite_file = + files.GetFileSpecAtIndex(entry->data.first); + callsite_up = + std::make_unique<Declaration>(callsite_file, entry->data.second); + } + } + } + + // Get the inlined function name. + CVType inlinee_cvt = m_index->ipi().getType(inline_site.Inlinee); + std::string inlinee_name; + if (inlinee_cvt.kind() == LF_MFUNC_ID) { + MemberFuncIdRecord mfr; + cantFail( + TypeDeserializer::deserializeAs<MemberFuncIdRecord>(inlinee_cvt, mfr)); + LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); + inlinee_name.append(std::string(types.getTypeName(mfr.ClassType))); + inlinee_name.append("::"); + inlinee_name.append(mfr.getName().str()); + } else if (inlinee_cvt.kind() == LF_FUNC_ID) { + FuncIdRecord fir; + cantFail(TypeDeserializer::deserializeAs<FuncIdRecord>(inlinee_cvt, fir)); + TypeIndex parent_idx = fir.getParentScope(); + if (!parent_idx.isNoneType()) { + LazyRandomTypeCollection &ids = m_index->ipi().typeCollection(); + inlinee_name.append(std::string(ids.getTypeName(parent_idx))); + inlinee_name.append("::"); + } + inlinee_name.append(fir.getName().str()); + } + inline_site_sp->inline_function_info = std::make_shared<InlineFunctionInfo>( + inlinee_name.c_str(), llvm::StringRef(), decl_up.get(), + callsite_up.get()); + + m_inline_sites[opaque_uid] = inline_site_sp; +} + size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - GetOrCreateBlock(PdbSymUid(func.GetID()).asCompilandSym()); - // FIXME: Parse child blocks - return 1; + PdbCompilandSymId func_id = PdbSymUid(func.GetID()).asCompilandSym(); + // After we iterate through inline sites inside the function, we already get + // all the info needed, removing from the map to save memory. + std::set<uint64_t> remove_uids; + auto parse_blocks = [&](SymbolKind kind, PdbCompilandSymId id) { + if (kind == S_GPROC32 || kind == S_LPROC32 || kind == S_BLOCK32 || + kind == S_INLINESITE) { + GetOrCreateBlock(id); + if (kind == S_INLINESITE) + remove_uids.insert(toOpaqueUid(id)); + return true; + } + return false; + }; + size_t count = ParseSymbolArrayInScope(func_id, parse_blocks); + for (uint64_t uid : remove_uids) { + m_inline_sites.erase(uid); + } + return count; +} + +size_t SymbolFileNativePDB::ParseSymbolArrayInScope( + PdbCompilandSymId parent_id, + llvm::function_ref<bool(SymbolKind, PdbCompilandSymId)> fn) { + CompilandIndexItem *cii = m_index->compilands().GetCompiland(parent_id.modi); + CVSymbolArray syms = + cii->m_debug_stream.getSymbolArrayForScope(parent_id.offset); + + size_t count = 1; + for (auto iter = syms.begin(); iter != syms.end(); ++iter) { + PdbCompilandSymId child_id(parent_id.modi, iter.offset()); + if (fn(iter->kind(), child_id)) + ++count; + } + + return count; } void SymbolFileNativePDB::DumpClangAST(Stream &s) { m_ast->Dump(s); } @@ -1396,6 +1730,9 @@ size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) { } case S_BLOCK32: break; + case S_INLINESITE: + // TODO: Handle inline site case. + return 0; default: lldbassert(false && "Symbol is not a block!"); return 0; |
