130fdc8d8SChris Lattner //===-- ThreadPlanStepInRange.cpp -------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepInRange.h" 1130fdc8d8SChris Lattner 1230fdc8d8SChris Lattner // C Includes 1330fdc8d8SChris Lattner // C++ Includes 1430fdc8d8SChris Lattner // Other libraries and framework includes 1530fdc8d8SChris Lattner // Project includes 1630fdc8d8SChris Lattner 1730fdc8d8SChris Lattner #include "lldb/lldb-private-log.h" 1830fdc8d8SChris Lattner #include "lldb/Core/Log.h" 19*4da6206dSJim Ingham #include "lldb/Core/Module.h" 2030fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 21a56c8006SJim Ingham #include "lldb/Symbol/Symbol.h" 227ce490c6SJim Ingham #include "lldb/Symbol/Function.h" 2330fdc8d8SChris Lattner #include "lldb/Target/Process.h" 2430fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 25514487e8SGreg Clayton #include "lldb/Target/Target.h" 2630fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 2730fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepOut.h" 2830fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepThrough.h" 29a56c8006SJim Ingham #include "lldb/Core/RegularExpression.h" 3030fdc8d8SChris Lattner 3130fdc8d8SChris Lattner using namespace lldb; 3230fdc8d8SChris Lattner using namespace lldb_private; 3330fdc8d8SChris Lattner 3430fdc8d8SChris Lattner uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eAvoidNoDebug; 3530fdc8d8SChris Lattner 3630fdc8d8SChris Lattner //---------------------------------------------------------------------- 3730fdc8d8SChris Lattner // ThreadPlanStepInRange: Step through a stack range, either stepping over or into 3830fdc8d8SChris Lattner // based on the value of \a type. 3930fdc8d8SChris Lattner //---------------------------------------------------------------------- 4030fdc8d8SChris Lattner 4130fdc8d8SChris Lattner ThreadPlanStepInRange::ThreadPlanStepInRange 4230fdc8d8SChris Lattner ( 4330fdc8d8SChris Lattner Thread &thread, 4430fdc8d8SChris Lattner const AddressRange &range, 4530fdc8d8SChris Lattner const SymbolContext &addr_context, 4630fdc8d8SChris Lattner lldb::RunMode stop_others 4730fdc8d8SChris Lattner ) : 48b01e742aSJim Ingham ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others), 497ce490c6SJim Ingham ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL), 50f02a2e96SJim Ingham m_step_past_prologue (true), 51f02a2e96SJim Ingham m_virtual_step (false) 5230fdc8d8SChris Lattner { 5330fdc8d8SChris Lattner SetFlagsToDefault (); 5430fdc8d8SChris Lattner } 5530fdc8d8SChris Lattner 56c627682eSJim Ingham ThreadPlanStepInRange::ThreadPlanStepInRange 57c627682eSJim Ingham ( 58c627682eSJim Ingham Thread &thread, 59c627682eSJim Ingham const AddressRange &range, 60c627682eSJim Ingham const SymbolContext &addr_context, 61c627682eSJim Ingham const char *step_into_target, 62c627682eSJim Ingham lldb::RunMode stop_others 63c627682eSJim Ingham ) : 64c627682eSJim Ingham ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others), 65c627682eSJim Ingham ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL), 66c627682eSJim Ingham m_step_past_prologue (true), 67c627682eSJim Ingham m_virtual_step (false), 68c627682eSJim Ingham m_step_into_target (step_into_target) 69c627682eSJim Ingham { 70c627682eSJim Ingham SetFlagsToDefault (); 71c627682eSJim Ingham } 72c627682eSJim Ingham 7330fdc8d8SChris Lattner ThreadPlanStepInRange::~ThreadPlanStepInRange () 7430fdc8d8SChris Lattner { 7530fdc8d8SChris Lattner } 7630fdc8d8SChris Lattner 7730fdc8d8SChris Lattner void 7830fdc8d8SChris Lattner ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level) 7930fdc8d8SChris Lattner { 8030fdc8d8SChris Lattner if (level == lldb::eDescriptionLevelBrief) 8130fdc8d8SChris Lattner s->Printf("step in"); 8230fdc8d8SChris Lattner else 8330fdc8d8SChris Lattner { 8430fdc8d8SChris Lattner s->Printf ("Stepping through range (stepping into functions): "); 85c4c9fedcSJim Ingham DumpRanges(s); 864d56e9c1SJim Ingham const char *step_into_target = m_step_into_target.AsCString(); 874d56e9c1SJim Ingham if (step_into_target && step_into_target[0] != '\0') 88c627682eSJim Ingham s->Printf (" targeting %s.", m_step_into_target.AsCString()); 894d56e9c1SJim Ingham else 904d56e9c1SJim Ingham s->PutChar('.'); 9130fdc8d8SChris Lattner } 9230fdc8d8SChris Lattner } 9330fdc8d8SChris Lattner 9430fdc8d8SChris Lattner bool 9530fdc8d8SChris Lattner ThreadPlanStepInRange::ShouldStop (Event *event_ptr) 9630fdc8d8SChris Lattner { 975160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 9830fdc8d8SChris Lattner 9930fdc8d8SChris Lattner if (log) 10030fdc8d8SChris Lattner { 10130fdc8d8SChris Lattner StreamString s; 102514487e8SGreg Clayton s.Address (m_thread.GetRegisterContext()->GetPC(), 1031ac04c30SGreg Clayton m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); 10430fdc8d8SChris Lattner log->Printf("ThreadPlanStepInRange reached %s.", s.GetData()); 10530fdc8d8SChris Lattner } 10630fdc8d8SChris Lattner 10725f66700SJim Ingham if (IsPlanComplete()) 10825f66700SJim Ingham return true; 10925f66700SJim Ingham 1104d56e9c1SJim Ingham m_no_more_plans = false; 1114d56e9c1SJim Ingham if (m_sub_plan_sp && m_sub_plan_sp->IsPlanComplete()) 1124d56e9c1SJim Ingham { 1134d56e9c1SJim Ingham if (!m_sub_plan_sp->PlanSucceeded()) 1144d56e9c1SJim Ingham { 1154d56e9c1SJim Ingham SetPlanComplete(); 1164d56e9c1SJim Ingham m_no_more_plans = true; 1174d56e9c1SJim Ingham return true; 1184d56e9c1SJim Ingham } 1194d56e9c1SJim Ingham else 1204d56e9c1SJim Ingham m_sub_plan_sp.reset(); 1214d56e9c1SJim Ingham } 12230fdc8d8SChris Lattner 123f02a2e96SJim Ingham if (m_virtual_step) 124f02a2e96SJim Ingham { 125f02a2e96SJim Ingham // If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise 126f02a2e96SJim Ingham // we're done. 1274d56e9c1SJim Ingham m_sub_plan_sp = InvokeShouldStopHereCallback(); 128f02a2e96SJim Ingham } 129f02a2e96SJim Ingham else 130f02a2e96SJim Ingham { 1314a58e968SJim Ingham // Stepping through should be done running other threads in general, since we're setting a breakpoint and 1324a58e968SJim Ingham // continuing. So only stop others if we are explicitly told to do so. 1339d790c5dSJim Ingham 13430fdc8d8SChris Lattner bool stop_others; 1354a58e968SJim Ingham if (m_stop_others == lldb::eOnlyThisThread) 1364a58e968SJim Ingham stop_others = true; 1376cf5b8f1SEd Maste else 1386cf5b8f1SEd Maste stop_others = false; 13930fdc8d8SChris Lattner 140b5c0d1ccSJim Ingham FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 141b5c0d1ccSJim Ingham 142b5c0d1ccSJim Ingham if (frame_order == eFrameCompareOlder) 1435822173bSJim Ingham { 1445822173bSJim Ingham // If we're in an older frame then we should stop. 1455822173bSJim Ingham // 1465822173bSJim Ingham // A caveat to this is if we think the frame is older but we're actually in a trampoline. 1475822173bSJim Ingham // I'm going to make the assumption that you wouldn't RETURN to a trampoline. So if we are 1485822173bSJim Ingham // in a trampoline we think the frame is older because the trampoline confused the backtracer. 1494d56e9c1SJim Ingham m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); 1504d56e9c1SJim Ingham if (!m_sub_plan_sp) 1515822173bSJim Ingham return true; 1525822173bSJim Ingham else if (log) 1535822173bSJim Ingham { 1545822173bSJim Ingham log->Printf("Thought I stepped out, but in fact arrived at a trampoline."); 1555822173bSJim Ingham } 1565822173bSJim Ingham 1575822173bSJim Ingham } 158564d8bc2SJim Ingham else if (frame_order == eFrameCompareEqual && InSymbol()) 1595822173bSJim Ingham { 1605822173bSJim Ingham // If we are not in a place we should step through, we're done. 1615822173bSJim Ingham // One tricky bit here is that some stubs don't push a frame, so we have to check 1625822173bSJim Ingham // both the case of a frame that is younger, or the same as this frame. 1635822173bSJim Ingham // However, if the frame is the same, and we are still in the symbol we started 1645822173bSJim Ingham // in, the we don't need to do this. This first check isn't strictly necessary, 1655822173bSJim Ingham // but it is more efficient. 1665822173bSJim Ingham 167564d8bc2SJim Ingham // If we're still in the range, keep going, either by running to the next branch breakpoint, or by 168564d8bc2SJim Ingham // stepping. 169564d8bc2SJim Ingham if (InRange()) 170564d8bc2SJim Ingham { 171564d8bc2SJim Ingham SetNextBranchBreakpoint(); 172564d8bc2SJim Ingham return false; 173564d8bc2SJim Ingham } 174564d8bc2SJim Ingham 1755822173bSJim Ingham SetPlanComplete(); 176c627682eSJim Ingham m_no_more_plans = true; 1775822173bSJim Ingham return true; 1785822173bSJim Ingham } 1795822173bSJim Ingham 180564d8bc2SJim Ingham // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it: 181564d8bc2SJim Ingham ClearNextBranchBreakpoint(); 182564d8bc2SJim Ingham 1835822173bSJim Ingham // We may have set the plan up above in the FrameIsOlder section: 1845822173bSJim Ingham 1854d56e9c1SJim Ingham if (!m_sub_plan_sp) 1864d56e9c1SJim Ingham m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); 18708b87e0dSJim Ingham 18808b87e0dSJim Ingham if (log) 18908b87e0dSJim Ingham { 1904d56e9c1SJim Ingham if (m_sub_plan_sp) 1914d56e9c1SJim Ingham log->Printf ("Found a step through plan: %s", m_sub_plan_sp->GetName()); 19208b87e0dSJim Ingham else 19308b87e0dSJim Ingham log->Printf ("No step through plan found."); 19408b87e0dSJim Ingham } 19508b87e0dSJim Ingham 19630fdc8d8SChris Lattner // If not, give the "should_stop" callback a chance to push a plan to get us out of here. 19730fdc8d8SChris Lattner // But only do that if we actually have stepped in. 1984d56e9c1SJim Ingham if (!m_sub_plan_sp && frame_order == eFrameCompareYounger) 1994d56e9c1SJim Ingham m_sub_plan_sp = InvokeShouldStopHereCallback(); 20030fdc8d8SChris Lattner 2017ce490c6SJim Ingham // If we've stepped in and we are going to stop here, check to see if we were asked to 2027ce490c6SJim Ingham // run past the prologue, and if so do that. 2037ce490c6SJim Ingham 2044d56e9c1SJim Ingham if (!m_sub_plan_sp && frame_order == eFrameCompareYounger && m_step_past_prologue) 2057ce490c6SJim Ingham { 206b57e4a1bSJason Molenda lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0); 2077ce490c6SJim Ingham if (curr_frame) 2087ce490c6SJim Ingham { 2097ce490c6SJim Ingham size_t bytes_to_skip = 0; 2107ce490c6SJim Ingham lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC(); 2117ce490c6SJim Ingham Address func_start_address; 2127ce490c6SJim Ingham 2137ce490c6SJim Ingham SymbolContext sc = curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextSymbol); 2147ce490c6SJim Ingham 2157ce490c6SJim Ingham if (sc.function) 2167ce490c6SJim Ingham { 2177ce490c6SJim Ingham func_start_address = sc.function->GetAddressRange().GetBaseAddress(); 218d9e416c0SGreg Clayton if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) 2197ce490c6SJim Ingham bytes_to_skip = sc.function->GetPrologueByteSize(); 2207ce490c6SJim Ingham } 2217ce490c6SJim Ingham else if (sc.symbol) 2227ce490c6SJim Ingham { 223e7612134SGreg Clayton func_start_address = sc.symbol->GetAddress(); 224d9e416c0SGreg Clayton if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) 2257ce490c6SJim Ingham bytes_to_skip = sc.symbol->GetPrologueByteSize(); 2267ce490c6SJim Ingham } 2277ce490c6SJim Ingham 2287ce490c6SJim Ingham if (bytes_to_skip != 0) 2297ce490c6SJim Ingham { 2307ce490c6SJim Ingham func_start_address.Slide (bytes_to_skip); 23120ad3c40SCaroline Tice log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 2327ce490c6SJim Ingham if (log) 2337ce490c6SJim Ingham log->Printf ("Pushing past prologue "); 2347ce490c6SJim Ingham 2354d56e9c1SJim Ingham m_sub_plan_sp = m_thread.QueueThreadPlanForRunToAddress(false, func_start_address,true); 2367ce490c6SJim Ingham } 2377ce490c6SJim Ingham } 2387ce490c6SJim Ingham } 239f02a2e96SJim Ingham } 2407ce490c6SJim Ingham 2414d56e9c1SJim Ingham if (!m_sub_plan_sp) 24230fdc8d8SChris Lattner { 24330fdc8d8SChris Lattner m_no_more_plans = true; 24430fdc8d8SChris Lattner SetPlanComplete(); 24530fdc8d8SChris Lattner return true; 24630fdc8d8SChris Lattner } 24730fdc8d8SChris Lattner else 24830fdc8d8SChris Lattner { 24930fdc8d8SChris Lattner m_no_more_plans = false; 25030fdc8d8SChris Lattner return false; 25130fdc8d8SChris Lattner } 25230fdc8d8SChris Lattner } 25330fdc8d8SChris Lattner 25430fdc8d8SChris Lattner void 25530fdc8d8SChris Lattner ThreadPlanStepInRange::SetFlagsToDefault () 25630fdc8d8SChris Lattner { 25730fdc8d8SChris Lattner GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values); 25830fdc8d8SChris Lattner } 25930fdc8d8SChris Lattner 26030fdc8d8SChris Lattner void 261a56c8006SJim Ingham ThreadPlanStepInRange::SetAvoidRegexp(const char *name) 262a56c8006SJim Ingham { 263a56c8006SJim Ingham if (m_avoid_regexp_ap.get() == NULL) 264a56c8006SJim Ingham m_avoid_regexp_ap.reset (new RegularExpression(name)); 265a56c8006SJim Ingham 266a56c8006SJim Ingham m_avoid_regexp_ap->Compile (name); 267a56c8006SJim Ingham } 268a56c8006SJim Ingham 269a56c8006SJim Ingham void 27030fdc8d8SChris Lattner ThreadPlanStepInRange::SetDefaultFlagValue (uint32_t new_value) 27130fdc8d8SChris Lattner { 27230fdc8d8SChris Lattner // TODO: Should we test this for sanity? 27330fdc8d8SChris Lattner ThreadPlanStepInRange::s_default_flag_values = new_value; 27430fdc8d8SChris Lattner } 27530fdc8d8SChris Lattner 276a56c8006SJim Ingham bool 277*4da6206dSJim Ingham ThreadPlanStepInRange::FrameMatchesAvoidCriteria () 278a56c8006SJim Ingham { 279b57e4a1bSJason Molenda StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get(); 280a56c8006SJim Ingham 281*4da6206dSJim Ingham // Check the library list first, as that's cheapest: 282*4da6206dSJim Ingham FileSpecList libraries_to_avoid (GetThread().GetLibrariesToAvoid()); 283*4da6206dSJim Ingham size_t num_libraries = libraries_to_avoid.GetSize(); 284*4da6206dSJim Ingham bool libraries_say_avoid = false; 285*4da6206dSJim Ingham SymbolContext sc(frame->GetSymbolContext(eSymbolContextModule)); 286*4da6206dSJim Ingham FileSpec frame_library(sc.module_sp->GetFileSpec()); 287*4da6206dSJim Ingham 288*4da6206dSJim Ingham if (frame_library) 289*4da6206dSJim Ingham { 290*4da6206dSJim Ingham for (size_t i = 0; i < num_libraries; i++) 291*4da6206dSJim Ingham { 292*4da6206dSJim Ingham const FileSpec &file_spec(libraries_to_avoid.GetFileSpecAtIndex(i)); 293*4da6206dSJim Ingham if (FileSpec::Equal (file_spec, frame_library, false)) 294*4da6206dSJim Ingham { 295*4da6206dSJim Ingham libraries_say_avoid = true; 296*4da6206dSJim Ingham break; 297*4da6206dSJim Ingham } 298*4da6206dSJim Ingham } 299*4da6206dSJim Ingham } 300*4da6206dSJim Ingham if (libraries_say_avoid) 301*4da6206dSJim Ingham return true; 302*4da6206dSJim Ingham 30367cc0636SGreg Clayton const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get(); 304ee8aea10SJim Ingham if (avoid_regexp_to_use == NULL) 305ee8aea10SJim Ingham avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp(); 306ee8aea10SJim Ingham 307ee8aea10SJim Ingham if (avoid_regexp_to_use != NULL) 308a56c8006SJim Ingham { 3094592cbc4SGreg Clayton SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); 310a56c8006SJim Ingham if (sc.symbol != NULL) 311a56c8006SJim Ingham { 3124592cbc4SGreg Clayton const char *frame_function_name = sc.GetFunctionName().GetCString(); 3134592cbc4SGreg Clayton if (frame_function_name) 3143101ba33SJim Ingham { 315cf2667c4SJim Ingham size_t num_matches = 0; 3165160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 3173101ba33SJim Ingham if (log) 318cf2667c4SJim Ingham num_matches = 1; 319bc43cab5SGreg Clayton 320bc43cab5SGreg Clayton RegularExpression::Match regex_match(num_matches); 321bc43cab5SGreg Clayton 322bc43cab5SGreg Clayton bool return_value = avoid_regexp_to_use->Execute(frame_function_name, ®ex_match); 323cf2667c4SJim Ingham if (return_value) 324cf2667c4SJim Ingham { 325cf2667c4SJim Ingham if (log) 326cf2667c4SJim Ingham { 327cf2667c4SJim Ingham std::string match; 328bc43cab5SGreg Clayton regex_match.GetMatchAtIndex(frame_function_name,0, match); 329cf2667c4SJim Ingham log->Printf ("Stepping out of function \"%s\" because it matches the avoid regexp \"%s\" - match substring: \"%s\".", 3303101ba33SJim Ingham frame_function_name, 331cf2667c4SJim Ingham avoid_regexp_to_use->GetText(), 332cf2667c4SJim Ingham match.c_str()); 333cf2667c4SJim Ingham } 3343101ba33SJim Ingham 3353101ba33SJim Ingham } 3363101ba33SJim Ingham return return_value; 3373101ba33SJim Ingham } 338a56c8006SJim Ingham } 339a56c8006SJim Ingham } 340a56c8006SJim Ingham return false; 341a56c8006SJim Ingham } 342a56c8006SJim Ingham 3434d56e9c1SJim Ingham ThreadPlanSP 34430fdc8d8SChris Lattner ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton) 34530fdc8d8SChris Lattner { 346a56c8006SJim Ingham bool should_step_out = false; 347b57e4a1bSJason Molenda StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get(); 3485160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 34930fdc8d8SChris Lattner 35073b472d4SGreg Clayton if (flags.Test(eAvoidNoDebug)) 351a56c8006SJim Ingham { 35230fdc8d8SChris Lattner if (!frame->HasDebugInformation()) 353af0f1759SJim Ingham { 354af0f1759SJim Ingham if (log) 355af0f1759SJim Ingham log->Printf ("Stepping out of frame with no debug info"); 356af0f1759SJim Ingham 357a56c8006SJim Ingham should_step_out = true; 358a56c8006SJim Ingham } 359af0f1759SJim Ingham } 360a56c8006SJim Ingham 361a56c8006SJim Ingham if (current_plan->GetKind() == eKindStepInRange) 362a56c8006SJim Ingham { 363a56c8006SJim Ingham ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); 364c627682eSJim Ingham if (step_in_range_plan->m_step_into_target) 365c627682eSJim Ingham { 366c627682eSJim Ingham SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); 367c627682eSJim Ingham if (sc.symbol != NULL) 368c627682eSJim Ingham { 369c627682eSJim Ingham // First try an exact match, since that's cheap with ConstStrings. Then do a strstr compare. 370c627682eSJim Ingham if (step_in_range_plan->m_step_into_target == sc.GetFunctionName()) 371c627682eSJim Ingham { 372c627682eSJim Ingham should_step_out = false; 373c627682eSJim Ingham } 374c627682eSJim Ingham else 375c627682eSJim Ingham { 376c627682eSJim Ingham const char *target_name = step_in_range_plan->m_step_into_target.AsCString(); 377c627682eSJim Ingham const char *function_name = sc.GetFunctionName().AsCString(); 378c627682eSJim Ingham 379c627682eSJim Ingham if (function_name == NULL) 380c627682eSJim Ingham should_step_out = true; 381c627682eSJim Ingham else if (strstr (function_name, target_name) == NULL) 382c627682eSJim Ingham should_step_out = true; 383c627682eSJim Ingham } 3843101ba33SJim Ingham if (log && should_step_out) 3853101ba33SJim Ingham log->Printf("Stepping out of frame %s which did not match step into target %s.", 3863101ba33SJim Ingham sc.GetFunctionName().AsCString(), 3873101ba33SJim Ingham step_in_range_plan->m_step_into_target.AsCString()); 388c627682eSJim Ingham } 389c627682eSJim Ingham } 390c627682eSJim Ingham 391c627682eSJim Ingham if (!should_step_out) 392c627682eSJim Ingham { 393c627682eSJim Ingham ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); 394*4da6206dSJim Ingham // Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidCriteria. 395*4da6206dSJim Ingham should_step_out = step_in_range_plan->FrameMatchesAvoidCriteria (); 396a56c8006SJim Ingham } 397a56c8006SJim Ingham } 398a56c8006SJim Ingham 399c627682eSJim Ingham 400a56c8006SJim Ingham if (should_step_out) 40130fdc8d8SChris Lattner { 40230fdc8d8SChris Lattner // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions. 4034a58e968SJim Ingham // We really should have all plans take the tri-state for "stop others" so we can do the right 4044a58e968SJim Ingham // thing. For now let's be safe and always run others when we are likely to run arbitrary code. 4054a58e968SJim Ingham const bool stop_others = false; 406481cef25SGreg Clayton return current_plan->GetThread().QueueThreadPlanForStepOut (false, 407481cef25SGreg Clayton NULL, 408481cef25SGreg Clayton true, 4094a58e968SJim Ingham stop_others, 410481cef25SGreg Clayton eVoteNo, 411481cef25SGreg Clayton eVoteNoOpinion, 412481cef25SGreg Clayton 0); // Frame index 41330fdc8d8SChris Lattner } 41430fdc8d8SChris Lattner 4154d56e9c1SJim Ingham return ThreadPlanSP(); 41630fdc8d8SChris Lattner } 417fbbfe6ecSJim Ingham 418fbbfe6ecSJim Ingham bool 419221d51cfSJim Ingham ThreadPlanStepInRange::DoPlanExplainsStop (Event *event_ptr) 420fbbfe6ecSJim Ingham { 421fbbfe6ecSJim Ingham // We always explain a stop. Either we've just done a single step, in which 422fbbfe6ecSJim Ingham // case we'll do our ordinary processing, or we stopped for some 423fbbfe6ecSJim Ingham // reason that isn't handled by our sub-plans, in which case we want to just stop right 424fbbfe6ecSJim Ingham // away. 425c627682eSJim Ingham // In general, we don't want to mark the plan as complete for unexplained stops. 426c627682eSJim Ingham // For instance, if you step in to some code with no debug info, so you step out 427c627682eSJim Ingham // and in the course of that hit a breakpoint, then you want to stop & show the user 428c627682eSJim Ingham // the breakpoint, but not unship the step in plan, since you still may want to complete that 429c627682eSJim Ingham // plan when you continue. This is particularly true when doing "step in to target function." 430c627682eSJim Ingham // stepping. 431fbbfe6ecSJim Ingham // 432fbbfe6ecSJim Ingham // The only variation is that if we are doing "step by running to next branch" in which case 433fbbfe6ecSJim Ingham // if we hit our branch breakpoint we don't set the plan to complete. 434fbbfe6ecSJim Ingham 435221d51cfSJim Ingham bool return_value; 436f02a2e96SJim Ingham 437221d51cfSJim Ingham if (m_virtual_step) 438221d51cfSJim Ingham { 439221d51cfSJim Ingham return_value = true; 440221d51cfSJim Ingham } 441221d51cfSJim Ingham else 442221d51cfSJim Ingham { 44360c4118cSJim Ingham StopInfoSP stop_info_sp = GetPrivateStopInfo (); 444fbbfe6ecSJim Ingham if (stop_info_sp) 445fbbfe6ecSJim Ingham { 446fbbfe6ecSJim Ingham StopReason reason = stop_info_sp->GetStopReason(); 447fbbfe6ecSJim Ingham 448fbbfe6ecSJim Ingham switch (reason) 449fbbfe6ecSJim Ingham { 450fbbfe6ecSJim Ingham case eStopReasonBreakpoint: 451fbbfe6ecSJim Ingham if (NextRangeBreakpointExplainsStop(stop_info_sp)) 452221d51cfSJim Ingham { 453221d51cfSJim Ingham return_value = true; 454221d51cfSJim Ingham break; 455221d51cfSJim Ingham } 456fbbfe6ecSJim Ingham case eStopReasonWatchpoint: 457fbbfe6ecSJim Ingham case eStopReasonSignal: 458fbbfe6ecSJim Ingham case eStopReasonException: 45990ba8115SGreg Clayton case eStopReasonExec: 460f85defaeSAndrew Kaylor case eStopReasonThreadExiting: 461513c6bb8SJim Ingham { 4625160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 463fbbfe6ecSJim Ingham if (log) 464fbbfe6ecSJim Ingham log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step."); 465513c6bb8SJim Ingham } 466221d51cfSJim Ingham return_value = false; 467fbbfe6ecSJim Ingham break; 468fbbfe6ecSJim Ingham default: 469221d51cfSJim Ingham return_value = true; 470fbbfe6ecSJim Ingham break; 471fbbfe6ecSJim Ingham } 472fbbfe6ecSJim Ingham } 473221d51cfSJim Ingham else 474221d51cfSJim Ingham return_value = true; 475221d51cfSJim Ingham } 476221d51cfSJim Ingham 477221d51cfSJim Ingham return return_value; 478fbbfe6ecSJim Ingham } 479513c6bb8SJim Ingham 480513c6bb8SJim Ingham bool 481221d51cfSJim Ingham ThreadPlanStepInRange::DoWillResume (lldb::StateType resume_state, bool current_plan) 482513c6bb8SJim Ingham { 483513c6bb8SJim Ingham if (resume_state == eStateStepping && current_plan) 484513c6bb8SJim Ingham { 485513c6bb8SJim Ingham // See if we are about to step over a virtual inlined call. 486513c6bb8SJim Ingham bool step_without_resume = m_thread.DecrementCurrentInlinedDepth(); 487513c6bb8SJim Ingham if (step_without_resume) 488513c6bb8SJim Ingham { 4895160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 490513c6bb8SJim Ingham if (log) 491221d51cfSJim Ingham log->Printf ("ThreadPlanStepInRange::DoWillResume: returning false, inline_depth: %d", 492513c6bb8SJim Ingham m_thread.GetCurrentInlinedDepth()); 493513c6bb8SJim Ingham SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread)); 494f02a2e96SJim Ingham 495f02a2e96SJim Ingham // FIXME: Maybe it would be better to create a InlineStep stop reason, but then 496f02a2e96SJim Ingham // the whole rest of the world would have to handle that stop reason. 497f02a2e96SJim Ingham m_virtual_step = true; 498513c6bb8SJim Ingham } 499513c6bb8SJim Ingham return !step_without_resume; 500513c6bb8SJim Ingham } 501221d51cfSJim Ingham return true; 502513c6bb8SJim Ingham } 503246cb611SDaniel Malea 504246cb611SDaniel Malea bool 505246cb611SDaniel Malea ThreadPlanStepInRange::IsVirtualStep() 506246cb611SDaniel Malea { 507246cb611SDaniel Malea return m_virtual_step; 508246cb611SDaniel Malea } 509