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"
1930fdc8d8SChris Lattner #include "lldb/Core/Stream.h"
20a56c8006SJim Ingham #include "lldb/Symbol/Symbol.h"
217ce490c6SJim Ingham #include "lldb/Symbol/Function.h"
2230fdc8d8SChris Lattner #include "lldb/Target/Process.h"
2330fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
24514487e8SGreg Clayton #include "lldb/Target/Target.h"
2530fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
2630fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepOut.h"
2730fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanStepThrough.h"
28a56c8006SJim Ingham #include "lldb/Core/RegularExpression.h"
2930fdc8d8SChris Lattner 
3030fdc8d8SChris Lattner using namespace lldb;
3130fdc8d8SChris Lattner using namespace lldb_private;
3230fdc8d8SChris Lattner 
3330fdc8d8SChris Lattner uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eAvoidNoDebug;
3430fdc8d8SChris Lattner 
3530fdc8d8SChris Lattner //----------------------------------------------------------------------
3630fdc8d8SChris Lattner // ThreadPlanStepInRange: Step through a stack range, either stepping over or into
3730fdc8d8SChris Lattner // based on the value of \a type.
3830fdc8d8SChris Lattner //----------------------------------------------------------------------
3930fdc8d8SChris Lattner 
4030fdc8d8SChris Lattner ThreadPlanStepInRange::ThreadPlanStepInRange
4130fdc8d8SChris Lattner (
4230fdc8d8SChris Lattner     Thread &thread,
4330fdc8d8SChris Lattner     const AddressRange &range,
4430fdc8d8SChris Lattner     const SymbolContext &addr_context,
4530fdc8d8SChris Lattner     lldb::RunMode stop_others
4630fdc8d8SChris Lattner ) :
47b01e742aSJim Ingham     ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others),
487ce490c6SJim Ingham     ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL),
49f02a2e96SJim Ingham     m_step_past_prologue (true),
50f02a2e96SJim Ingham     m_virtual_step (false)
5130fdc8d8SChris Lattner {
5230fdc8d8SChris Lattner     SetFlagsToDefault ();
5330fdc8d8SChris Lattner }
5430fdc8d8SChris Lattner 
55c627682eSJim Ingham ThreadPlanStepInRange::ThreadPlanStepInRange
56c627682eSJim Ingham (
57c627682eSJim Ingham     Thread &thread,
58c627682eSJim Ingham     const AddressRange &range,
59c627682eSJim Ingham     const SymbolContext &addr_context,
60c627682eSJim Ingham     const char *step_into_target,
61c627682eSJim Ingham     lldb::RunMode stop_others
62c627682eSJim Ingham ) :
63c627682eSJim Ingham     ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others),
64c627682eSJim Ingham     ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL),
65c627682eSJim Ingham     m_step_past_prologue (true),
66c627682eSJim Ingham     m_virtual_step (false),
67c627682eSJim Ingham     m_step_into_target (step_into_target)
68c627682eSJim Ingham {
69c627682eSJim Ingham     SetFlagsToDefault ();
70c627682eSJim Ingham }
71c627682eSJim Ingham 
7230fdc8d8SChris Lattner ThreadPlanStepInRange::~ThreadPlanStepInRange ()
7330fdc8d8SChris Lattner {
7430fdc8d8SChris Lattner }
7530fdc8d8SChris Lattner 
7630fdc8d8SChris Lattner void
7730fdc8d8SChris Lattner ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
7830fdc8d8SChris Lattner {
7930fdc8d8SChris Lattner     if (level == lldb::eDescriptionLevelBrief)
8030fdc8d8SChris Lattner         s->Printf("step in");
8130fdc8d8SChris Lattner     else
8230fdc8d8SChris Lattner     {
8330fdc8d8SChris Lattner         s->Printf ("Stepping through range (stepping into functions): ");
84c4c9fedcSJim Ingham         DumpRanges(s);
854d56e9c1SJim Ingham         const char *step_into_target = m_step_into_target.AsCString();
864d56e9c1SJim Ingham         if (step_into_target && step_into_target[0] != '\0')
87c627682eSJim Ingham             s->Printf (" targeting %s.", m_step_into_target.AsCString());
884d56e9c1SJim Ingham         else
894d56e9c1SJim Ingham             s->PutChar('.');
9030fdc8d8SChris Lattner     }
9130fdc8d8SChris Lattner }
9230fdc8d8SChris Lattner 
9330fdc8d8SChris Lattner bool
9430fdc8d8SChris Lattner ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
9530fdc8d8SChris Lattner {
965160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
9730fdc8d8SChris Lattner 
9830fdc8d8SChris Lattner     if (log)
9930fdc8d8SChris Lattner     {
10030fdc8d8SChris Lattner         StreamString s;
101514487e8SGreg Clayton         s.Address (m_thread.GetRegisterContext()->GetPC(),
1021ac04c30SGreg Clayton                    m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
10330fdc8d8SChris Lattner         log->Printf("ThreadPlanStepInRange reached %s.", s.GetData());
10430fdc8d8SChris Lattner     }
10530fdc8d8SChris Lattner 
10625f66700SJim Ingham     if (IsPlanComplete())
10725f66700SJim Ingham         return true;
10825f66700SJim Ingham 
1094d56e9c1SJim Ingham     m_no_more_plans = false;
1104d56e9c1SJim Ingham     if (m_sub_plan_sp && m_sub_plan_sp->IsPlanComplete())
1114d56e9c1SJim Ingham     {
1124d56e9c1SJim Ingham         if (!m_sub_plan_sp->PlanSucceeded())
1134d56e9c1SJim Ingham         {
1144d56e9c1SJim Ingham             SetPlanComplete();
1154d56e9c1SJim Ingham             m_no_more_plans = true;
1164d56e9c1SJim Ingham             return true;
1174d56e9c1SJim Ingham         }
1184d56e9c1SJim Ingham         else
1194d56e9c1SJim Ingham             m_sub_plan_sp.reset();
1204d56e9c1SJim Ingham     }
12130fdc8d8SChris Lattner 
122f02a2e96SJim Ingham     if (m_virtual_step)
123f02a2e96SJim Ingham     {
124f02a2e96SJim Ingham         // If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise
125f02a2e96SJim Ingham         // we're done.
1264d56e9c1SJim Ingham         m_sub_plan_sp = InvokeShouldStopHereCallback();
127f02a2e96SJim Ingham     }
128f02a2e96SJim Ingham     else
129f02a2e96SJim Ingham     {
1304a58e968SJim Ingham         // Stepping through should be done running other threads in general, since we're setting a breakpoint and
1314a58e968SJim Ingham         // continuing.  So only stop others if we are explicitly told to do so.
1329d790c5dSJim Ingham 
13330fdc8d8SChris Lattner         bool stop_others;
1344a58e968SJim Ingham         if (m_stop_others == lldb::eOnlyThisThread)
1354a58e968SJim Ingham             stop_others = true;
136*6cf5b8f1SEd Maste         else
137*6cf5b8f1SEd Maste             stop_others = false;
13830fdc8d8SChris Lattner 
139b5c0d1ccSJim Ingham         FrameComparison frame_order = CompareCurrentFrameToStartFrame();
140b5c0d1ccSJim Ingham 
141b5c0d1ccSJim Ingham         if (frame_order == eFrameCompareOlder)
1425822173bSJim Ingham         {
1435822173bSJim Ingham             // If we're in an older frame then we should stop.
1445822173bSJim Ingham             //
1455822173bSJim Ingham             // A caveat to this is if we think the frame is older but we're actually in a trampoline.
1465822173bSJim Ingham             // I'm going to make the assumption that you wouldn't RETURN to a trampoline.  So if we are
1475822173bSJim Ingham             // in a trampoline we think the frame is older because the trampoline confused the backtracer.
1484d56e9c1SJim Ingham             m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others);
1494d56e9c1SJim Ingham             if (!m_sub_plan_sp)
1505822173bSJim Ingham                 return true;
1515822173bSJim Ingham             else if (log)
1525822173bSJim Ingham             {
1535822173bSJim Ingham                 log->Printf("Thought I stepped out, but in fact arrived at a trampoline.");
1545822173bSJim Ingham             }
1555822173bSJim Ingham 
1565822173bSJim Ingham         }
157564d8bc2SJim Ingham         else if (frame_order == eFrameCompareEqual && InSymbol())
1585822173bSJim Ingham         {
1595822173bSJim Ingham             // If we are not in a place we should step through, we're done.
1605822173bSJim Ingham             // One tricky bit here is that some stubs don't push a frame, so we have to check
1615822173bSJim Ingham             // both the case of a frame that is younger, or the same as this frame.
1625822173bSJim Ingham             // However, if the frame is the same, and we are still in the symbol we started
1635822173bSJim Ingham             // in, the we don't need to do this.  This first check isn't strictly necessary,
1645822173bSJim Ingham             // but it is more efficient.
1655822173bSJim Ingham 
166564d8bc2SJim Ingham             // If we're still in the range, keep going, either by running to the next branch breakpoint, or by
167564d8bc2SJim Ingham             // stepping.
168564d8bc2SJim Ingham             if (InRange())
169564d8bc2SJim Ingham             {
170564d8bc2SJim Ingham                 SetNextBranchBreakpoint();
171564d8bc2SJim Ingham                 return false;
172564d8bc2SJim Ingham             }
173564d8bc2SJim Ingham 
1745822173bSJim Ingham             SetPlanComplete();
175c627682eSJim Ingham             m_no_more_plans = true;
1765822173bSJim Ingham             return true;
1775822173bSJim Ingham         }
1785822173bSJim Ingham 
179564d8bc2SJim Ingham         // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it:
180564d8bc2SJim Ingham         ClearNextBranchBreakpoint();
181564d8bc2SJim Ingham 
1825822173bSJim Ingham         // We may have set the plan up above in the FrameIsOlder section:
1835822173bSJim Ingham 
1844d56e9c1SJim Ingham         if (!m_sub_plan_sp)
1854d56e9c1SJim Ingham             m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others);
18608b87e0dSJim Ingham 
18708b87e0dSJim Ingham         if (log)
18808b87e0dSJim Ingham         {
1894d56e9c1SJim Ingham             if (m_sub_plan_sp)
1904d56e9c1SJim Ingham                 log->Printf ("Found a step through plan: %s", m_sub_plan_sp->GetName());
19108b87e0dSJim Ingham             else
19208b87e0dSJim Ingham                 log->Printf ("No step through plan found.");
19308b87e0dSJim Ingham         }
19408b87e0dSJim Ingham 
19530fdc8d8SChris Lattner         // If not, give the "should_stop" callback a chance to push a plan to get us out of here.
19630fdc8d8SChris Lattner         // But only do that if we actually have stepped in.
1974d56e9c1SJim Ingham         if (!m_sub_plan_sp && frame_order == eFrameCompareYounger)
1984d56e9c1SJim Ingham             m_sub_plan_sp = InvokeShouldStopHereCallback();
19930fdc8d8SChris Lattner 
2007ce490c6SJim Ingham         // If we've stepped in and we are going to stop here, check to see if we were asked to
2017ce490c6SJim Ingham         // run past the prologue, and if so do that.
2027ce490c6SJim Ingham 
2034d56e9c1SJim Ingham         if (!m_sub_plan_sp && frame_order == eFrameCompareYounger && m_step_past_prologue)
2047ce490c6SJim Ingham         {
205b57e4a1bSJason Molenda             lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0);
2067ce490c6SJim Ingham             if (curr_frame)
2077ce490c6SJim Ingham             {
2087ce490c6SJim Ingham                 size_t bytes_to_skip = 0;
2097ce490c6SJim Ingham                 lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC();
2107ce490c6SJim Ingham                 Address func_start_address;
2117ce490c6SJim Ingham 
2127ce490c6SJim Ingham                 SymbolContext sc = curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextSymbol);
2137ce490c6SJim Ingham 
2147ce490c6SJim Ingham                 if (sc.function)
2157ce490c6SJim Ingham                 {
2167ce490c6SJim Ingham                     func_start_address = sc.function->GetAddressRange().GetBaseAddress();
217d9e416c0SGreg Clayton                     if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get()))
2187ce490c6SJim Ingham                         bytes_to_skip = sc.function->GetPrologueByteSize();
2197ce490c6SJim Ingham                 }
2207ce490c6SJim Ingham                 else if (sc.symbol)
2217ce490c6SJim Ingham                 {
222e7612134SGreg Clayton                     func_start_address = sc.symbol->GetAddress();
223d9e416c0SGreg Clayton                     if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get()))
2247ce490c6SJim Ingham                         bytes_to_skip = sc.symbol->GetPrologueByteSize();
2257ce490c6SJim Ingham                 }
2267ce490c6SJim Ingham 
2277ce490c6SJim Ingham                 if (bytes_to_skip != 0)
2287ce490c6SJim Ingham                 {
2297ce490c6SJim Ingham                     func_start_address.Slide (bytes_to_skip);
23020ad3c40SCaroline Tice                     log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
2317ce490c6SJim Ingham                     if (log)
2327ce490c6SJim Ingham                         log->Printf ("Pushing past prologue ");
2337ce490c6SJim Ingham 
2344d56e9c1SJim Ingham                     m_sub_plan_sp = m_thread.QueueThreadPlanForRunToAddress(false, func_start_address,true);
2357ce490c6SJim Ingham                 }
2367ce490c6SJim Ingham             }
2377ce490c6SJim Ingham         }
238f02a2e96SJim Ingham      }
2397ce490c6SJim Ingham 
2404d56e9c1SJim Ingham      if (!m_sub_plan_sp)
24130fdc8d8SChris Lattner      {
24230fdc8d8SChris Lattner         m_no_more_plans = true;
24330fdc8d8SChris Lattner         SetPlanComplete();
24430fdc8d8SChris Lattner         return true;
24530fdc8d8SChris Lattner     }
24630fdc8d8SChris Lattner     else
24730fdc8d8SChris Lattner     {
24830fdc8d8SChris Lattner         m_no_more_plans = false;
24930fdc8d8SChris Lattner         return false;
25030fdc8d8SChris Lattner     }
25130fdc8d8SChris Lattner }
25230fdc8d8SChris Lattner 
25330fdc8d8SChris Lattner void
25430fdc8d8SChris Lattner ThreadPlanStepInRange::SetFlagsToDefault ()
25530fdc8d8SChris Lattner {
25630fdc8d8SChris Lattner     GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values);
25730fdc8d8SChris Lattner }
25830fdc8d8SChris Lattner 
25930fdc8d8SChris Lattner void
260a56c8006SJim Ingham ThreadPlanStepInRange::SetAvoidRegexp(const char *name)
261a56c8006SJim Ingham {
262a56c8006SJim Ingham     if (m_avoid_regexp_ap.get() == NULL)
263a56c8006SJim Ingham         m_avoid_regexp_ap.reset (new RegularExpression(name));
264a56c8006SJim Ingham 
265a56c8006SJim Ingham     m_avoid_regexp_ap->Compile (name);
266a56c8006SJim Ingham }
267a56c8006SJim Ingham 
268a56c8006SJim Ingham void
26930fdc8d8SChris Lattner ThreadPlanStepInRange::SetDefaultFlagValue (uint32_t new_value)
27030fdc8d8SChris Lattner {
27130fdc8d8SChris Lattner     // TODO: Should we test this for sanity?
27230fdc8d8SChris Lattner     ThreadPlanStepInRange::s_default_flag_values = new_value;
27330fdc8d8SChris Lattner }
27430fdc8d8SChris Lattner 
275a56c8006SJim Ingham bool
276a56c8006SJim Ingham ThreadPlanStepInRange::FrameMatchesAvoidRegexp ()
277a56c8006SJim Ingham {
278b57e4a1bSJason Molenda     StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get();
279a56c8006SJim Ingham 
28067cc0636SGreg Clayton     const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get();
281ee8aea10SJim Ingham     if (avoid_regexp_to_use == NULL)
282ee8aea10SJim Ingham         avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp();
283ee8aea10SJim Ingham 
284ee8aea10SJim Ingham     if (avoid_regexp_to_use != NULL)
285a56c8006SJim Ingham     {
2864592cbc4SGreg Clayton         SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
287a56c8006SJim Ingham         if (sc.symbol != NULL)
288a56c8006SJim Ingham         {
2894592cbc4SGreg Clayton             const char *frame_function_name = sc.GetFunctionName().GetCString();
2904592cbc4SGreg Clayton             if (frame_function_name)
2913101ba33SJim Ingham             {
292cf2667c4SJim Ingham                 size_t num_matches = 0;
2935160ce5cSGreg Clayton                 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
2943101ba33SJim Ingham                 if (log)
295cf2667c4SJim Ingham                     num_matches = 1;
296bc43cab5SGreg Clayton 
297bc43cab5SGreg Clayton                 RegularExpression::Match regex_match(num_matches);
298bc43cab5SGreg Clayton 
299bc43cab5SGreg Clayton                 bool return_value = avoid_regexp_to_use->Execute(frame_function_name, &regex_match);
300cf2667c4SJim Ingham                 if (return_value)
301cf2667c4SJim Ingham                 {
302cf2667c4SJim Ingham                     if (log)
303cf2667c4SJim Ingham                     {
304cf2667c4SJim Ingham                         std::string match;
305bc43cab5SGreg Clayton                         regex_match.GetMatchAtIndex(frame_function_name,0, match);
306cf2667c4SJim Ingham                         log->Printf ("Stepping out of function \"%s\" because it matches the avoid regexp \"%s\" - match substring: \"%s\".",
3073101ba33SJim Ingham                                      frame_function_name,
308cf2667c4SJim Ingham                                      avoid_regexp_to_use->GetText(),
309cf2667c4SJim Ingham                                      match.c_str());
310cf2667c4SJim Ingham                     }
3113101ba33SJim Ingham 
3123101ba33SJim Ingham                 }
3133101ba33SJim Ingham                 return return_value;
3143101ba33SJim Ingham             }
315a56c8006SJim Ingham         }
316a56c8006SJim Ingham     }
317a56c8006SJim Ingham     return false;
318a56c8006SJim Ingham }
319a56c8006SJim Ingham 
3204d56e9c1SJim Ingham ThreadPlanSP
32130fdc8d8SChris Lattner ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton)
32230fdc8d8SChris Lattner {
323a56c8006SJim Ingham     bool should_step_out = false;
324b57e4a1bSJason Molenda     StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
3255160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
32630fdc8d8SChris Lattner 
32773b472d4SGreg Clayton     if (flags.Test(eAvoidNoDebug))
328a56c8006SJim Ingham     {
32930fdc8d8SChris Lattner         if (!frame->HasDebugInformation())
330af0f1759SJim Ingham         {
331af0f1759SJim Ingham             if (log)
332af0f1759SJim Ingham                 log->Printf ("Stepping out of frame with no debug info");
333af0f1759SJim Ingham 
334a56c8006SJim Ingham             should_step_out = true;
335a56c8006SJim Ingham         }
336af0f1759SJim Ingham     }
337a56c8006SJim Ingham 
338a56c8006SJim Ingham     if (current_plan->GetKind() == eKindStepInRange)
339a56c8006SJim Ingham     {
340a56c8006SJim Ingham         ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
341c627682eSJim Ingham         if (step_in_range_plan->m_step_into_target)
342c627682eSJim Ingham         {
343c627682eSJim Ingham             SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
344c627682eSJim Ingham             if (sc.symbol != NULL)
345c627682eSJim Ingham             {
346c627682eSJim Ingham                 // First try an exact match, since that's cheap with ConstStrings.  Then do a strstr compare.
347c627682eSJim Ingham                 if (step_in_range_plan->m_step_into_target == sc.GetFunctionName())
348c627682eSJim Ingham                 {
349c627682eSJim Ingham                     should_step_out = false;
350c627682eSJim Ingham                 }
351c627682eSJim Ingham                 else
352c627682eSJim Ingham                 {
353c627682eSJim Ingham                     const char *target_name = step_in_range_plan->m_step_into_target.AsCString();
354c627682eSJim Ingham                     const char *function_name = sc.GetFunctionName().AsCString();
355c627682eSJim Ingham 
356c627682eSJim Ingham                     if (function_name == NULL)
357c627682eSJim Ingham                         should_step_out = true;
358c627682eSJim Ingham                     else if (strstr (function_name, target_name) == NULL)
359c627682eSJim Ingham                         should_step_out = true;
360c627682eSJim Ingham                 }
3613101ba33SJim Ingham                 if (log && should_step_out)
3623101ba33SJim Ingham                     log->Printf("Stepping out of frame %s which did not match step into target %s.",
3633101ba33SJim Ingham                                 sc.GetFunctionName().AsCString(),
3643101ba33SJim Ingham                                 step_in_range_plan->m_step_into_target.AsCString());
365c627682eSJim Ingham             }
366c627682eSJim Ingham         }
367c627682eSJim Ingham 
368c627682eSJim Ingham         if (!should_step_out)
369c627682eSJim Ingham         {
370c627682eSJim Ingham             ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
3713101ba33SJim Ingham             // Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidRegexp.
372a56c8006SJim Ingham             should_step_out = step_in_range_plan->FrameMatchesAvoidRegexp ();
373a56c8006SJim Ingham         }
374a56c8006SJim Ingham     }
375a56c8006SJim Ingham 
376c627682eSJim Ingham 
377a56c8006SJim Ingham     if (should_step_out)
37830fdc8d8SChris Lattner     {
37930fdc8d8SChris Lattner         // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions.
3804a58e968SJim Ingham         // We really should have all plans take the tri-state for "stop others" so we can do the right
3814a58e968SJim Ingham         // thing.  For now let's be safe and always run others when we are likely to run arbitrary code.
3824a58e968SJim Ingham         const bool stop_others = false;
383481cef25SGreg Clayton         return current_plan->GetThread().QueueThreadPlanForStepOut (false,
384481cef25SGreg Clayton                                                                     NULL,
385481cef25SGreg Clayton                                                                     true,
3864a58e968SJim Ingham                                                                     stop_others,
387481cef25SGreg Clayton                                                                     eVoteNo,
388481cef25SGreg Clayton                                                                     eVoteNoOpinion,
389481cef25SGreg Clayton                                                                     0); // Frame index
39030fdc8d8SChris Lattner     }
39130fdc8d8SChris Lattner 
3924d56e9c1SJim Ingham     return ThreadPlanSP();
39330fdc8d8SChris Lattner }
394fbbfe6ecSJim Ingham 
395fbbfe6ecSJim Ingham bool
396221d51cfSJim Ingham ThreadPlanStepInRange::DoPlanExplainsStop (Event *event_ptr)
397fbbfe6ecSJim Ingham {
398fbbfe6ecSJim Ingham     // We always explain a stop.  Either we've just done a single step, in which
399fbbfe6ecSJim Ingham     // case we'll do our ordinary processing, or we stopped for some
400fbbfe6ecSJim Ingham     // reason that isn't handled by our sub-plans, in which case we want to just stop right
401fbbfe6ecSJim Ingham     // away.
402c627682eSJim Ingham     // In general, we don't want to mark the plan as complete for unexplained stops.
403c627682eSJim Ingham     // For instance, if you step in to some code with no debug info, so you step out
404c627682eSJim Ingham     // and in the course of that hit a breakpoint, then you want to stop & show the user
405c627682eSJim Ingham     // the breakpoint, but not unship the step in plan, since you still may want to complete that
406c627682eSJim Ingham     // plan when you continue.  This is particularly true when doing "step in to target function."
407c627682eSJim Ingham     // stepping.
408fbbfe6ecSJim Ingham     //
409fbbfe6ecSJim Ingham     // The only variation is that if we are doing "step by running to next branch" in which case
410fbbfe6ecSJim Ingham     // if we hit our branch breakpoint we don't set the plan to complete.
411fbbfe6ecSJim Ingham 
412221d51cfSJim Ingham     bool return_value;
413f02a2e96SJim Ingham 
414221d51cfSJim Ingham     if (m_virtual_step)
415221d51cfSJim Ingham     {
416221d51cfSJim Ingham         return_value = true;
417221d51cfSJim Ingham     }
418221d51cfSJim Ingham     else
419221d51cfSJim Ingham     {
42060c4118cSJim Ingham         StopInfoSP stop_info_sp = GetPrivateStopInfo ();
421fbbfe6ecSJim Ingham         if (stop_info_sp)
422fbbfe6ecSJim Ingham         {
423fbbfe6ecSJim Ingham             StopReason reason = stop_info_sp->GetStopReason();
424fbbfe6ecSJim Ingham 
425fbbfe6ecSJim Ingham             switch (reason)
426fbbfe6ecSJim Ingham             {
427fbbfe6ecSJim Ingham             case eStopReasonBreakpoint:
428fbbfe6ecSJim Ingham                 if (NextRangeBreakpointExplainsStop(stop_info_sp))
429221d51cfSJim Ingham                 {
430221d51cfSJim Ingham                     return_value = true;
431221d51cfSJim Ingham                     break;
432221d51cfSJim Ingham                 }
433fbbfe6ecSJim Ingham             case eStopReasonWatchpoint:
434fbbfe6ecSJim Ingham             case eStopReasonSignal:
435fbbfe6ecSJim Ingham             case eStopReasonException:
43690ba8115SGreg Clayton             case eStopReasonExec:
437f85defaeSAndrew Kaylor             case eStopReasonThreadExiting:
438513c6bb8SJim Ingham                 {
4395160ce5cSGreg Clayton                     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
440fbbfe6ecSJim Ingham                     if (log)
441fbbfe6ecSJim Ingham                         log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
442513c6bb8SJim Ingham                 }
443221d51cfSJim Ingham                 return_value = false;
444fbbfe6ecSJim Ingham                 break;
445fbbfe6ecSJim Ingham             default:
446221d51cfSJim Ingham                 return_value = true;
447fbbfe6ecSJim Ingham                 break;
448fbbfe6ecSJim Ingham             }
449fbbfe6ecSJim Ingham         }
450221d51cfSJim Ingham         else
451221d51cfSJim Ingham             return_value = true;
452221d51cfSJim Ingham     }
453221d51cfSJim Ingham 
454221d51cfSJim Ingham     return return_value;
455fbbfe6ecSJim Ingham }
456513c6bb8SJim Ingham 
457513c6bb8SJim Ingham bool
458221d51cfSJim Ingham ThreadPlanStepInRange::DoWillResume (lldb::StateType resume_state, bool current_plan)
459513c6bb8SJim Ingham {
460513c6bb8SJim Ingham     if (resume_state == eStateStepping && current_plan)
461513c6bb8SJim Ingham     {
462513c6bb8SJim Ingham         // See if we are about to step over a virtual inlined call.
463513c6bb8SJim Ingham         bool step_without_resume = m_thread.DecrementCurrentInlinedDepth();
464513c6bb8SJim Ingham         if (step_without_resume)
465513c6bb8SJim Ingham         {
4665160ce5cSGreg Clayton             Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
467513c6bb8SJim Ingham             if (log)
468221d51cfSJim Ingham                 log->Printf ("ThreadPlanStepInRange::DoWillResume: returning false, inline_depth: %d",
469513c6bb8SJim Ingham                              m_thread.GetCurrentInlinedDepth());
470513c6bb8SJim Ingham             SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread));
471f02a2e96SJim Ingham 
472f02a2e96SJim Ingham             // FIXME: Maybe it would be better to create a InlineStep stop reason, but then
473f02a2e96SJim Ingham             // the whole rest of the world would have to handle that stop reason.
474f02a2e96SJim Ingham             m_virtual_step = true;
475513c6bb8SJim Ingham         }
476513c6bb8SJim Ingham         return !step_without_resume;
477513c6bb8SJim Ingham     }
478221d51cfSJim Ingham     return true;
479513c6bb8SJim Ingham }
480246cb611SDaniel Malea 
481246cb611SDaniel Malea bool
482246cb611SDaniel Malea ThreadPlanStepInRange::IsVirtualStep()
483246cb611SDaniel Malea {
484246cb611SDaniel Malea   return m_virtual_step;
485246cb611SDaniel Malea }
486