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 #include "lldb/Core/Log.h" 174da6206dSJim Ingham #include "lldb/Core/Module.h" 1830fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 19a56c8006SJim Ingham #include "lldb/Symbol/Symbol.h" 207ce490c6SJim Ingham #include "lldb/Symbol/Function.h" 2130fdc8d8SChris Lattner #include "lldb/Target/Process.h" 2230fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 23514487e8SGreg Clayton #include "lldb/Target/Target.h" 2430fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 2530fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepOut.h" 2630fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepThrough.h" 27a56c8006SJim Ingham #include "lldb/Core/RegularExpression.h" 2830fdc8d8SChris Lattner 2930fdc8d8SChris Lattner using namespace lldb; 3030fdc8d8SChris Lattner using namespace lldb_private; 3130fdc8d8SChris Lattner 324b4b2478SJim Ingham uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eStepInAvoidNoDebug; 3330fdc8d8SChris Lattner 3430fdc8d8SChris Lattner //---------------------------------------------------------------------- 3530fdc8d8SChris Lattner // ThreadPlanStepInRange: Step through a stack range, either stepping over or into 3630fdc8d8SChris Lattner // based on the value of \a type. 3730fdc8d8SChris Lattner //---------------------------------------------------------------------- 3830fdc8d8SChris Lattner 3930fdc8d8SChris Lattner ThreadPlanStepInRange::ThreadPlanStepInRange 4030fdc8d8SChris Lattner ( 4130fdc8d8SChris Lattner Thread &thread, 4230fdc8d8SChris Lattner const AddressRange &range, 4330fdc8d8SChris Lattner const SymbolContext &addr_context, 444b4b2478SJim Ingham lldb::RunMode stop_others, 454b4b2478SJim Ingham LazyBool step_in_avoids_code_without_debug_info, 464b4b2478SJim Ingham LazyBool step_out_avoids_code_without_debug_info 4730fdc8d8SChris Lattner ) : 48b01e742aSJim Ingham ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others), 494b4b2478SJim Ingham ThreadPlanShouldStopHere (this), 50f02a2e96SJim Ingham m_step_past_prologue (true), 51f02a2e96SJim Ingham m_virtual_step (false) 5230fdc8d8SChris Lattner { 534b4b2478SJim Ingham SetCallbacks(); 5430fdc8d8SChris Lattner SetFlagsToDefault (); 554b4b2478SJim Ingham SetupAvoidNoDebug(step_in_avoids_code_without_debug_info, step_out_avoids_code_without_debug_info); 5630fdc8d8SChris Lattner } 5730fdc8d8SChris Lattner 58c627682eSJim Ingham ThreadPlanStepInRange::ThreadPlanStepInRange 59c627682eSJim Ingham ( 60c627682eSJim Ingham Thread &thread, 61c627682eSJim Ingham const AddressRange &range, 62c627682eSJim Ingham const SymbolContext &addr_context, 63c627682eSJim Ingham const char *step_into_target, 644b4b2478SJim Ingham lldb::RunMode stop_others, 654b4b2478SJim Ingham LazyBool step_in_avoids_code_without_debug_info, 664b4b2478SJim Ingham LazyBool step_out_avoids_code_without_debug_info 67c627682eSJim Ingham ) : 68c627682eSJim Ingham ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others), 694b4b2478SJim Ingham ThreadPlanShouldStopHere (this), 70c627682eSJim Ingham m_step_past_prologue (true), 71c627682eSJim Ingham m_virtual_step (false), 72c627682eSJim Ingham m_step_into_target (step_into_target) 73c627682eSJim Ingham { 744b4b2478SJim Ingham SetCallbacks(); 75c627682eSJim Ingham SetFlagsToDefault (); 764b4b2478SJim Ingham SetupAvoidNoDebug(step_in_avoids_code_without_debug_info, step_out_avoids_code_without_debug_info); 77c627682eSJim Ingham } 78c627682eSJim Ingham 7930fdc8d8SChris Lattner ThreadPlanStepInRange::~ThreadPlanStepInRange () 8030fdc8d8SChris Lattner { 8130fdc8d8SChris Lattner } 8230fdc8d8SChris Lattner 8330fdc8d8SChris Lattner void 844b4b2478SJim Ingham ThreadPlanStepInRange::SetupAvoidNoDebug(LazyBool step_in_avoids_code_without_debug_info, 854b4b2478SJim Ingham LazyBool step_out_avoids_code_without_debug_info) 864b4b2478SJim Ingham { 874b4b2478SJim Ingham bool avoid_nodebug = true; 884b4b2478SJim Ingham 894b4b2478SJim Ingham switch (step_in_avoids_code_without_debug_info) 904b4b2478SJim Ingham { 914b4b2478SJim Ingham case eLazyBoolYes: 924b4b2478SJim Ingham avoid_nodebug = true; 934b4b2478SJim Ingham break; 944b4b2478SJim Ingham case eLazyBoolNo: 954b4b2478SJim Ingham avoid_nodebug = false; 964b4b2478SJim Ingham break; 974b4b2478SJim Ingham case eLazyBoolCalculate: 984b4b2478SJim Ingham avoid_nodebug = m_thread.GetStepInAvoidsNoDebug(); 994b4b2478SJim Ingham break; 1004b4b2478SJim Ingham } 1014b4b2478SJim Ingham if (avoid_nodebug) 1024b4b2478SJim Ingham GetFlags().Set (ThreadPlanShouldStopHere::eStepInAvoidNoDebug); 1034b4b2478SJim Ingham else 1044b4b2478SJim Ingham GetFlags().Clear (ThreadPlanShouldStopHere::eStepInAvoidNoDebug); 1054b4b2478SJim Ingham 1064b4b2478SJim Ingham switch (step_out_avoids_code_without_debug_info) 1074b4b2478SJim Ingham { 1084b4b2478SJim Ingham case eLazyBoolYes: 1094b4b2478SJim Ingham avoid_nodebug = true; 1104b4b2478SJim Ingham break; 1114b4b2478SJim Ingham case eLazyBoolNo: 1124b4b2478SJim Ingham avoid_nodebug = false; 1134b4b2478SJim Ingham break; 1144b4b2478SJim Ingham case eLazyBoolCalculate: 1154b4b2478SJim Ingham avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug(); 1164b4b2478SJim Ingham break; 1174b4b2478SJim Ingham } 1184b4b2478SJim Ingham if (avoid_nodebug) 1194b4b2478SJim Ingham GetFlags().Set (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug); 1204b4b2478SJim Ingham else 1214b4b2478SJim Ingham GetFlags().Clear (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug); 1224b4b2478SJim Ingham } 1234b4b2478SJim Ingham 1244b4b2478SJim Ingham void 12530fdc8d8SChris Lattner ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level) 12630fdc8d8SChris Lattner { 12730fdc8d8SChris Lattner if (level == lldb::eDescriptionLevelBrief) 12830fdc8d8SChris Lattner { 1292bdbfd50SJim Ingham s->Printf("step in"); 1302bdbfd50SJim Ingham return; 1312bdbfd50SJim Ingham } 1322bdbfd50SJim Ingham 1332bdbfd50SJim Ingham s->Printf ("Stepping in"); 1342bdbfd50SJim Ingham bool printed_line_info = false; 1352bdbfd50SJim Ingham if (m_addr_context.line_entry.IsValid()) 1362bdbfd50SJim Ingham { 1372bdbfd50SJim Ingham s->Printf (" through line "); 1382bdbfd50SJim Ingham m_addr_context.line_entry.DumpStopContext (s, false); 1392bdbfd50SJim Ingham printed_line_info = true; 1402bdbfd50SJim Ingham } 1412bdbfd50SJim Ingham 1424d56e9c1SJim Ingham const char *step_into_target = m_step_into_target.AsCString(); 1434d56e9c1SJim Ingham if (step_into_target && step_into_target[0] != '\0') 1442bdbfd50SJim Ingham s->Printf (" targeting %s", m_step_into_target.AsCString()); 1452bdbfd50SJim Ingham 1462bdbfd50SJim Ingham if (!printed_line_info || level == eDescriptionLevelVerbose) 1472bdbfd50SJim Ingham { 1482bdbfd50SJim Ingham s->Printf (" using ranges:"); 1492bdbfd50SJim Ingham DumpRanges(s); 15030fdc8d8SChris Lattner } 1512bdbfd50SJim Ingham 1522bdbfd50SJim Ingham s->PutChar('.'); 15330fdc8d8SChris Lattner } 15430fdc8d8SChris Lattner 15530fdc8d8SChris Lattner bool 15630fdc8d8SChris Lattner ThreadPlanStepInRange::ShouldStop (Event *event_ptr) 15730fdc8d8SChris Lattner { 1585160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 15930fdc8d8SChris Lattner 16030fdc8d8SChris Lattner if (log) 16130fdc8d8SChris Lattner { 16230fdc8d8SChris Lattner StreamString s; 163514487e8SGreg Clayton s.Address (m_thread.GetRegisterContext()->GetPC(), 1641ac04c30SGreg Clayton m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize()); 16530fdc8d8SChris Lattner log->Printf("ThreadPlanStepInRange reached %s.", s.GetData()); 16630fdc8d8SChris Lattner } 16730fdc8d8SChris Lattner 16825f66700SJim Ingham if (IsPlanComplete()) 16925f66700SJim Ingham return true; 17025f66700SJim Ingham 1714d56e9c1SJim Ingham m_no_more_plans = false; 1724d56e9c1SJim Ingham if (m_sub_plan_sp && m_sub_plan_sp->IsPlanComplete()) 1734d56e9c1SJim Ingham { 1744d56e9c1SJim Ingham if (!m_sub_plan_sp->PlanSucceeded()) 1754d56e9c1SJim Ingham { 1764d56e9c1SJim Ingham SetPlanComplete(); 1774d56e9c1SJim Ingham m_no_more_plans = true; 1784d56e9c1SJim Ingham return true; 1794d56e9c1SJim Ingham } 1804d56e9c1SJim Ingham else 1814d56e9c1SJim Ingham m_sub_plan_sp.reset(); 1824d56e9c1SJim Ingham } 18330fdc8d8SChris Lattner 184f02a2e96SJim Ingham if (m_virtual_step) 185f02a2e96SJim Ingham { 186f02a2e96SJim Ingham // If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise 187f02a2e96SJim Ingham // we're done. 1884b4b2478SJim Ingham // FIXME - This can be both a step in and a step out. Probably should record which in the m_virtual_step. 1894b4b2478SJim Ingham m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger); 190f02a2e96SJim Ingham } 191f02a2e96SJim Ingham else 192f02a2e96SJim Ingham { 1934a58e968SJim Ingham // Stepping through should be done running other threads in general, since we're setting a breakpoint and 1944a58e968SJim Ingham // continuing. So only stop others if we are explicitly told to do so. 1959d790c5dSJim Ingham 19630fdc8d8SChris Lattner bool stop_others; 1974a58e968SJim Ingham if (m_stop_others == lldb::eOnlyThisThread) 1984a58e968SJim Ingham stop_others = true; 1996cf5b8f1SEd Maste else 2006cf5b8f1SEd Maste stop_others = false; 20130fdc8d8SChris Lattner 202b5c0d1ccSJim Ingham FrameComparison frame_order = CompareCurrentFrameToStartFrame(); 203b5c0d1ccSJim Ingham 204862d1bbdSJim Ingham if (frame_order == eFrameCompareOlder || frame_order == eFrameCompareSameParent) 2055822173bSJim Ingham { 2065822173bSJim Ingham // If we're in an older frame then we should stop. 2075822173bSJim Ingham // 2085822173bSJim Ingham // A caveat to this is if we think the frame is older but we're actually in a trampoline. 2095822173bSJim Ingham // I'm going to make the assumption that you wouldn't RETURN to a trampoline. So if we are 2105822173bSJim Ingham // in a trampoline we think the frame is older because the trampoline confused the backtracer. 2114d56e9c1SJim Ingham m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); 2124d56e9c1SJim Ingham if (!m_sub_plan_sp) 2134b4b2478SJim Ingham { 2144b4b2478SJim Ingham // Otherwise check the ShouldStopHere for step out: 215862d1bbdSJim Ingham m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order); 2164b4b2478SJim Ingham if (log) 2174b4b2478SJim Ingham log->Printf ("ShouldStopHere says we should step out of this frame."); 2184b4b2478SJim Ingham } 2195822173bSJim Ingham else if (log) 2205822173bSJim Ingham { 2215822173bSJim Ingham log->Printf("Thought I stepped out, but in fact arrived at a trampoline."); 2225822173bSJim Ingham } 2235822173bSJim Ingham 2245822173bSJim Ingham } 225564d8bc2SJim Ingham else if (frame_order == eFrameCompareEqual && InSymbol()) 2265822173bSJim Ingham { 2275822173bSJim Ingham // If we are not in a place we should step through, we're done. 2285822173bSJim Ingham // One tricky bit here is that some stubs don't push a frame, so we have to check 2295822173bSJim Ingham // both the case of a frame that is younger, or the same as this frame. 2305822173bSJim Ingham // However, if the frame is the same, and we are still in the symbol we started 2315822173bSJim Ingham // in, the we don't need to do this. This first check isn't strictly necessary, 2325822173bSJim Ingham // but it is more efficient. 2335822173bSJim Ingham 234564d8bc2SJim Ingham // If we're still in the range, keep going, either by running to the next branch breakpoint, or by 235564d8bc2SJim Ingham // stepping. 236564d8bc2SJim Ingham if (InRange()) 237564d8bc2SJim Ingham { 238564d8bc2SJim Ingham SetNextBranchBreakpoint(); 239564d8bc2SJim Ingham return false; 240564d8bc2SJim Ingham } 241564d8bc2SJim Ingham 2425822173bSJim Ingham SetPlanComplete(); 243c627682eSJim Ingham m_no_more_plans = true; 2445822173bSJim Ingham return true; 2455822173bSJim Ingham } 2465822173bSJim Ingham 247564d8bc2SJim Ingham // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it: 248564d8bc2SJim Ingham ClearNextBranchBreakpoint(); 249564d8bc2SJim Ingham 2505822173bSJim Ingham // We may have set the plan up above in the FrameIsOlder section: 2515822173bSJim Ingham 2524d56e9c1SJim Ingham if (!m_sub_plan_sp) 2534d56e9c1SJim Ingham m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); 25408b87e0dSJim Ingham 25508b87e0dSJim Ingham if (log) 25608b87e0dSJim Ingham { 2574d56e9c1SJim Ingham if (m_sub_plan_sp) 2584d56e9c1SJim Ingham log->Printf ("Found a step through plan: %s", m_sub_plan_sp->GetName()); 25908b87e0dSJim Ingham else 26008b87e0dSJim Ingham log->Printf ("No step through plan found."); 26108b87e0dSJim Ingham } 26208b87e0dSJim Ingham 26330fdc8d8SChris Lattner // If not, give the "should_stop" callback a chance to push a plan to get us out of here. 26430fdc8d8SChris Lattner // But only do that if we actually have stepped in. 2654d56e9c1SJim Ingham if (!m_sub_plan_sp && frame_order == eFrameCompareYounger) 2664b4b2478SJim Ingham m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order); 26730fdc8d8SChris Lattner 2687ce490c6SJim Ingham // If we've stepped in and we are going to stop here, check to see if we were asked to 2697ce490c6SJim Ingham // run past the prologue, and if so do that. 2707ce490c6SJim Ingham 2714d56e9c1SJim Ingham if (!m_sub_plan_sp && frame_order == eFrameCompareYounger && m_step_past_prologue) 2727ce490c6SJim Ingham { 273b57e4a1bSJason Molenda lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0); 2747ce490c6SJim Ingham if (curr_frame) 2757ce490c6SJim Ingham { 2767ce490c6SJim Ingham size_t bytes_to_skip = 0; 2777ce490c6SJim Ingham lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC(); 2787ce490c6SJim Ingham Address func_start_address; 2797ce490c6SJim Ingham 2807ce490c6SJim Ingham SymbolContext sc = curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextSymbol); 2817ce490c6SJim Ingham 2827ce490c6SJim Ingham if (sc.function) 2837ce490c6SJim Ingham { 2847ce490c6SJim Ingham func_start_address = sc.function->GetAddressRange().GetBaseAddress(); 285d9e416c0SGreg Clayton if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) 2867ce490c6SJim Ingham bytes_to_skip = sc.function->GetPrologueByteSize(); 2877ce490c6SJim Ingham } 2887ce490c6SJim Ingham else if (sc.symbol) 2897ce490c6SJim Ingham { 290e7612134SGreg Clayton func_start_address = sc.symbol->GetAddress(); 291d9e416c0SGreg Clayton if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) 2927ce490c6SJim Ingham bytes_to_skip = sc.symbol->GetPrologueByteSize(); 2937ce490c6SJim Ingham } 2947ce490c6SJim Ingham 2957ce490c6SJim Ingham if (bytes_to_skip != 0) 2967ce490c6SJim Ingham { 2977ce490c6SJim Ingham func_start_address.Slide (bytes_to_skip); 29820ad3c40SCaroline Tice log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 2997ce490c6SJim Ingham if (log) 3007ce490c6SJim Ingham log->Printf ("Pushing past prologue "); 3017ce490c6SJim Ingham 3024d56e9c1SJim Ingham m_sub_plan_sp = m_thread.QueueThreadPlanForRunToAddress(false, func_start_address,true); 3037ce490c6SJim Ingham } 3047ce490c6SJim Ingham } 3057ce490c6SJim Ingham } 306f02a2e96SJim Ingham } 3077ce490c6SJim Ingham 3084d56e9c1SJim Ingham if (!m_sub_plan_sp) 30930fdc8d8SChris Lattner { 31030fdc8d8SChris Lattner m_no_more_plans = true; 31130fdc8d8SChris Lattner SetPlanComplete(); 31230fdc8d8SChris Lattner return true; 31330fdc8d8SChris Lattner } 31430fdc8d8SChris Lattner else 31530fdc8d8SChris Lattner { 31630fdc8d8SChris Lattner m_no_more_plans = false; 3172bdbfd50SJim Ingham m_sub_plan_sp->SetPrivate(true); 31830fdc8d8SChris Lattner return false; 31930fdc8d8SChris Lattner } 32030fdc8d8SChris Lattner } 32130fdc8d8SChris Lattner 32230fdc8d8SChris Lattner void 323a56c8006SJim Ingham ThreadPlanStepInRange::SetAvoidRegexp(const char *name) 324a56c8006SJim Ingham { 325a56c8006SJim Ingham if (m_avoid_regexp_ap.get() == NULL) 326a56c8006SJim Ingham m_avoid_regexp_ap.reset (new RegularExpression(name)); 327a56c8006SJim Ingham 328a56c8006SJim Ingham m_avoid_regexp_ap->Compile (name); 329a56c8006SJim Ingham } 330a56c8006SJim Ingham 331a56c8006SJim Ingham void 33230fdc8d8SChris Lattner ThreadPlanStepInRange::SetDefaultFlagValue (uint32_t new_value) 33330fdc8d8SChris Lattner { 33430fdc8d8SChris Lattner // TODO: Should we test this for sanity? 33530fdc8d8SChris Lattner ThreadPlanStepInRange::s_default_flag_values = new_value; 33630fdc8d8SChris Lattner } 33730fdc8d8SChris Lattner 338a56c8006SJim Ingham bool 3394da6206dSJim Ingham ThreadPlanStepInRange::FrameMatchesAvoidCriteria () 340a56c8006SJim Ingham { 341b57e4a1bSJason Molenda StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get(); 342a56c8006SJim Ingham 3434da6206dSJim Ingham // Check the library list first, as that's cheapest: 344a786e539SJim Ingham bool libraries_say_avoid = false; 345a786e539SJim Ingham 3464da6206dSJim Ingham FileSpecList libraries_to_avoid (GetThread().GetLibrariesToAvoid()); 3474da6206dSJim Ingham size_t num_libraries = libraries_to_avoid.GetSize(); 348a786e539SJim Ingham if (num_libraries > 0) 349a786e539SJim Ingham { 3504da6206dSJim Ingham SymbolContext sc(frame->GetSymbolContext(eSymbolContextModule)); 3514da6206dSJim Ingham FileSpec frame_library(sc.module_sp->GetFileSpec()); 3524da6206dSJim Ingham 3534da6206dSJim Ingham if (frame_library) 3544da6206dSJim Ingham { 3554da6206dSJim Ingham for (size_t i = 0; i < num_libraries; i++) 3564da6206dSJim Ingham { 3574da6206dSJim Ingham const FileSpec &file_spec(libraries_to_avoid.GetFileSpecAtIndex(i)); 3584da6206dSJim Ingham if (FileSpec::Equal (file_spec, frame_library, false)) 3594da6206dSJim Ingham { 3604da6206dSJim Ingham libraries_say_avoid = true; 3614da6206dSJim Ingham break; 3624da6206dSJim Ingham } 3634da6206dSJim Ingham } 3644da6206dSJim Ingham } 365a786e539SJim Ingham } 3664da6206dSJim Ingham if (libraries_say_avoid) 3674da6206dSJim Ingham return true; 3684da6206dSJim Ingham 36967cc0636SGreg Clayton const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get(); 370ee8aea10SJim Ingham if (avoid_regexp_to_use == NULL) 371ee8aea10SJim Ingham avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp(); 372ee8aea10SJim Ingham 373ee8aea10SJim Ingham if (avoid_regexp_to_use != NULL) 374a56c8006SJim Ingham { 3754592cbc4SGreg Clayton SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); 376a56c8006SJim Ingham if (sc.symbol != NULL) 377a56c8006SJim Ingham { 378*5aa27e1aSTamas Berghammer const char *frame_function_name = sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments).GetCString(); 3794592cbc4SGreg Clayton if (frame_function_name) 3803101ba33SJim Ingham { 381cf2667c4SJim Ingham size_t num_matches = 0; 3825160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 3833101ba33SJim Ingham if (log) 384cf2667c4SJim Ingham num_matches = 1; 385bc43cab5SGreg Clayton 386bc43cab5SGreg Clayton RegularExpression::Match regex_match(num_matches); 387bc43cab5SGreg Clayton 388bc43cab5SGreg Clayton bool return_value = avoid_regexp_to_use->Execute(frame_function_name, ®ex_match); 389cf2667c4SJim Ingham if (return_value) 390cf2667c4SJim Ingham { 391cf2667c4SJim Ingham if (log) 392cf2667c4SJim Ingham { 393cf2667c4SJim Ingham std::string match; 394bc43cab5SGreg Clayton regex_match.GetMatchAtIndex(frame_function_name,0, match); 395cf2667c4SJim Ingham log->Printf ("Stepping out of function \"%s\" because it matches the avoid regexp \"%s\" - match substring: \"%s\".", 3963101ba33SJim Ingham frame_function_name, 397cf2667c4SJim Ingham avoid_regexp_to_use->GetText(), 398cf2667c4SJim Ingham match.c_str()); 399cf2667c4SJim Ingham } 4003101ba33SJim Ingham 4013101ba33SJim Ingham } 4023101ba33SJim Ingham return return_value; 4033101ba33SJim Ingham } 404a56c8006SJim Ingham } 405a56c8006SJim Ingham } 406a56c8006SJim Ingham return false; 407a56c8006SJim Ingham } 408a56c8006SJim Ingham 4094b4b2478SJim Ingham bool 4104b4b2478SJim Ingham ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, FrameComparison operation, void *baton) 41130fdc8d8SChris Lattner { 4124b4b2478SJim Ingham bool should_stop_here = true; 413b57e4a1bSJason Molenda StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get(); 4145160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 41530fdc8d8SChris Lattner 4160c2b9d2aSJim Ingham // First see if the ThreadPlanShouldStopHere default implementation thinks we should get out of here: 4170c2b9d2aSJim Ingham should_stop_here = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback (current_plan, flags, operation, baton); 4180c2b9d2aSJim Ingham if (!should_stop_here) 4190c2b9d2aSJim Ingham return should_stop_here; 420a56c8006SJim Ingham 4214b4b2478SJim Ingham if (should_stop_here && current_plan->GetKind() == eKindStepInRange && operation == eFrameCompareYounger) 422a56c8006SJim Ingham { 423a56c8006SJim Ingham ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); 424c627682eSJim Ingham if (step_in_range_plan->m_step_into_target) 425c627682eSJim Ingham { 426c627682eSJim Ingham SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol); 427c627682eSJim Ingham if (sc.symbol != NULL) 428c627682eSJim Ingham { 429c627682eSJim Ingham // First try an exact match, since that's cheap with ConstStrings. Then do a strstr compare. 430c627682eSJim Ingham if (step_in_range_plan->m_step_into_target == sc.GetFunctionName()) 431c627682eSJim Ingham { 4324b4b2478SJim Ingham should_stop_here = true; 433c627682eSJim Ingham } 434c627682eSJim Ingham else 435c627682eSJim Ingham { 436c627682eSJim Ingham const char *target_name = step_in_range_plan->m_step_into_target.AsCString(); 437c627682eSJim Ingham const char *function_name = sc.GetFunctionName().AsCString(); 438c627682eSJim Ingham 439c627682eSJim Ingham if (function_name == NULL) 4404b4b2478SJim Ingham should_stop_here = false; 441c627682eSJim Ingham else if (strstr (function_name, target_name) == NULL) 4424b4b2478SJim Ingham should_stop_here = false; 443c627682eSJim Ingham } 4444b4b2478SJim Ingham if (log && !should_stop_here) 4453101ba33SJim Ingham log->Printf("Stepping out of frame %s which did not match step into target %s.", 4463101ba33SJim Ingham sc.GetFunctionName().AsCString(), 4473101ba33SJim Ingham step_in_range_plan->m_step_into_target.AsCString()); 448c627682eSJim Ingham } 449c627682eSJim Ingham } 450c627682eSJim Ingham 4514b4b2478SJim Ingham if (should_stop_here) 452c627682eSJim Ingham { 453c627682eSJim Ingham ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan); 4544da6206dSJim Ingham // Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidCriteria. 4554b4b2478SJim Ingham should_stop_here = !step_in_range_plan->FrameMatchesAvoidCriteria (); 456a56c8006SJim Ingham } 457a56c8006SJim Ingham } 458a56c8006SJim Ingham 4594b4b2478SJim Ingham return should_stop_here; 46030fdc8d8SChris Lattner } 461fbbfe6ecSJim Ingham 462fbbfe6ecSJim Ingham bool 463221d51cfSJim Ingham ThreadPlanStepInRange::DoPlanExplainsStop (Event *event_ptr) 464fbbfe6ecSJim Ingham { 465fbbfe6ecSJim Ingham // We always explain a stop. Either we've just done a single step, in which 466fbbfe6ecSJim Ingham // case we'll do our ordinary processing, or we stopped for some 467fbbfe6ecSJim Ingham // reason that isn't handled by our sub-plans, in which case we want to just stop right 468fbbfe6ecSJim Ingham // away. 469c627682eSJim Ingham // In general, we don't want to mark the plan as complete for unexplained stops. 470c627682eSJim Ingham // For instance, if you step in to some code with no debug info, so you step out 471c627682eSJim Ingham // and in the course of that hit a breakpoint, then you want to stop & show the user 472c627682eSJim Ingham // the breakpoint, but not unship the step in plan, since you still may want to complete that 473c627682eSJim Ingham // plan when you continue. This is particularly true when doing "step in to target function." 474c627682eSJim Ingham // stepping. 475fbbfe6ecSJim Ingham // 476fbbfe6ecSJim Ingham // The only variation is that if we are doing "step by running to next branch" in which case 477fbbfe6ecSJim Ingham // if we hit our branch breakpoint we don't set the plan to complete. 478fbbfe6ecSJim Ingham 4799b03fa0cSJim Ingham bool return_value = false; 480f02a2e96SJim Ingham 481221d51cfSJim Ingham if (m_virtual_step) 482221d51cfSJim Ingham { 483221d51cfSJim Ingham return_value = true; 484221d51cfSJim Ingham } 485221d51cfSJim Ingham else 486221d51cfSJim Ingham { 48760c4118cSJim Ingham StopInfoSP stop_info_sp = GetPrivateStopInfo (); 488fbbfe6ecSJim Ingham if (stop_info_sp) 489fbbfe6ecSJim Ingham { 490fbbfe6ecSJim Ingham StopReason reason = stop_info_sp->GetStopReason(); 491fbbfe6ecSJim Ingham 4929b03fa0cSJim Ingham if (reason == eStopReasonBreakpoint) 493fbbfe6ecSJim Ingham { 494fbbfe6ecSJim Ingham if (NextRangeBreakpointExplainsStop(stop_info_sp)) 495221d51cfSJim Ingham { 496221d51cfSJim Ingham return_value = true; 497221d51cfSJim Ingham } 4989b03fa0cSJim Ingham } 4999b03fa0cSJim Ingham else if (IsUsuallyUnexplainedStopReason(reason)) 500513c6bb8SJim Ingham { 5015160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 502fbbfe6ecSJim Ingham if (log) 503fbbfe6ecSJim Ingham log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step."); 504221d51cfSJim Ingham return_value = false; 5059b03fa0cSJim Ingham } 5069b03fa0cSJim Ingham else 5079b03fa0cSJim Ingham { 508221d51cfSJim Ingham return_value = true; 509fbbfe6ecSJim Ingham } 510fbbfe6ecSJim Ingham } 511221d51cfSJim Ingham else 512221d51cfSJim Ingham return_value = true; 513221d51cfSJim Ingham } 514221d51cfSJim Ingham 515221d51cfSJim Ingham return return_value; 516fbbfe6ecSJim Ingham } 517513c6bb8SJim Ingham 518513c6bb8SJim Ingham bool 519221d51cfSJim Ingham ThreadPlanStepInRange::DoWillResume (lldb::StateType resume_state, bool current_plan) 520513c6bb8SJim Ingham { 52169fc298aSTamas Berghammer m_virtual_step = false; 522513c6bb8SJim Ingham if (resume_state == eStateStepping && current_plan) 523513c6bb8SJim Ingham { 524513c6bb8SJim Ingham // See if we are about to step over a virtual inlined call. 525513c6bb8SJim Ingham bool step_without_resume = m_thread.DecrementCurrentInlinedDepth(); 526513c6bb8SJim Ingham if (step_without_resume) 527513c6bb8SJim Ingham { 5285160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 529513c6bb8SJim Ingham if (log) 530221d51cfSJim Ingham log->Printf ("ThreadPlanStepInRange::DoWillResume: returning false, inline_depth: %d", 531513c6bb8SJim Ingham m_thread.GetCurrentInlinedDepth()); 532513c6bb8SJim Ingham SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread)); 533f02a2e96SJim Ingham 534f02a2e96SJim Ingham // FIXME: Maybe it would be better to create a InlineStep stop reason, but then 535f02a2e96SJim Ingham // the whole rest of the world would have to handle that stop reason. 536f02a2e96SJim Ingham m_virtual_step = true; 537513c6bb8SJim Ingham } 538513c6bb8SJim Ingham return !step_without_resume; 539513c6bb8SJim Ingham } 540221d51cfSJim Ingham return true; 541513c6bb8SJim Ingham } 542246cb611SDaniel Malea 543246cb611SDaniel Malea bool 544246cb611SDaniel Malea ThreadPlanStepInRange::IsVirtualStep() 545246cb611SDaniel Malea { 546246cb611SDaniel Malea return m_virtual_step; 547246cb611SDaniel Malea } 548