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 
5530fdc8d8SChris Lattner ThreadPlanStepInRange::~ThreadPlanStepInRange ()
5630fdc8d8SChris Lattner {
5730fdc8d8SChris Lattner }
5830fdc8d8SChris Lattner 
5930fdc8d8SChris Lattner void
6030fdc8d8SChris Lattner ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
6130fdc8d8SChris Lattner {
6230fdc8d8SChris Lattner     if (level == lldb::eDescriptionLevelBrief)
6330fdc8d8SChris Lattner         s->Printf("step in");
6430fdc8d8SChris Lattner     else
6530fdc8d8SChris Lattner     {
6630fdc8d8SChris Lattner         s->Printf ("Stepping through range (stepping into functions): ");
67c4c9fedcSJim Ingham         DumpRanges(s);
6830fdc8d8SChris Lattner     }
6930fdc8d8SChris Lattner }
7030fdc8d8SChris Lattner 
7130fdc8d8SChris Lattner bool
7230fdc8d8SChris Lattner ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
7330fdc8d8SChris Lattner {
742d4edfbcSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
7530fdc8d8SChris Lattner     m_no_more_plans = false;
7630fdc8d8SChris Lattner 
7730fdc8d8SChris Lattner     if (log)
7830fdc8d8SChris Lattner     {
7930fdc8d8SChris Lattner         StreamString s;
80514487e8SGreg Clayton         s.Address (m_thread.GetRegisterContext()->GetPC(),
811ac04c30SGreg Clayton                    m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
8230fdc8d8SChris Lattner         log->Printf("ThreadPlanStepInRange reached %s.", s.GetData());
8330fdc8d8SChris Lattner     }
8430fdc8d8SChris Lattner 
8525f66700SJim Ingham     if (IsPlanComplete())
8625f66700SJim Ingham         return true;
8725f66700SJim Ingham 
8830fdc8d8SChris Lattner     ThreadPlan* new_plan = NULL;
8930fdc8d8SChris Lattner 
90f02a2e96SJim Ingham     if (m_virtual_step)
91f02a2e96SJim Ingham     {
92f02a2e96SJim Ingham         // If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise
93f02a2e96SJim Ingham         // we're done.
94f02a2e96SJim Ingham         new_plan = InvokeShouldStopHereCallback();
95f02a2e96SJim Ingham     }
96f02a2e96SJim Ingham     else
97f02a2e96SJim Ingham     {
98*4a58e968SJim Ingham         // Stepping through should be done running other threads in general, since we're setting a breakpoint and
99*4a58e968SJim Ingham         // continuing.  So only stop others if we are explicitly told to do so.
1009d790c5dSJim Ingham 
10130fdc8d8SChris Lattner         bool stop_others;
102*4a58e968SJim Ingham         if (m_stop_others == lldb::eOnlyThisThread)
10330fdc8d8SChris Lattner             stop_others = false;
104*4a58e968SJim Ingham         else
105*4a58e968SJim Ingham             stop_others = true;
10630fdc8d8SChris Lattner 
107b5c0d1ccSJim Ingham         FrameComparison frame_order = CompareCurrentFrameToStartFrame();
108b5c0d1ccSJim Ingham 
109b5c0d1ccSJim Ingham         if (frame_order == eFrameCompareOlder)
1105822173bSJim Ingham         {
1115822173bSJim Ingham             // If we're in an older frame then we should stop.
1125822173bSJim Ingham             //
1135822173bSJim Ingham             // A caveat to this is if we think the frame is older but we're actually in a trampoline.
1145822173bSJim Ingham             // I'm going to make the assumption that you wouldn't RETURN to a trampoline.  So if we are
1155822173bSJim Ingham             // in a trampoline we think the frame is older because the trampoline confused the backtracer.
11618de2fdcSJim Ingham             new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others);
1175822173bSJim Ingham             if (new_plan == NULL)
1185822173bSJim Ingham                 return true;
1195822173bSJim Ingham             else if (log)
1205822173bSJim Ingham             {
1215822173bSJim Ingham                 log->Printf("Thought I stepped out, but in fact arrived at a trampoline.");
1225822173bSJim Ingham             }
1235822173bSJim Ingham 
1245822173bSJim Ingham         }
125564d8bc2SJim Ingham         else if (frame_order == eFrameCompareEqual && InSymbol())
1265822173bSJim Ingham         {
1275822173bSJim Ingham             // If we are not in a place we should step through, we're done.
1285822173bSJim Ingham             // One tricky bit here is that some stubs don't push a frame, so we have to check
1295822173bSJim Ingham             // both the case of a frame that is younger, or the same as this frame.
1305822173bSJim Ingham             // However, if the frame is the same, and we are still in the symbol we started
1315822173bSJim Ingham             // in, the we don't need to do this.  This first check isn't strictly necessary,
1325822173bSJim Ingham             // but it is more efficient.
1335822173bSJim Ingham 
134564d8bc2SJim Ingham             // If we're still in the range, keep going, either by running to the next branch breakpoint, or by
135564d8bc2SJim Ingham             // stepping.
136564d8bc2SJim Ingham             if (InRange())
137564d8bc2SJim Ingham             {
138564d8bc2SJim Ingham                 SetNextBranchBreakpoint();
139564d8bc2SJim Ingham                 return false;
140564d8bc2SJim Ingham             }
141564d8bc2SJim Ingham 
1425822173bSJim Ingham             SetPlanComplete();
1435822173bSJim Ingham             return true;
1445822173bSJim Ingham         }
1455822173bSJim Ingham 
146564d8bc2SJim Ingham         // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it:
147564d8bc2SJim Ingham         ClearNextBranchBreakpoint();
148564d8bc2SJim Ingham 
1495822173bSJim Ingham         // We may have set the plan up above in the FrameIsOlder section:
1505822173bSJim Ingham 
1515822173bSJim Ingham         if (new_plan == NULL)
15218de2fdcSJim Ingham             new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others);
15308b87e0dSJim Ingham 
15408b87e0dSJim Ingham         if (log)
15508b87e0dSJim Ingham         {
15608b87e0dSJim Ingham             if (new_plan != NULL)
15708b87e0dSJim Ingham                 log->Printf ("Found a step through plan: %s", new_plan->GetName());
15808b87e0dSJim Ingham             else
15908b87e0dSJim Ingham                 log->Printf ("No step through plan found.");
16008b87e0dSJim Ingham         }
16108b87e0dSJim Ingham 
16230fdc8d8SChris Lattner         // If not, give the "should_stop" callback a chance to push a plan to get us out of here.
16330fdc8d8SChris Lattner         // But only do that if we actually have stepped in.
164b5c0d1ccSJim Ingham         if (!new_plan && frame_order == eFrameCompareYounger)
16530fdc8d8SChris Lattner             new_plan = InvokeShouldStopHereCallback();
16630fdc8d8SChris Lattner 
1677ce490c6SJim Ingham         // If we've stepped in and we are going to stop here, check to see if we were asked to
1687ce490c6SJim Ingham         // run past the prologue, and if so do that.
1697ce490c6SJim Ingham 
170b5c0d1ccSJim Ingham         if (new_plan == NULL && frame_order == eFrameCompareYounger && m_step_past_prologue)
1717ce490c6SJim Ingham         {
1727ce490c6SJim Ingham             lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0);
1737ce490c6SJim Ingham             if (curr_frame)
1747ce490c6SJim Ingham             {
1757ce490c6SJim Ingham                 size_t bytes_to_skip = 0;
1767ce490c6SJim Ingham                 lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC();
1777ce490c6SJim Ingham                 Address func_start_address;
1787ce490c6SJim Ingham 
1797ce490c6SJim Ingham                 SymbolContext sc = curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextSymbol);
1807ce490c6SJim Ingham 
1817ce490c6SJim Ingham                 if (sc.function)
1827ce490c6SJim Ingham                 {
1837ce490c6SJim Ingham                     func_start_address = sc.function->GetAddressRange().GetBaseAddress();
184d9e416c0SGreg Clayton                     if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get()))
1857ce490c6SJim Ingham                         bytes_to_skip = sc.function->GetPrologueByteSize();
1867ce490c6SJim Ingham                 }
1877ce490c6SJim Ingham                 else if (sc.symbol)
1887ce490c6SJim Ingham                 {
189e7612134SGreg Clayton                     func_start_address = sc.symbol->GetAddress();
190d9e416c0SGreg Clayton                     if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get()))
1917ce490c6SJim Ingham                         bytes_to_skip = sc.symbol->GetPrologueByteSize();
1927ce490c6SJim Ingham                 }
1937ce490c6SJim Ingham 
1947ce490c6SJim Ingham                 if (bytes_to_skip != 0)
1957ce490c6SJim Ingham                 {
1967ce490c6SJim Ingham                     func_start_address.Slide (bytes_to_skip);
19720ad3c40SCaroline Tice                     log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
1987ce490c6SJim Ingham                     if (log)
1997ce490c6SJim Ingham                         log->Printf ("Pushing past prologue ");
2007ce490c6SJim Ingham 
2017ce490c6SJim Ingham                     new_plan = m_thread.QueueThreadPlanForRunToAddress(false, func_start_address,true);
2027ce490c6SJim Ingham                 }
2037ce490c6SJim Ingham             }
2047ce490c6SJim Ingham         }
205f02a2e96SJim Ingham      }
2067ce490c6SJim Ingham 
20730fdc8d8SChris Lattner      if (new_plan == NULL)
20830fdc8d8SChris Lattner      {
20930fdc8d8SChris Lattner         m_no_more_plans = true;
21030fdc8d8SChris Lattner         SetPlanComplete();
21130fdc8d8SChris Lattner         return true;
21230fdc8d8SChris Lattner     }
21330fdc8d8SChris Lattner     else
21430fdc8d8SChris Lattner     {
21530fdc8d8SChris Lattner         m_no_more_plans = false;
21630fdc8d8SChris Lattner         return false;
21730fdc8d8SChris Lattner     }
21830fdc8d8SChris Lattner }
21930fdc8d8SChris Lattner 
22030fdc8d8SChris Lattner void
22130fdc8d8SChris Lattner ThreadPlanStepInRange::SetFlagsToDefault ()
22230fdc8d8SChris Lattner {
22330fdc8d8SChris Lattner     GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values);
22430fdc8d8SChris Lattner }
22530fdc8d8SChris Lattner 
22630fdc8d8SChris Lattner void
227a56c8006SJim Ingham ThreadPlanStepInRange::SetAvoidRegexp(const char *name)
228a56c8006SJim Ingham {
229a56c8006SJim Ingham     if (m_avoid_regexp_ap.get() == NULL)
230a56c8006SJim Ingham         m_avoid_regexp_ap.reset (new RegularExpression(name));
231a56c8006SJim Ingham 
232a56c8006SJim Ingham     m_avoid_regexp_ap->Compile (name);
233a56c8006SJim Ingham }
234a56c8006SJim Ingham 
235a56c8006SJim Ingham void
23630fdc8d8SChris Lattner ThreadPlanStepInRange::SetDefaultFlagValue (uint32_t new_value)
23730fdc8d8SChris Lattner {
23830fdc8d8SChris Lattner     // TODO: Should we test this for sanity?
23930fdc8d8SChris Lattner     ThreadPlanStepInRange::s_default_flag_values = new_value;
24030fdc8d8SChris Lattner }
24130fdc8d8SChris Lattner 
242a56c8006SJim Ingham bool
243a56c8006SJim Ingham ThreadPlanStepInRange::FrameMatchesAvoidRegexp ()
244a56c8006SJim Ingham {
245a56c8006SJim Ingham     StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get();
246a56c8006SJim Ingham 
24767cc0636SGreg Clayton     const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get();
248ee8aea10SJim Ingham     if (avoid_regexp_to_use == NULL)
249ee8aea10SJim Ingham         avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp();
250ee8aea10SJim Ingham 
251ee8aea10SJim Ingham     if (avoid_regexp_to_use != NULL)
252a56c8006SJim Ingham     {
2534592cbc4SGreg Clayton         SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
254a56c8006SJim Ingham         if (sc.symbol != NULL)
255a56c8006SJim Ingham         {
2564592cbc4SGreg Clayton             const char *frame_function_name = sc.GetFunctionName().GetCString();
2574592cbc4SGreg Clayton             if (frame_function_name)
2584592cbc4SGreg Clayton                return avoid_regexp_to_use->Execute(frame_function_name);
259a56c8006SJim Ingham         }
260a56c8006SJim Ingham     }
261a56c8006SJim Ingham     return false;
262a56c8006SJim Ingham }
263a56c8006SJim Ingham 
26430fdc8d8SChris Lattner ThreadPlan *
26530fdc8d8SChris Lattner ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton)
26630fdc8d8SChris Lattner {
267a56c8006SJim Ingham     bool should_step_out = false;
26830fdc8d8SChris Lattner     StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
26930fdc8d8SChris Lattner 
27073b472d4SGreg Clayton     if (flags.Test(eAvoidNoDebug))
271a56c8006SJim Ingham     {
27230fdc8d8SChris Lattner         if (!frame->HasDebugInformation())
273af0f1759SJim Ingham         {
274513c6bb8SJim Ingham             LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
275af0f1759SJim Ingham             if (log)
276af0f1759SJim Ingham                 log->Printf ("Stepping out of frame with no debug info");
277af0f1759SJim Ingham 
278a56c8006SJim Ingham             should_step_out = true;
279a56c8006SJim Ingham         }
280af0f1759SJim Ingham     }
281a56c8006SJim Ingham 
282a56c8006SJim Ingham     if (!should_step_out)
283a56c8006SJim Ingham     {
284a56c8006SJim Ingham         if (current_plan->GetKind() == eKindStepInRange)
285a56c8006SJim Ingham         {
286a56c8006SJim Ingham             ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
287a56c8006SJim Ingham             should_step_out = step_in_range_plan->FrameMatchesAvoidRegexp ();
288a56c8006SJim Ingham         }
289a56c8006SJim Ingham     }
290a56c8006SJim Ingham 
291a56c8006SJim Ingham     if (should_step_out)
29230fdc8d8SChris Lattner     {
29330fdc8d8SChris Lattner         // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions.
294*4a58e968SJim Ingham         // We really should have all plans take the tri-state for "stop others" so we can do the right
295*4a58e968SJim Ingham         // thing.  For now let's be safe and always run others when we are likely to run arbitrary code.
296*4a58e968SJim Ingham         const bool stop_others = false;
297481cef25SGreg Clayton         return current_plan->GetThread().QueueThreadPlanForStepOut (false,
298481cef25SGreg Clayton                                                                     NULL,
299481cef25SGreg Clayton                                                                     true,
300*4a58e968SJim Ingham                                                                     stop_others,
301481cef25SGreg Clayton                                                                     eVoteNo,
302481cef25SGreg Clayton                                                                     eVoteNoOpinion,
303481cef25SGreg Clayton                                                                     0); // Frame index
30430fdc8d8SChris Lattner     }
30530fdc8d8SChris Lattner 
30630fdc8d8SChris Lattner     return NULL;
30730fdc8d8SChris Lattner }
308fbbfe6ecSJim Ingham 
309fbbfe6ecSJim Ingham bool
310fbbfe6ecSJim Ingham ThreadPlanStepInRange::PlanExplainsStop ()
311fbbfe6ecSJim Ingham {
312fbbfe6ecSJim Ingham     // We always explain a stop.  Either we've just done a single step, in which
313fbbfe6ecSJim Ingham     // case we'll do our ordinary processing, or we stopped for some
314fbbfe6ecSJim Ingham     // reason that isn't handled by our sub-plans, in which case we want to just stop right
315fbbfe6ecSJim Ingham     // away.
316fbbfe6ecSJim Ingham     // We also set ourselves complete when we stop for this sort of unintended reason, but mark
317fbbfe6ecSJim Ingham     // success as false so we don't end up being the reason for the stop.
318fbbfe6ecSJim Ingham     //
319fbbfe6ecSJim Ingham     // The only variation is that if we are doing "step by running to next branch" in which case
320fbbfe6ecSJim Ingham     // if we hit our branch breakpoint we don't set the plan to complete.
321fbbfe6ecSJim Ingham 
322f02a2e96SJim Ingham     if (m_virtual_step)
323f02a2e96SJim Ingham         return true;
324f02a2e96SJim Ingham 
325fbbfe6ecSJim Ingham     StopInfoSP stop_info_sp = GetPrivateStopReason();
326fbbfe6ecSJim Ingham     if (stop_info_sp)
327fbbfe6ecSJim Ingham     {
328fbbfe6ecSJim Ingham         StopReason reason = stop_info_sp->GetStopReason();
329fbbfe6ecSJim Ingham 
330fbbfe6ecSJim Ingham         switch (reason)
331fbbfe6ecSJim Ingham         {
332fbbfe6ecSJim Ingham         case eStopReasonBreakpoint:
333fbbfe6ecSJim Ingham             if (NextRangeBreakpointExplainsStop(stop_info_sp))
334fbbfe6ecSJim Ingham                 return true;
335fbbfe6ecSJim Ingham         case eStopReasonWatchpoint:
336fbbfe6ecSJim Ingham         case eStopReasonSignal:
337fbbfe6ecSJim Ingham         case eStopReasonException:
338513c6bb8SJim Ingham             {
339513c6bb8SJim Ingham                 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
340fbbfe6ecSJim Ingham                 if (log)
341fbbfe6ecSJim Ingham                     log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
342fbbfe6ecSJim Ingham                 SetPlanComplete(false);
343513c6bb8SJim Ingham             }
344fbbfe6ecSJim Ingham             break;
345fbbfe6ecSJim Ingham         default:
346fbbfe6ecSJim Ingham             break;
347fbbfe6ecSJim Ingham         }
348fbbfe6ecSJim Ingham     }
349fbbfe6ecSJim Ingham     return true;
350fbbfe6ecSJim Ingham }
351513c6bb8SJim Ingham 
352513c6bb8SJim Ingham bool
353513c6bb8SJim Ingham ThreadPlanStepInRange::WillResume (lldb::StateType resume_state, bool current_plan)
354513c6bb8SJim Ingham {
355513c6bb8SJim Ingham     if (resume_state == eStateStepping && current_plan)
356513c6bb8SJim Ingham     {
357513c6bb8SJim Ingham         // See if we are about to step over a virtual inlined call.
358513c6bb8SJim Ingham         bool step_without_resume = m_thread.DecrementCurrentInlinedDepth();
359513c6bb8SJim Ingham         if (step_without_resume)
360513c6bb8SJim Ingham         {
361513c6bb8SJim Ingham             LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
362513c6bb8SJim Ingham             if (log)
363513c6bb8SJim Ingham                 log->Printf ("ThreadPlanStepInRange::WillResume: returning false, inline_depth: %d",
364513c6bb8SJim Ingham                              m_thread.GetCurrentInlinedDepth());
365513c6bb8SJim Ingham             SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread));
366f02a2e96SJim Ingham 
367f02a2e96SJim Ingham             // FIXME: Maybe it would be better to create a InlineStep stop reason, but then
368f02a2e96SJim Ingham             // the whole rest of the world would have to handle that stop reason.
369f02a2e96SJim Ingham             m_virtual_step = true;
370513c6bb8SJim Ingham         }
371513c6bb8SJim Ingham         return !step_without_resume;
372513c6bb8SJim Ingham     }
373513c6bb8SJim Ingham     else
374513c6bb8SJim Ingham         return ThreadPlan::WillResume(resume_state, current_plan);
375513c6bb8SJim Ingham 
376513c6bb8SJim Ingham }
377