diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp | 893 |
1 files changed, 431 insertions, 462 deletions
diff --git a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp index 3771e21..03f6679 100644 --- a/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp +++ b/contrib/llvm/tools/lldb/source/Target/ThreadPlanStepInRange.cpp @@ -14,526 +14,495 @@ #include "lldb/Target/ThreadPlanStepInRange.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" +#include "lldb/Core/RegularExpression.h" #include "lldb/Core/Stream.h" -#include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/Function.h" +#include "lldb/Symbol/Symbol.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlanStepOut.h" #include "lldb/Target/ThreadPlanStepThrough.h" -#include "lldb/Core/RegularExpression.h" using namespace lldb; using namespace lldb_private; -uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eStepInAvoidNoDebug; +uint32_t ThreadPlanStepInRange::s_default_flag_values = + ThreadPlanShouldStopHere::eStepInAvoidNoDebug; //---------------------------------------------------------------------- -// ThreadPlanStepInRange: Step through a stack range, either stepping over or into +// ThreadPlanStepInRange: Step through a stack range, either stepping over or +// into // based on the value of \a type. //---------------------------------------------------------------------- -ThreadPlanStepInRange::ThreadPlanStepInRange -( - Thread &thread, - const AddressRange &range, - const SymbolContext &addr_context, - lldb::RunMode stop_others, +ThreadPlanStepInRange::ThreadPlanStepInRange( + Thread &thread, const AddressRange &range, + const SymbolContext &addr_context, lldb::RunMode stop_others, LazyBool step_in_avoids_code_without_debug_info, - LazyBool step_out_avoids_code_without_debug_info -) : - ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others), - ThreadPlanShouldStopHere (this), - m_step_past_prologue (true), - m_virtual_step (false) -{ - SetCallbacks(); - SetFlagsToDefault (); - SetupAvoidNoDebug(step_in_avoids_code_without_debug_info, step_out_avoids_code_without_debug_info); + LazyBool step_out_avoids_code_without_debug_info) + : ThreadPlanStepRange(ThreadPlan::eKindStepInRange, + "Step Range stepping in", thread, range, addr_context, + stop_others), + ThreadPlanShouldStopHere(this), m_step_past_prologue(true), + m_virtual_step(false) { + SetCallbacks(); + SetFlagsToDefault(); + SetupAvoidNoDebug(step_in_avoids_code_without_debug_info, + step_out_avoids_code_without_debug_info); } -ThreadPlanStepInRange::ThreadPlanStepInRange -( - Thread &thread, - const AddressRange &range, - const SymbolContext &addr_context, - const char *step_into_target, - lldb::RunMode stop_others, - LazyBool step_in_avoids_code_without_debug_info, - LazyBool step_out_avoids_code_without_debug_info -) : - ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others), - ThreadPlanShouldStopHere (this), - m_step_past_prologue (true), - m_virtual_step (false), - m_step_into_target (step_into_target) -{ - SetCallbacks(); - SetFlagsToDefault (); - SetupAvoidNoDebug(step_in_avoids_code_without_debug_info, step_out_avoids_code_without_debug_info); +ThreadPlanStepInRange::ThreadPlanStepInRange( + Thread &thread, const AddressRange &range, + const SymbolContext &addr_context, const char *step_into_target, + lldb::RunMode stop_others, LazyBool step_in_avoids_code_without_debug_info, + LazyBool step_out_avoids_code_without_debug_info) + : ThreadPlanStepRange(ThreadPlan::eKindStepInRange, + "Step Range stepping in", thread, range, addr_context, + stop_others), + ThreadPlanShouldStopHere(this), m_step_past_prologue(true), + m_virtual_step(false), m_step_into_target(step_into_target) { + SetCallbacks(); + SetFlagsToDefault(); + SetupAvoidNoDebug(step_in_avoids_code_without_debug_info, + step_out_avoids_code_without_debug_info); } ThreadPlanStepInRange::~ThreadPlanStepInRange() = default; -void -ThreadPlanStepInRange::SetupAvoidNoDebug(LazyBool step_in_avoids_code_without_debug_info, - LazyBool step_out_avoids_code_without_debug_info) -{ - bool avoid_nodebug = true; - - switch (step_in_avoids_code_without_debug_info) - { - case eLazyBoolYes: - avoid_nodebug = true; - break; - case eLazyBoolNo: - avoid_nodebug = false; - break; - case eLazyBoolCalculate: - avoid_nodebug = m_thread.GetStepInAvoidsNoDebug(); - break; - } - if (avoid_nodebug) - GetFlags().Set (ThreadPlanShouldStopHere::eStepInAvoidNoDebug); - else - GetFlags().Clear (ThreadPlanShouldStopHere::eStepInAvoidNoDebug); - - switch (step_out_avoids_code_without_debug_info) - { - case eLazyBoolYes: - avoid_nodebug = true; - break; - case eLazyBoolNo: - avoid_nodebug = false; - break; - case eLazyBoolCalculate: - avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug(); - break; - } - if (avoid_nodebug) - GetFlags().Set (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug); - else - GetFlags().Clear (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug); +void ThreadPlanStepInRange::SetupAvoidNoDebug( + LazyBool step_in_avoids_code_without_debug_info, + LazyBool step_out_avoids_code_without_debug_info) { + bool avoid_nodebug = true; + + switch (step_in_avoids_code_without_debug_info) { + case eLazyBoolYes: + avoid_nodebug = true; + break; + case eLazyBoolNo: + avoid_nodebug = false; + break; + case eLazyBoolCalculate: + avoid_nodebug = m_thread.GetStepInAvoidsNoDebug(); + break; + } + if (avoid_nodebug) + GetFlags().Set(ThreadPlanShouldStopHere::eStepInAvoidNoDebug); + else + GetFlags().Clear(ThreadPlanShouldStopHere::eStepInAvoidNoDebug); + + switch (step_out_avoids_code_without_debug_info) { + case eLazyBoolYes: + avoid_nodebug = true; + break; + case eLazyBoolNo: + avoid_nodebug = false; + break; + case eLazyBoolCalculate: + avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug(); + break; + } + if (avoid_nodebug) + GetFlags().Set(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug); + else + GetFlags().Clear(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug); } -void -ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level) -{ - if (level == lldb::eDescriptionLevelBrief) - { - s->Printf("step in"); - return; - } +void ThreadPlanStepInRange::GetDescription(Stream *s, + lldb::DescriptionLevel level) { + if (level == lldb::eDescriptionLevelBrief) { + s->Printf("step in"); + return; + } - s->Printf ("Stepping in"); - bool printed_line_info = false; - if (m_addr_context.line_entry.IsValid()) - { - s->Printf (" through line "); - m_addr_context.line_entry.DumpStopContext (s, false); - printed_line_info = true; - } + s->Printf("Stepping in"); + bool printed_line_info = false; + if (m_addr_context.line_entry.IsValid()) { + s->Printf(" through line "); + m_addr_context.line_entry.DumpStopContext(s, false); + printed_line_info = true; + } - const char *step_into_target = m_step_into_target.AsCString(); - if (step_into_target && step_into_target[0] != '\0') - s->Printf (" targeting %s", m_step_into_target.AsCString()); + const char *step_into_target = m_step_into_target.AsCString(); + if (step_into_target && step_into_target[0] != '\0') + s->Printf(" targeting %s", m_step_into_target.AsCString()); - if (!printed_line_info || level == eDescriptionLevelVerbose) - { - s->Printf (" using ranges:"); - DumpRanges(s); - } + if (!printed_line_info || level == eDescriptionLevelVerbose) { + s->Printf(" using ranges:"); + DumpRanges(s); + } - s->PutChar('.'); + s->PutChar('.'); } -bool -ThreadPlanStepInRange::ShouldStop (Event *event_ptr) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - - if (log) - { - StreamString s; - s.Address (m_thread.GetRegisterContext()->GetPC(), - m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); - log->Printf("ThreadPlanStepInRange reached %s.", s.GetData()); - } +bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); - if (IsPlanComplete()) - return true; - - m_no_more_plans = false; - if (m_sub_plan_sp && m_sub_plan_sp->IsPlanComplete()) - { - if (!m_sub_plan_sp->PlanSucceeded()) - { - SetPlanComplete(); - m_no_more_plans = true; - return true; - } - else - m_sub_plan_sp.reset(); + if (log) { + StreamString s; + s.Address( + m_thread.GetRegisterContext()->GetPC(), + m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); + log->Printf("ThreadPlanStepInRange reached %s.", s.GetData()); + } + + if (IsPlanComplete()) + return true; + + m_no_more_plans = false; + if (m_sub_plan_sp && m_sub_plan_sp->IsPlanComplete()) { + if (!m_sub_plan_sp->PlanSucceeded()) { + SetPlanComplete(); + m_no_more_plans = true; + return true; + } else + m_sub_plan_sp.reset(); + } + + if (m_virtual_step) { + // If we've just completed a virtual step, all we need to do is check for a + // ShouldStopHere plan, and otherwise + // we're done. + // FIXME - This can be both a step in and a step out. Probably should + // record which in the m_virtual_step. + m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger); + } else { + // Stepping through should be done running other threads in general, since + // we're setting a breakpoint and + // continuing. So only stop others if we are explicitly told to do so. + + bool stop_others = (m_stop_others == lldb::eOnlyThisThread); + + FrameComparison frame_order = CompareCurrentFrameToStartFrame(); + + if (frame_order == eFrameCompareOlder || + frame_order == eFrameCompareSameParent) { + // If we're in an older frame then we should stop. + // + // A caveat to this is if we think the frame is older but we're actually + // in a trampoline. + // I'm going to make the assumption that you wouldn't RETURN to a + // trampoline. So if we are + // in a trampoline we think the frame is older because the trampoline + // confused the backtracer. + m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false, + stop_others); + if (!m_sub_plan_sp) { + // Otherwise check the ShouldStopHere for step out: + m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order); + if (log) + log->Printf("ShouldStopHere says we should step out of this frame."); + } else if (log) { + log->Printf( + "Thought I stepped out, but in fact arrived at a trampoline."); + } + } else if (frame_order == eFrameCompareEqual && InSymbol()) { + // If we are not in a place we should step through, we're done. + // One tricky bit here is that some stubs don't push a frame, so we have + // to check + // both the case of a frame that is younger, or the same as this frame. + // However, if the frame is the same, and we are still in the symbol we + // started + // in, the we don't need to do this. This first check isn't strictly + // necessary, + // but it is more efficient. + + // If we're still in the range, keep going, either by running to the next + // branch breakpoint, or by + // stepping. + if (InRange()) { + SetNextBranchBreakpoint(); + return false; + } + + SetPlanComplete(); + m_no_more_plans = true; + return true; } - - if (m_virtual_step) - { - // If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise - // we're done. - // FIXME - This can be both a step in and a step out. Probably should record which in the m_virtual_step. - m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger); + + // If we get to this point, we're not going to use a previously set "next + // branch" breakpoint, so delete it: + ClearNextBranchBreakpoint(); + + // We may have set the plan up above in the FrameIsOlder section: + + if (!m_sub_plan_sp) + m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false, + stop_others); + + if (log) { + if (m_sub_plan_sp) + log->Printf("Found a step through plan: %s", m_sub_plan_sp->GetName()); + else + log->Printf("No step through plan found."); } - else - { - // Stepping through should be done running other threads in general, since we're setting a breakpoint and - // continuing. So only stop others if we are explicitly told to do so. - - bool stop_others = (m_stop_others == lldb::eOnlyThisThread); - - FrameComparison frame_order = CompareCurrentFrameToStartFrame(); - - if (frame_order == eFrameCompareOlder || frame_order == eFrameCompareSameParent) - { - // If we're in an older frame then we should stop. - // - // A caveat to this is if we think the frame is older but we're actually in a trampoline. - // I'm going to make the assumption that you wouldn't RETURN to a trampoline. So if we are - // in a trampoline we think the frame is older because the trampoline confused the backtracer. - m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); - if (!m_sub_plan_sp) - { - // Otherwise check the ShouldStopHere for step out: - m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order); - if (log) - log->Printf ("ShouldStopHere says we should step out of this frame."); - } - else if (log) - { - log->Printf("Thought I stepped out, but in fact arrived at a trampoline."); - } - } - else if (frame_order == eFrameCompareEqual && InSymbol()) - { - // If we are not in a place we should step through, we're done. - // One tricky bit here is that some stubs don't push a frame, so we have to check - // both the case of a frame that is younger, or the same as this frame. - // However, if the frame is the same, and we are still in the symbol we started - // in, the we don't need to do this. This first check isn't strictly necessary, - // but it is more efficient. - - // If we're still in the range, keep going, either by running to the next branch breakpoint, or by - // stepping. - if (InRange()) - { - SetNextBranchBreakpoint(); - return false; - } - - SetPlanComplete(); - m_no_more_plans = true; - return true; - } - - // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it: - ClearNextBranchBreakpoint(); - - // We may have set the plan up above in the FrameIsOlder section: - - if (!m_sub_plan_sp) - m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); - - if (log) - { - if (m_sub_plan_sp) - log->Printf ("Found a step through plan: %s", m_sub_plan_sp->GetName()); - else - log->Printf ("No step through plan found."); + + // If not, give the "should_stop" callback a chance to push a plan to get us + // out of here. + // But only do that if we actually have stepped in. + if (!m_sub_plan_sp && frame_order == eFrameCompareYounger) + m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order); + + // If we've stepped in and we are going to stop here, check to see if we + // were asked to + // run past the prologue, and if so do that. + + if (!m_sub_plan_sp && frame_order == eFrameCompareYounger && + m_step_past_prologue) { + lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0); + if (curr_frame) { + size_t bytes_to_skip = 0; + lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC(); + Address func_start_address; + + SymbolContext sc = curr_frame->GetSymbolContext(eSymbolContextFunction | + eSymbolContextSymbol); + + if (sc.function) { + func_start_address = sc.function->GetAddressRange().GetBaseAddress(); + if (curr_addr == + func_start_address.GetLoadAddress( + m_thread.CalculateTarget().get())) + bytes_to_skip = sc.function->GetPrologueByteSize(); + } else if (sc.symbol) { + func_start_address = sc.symbol->GetAddress(); + if (curr_addr == + func_start_address.GetLoadAddress( + m_thread.CalculateTarget().get())) + bytes_to_skip = sc.symbol->GetPrologueByteSize(); } - - // If not, give the "should_stop" callback a chance to push a plan to get us out of here. - // But only do that if we actually have stepped in. - if (!m_sub_plan_sp && frame_order == eFrameCompareYounger) - m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order); - - // If we've stepped in and we are going to stop here, check to see if we were asked to - // run past the prologue, and if so do that. - - if (!m_sub_plan_sp && frame_order == eFrameCompareYounger && m_step_past_prologue) - { - lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0); - if (curr_frame) - { - size_t bytes_to_skip = 0; - lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC(); - Address func_start_address; - - SymbolContext sc = curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextSymbol); - - if (sc.function) - { - func_start_address = sc.function->GetAddressRange().GetBaseAddress(); - if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) - bytes_to_skip = sc.function->GetPrologueByteSize(); - } - else if (sc.symbol) - { - func_start_address = sc.symbol->GetAddress(); - if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) - bytes_to_skip = sc.symbol->GetPrologueByteSize(); - } - - if (bytes_to_skip != 0) - { - func_start_address.Slide (bytes_to_skip); - log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); - if (log) - log->Printf ("Pushing past prologue "); - - m_sub_plan_sp = m_thread.QueueThreadPlanForRunToAddress(false, func_start_address,true); - } - } + + if (bytes_to_skip != 0) { + func_start_address.Slide(bytes_to_skip); + log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP); + if (log) + log->Printf("Pushing past prologue "); + + m_sub_plan_sp = m_thread.QueueThreadPlanForRunToAddress( + false, func_start_address, true); } - } - - if (!m_sub_plan_sp) - { - m_no_more_plans = true; - SetPlanComplete(); - return true; - } - else - { - m_no_more_plans = false; - m_sub_plan_sp->SetPrivate(true); - return false; + } } + } + + if (!m_sub_plan_sp) { + m_no_more_plans = true; + SetPlanComplete(); + return true; + } else { + m_no_more_plans = false; + m_sub_plan_sp->SetPrivate(true); + return false; + } } -void -ThreadPlanStepInRange::SetAvoidRegexp(const char *name) -{ - if (!m_avoid_regexp_ap) - m_avoid_regexp_ap.reset (new RegularExpression(name)); +void ThreadPlanStepInRange::SetAvoidRegexp(const char *name) { + auto name_ref = llvm::StringRef::withNullAsEmpty(name); + if (!m_avoid_regexp_ap) + m_avoid_regexp_ap.reset(new RegularExpression(name_ref)); - m_avoid_regexp_ap->Compile (name); + m_avoid_regexp_ap->Compile(name_ref); } -void -ThreadPlanStepInRange::SetDefaultFlagValue (uint32_t new_value) -{ - // TODO: Should we test this for sanity? - ThreadPlanStepInRange::s_default_flag_values = new_value; +void ThreadPlanStepInRange::SetDefaultFlagValue(uint32_t new_value) { + // TODO: Should we test this for sanity? + ThreadPlanStepInRange::s_default_flag_values = new_value; } -bool -ThreadPlanStepInRange::FrameMatchesAvoidCriteria () -{ - StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get(); - - // Check the library list first, as that's cheapest: - bool libraries_say_avoid = false; - - FileSpecList libraries_to_avoid (GetThread().GetLibrariesToAvoid()); - size_t num_libraries = libraries_to_avoid.GetSize(); - if (num_libraries > 0) - { - SymbolContext sc(frame->GetSymbolContext(eSymbolContextModule)); - FileSpec frame_library(sc.module_sp->GetFileSpec()); - - if (frame_library) - { - for (size_t i = 0; i < num_libraries; i++) - { - const FileSpec &file_spec(libraries_to_avoid.GetFileSpecAtIndex(i)); - if (FileSpec::Equal (file_spec, frame_library, false)) - { - libraries_say_avoid = true; - break; - } - } +bool ThreadPlanStepInRange::FrameMatchesAvoidCriteria() { + StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get(); + + // Check the library list first, as that's cheapest: + bool libraries_say_avoid = false; + + FileSpecList libraries_to_avoid(GetThread().GetLibrariesToAvoid()); + size_t num_libraries = libraries_to_avoid.GetSize(); + if (num_libraries > 0) { + SymbolContext sc(frame->GetSymbolContext(eSymbolContextModule)); + FileSpec frame_library(sc.module_sp->GetFileSpec()); + + if (frame_library) { + for (size_t i = 0; i < num_libraries; i++) { + const FileSpec &file_spec(libraries_to_avoid.GetFileSpecAtIndex(i)); + if (FileSpec::Equal(file_spec, frame_library, false)) { + libraries_say_avoid = true; + break; } + } } - if (libraries_say_avoid) - return true; - - const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get(); - if (avoid_regexp_to_use == nullptr) - avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp(); - - if (avoid_regexp_to_use != nullptr) - { - SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); - if (sc.symbol != nullptr) - { - const char *frame_function_name = sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments).GetCString(); - if (frame_function_name) - { - size_t num_matches = 0; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - if (log) - num_matches = 1; - - RegularExpression::Match regex_match(num_matches); - - bool return_value = avoid_regexp_to_use->Execute(frame_function_name, ®ex_match); - if (return_value) - { - if (log) - { - std::string match; - regex_match.GetMatchAtIndex(frame_function_name,0, match); - log->Printf ("Stepping out of function \"%s\" because it matches the avoid regexp \"%s\" - match substring: \"%s\".", - frame_function_name, - avoid_regexp_to_use->GetText(), - match.c_str()); - } - - } - return return_value; - } + } + if (libraries_say_avoid) + return true; + + const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get(); + if (avoid_regexp_to_use == nullptr) + avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp(); + + if (avoid_regexp_to_use != nullptr) { + SymbolContext sc = frame->GetSymbolContext( + eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol); + if (sc.symbol != nullptr) { + const char *frame_function_name = + sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments) + .GetCString(); + if (frame_function_name) { + size_t num_matches = 0; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (log) + num_matches = 1; + + RegularExpression::Match regex_match(num_matches); + + bool return_value = + avoid_regexp_to_use->Execute(frame_function_name, ®ex_match); + if (return_value) { + if (log) { + std::string match; + regex_match.GetMatchAtIndex(frame_function_name, 0, match); + log->Printf("Stepping out of function \"%s\" because it matches " + "the avoid regexp \"%s\" - match substring: \"%s\".", + frame_function_name, + avoid_regexp_to_use->GetText().str().c_str(), + match.c_str()); + } } + return return_value; + } } - return false; + } + return false; } -bool -ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, FrameComparison operation, void *baton) -{ - bool should_stop_here = true; - StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get(); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - - // First see if the ThreadPlanShouldStopHere default implementation thinks we should get out of here: - should_stop_here = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback (current_plan, flags, operation, baton); - if (!should_stop_here) - return should_stop_here; - - if (should_stop_here && current_plan->GetKind() == eKindStepInRange && operation == eFrameCompareYounger) - { - ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); - if (step_in_range_plan->m_step_into_target) - { - SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); - if (sc.symbol != nullptr) - { - // First try an exact match, since that's cheap with ConstStrings. Then do a strstr compare. - if (step_in_range_plan->m_step_into_target == sc.GetFunctionName()) - { - should_stop_here = true; - } - else - { - const char *target_name = step_in_range_plan->m_step_into_target.AsCString(); - const char *function_name = sc.GetFunctionName().AsCString(); - - if (function_name == nullptr) - should_stop_here = false; - else if (strstr(function_name, target_name) == nullptr) - should_stop_here = false; - } - if (log && !should_stop_here) - log->Printf("Stepping out of frame %s which did not match step into target %s.", - sc.GetFunctionName().AsCString(), - step_in_range_plan->m_step_into_target.AsCString()); - } - } - - if (should_stop_here) - { - ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); - // Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidCriteria. - should_stop_here = !step_in_range_plan->FrameMatchesAvoidCriteria (); - } - } - +bool ThreadPlanStepInRange::DefaultShouldStopHereCallback( + ThreadPlan *current_plan, Flags &flags, FrameComparison operation, + void *baton) { + bool should_stop_here = true; + StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get(); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + + // First see if the ThreadPlanShouldStopHere default implementation thinks we + // should get out of here: + should_stop_here = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback( + current_plan, flags, operation, baton); + if (!should_stop_here) return should_stop_here; -} -bool -ThreadPlanStepInRange::DoPlanExplainsStop (Event *event_ptr) -{ - // We always explain a stop. Either we've just done a single step, in which - // case we'll do our ordinary processing, or we stopped for some - // reason that isn't handled by our sub-plans, in which case we want to just stop right - // away. - // In general, we don't want to mark the plan as complete for unexplained stops. - // For instance, if you step in to some code with no debug info, so you step out - // and in the course of that hit a breakpoint, then you want to stop & show the user - // the breakpoint, but not unship the step in plan, since you still may want to complete that - // plan when you continue. This is particularly true when doing "step in to target function." - // stepping. - // - // The only variation is that if we are doing "step by running to next branch" in which case - // if we hit our branch breakpoint we don't set the plan to complete. - - bool return_value = false; - - if (m_virtual_step) - { - return_value = true; - } - else - { - StopInfoSP stop_info_sp = GetPrivateStopInfo (); - if (stop_info_sp) - { - StopReason reason = stop_info_sp->GetStopReason(); - - if (reason == eStopReasonBreakpoint) - { - if (NextRangeBreakpointExplainsStop(stop_info_sp)) - { - return_value = true; - } - } - else if (IsUsuallyUnexplainedStopReason(reason)) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - if (log) - log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step."); - return_value = false; - } - else - { - return_value = true; - } + if (should_stop_here && current_plan->GetKind() == eKindStepInRange && + operation == eFrameCompareYounger) { + ThreadPlanStepInRange *step_in_range_plan = + static_cast<ThreadPlanStepInRange *>(current_plan); + if (step_in_range_plan->m_step_into_target) { + SymbolContext sc = frame->GetSymbolContext( + eSymbolContextFunction | eSymbolContextBlock | eSymbolContextSymbol); + if (sc.symbol != nullptr) { + // First try an exact match, since that's cheap with ConstStrings. Then + // do a strstr compare. + if (step_in_range_plan->m_step_into_target == sc.GetFunctionName()) { + should_stop_here = true; + } else { + const char *target_name = + step_in_range_plan->m_step_into_target.AsCString(); + const char *function_name = sc.GetFunctionName().AsCString(); + + if (function_name == nullptr) + should_stop_here = false; + else if (strstr(function_name, target_name) == nullptr) + should_stop_here = false; } - else - return_value = true; + if (log && !should_stop_here) + log->Printf("Stepping out of frame %s which did not match step into " + "target %s.", + sc.GetFunctionName().AsCString(), + step_in_range_plan->m_step_into_target.AsCString()); + } } - - return return_value; + + if (should_stop_here) { + ThreadPlanStepInRange *step_in_range_plan = + static_cast<ThreadPlanStepInRange *>(current_plan); + // Don't log the should_step_out here, it's easier to do it in + // FrameMatchesAvoidCriteria. + should_stop_here = !step_in_range_plan->FrameMatchesAvoidCriteria(); + } + } + + return should_stop_here; } -bool -ThreadPlanStepInRange::DoWillResume (lldb::StateType resume_state, bool current_plan) -{ - m_virtual_step = false; - if (resume_state == eStateStepping && current_plan) - { - // See if we are about to step over a virtual inlined call. - bool step_without_resume = m_thread.DecrementCurrentInlinedDepth(); - if (step_without_resume) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - if (log) - log->Printf ("ThreadPlanStepInRange::DoWillResume: returning false, inline_depth: %d", - m_thread.GetCurrentInlinedDepth()); - SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread)); - - // FIXME: Maybe it would be better to create a InlineStep stop reason, but then - // the whole rest of the world would have to handle that stop reason. - m_virtual_step = true; +bool ThreadPlanStepInRange::DoPlanExplainsStop(Event *event_ptr) { + // We always explain a stop. Either we've just done a single step, in which + // case we'll do our ordinary processing, or we stopped for some + // reason that isn't handled by our sub-plans, in which case we want to just + // stop right + // away. + // In general, we don't want to mark the plan as complete for unexplained + // stops. + // For instance, if you step in to some code with no debug info, so you step + // out + // and in the course of that hit a breakpoint, then you want to stop & show + // the user + // the breakpoint, but not unship the step in plan, since you still may want + // to complete that + // plan when you continue. This is particularly true when doing "step in to + // target function." + // stepping. + // + // The only variation is that if we are doing "step by running to next branch" + // in which case + // if we hit our branch breakpoint we don't set the plan to complete. + + bool return_value = false; + + if (m_virtual_step) { + return_value = true; + } else { + StopInfoSP stop_info_sp = GetPrivateStopInfo(); + if (stop_info_sp) { + StopReason reason = stop_info_sp->GetStopReason(); + + if (reason == eStopReasonBreakpoint) { + if (NextRangeBreakpointExplainsStop(stop_info_sp)) { + return_value = true; } - return !step_without_resume; - } - return true; + } else if (IsUsuallyUnexplainedStopReason(reason)) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (log) + log->PutCString("ThreadPlanStepInRange got asked if it explains the " + "stop for some reason other than step."); + return_value = false; + } else { + return_value = true; + } + } else + return_value = true; + } + + return return_value; } -bool -ThreadPlanStepInRange::IsVirtualStep() -{ - return m_virtual_step; +bool ThreadPlanStepInRange::DoWillResume(lldb::StateType resume_state, + bool current_plan) { + m_virtual_step = false; + if (resume_state == eStateStepping && current_plan) { + // See if we are about to step over a virtual inlined call. + bool step_without_resume = m_thread.DecrementCurrentInlinedDepth(); + if (step_without_resume) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (log) + log->Printf("ThreadPlanStepInRange::DoWillResume: returning false, " + "inline_depth: %d", + m_thread.GetCurrentInlinedDepth()); + SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread)); + + // FIXME: Maybe it would be better to create a InlineStep stop reason, but + // then + // the whole rest of the world would have to handle that stop reason. + m_virtual_step = true; + } + return !step_without_resume; + } + return true; } + +bool ThreadPlanStepInRange::IsVirtualStep() { return m_virtual_step; } |