size_t ModuleList::FindFunctions(const RegularExpression &name, bool include_symbols, bool include_inlines, bool append, SymbolContextList& sc_list) { const size_t initial_size = sc_list.GetSize(); Mutex::Locker locker(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); collection dylinker_modules; for (pos = m_modules.begin(); pos != end; ++pos) { if (!(*pos)->GetIsDynamicLinkEditor()) (*pos)->FindFunctions (name, include_symbols, include_inlines, append, sc_list); else dylinker_modules.push_back(*pos); } bool keep_looking = KeepLookingInDylinker(sc_list, initial_size); if (keep_looking) { end = dylinker_modules.end(); for (pos = dylinker_modules.begin() ; pos != end; pos++) (*pos)->FindFunctions (name, include_symbols, include_inlines, append, sc_list); } return sc_list.GetSize() - initial_size; }
size_t ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, lldb::SymbolType symbol_type, SymbolContextList &sc_list, bool append) const { Mutex::Locker locker(m_modules_mutex); if (!append) sc_list.Clear(); size_t initial_size = sc_list.GetSize(); collection::const_iterator pos, end = m_modules.end(); collection dylinker_modules; for (pos = m_modules.begin(); pos != end; ++pos) { if (!(*pos)->GetIsDynamicLinkEditor()) (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list); else dylinker_modules.push_back (*pos); } bool keep_looking = KeepLookingInDylinker(sc_list, initial_size); if (keep_looking) { end = dylinker_modules.end(); for (pos = dylinker_modules.begin(); pos != end; ++pos) (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list); } return sc_list.GetSize() - initial_size; }
size_t ModuleList::FindFunctionSymbols (const ConstString &name, uint32_t name_type_mask, SymbolContextList& sc_list) { const size_t old_size = sc_list.GetSize(); if (name_type_mask & eFunctionNameTypeAuto) { ConstString lookup_name; uint32_t lookup_name_type_mask = 0; bool match_name_after_lookup = false; Module::PrepareForFunctionNameLookup (name, name_type_mask, eLanguageTypeUnknown, // TODO: add support lookup_name, lookup_name_type_mask, match_name_after_lookup); Mutex::Locker locker(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindFunctionSymbols (lookup_name, lookup_name_type_mask, sc_list); } if (match_name_after_lookup) { SymbolContext sc; size_t i = old_size; while (i < sc_list.GetSize()) { if (sc_list.GetContextAtIndex(i, sc)) { const char *func_name = sc.GetFunctionName().GetCString(); if (func_name != nullptr && strstr(func_name, name.GetCString()) == nullptr) { // Remove the current context sc_list.RemoveContextAtIndex(i); // Don't increment i and continue in the loop continue; } } ++i; } } } else { Mutex::Locker locker(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindFunctionSymbols (name, name_type_mask, sc_list); } } return sc_list.GetSize() - old_size; }
size_t ModuleList::FindSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, SymbolContextList &sc_list, bool append) const { Mutex::Locker locker(m_modules_mutex); if (!append) sc_list.Clear(); size_t initial_size = sc_list.GetSize(); collection::const_iterator pos, end = m_modules.end(); collection dylinker_modules; for (pos = m_modules.begin(); pos != end; ++pos) { if (!(*pos)->GetIsDynamicLinkEditor()) (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list); else dylinker_modules.push_back (*pos); } // Lets see if we found anything but undefined symbols. If so, then we'll also look in the dylinker. bool keep_looking = KeepLookingInDylinker(sc_list, initial_size); if (keep_looking) { end = dylinker_modules.end(); for (pos = dylinker_modules.begin(); pos != end; ++pos) (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list); } return sc_list.GetSize() - initial_size; }
size_t Module::FindSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, SymbolContextList &sc_list) { // No need to protect this call using m_mutex all other method calls are // already thread safe. Timer scoped_timer(__PRETTY_FUNCTION__, "Module::FindSymbolsWithNameAndType (name = %s, type = %i)", name.AsCString(), symbol_type); const size_t initial_size = sc_list.GetSize(); ObjectFile *objfile = GetObjectFile (); if (objfile) { Symtab *symtab = objfile->GetSymtab(); if (symtab) { std::vector<uint32_t> symbol_indexes; symtab->FindAllSymbolsWithNameAndType (name, symbol_type, symbol_indexes); SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list); } } return sc_list.GetSize() - initial_size; }
static bool KeepLookingInDylinker (SymbolContextList &sc_list, size_t start_idx) { bool keep_looking = true; if (sc_list.GetSize() == start_idx) { return true; } SymbolContext sc; size_t num_symbols = sc_list.GetSize(); for (size_t idx = start_idx; idx < num_symbols; idx++) { sc_list.GetContextAtIndex(idx, sc); if (sc.symbol && sc.symbol->GetType() != lldb::eSymbolTypeUndefined) { keep_looking = false; break; } // If we have a function it's not going to be an undefined symbol... if (sc.function) { keep_looking = false; break; } } return keep_looking; }
size_t ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, lldb::SymbolType symbol_type, SymbolContextList &sc_list, bool append) const { Mutex::Locker locker(m_modules_mutex); if (!append) sc_list.Clear(); size_t initial_size = sc_list.GetSize(); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list); return sc_list.GetSize() - initial_size; }
size_t ModuleList::FindSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, SymbolContextList &sc_list, bool append) const { Mutex::Locker locker(m_modules_mutex); if (!append) sc_list.Clear(); size_t initial_size = sc_list.GetSize(); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list); return sc_list.GetSize() - initial_size; }
size_t Disassembler::Disassemble ( Debugger &debugger, const ArchSpec &arch, const ExecutionContext &exe_ctx, SymbolContextList &sc_list, uint32_t num_mixed_context_lines, bool show_bytes, Stream &strm ) { size_t success_count = 0; const size_t count = sc_list.GetSize(); SymbolContext sc; AddressRange range; for (size_t i=0; i<count; ++i) { if (sc_list.GetContextAtIndex(i, sc) == false) break; if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range)) { if (Disassemble (debugger, arch, exe_ctx, range, num_mixed_context_lines, show_bytes, strm)) { ++success_count; strm.EOL(); } } } return success_count; }
uint32_t Module::FindFunctions (const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_symbols, bool include_inlines, bool append, SymbolContextList& sc_list) { if (!append) sc_list.Clear(); const uint32_t start_size = sc_list.GetSize(); // Find all the functions (not symbols, but debug information functions... SymbolVendor *symbols = GetSymbolVendor (); if (symbols) symbols->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list); // Now check our symbol table for symbols that are code symbols if requested if (include_symbols) { ObjectFile *objfile = GetObjectFile(); if (objfile) { Symtab *symtab = objfile->GetSymtab(); if (symtab) { std::vector<uint32_t> symbol_indexes; symtab->FindAllSymbolsWithNameAndType (name, eSymbolTypeCode, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); const uint32_t num_matches = symbol_indexes.size(); if (num_matches) { const bool merge_symbol_into_function = true; SymbolContext sc(this); for (uint32_t i=0; i<num_matches; i++) { sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); sc_list.AppendIfUnique (sc, merge_symbol_into_function); } } } } } return sc_list.GetSize() - start_size; }
size_t ModuleList::FindFunctions(const RegularExpression &name, bool include_symbols, bool include_inlines, bool append, SymbolContextList& sc_list) { const size_t old_size = sc_list.GetSize(); Mutex::Locker locker(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindFunctions (name, include_symbols, include_inlines, append, sc_list); } return sc_list.GetSize() - old_size; }
bool ContainsCompileUnit(const SymbolContextList &sc_list, const FileSpec &spec) const { for (size_t i = 0; i < sc_list.GetSize(); ++i) { const SymbolContext &sc = sc_list[i]; if (FileSpecMatchesAsBaseOrFull(*sc.comp_unit, spec)) return true; } return false; }
bool lldb_private::operator== (const SymbolContextList& lhs, const SymbolContextList& rhs) { const uint32_t size = lhs.GetSize(); if (size != rhs.GetSize()) return false; SymbolContext lhs_sc; SymbolContext rhs_sc; for (uint32_t i=0; i<size; ++i) { lhs.GetContextAtIndex(i, lhs_sc); rhs.GetContextAtIndex(i, rhs_sc); if (lhs_sc != rhs_sc) return false; } return true; }
uint32_t Module::FindFunctions (const RegularExpression& regex, bool include_symbols, bool include_inlines, bool append, SymbolContextList& sc_list) { if (!append) sc_list.Clear(); const uint32_t start_size = sc_list.GetSize(); SymbolVendor *symbols = GetSymbolVendor (); if (symbols) symbols->FindFunctions(regex, include_inlines, append, sc_list); // Now check our symbol table for symbols that are code symbols if requested if (include_symbols) { ObjectFile *objfile = GetObjectFile(); if (objfile) { Symtab *symtab = objfile->GetSymtab(); if (symtab) { std::vector<uint32_t> symbol_indexes; symtab->AppendSymbolIndexesMatchingRegExAndType (regex, eSymbolTypeCode, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); const uint32_t num_matches = symbol_indexes.size(); if (num_matches) { const bool merge_symbol_into_function = true; SymbolContext sc(this); for (uint32_t i=0; i<num_matches; i++) { sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); sc_list.AppendIfUnique (sc, merge_symbol_into_function); } } } } } return sc_list.GetSize() - start_size; }
uint32_t Module::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) { Mutex::Locker locker (m_mutex); Timer scoped_timer(__PRETTY_FUNCTION__, "Module::ResolveSymbolContextForFilePath (%s%s%s:%u, check_inlines = %s, resolve_scope = 0x%8.8x)", file_spec.GetDirectory().AsCString(""), file_spec.GetDirectory() ? "/" : "", file_spec.GetFilename().AsCString(""), line, check_inlines ? "yes" : "no", resolve_scope); const uint32_t initial_count = sc_list.GetSize(); SymbolVendor *symbols = GetSymbolVendor (); if (symbols) symbols->ResolveSymbolContext (file_spec, line, check_inlines, resolve_scope, sc_list); return sc_list.GetSize() - initial_count; }
uint32_t ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) const { Mutex::Locker locker(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); } return sc_list.GetSize(); }
uint32_t Module::FindCompileUnits (const FileSpec &path, bool append, SymbolContextList &sc_list) { if (!append) sc_list.Clear(); const uint32_t start_size = sc_list.GetSize(); const uint32_t num_compile_units = GetNumCompileUnits(); SymbolContext sc; sc.module_sp = this; const bool compare_directory = path.GetDirectory(); for (uint32_t i=0; i<num_compile_units; ++i) { sc.comp_unit = GetCompileUnitAtIndex(i).get(); if (FileSpec::Equal (*sc.comp_unit, path, compare_directory)) sc_list.Append(sc); } return sc_list.GetSize() - start_size; }
size_t Module::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, SymbolType symbol_type, SymbolContextList &sc_list) { // No need to protect this call using m_mutex all other method calls are // already thread safe. Timer scoped_timer(__PRETTY_FUNCTION__, "Module::FindSymbolsMatchingRegExAndType (regex = %s, type = %i)", regex.GetText(), symbol_type); const size_t initial_size = sc_list.GetSize(); ObjectFile *objfile = GetObjectFile (); if (objfile) { Symtab *symtab = objfile->GetSymtab(); if (symtab) { std::vector<uint32_t> symbol_indexes; symtab->FindAllSymbolsMatchingRexExAndType (regex, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list); } } return sc_list.GetSize() - initial_size; }
size_t ModuleList::FindCompileUnits (const FileSpec &path, bool append, SymbolContextList &sc_list) const { if (!append) sc_list.Clear(); Mutex::Locker locker(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindCompileUnits (path, true, sc_list); } return sc_list.GetSize(); }
size_t Disassembler::Disassemble ( Debugger &debugger, const ArchSpec &arch, const char *plugin_name, const char *flavor, const ExecutionContext &exe_ctx, SymbolContextList &sc_list, uint32_t num_instructions, uint32_t num_mixed_context_lines, uint32_t options, Stream &strm ) { size_t success_count = 0; const size_t count = sc_list.GetSize(); SymbolContext sc; AddressRange range; const uint32_t scope = eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol; const bool use_inline_block_range = true; for (size_t i=0; i<count; ++i) { if (sc_list.GetContextAtIndex(i, sc) == false) break; for (uint32_t range_idx = 0; sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); ++range_idx) { if (Disassemble (debugger, arch, plugin_name, flavor, exe_ctx, range, num_instructions, num_mixed_context_lines, options, strm)) { ++success_count; strm.EOL(); } } } return success_count; }
uint32_t ModuleList::FindFunctions (const ConstString &name, uint32_t name_type_mask, bool include_symbols, bool append, SymbolContextList &sc_list) { if (!append) sc_list.Clear(); Mutex::Locker locker(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, true, sc_list); } return sc_list.GetSize(); }
void BreakpointResolverName::LookupInfo::Prune (SymbolContextList &sc_list, size_t start_idx) const { if (match_name_after_lookup && name) { SymbolContext sc; size_t i = start_idx; while (i < sc_list.GetSize()) { if (!sc_list.GetContextAtIndex(i, sc)) break; ConstString full_name (sc.GetFunctionName()); if (full_name && ::strstr(full_name.GetCString(), name.GetCString()) == NULL) { sc_list.RemoveContextAtIndex(i); } else { ++i; } } } }
void BreakpointResolver::SetSCMatchesByLine (SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue, const char *log_ident) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); while (sc_list.GetSize() > 0) { SymbolContextList tmp_sc_list; unsigned current_idx = 0; SymbolContext sc; bool first_entry = true; FileSpec match_file_spec; FileSpec match_original_file_spec; uint32_t closest_line_number = UINT32_MAX; // Pull out the first entry, and all the others that match its file spec, and stuff them in the tmp list. while (current_idx < sc_list.GetSize()) { bool matches; sc_list.GetContextAtIndex (current_idx, sc); if (first_entry) { match_file_spec = sc.line_entry.file; match_original_file_spec = sc.line_entry.original_file; matches = true; first_entry = false; } else matches = ((sc.line_entry.file == match_file_spec) || (sc.line_entry.original_file == match_original_file_spec)); if (matches) { tmp_sc_list.Append (sc); sc_list.RemoveContextAtIndex(current_idx); // ResolveSymbolContext will always return a number that is >= the line number you pass in. // So the smaller line number is always better. if (sc.line_entry.line < closest_line_number) closest_line_number = sc.line_entry.line; } else current_idx++; } // Okay, we've found the closest line number match, now throw away all the others: current_idx = 0; while (current_idx < tmp_sc_list.GetSize()) { if (tmp_sc_list.GetContextAtIndex(current_idx, sc)) { if (sc.line_entry.line != closest_line_number) tmp_sc_list.RemoveContextAtIndex(current_idx); else current_idx++; } } // Next go through and see if there are line table entries that are contiguous, and if so keep only the // first of the contiguous range: current_idx = 0; std::map<Block *, lldb::addr_t> blocks_with_breakpoints; while (current_idx < tmp_sc_list.GetSize()) { if (tmp_sc_list.GetContextAtIndex(current_idx, sc)) { if (blocks_with_breakpoints.find (sc.block) != blocks_with_breakpoints.end()) tmp_sc_list.RemoveContextAtIndex(current_idx); else { blocks_with_breakpoints.insert (std::pair<Block *, lldb::addr_t>(sc.block, sc.line_entry.range.GetBaseAddress().GetFileAddress())); current_idx++; } } } // and make breakpoints out of the closest line number match. uint32_t tmp_sc_list_size = tmp_sc_list.GetSize(); for (uint32_t i = 0; i < tmp_sc_list_size; i++) { if (tmp_sc_list.GetContextAtIndex(i, sc)) { Address line_start = sc.line_entry.range.GetBaseAddress(); if (line_start.IsValid()) { if (filter.AddressPasses(line_start)) { // If the line number is before the prologue end, move it there... bool skipped_prologue = false; if (skip_prologue) { if (sc.function) { Address prologue_addr(sc.function->GetAddressRange().GetBaseAddress()); if (prologue_addr.IsValid() && (line_start == prologue_addr)) { const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); if (prologue_byte_size) { prologue_addr.Slide(prologue_byte_size); if (filter.AddressPasses(prologue_addr)) { skipped_prologue = true; line_start = prologue_addr; } } } } } BreakpointLocationSP bp_loc_sp (AddLocation(line_start)); if (log && bp_loc_sp && !m_breakpoint->IsInternal()) { StreamString s; bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose); log->Printf ("Added location (skipped prologue: %s): %s \n", skipped_prologue ? "yes" : "no", s.GetData()); } } else if (log) { log->Printf ("Breakpoint %s at file address 0x%" PRIx64 " didn't pass the filter.\n", log_ident ? log_ident : "", line_start.GetFileAddress()); } } else { if (log) log->Printf ("error: Unable to set breakpoint %s at file address 0x%" PRIx64 "\n", log_ident ? log_ident : "", line_start.GetFileAddress()); } } } } }
uint32_t CompileUnit::ResolveSymbolContext ( const FileSpec& file_spec, uint32_t line, bool check_inlines, bool exact, uint32_t resolve_scope, SymbolContextList &sc_list ) { // First find all of the file indexes that match our "file_spec". If // "file_spec" has an empty directory, then only compare the basenames // when finding file indexes std::vector<uint32_t> file_indexes; bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *this, !file_spec.GetDirectory().IsEmpty()); // If we are not looking for inlined functions and our file spec doesn't // match then we are done... if (file_spec_matches_cu_file_spec == false && check_inlines == false) return 0; uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec, true); while (file_idx != UINT32_MAX) { file_indexes.push_back (file_idx); file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec, true); } const size_t num_file_indexes = file_indexes.size(); if (num_file_indexes == 0) return 0; const uint32_t prev_size = sc_list.GetSize(); SymbolContext sc(GetModule()); sc.comp_unit = this; if (line != 0) { LineTable *line_table = sc.comp_unit->GetLineTable(); if (line_table != NULL) { uint32_t found_line; uint32_t line_idx; if (num_file_indexes == 1) { // We only have a single support file that matches, so use // the line table function that searches for a line entries // that match a single support file index LineEntry line_entry; line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes.front(), line, exact, &line_entry); // If "exact == true", then "found_line" will be the same // as "line". If "exact == false", the "found_line" will be the // closest line entry with a line number greater than "line" and // we will use this for our subsequent line exact matches below. found_line = line_entry.line; while (line_idx != UINT32_MAX) { // If they only asked for the line entry, then we're done, we can just copy that over. // But if they wanted more than just the line number, fill it in. if (resolve_scope == eSymbolContextLineEntry) { sc.line_entry = line_entry; } else { line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope); } sc_list.Append(sc); line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes.front(), found_line, true, &line_entry); } } else { // We found multiple support files that match "file_spec" so use // the line table function that searches for a line entries // that match a multiple support file indexes. LineEntry line_entry; line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes, line, exact, &line_entry); // If "exact == true", then "found_line" will be the same // as "line". If "exact == false", the "found_line" will be the // closest line entry with a line number greater than "line" and // we will use this for our subsequent line exact matches below. found_line = line_entry.line; while (line_idx != UINT32_MAX) { if (resolve_scope == eSymbolContextLineEntry) { sc.line_entry = line_entry; } else { line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope); } sc_list.Append(sc); line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes, found_line, true, &line_entry); } } } } else if (file_spec_matches_cu_file_spec && !check_inlines) { // only append the context if we aren't looking for inline call sites // by file and line and if the file spec matches that of the compile unit sc_list.Append(sc); } return sc_list.GetSize() - prev_size; }
void BreakpointResolver::SetSCMatchesByLine(SearchFilter &filter, SymbolContextList &sc_list, bool skip_prologue, llvm::StringRef log_ident, uint32_t line, uint32_t column) { llvm::SmallVector<SymbolContext, 16> all_scs; for (uint32_t i = 0; i < sc_list.GetSize(); ++i) all_scs.push_back(sc_list[i]); while (all_scs.size()) { uint32_t closest_line = UINT32_MAX; // Move all the elements with a matching file spec to the end. auto &match = all_scs[0]; auto worklist_begin = std::partition( all_scs.begin(), all_scs.end(), [&](const SymbolContext &sc) { if (sc.line_entry.file == match.line_entry.file || sc.line_entry.original_file == match.line_entry.original_file) { // When a match is found, keep track of the smallest line number. closest_line = std::min(closest_line, sc.line_entry.line); return false; } return true; }); // (worklist_begin, worklist_end) now contains all entries for one filespec. auto worklist_end = all_scs.end(); if (column) { // If a column was requested, do a more precise match and only // return the first location that comes after or at the // requested location. SourceLoc requested(line, column); // First, filter out all entries left of the requested column. worklist_end = std::remove_if( worklist_begin, worklist_end, [&](const SymbolContext &sc) { return SourceLoc(sc) < requested; }); // Sort the remaining entries by (line, column). llvm::sort(worklist_begin, worklist_end, [](const SymbolContext &a, const SymbolContext &b) { return SourceLoc(a) < SourceLoc(b); }); // Filter out all locations with a source location after the closest match. if (worklist_begin != worklist_end) worklist_end = std::remove_if( worklist_begin, worklist_end, [&](const SymbolContext &sc) { return SourceLoc(*worklist_begin) < SourceLoc(sc); }); } else { // Remove all entries with a larger line number. // ResolveSymbolContext will always return a number that is >= // the line number you pass in. So the smaller line number is // always better. worklist_end = std::remove_if(worklist_begin, worklist_end, [&](const SymbolContext &sc) { return closest_line != sc.line_entry.line; }); } // Sort by file address. llvm::sort(worklist_begin, worklist_end, [](const SymbolContext &a, const SymbolContext &b) { return a.line_entry.range.GetBaseAddress().GetFileAddress() < b.line_entry.range.GetBaseAddress().GetFileAddress(); }); // Go through and see if there are line table entries that are // contiguous, and if so keep only the first of the contiguous range. // We do this by picking the first location in each lexical block. llvm::SmallDenseSet<Block *, 8> blocks_with_breakpoints; for (auto first = worklist_begin; first != worklist_end; ++first) { assert(!blocks_with_breakpoints.count(first->block)); blocks_with_breakpoints.insert(first->block); worklist_end = std::remove_if(std::next(first), worklist_end, [&](const SymbolContext &sc) { return blocks_with_breakpoints.count(sc.block); }); } // Make breakpoints out of the closest line number match. for (auto &sc : llvm::make_range(worklist_begin, worklist_end)) AddLocation(filter, sc, skip_prologue, log_ident); // Remove all contexts processed by this iteration. all_scs.erase(worklist_begin, all_scs.end()); } }
size_t ModuleList::FindFunctions (const ConstString &name, uint32_t name_type_mask, bool include_symbols, bool include_inlines, bool append, SymbolContextList &sc_list) const { if (!append) sc_list.Clear(); const size_t old_size = sc_list.GetSize(); if (name_type_mask & eFunctionNameTypeAuto) { ConstString lookup_name; uint32_t lookup_name_type_mask = 0; bool match_name_after_lookup = false; Module::PrepareForFunctionNameLookup (name, name_type_mask, lookup_name, lookup_name_type_mask, match_name_after_lookup); Mutex::Locker locker(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindFunctions (lookup_name, NULL, lookup_name_type_mask, include_symbols, include_inlines, true, sc_list); } if (match_name_after_lookup) { SymbolContext sc; size_t i = old_size; while (i<sc_list.GetSize()) { if (sc_list.GetContextAtIndex(i, sc)) { const char *func_name = sc.GetFunctionName().GetCString(); if (func_name && strstr (func_name, name.GetCString()) == NULL) { // Remove the current context sc_list.RemoveContextAtIndex(i); // Don't increment i and continue in the loop continue; } } ++i; } } } else { Mutex::Locker locker(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list); } } return sc_list.GetSize() - old_size; }