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::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 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; }
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; }
ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, Address &function, ValueList &args, bool stop_other_threads, bool discard_on_error) : ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), m_valid (false), m_stop_other_threads (stop_other_threads), m_arg_addr (0), m_args (&args), m_process (thread.GetProcess()), m_thread (thread) { SetOkayToDiscard (discard_on_error); Process& process = thread.GetProcess(); Target& target = process.GetTarget(); const ABI *abi = process.GetABI(); if(!abi) return; lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); SymbolContextList contexts; SymbolContext context; ModuleSP executableModuleSP (target.GetExecutableModule()); if (!executableModuleSP || !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts)) return; contexts.GetContextAtIndex(0, context); m_start_addr = context.symbol->GetValue(); lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&process); if(!thread.SaveFrameZeroState(m_register_backup)) return; m_function_addr = function; lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&process); if (!abi->PrepareNormalCall(thread, spBelowRedZone, FunctionLoadAddr, StartLoadAddr, *m_args)) return; m_valid = true; }
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; }
Address * AppleObjCRuntime::GetPrintForDebuggerAddr() { if (!m_PrintForDebugger_addr.get()) { const ModuleList &modules = m_process->GetTarget().GetImages(); SymbolContextList contexts; SymbolContext context; if ((!modules.FindSymbolsWithNameAndType(ConstString ("_NSPrintForDebugger"), eSymbolTypeCode, contexts)) && (!modules.FindSymbolsWithNameAndType(ConstString ("_CFPrintForDebugger"), eSymbolTypeCode, contexts))) return NULL; contexts.GetContextAtIndex(0, context); m_PrintForDebugger_addr.reset(new Address(context.symbol->GetAddress())); } return m_PrintForDebugger_addr.get(); }
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()); } } } } }
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; }