blob: b793deb36a48cc2a5ce0d21b00e15d666b6e3e6a [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- ThreadPlanStepInRange.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Target/ThreadPlanStepInRange.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16
17#include "lldb/lldb-private-log.h"
18#include "lldb/Core/Log.h"
Jim Ingham4da62062014-01-23 21:52:47 +000019#include "lldb/Core/Module.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020#include "lldb/Core/Stream.h"
Jim Inghama56c8002010-07-10 02:27:39 +000021#include "lldb/Symbol/Symbol.h"
Jim Ingham7ce490c2010-09-16 00:58:09 +000022#include "lldb/Symbol/Function.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000023#include "lldb/Target/Process.h"
24#include "lldb/Target/RegisterContext.h"
Greg Clayton514487e2011-02-15 21:59:32 +000025#include "lldb/Target/Target.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000026#include "lldb/Target/Thread.h"
27#include "lldb/Target/ThreadPlanStepOut.h"
28#include "lldb/Target/ThreadPlanStepThrough.h"
Jim Inghama56c8002010-07-10 02:27:39 +000029#include "lldb/Core/RegularExpression.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000030
31using namespace lldb;
32using namespace lldb_private;
33
34uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eAvoidNoDebug;
35
36//----------------------------------------------------------------------
37// ThreadPlanStepInRange: Step through a stack range, either stepping over or into
38// based on the value of \a type.
39//----------------------------------------------------------------------
40
41ThreadPlanStepInRange::ThreadPlanStepInRange
42(
43 Thread &thread,
44 const AddressRange &range,
45 const SymbolContext &addr_context,
46 lldb::RunMode stop_others
47) :
Jim Inghamb01e7422010-06-19 04:45:32 +000048 ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others),
Jim Ingham7ce490c2010-09-16 00:58:09 +000049 ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL),
Jim Inghamf02a2e92012-09-07 01:11:44 +000050 m_step_past_prologue (true),
51 m_virtual_step (false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000052{
53 SetFlagsToDefault ();
54}
55
Jim Inghamc6276822012-12-12 19:58:40 +000056ThreadPlanStepInRange::ThreadPlanStepInRange
57(
58 Thread &thread,
59 const AddressRange &range,
60 const SymbolContext &addr_context,
61 const char *step_into_target,
62 lldb::RunMode stop_others
63) :
64 ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others),
65 ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL),
66 m_step_past_prologue (true),
67 m_virtual_step (false),
68 m_step_into_target (step_into_target)
69{
70 SetFlagsToDefault ();
71}
72
Chris Lattner30fdc8d2010-06-08 16:52:24 +000073ThreadPlanStepInRange::~ThreadPlanStepInRange ()
74{
75}
76
77void
78ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
79{
80 if (level == lldb::eDescriptionLevelBrief)
81 s->Printf("step in");
82 else
83 {
84 s->Printf ("Stepping through range (stepping into functions): ");
Jim Inghamc4c9fed2011-10-15 00:24:48 +000085 DumpRanges(s);
Jim Ingham4d56e9c2013-07-18 21:48:26 +000086 const char *step_into_target = m_step_into_target.AsCString();
87 if (step_into_target && step_into_target[0] != '\0')
88 s->Printf (" targeting %s.", m_step_into_target.AsCString());
89 else
90 s->PutChar('.');
Chris Lattner30fdc8d2010-06-08 16:52:24 +000091 }
92}
93
94bool
95ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
96{
Greg Clayton5160ce52013-03-27 23:08:40 +000097 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000098
99 if (log)
100 {
101 StreamString s;
Greg Clayton514487e2011-02-15 21:59:32 +0000102 s.Address (m_thread.GetRegisterContext()->GetPC(),
Greg Clayton1ac04c32012-02-21 00:09:25 +0000103 m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000104 log->Printf("ThreadPlanStepInRange reached %s.", s.GetData());
105 }
106
Jim Ingham25f66702011-12-03 01:52:59 +0000107 if (IsPlanComplete())
108 return true;
109
Jim Ingham4d56e9c2013-07-18 21:48:26 +0000110 m_no_more_plans = false;
111 if (m_sub_plan_sp && m_sub_plan_sp->IsPlanComplete())
112 {
113 if (!m_sub_plan_sp->PlanSucceeded())
114 {
115 SetPlanComplete();
116 m_no_more_plans = true;
117 return true;
118 }
119 else
120 m_sub_plan_sp.reset();
121 }
122
Jim Inghamf02a2e92012-09-07 01:11:44 +0000123 if (m_virtual_step)
Jim Ingham58221732010-11-05 00:18:21 +0000124 {
Jim Inghamf02a2e92012-09-07 01:11:44 +0000125 // If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise
126 // we're done.
Jim Ingham4d56e9c2013-07-18 21:48:26 +0000127 m_sub_plan_sp = InvokeShouldStopHereCallback();
Jim Inghamf02a2e92012-09-07 01:11:44 +0000128 }
129 else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000130 {
Jim Ingham4a58e962012-10-25 22:30:09 +0000131 // Stepping through should be done running other threads in general, since we're setting a breakpoint and
132 // continuing. So only stop others if we are explicitly told to do so.
Jim Inghamf02a2e92012-09-07 01:11:44 +0000133
134 bool stop_others;
Jim Ingham4a58e962012-10-25 22:30:09 +0000135 if (m_stop_others == lldb::eOnlyThisThread)
Jim Ingham4a58e962012-10-25 22:30:09 +0000136 stop_others = true;
Ed Maste6cf5b8f2013-11-25 16:36:47 +0000137 else
138 stop_others = false;
Jim Inghamf02a2e92012-09-07 01:11:44 +0000139
140 FrameComparison frame_order = CompareCurrentFrameToStartFrame();
141
142 if (frame_order == eFrameCompareOlder)
Jim Ingham7ce490c2010-09-16 00:58:09 +0000143 {
Jim Inghamf02a2e92012-09-07 01:11:44 +0000144 // If we're in an older frame then we should stop.
145 //
146 // A caveat to this is if we think the frame is older but we're actually in a trampoline.
147 // I'm going to make the assumption that you wouldn't RETURN to a trampoline. So if we are
148 // in a trampoline we think the frame is older because the trampoline confused the backtracer.
Jim Ingham4d56e9c2013-07-18 21:48:26 +0000149 m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others);
150 if (!m_sub_plan_sp)
Jim Inghamf02a2e92012-09-07 01:11:44 +0000151 return true;
152 else if (log)
Jim Ingham7ce490c2010-09-16 00:58:09 +0000153 {
Jim Inghamf02a2e92012-09-07 01:11:44 +0000154 log->Printf("Thought I stepped out, but in fact arrived at a trampoline.");
Jim Ingham7ce490c2010-09-16 00:58:09 +0000155 }
Jim Inghamf02a2e92012-09-07 01:11:44 +0000156
157 }
158 else if (frame_order == eFrameCompareEqual && InSymbol())
159 {
160 // If we are not in a place we should step through, we're done.
161 // One tricky bit here is that some stubs don't push a frame, so we have to check
162 // both the case of a frame that is younger, or the same as this frame.
163 // However, if the frame is the same, and we are still in the symbol we started
164 // in, the we don't need to do this. This first check isn't strictly necessary,
165 // but it is more efficient.
Jim Ingham7ce490c2010-09-16 00:58:09 +0000166
Jim Inghamf02a2e92012-09-07 01:11:44 +0000167 // If we're still in the range, keep going, either by running to the next branch breakpoint, or by
168 // stepping.
169 if (InRange())
Jim Ingham7ce490c2010-09-16 00:58:09 +0000170 {
Jim Inghamf02a2e92012-09-07 01:11:44 +0000171 SetNextBranchBreakpoint();
172 return false;
173 }
174
175 SetPlanComplete();
Jim Inghamc6276822012-12-12 19:58:40 +0000176 m_no_more_plans = true;
Jim Inghamf02a2e92012-09-07 01:11:44 +0000177 return true;
178 }
179
180 // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it:
181 ClearNextBranchBreakpoint();
182
183 // We may have set the plan up above in the FrameIsOlder section:
184
Jim Ingham4d56e9c2013-07-18 21:48:26 +0000185 if (!m_sub_plan_sp)
186 m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others);
Jim Inghamf02a2e92012-09-07 01:11:44 +0000187
188 if (log)
189 {
Jim Ingham4d56e9c2013-07-18 21:48:26 +0000190 if (m_sub_plan_sp)
191 log->Printf ("Found a step through plan: %s", m_sub_plan_sp->GetName());
Jim Inghamf02a2e92012-09-07 01:11:44 +0000192 else
193 log->Printf ("No step through plan found.");
194 }
195
196 // If not, give the "should_stop" callback a chance to push a plan to get us out of here.
197 // But only do that if we actually have stepped in.
Jim Ingham4d56e9c2013-07-18 21:48:26 +0000198 if (!m_sub_plan_sp && frame_order == eFrameCompareYounger)
199 m_sub_plan_sp = InvokeShouldStopHereCallback();
Jim Inghamf02a2e92012-09-07 01:11:44 +0000200
201 // If we've stepped in and we are going to stop here, check to see if we were asked to
202 // run past the prologue, and if so do that.
203
Jim Ingham4d56e9c2013-07-18 21:48:26 +0000204 if (!m_sub_plan_sp && frame_order == eFrameCompareYounger && m_step_past_prologue)
Jim Inghamf02a2e92012-09-07 01:11:44 +0000205 {
Jason Molendab57e4a12013-11-04 09:33:30 +0000206 lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0);
Jim Inghamf02a2e92012-09-07 01:11:44 +0000207 if (curr_frame)
208 {
209 size_t bytes_to_skip = 0;
210 lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC();
211 Address func_start_address;
212
213 SymbolContext sc = curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextSymbol);
214
215 if (sc.function)
216 {
217 func_start_address = sc.function->GetAddressRange().GetBaseAddress();
218 if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get()))
219 bytes_to_skip = sc.function->GetPrologueByteSize();
220 }
221 else if (sc.symbol)
222 {
223 func_start_address = sc.symbol->GetAddress();
224 if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get()))
225 bytes_to_skip = sc.symbol->GetPrologueByteSize();
226 }
227
228 if (bytes_to_skip != 0)
229 {
230 func_start_address.Slide (bytes_to_skip);
231 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
232 if (log)
233 log->Printf ("Pushing past prologue ");
234
Jim Ingham4d56e9c2013-07-18 21:48:26 +0000235 m_sub_plan_sp = m_thread.QueueThreadPlanForRunToAddress(false, func_start_address,true);
Jim Inghamf02a2e92012-09-07 01:11:44 +0000236 }
Jim Ingham7ce490c2010-09-16 00:58:09 +0000237 }
238 }
Jim Inghamf02a2e92012-09-07 01:11:44 +0000239 }
Jim Ingham7ce490c2010-09-16 00:58:09 +0000240
Jim Ingham4d56e9c2013-07-18 21:48:26 +0000241 if (!m_sub_plan_sp)
Jim Ingham7ce490c2010-09-16 00:58:09 +0000242 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000243 m_no_more_plans = true;
244 SetPlanComplete();
245 return true;
246 }
247 else
248 {
249 m_no_more_plans = false;
250 return false;
251 }
252}
253
254void
255ThreadPlanStepInRange::SetFlagsToDefault ()
256{
257 GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values);
258}
259
Jim Inghama56c8002010-07-10 02:27:39 +0000260void
261ThreadPlanStepInRange::SetAvoidRegexp(const char *name)
262{
263 if (m_avoid_regexp_ap.get() == NULL)
264 m_avoid_regexp_ap.reset (new RegularExpression(name));
265
266 m_avoid_regexp_ap->Compile (name);
267}
268
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000269void
270ThreadPlanStepInRange::SetDefaultFlagValue (uint32_t new_value)
271{
272 // TODO: Should we test this for sanity?
273 ThreadPlanStepInRange::s_default_flag_values = new_value;
274}
275
Jim Inghama56c8002010-07-10 02:27:39 +0000276bool
Jim Ingham4da62062014-01-23 21:52:47 +0000277ThreadPlanStepInRange::FrameMatchesAvoidCriteria ()
Jim Inghama56c8002010-07-10 02:27:39 +0000278{
Jason Molendab57e4a12013-11-04 09:33:30 +0000279 StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get();
Jim Ingham4da62062014-01-23 21:52:47 +0000280
281 // Check the library list first, as that's cheapest:
282 FileSpecList libraries_to_avoid (GetThread().GetLibrariesToAvoid());
283 size_t num_libraries = libraries_to_avoid.GetSize();
284 bool libraries_say_avoid = false;
285 SymbolContext sc(frame->GetSymbolContext(eSymbolContextModule));
286 FileSpec frame_library(sc.module_sp->GetFileSpec());
287
288 if (frame_library)
289 {
290 for (size_t i = 0; i < num_libraries; i++)
291 {
292 const FileSpec &file_spec(libraries_to_avoid.GetFileSpecAtIndex(i));
293 if (FileSpec::Equal (file_spec, frame_library, false))
294 {
295 libraries_say_avoid = true;
296 break;
297 }
298 }
299 }
300 if (libraries_say_avoid)
301 return true;
302
Greg Clayton67cc0632012-08-22 17:17:09 +0000303 const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get();
Jim Inghamee8aea12010-09-08 03:14:33 +0000304 if (avoid_regexp_to_use == NULL)
305 avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp();
306
307 if (avoid_regexp_to_use != NULL)
Jim Inghama56c8002010-07-10 02:27:39 +0000308 {
Greg Clayton4592cbc2012-07-13 00:19:40 +0000309 SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
Jim Inghama56c8002010-07-10 02:27:39 +0000310 if (sc.symbol != NULL)
311 {
Greg Clayton4592cbc2012-07-13 00:19:40 +0000312 const char *frame_function_name = sc.GetFunctionName().GetCString();
313 if (frame_function_name)
Jim Ingham3101ba32013-03-14 21:44:36 +0000314 {
Jim Inghamcf2667c2013-03-14 22:00:18 +0000315 size_t num_matches = 0;
Greg Clayton5160ce52013-03-27 23:08:40 +0000316 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Inghamcf2667c2013-03-14 22:00:18 +0000317 if (log)
318 num_matches = 1;
Greg Claytonbc43cab2013-04-03 21:37:16 +0000319
320 RegularExpression::Match regex_match(num_matches);
321
322 bool return_value = avoid_regexp_to_use->Execute(frame_function_name, &regex_match);
Jim Ingham3101ba32013-03-14 21:44:36 +0000323 if (return_value)
324 {
Jim Ingham3101ba32013-03-14 21:44:36 +0000325 if (log)
Jim Inghamcf2667c2013-03-14 22:00:18 +0000326 {
327 std::string match;
Greg Claytonbc43cab2013-04-03 21:37:16 +0000328 regex_match.GetMatchAtIndex(frame_function_name,0, match);
Jim Inghamcf2667c2013-03-14 22:00:18 +0000329 log->Printf ("Stepping out of function \"%s\" because it matches the avoid regexp \"%s\" - match substring: \"%s\".",
Jim Ingham3101ba32013-03-14 21:44:36 +0000330 frame_function_name,
Jim Inghamcf2667c2013-03-14 22:00:18 +0000331 avoid_regexp_to_use->GetText(),
332 match.c_str());
333 }
Jim Ingham3101ba32013-03-14 21:44:36 +0000334
335 }
336 return return_value;
337 }
Jim Inghama56c8002010-07-10 02:27:39 +0000338 }
339 }
340 return false;
341}
342
Jim Ingham4d56e9c2013-07-18 21:48:26 +0000343ThreadPlanSP
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000344ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton)
345{
Jim Inghama56c8002010-07-10 02:27:39 +0000346 bool should_step_out = false;
Jason Molendab57e4a12013-11-04 09:33:30 +0000347 StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
Greg Clayton5160ce52013-03-27 23:08:40 +0000348 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Inghama56c8002010-07-10 02:27:39 +0000349
Greg Clayton73b472d2010-10-27 03:32:59 +0000350 if (flags.Test(eAvoidNoDebug))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000351 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000352 if (!frame->HasDebugInformation())
Jim Inghamaf0f1752010-09-15 00:06:51 +0000353 {
354 if (log)
355 log->Printf ("Stepping out of frame with no debug info");
356
Jim Inghama56c8002010-07-10 02:27:39 +0000357 should_step_out = true;
Jim Inghamaf0f1752010-09-15 00:06:51 +0000358 }
Jim Inghama56c8002010-07-10 02:27:39 +0000359 }
360
Jim Inghamc6276822012-12-12 19:58:40 +0000361 if (current_plan->GetKind() == eKindStepInRange)
Jim Inghama56c8002010-07-10 02:27:39 +0000362 {
Jim Inghamc6276822012-12-12 19:58:40 +0000363 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
364 if (step_in_range_plan->m_step_into_target)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000365 {
Jim Inghamc6276822012-12-12 19:58:40 +0000366 SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
367 if (sc.symbol != NULL)
368 {
369 // First try an exact match, since that's cheap with ConstStrings. Then do a strstr compare.
370 if (step_in_range_plan->m_step_into_target == sc.GetFunctionName())
371 {
372 should_step_out = false;
373 }
374 else
375 {
376 const char *target_name = step_in_range_plan->m_step_into_target.AsCString();
377 const char *function_name = sc.GetFunctionName().AsCString();
378
379 if (function_name == NULL)
380 should_step_out = true;
381 else if (strstr (function_name, target_name) == NULL)
382 should_step_out = true;
383 }
Jim Ingham3101ba32013-03-14 21:44:36 +0000384 if (log && should_step_out)
385 log->Printf("Stepping out of frame %s which did not match step into target %s.",
386 sc.GetFunctionName().AsCString(),
387 step_in_range_plan->m_step_into_target.AsCString());
Jim Inghamc6276822012-12-12 19:58:40 +0000388 }
389 }
390
391 if (!should_step_out)
392 {
Jim Ingham3101ba32013-03-14 21:44:36 +0000393 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
Jim Ingham4da62062014-01-23 21:52:47 +0000394 // Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidCriteria.
395 should_step_out = step_in_range_plan->FrameMatchesAvoidCriteria ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000396 }
397 }
Jim Inghama56c8002010-07-10 02:27:39 +0000398
Jim Inghamc6276822012-12-12 19:58:40 +0000399
Jim Inghama56c8002010-07-10 02:27:39 +0000400 if (should_step_out)
401 {
402 // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions.
Jim Ingham4a58e962012-10-25 22:30:09 +0000403 // We really should have all plans take the tri-state for "stop others" so we can do the right
404 // thing. For now let's be safe and always run others when we are likely to run arbitrary code.
405 const bool stop_others = false;
Greg Clayton481cef22011-01-21 06:11:58 +0000406 return current_plan->GetThread().QueueThreadPlanForStepOut (false,
407 NULL,
408 true,
Jim Ingham4a58e962012-10-25 22:30:09 +0000409 stop_others,
Greg Clayton481cef22011-01-21 06:11:58 +0000410 eVoteNo,
411 eVoteNoOpinion,
412 0); // Frame index
Jim Inghama56c8002010-07-10 02:27:39 +0000413 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000414
Jim Ingham4d56e9c2013-07-18 21:48:26 +0000415 return ThreadPlanSP();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000416}
Jim Inghamfbbfe6e2012-05-01 18:38:37 +0000417
418bool
Jim Ingham221d51c2013-05-08 00:35:16 +0000419ThreadPlanStepInRange::DoPlanExplainsStop (Event *event_ptr)
Jim Inghamfbbfe6e2012-05-01 18:38:37 +0000420{
421 // We always explain a stop. Either we've just done a single step, in which
422 // case we'll do our ordinary processing, or we stopped for some
423 // reason that isn't handled by our sub-plans, in which case we want to just stop right
424 // away.
Jim Inghamc6276822012-12-12 19:58:40 +0000425 // In general, we don't want to mark the plan as complete for unexplained stops.
426 // For instance, if you step in to some code with no debug info, so you step out
427 // and in the course of that hit a breakpoint, then you want to stop & show the user
428 // the breakpoint, but not unship the step in plan, since you still may want to complete that
429 // plan when you continue. This is particularly true when doing "step in to target function."
430 // stepping.
Jim Inghamfbbfe6e2012-05-01 18:38:37 +0000431 //
432 // The only variation is that if we are doing "step by running to next branch" in which case
433 // if we hit our branch breakpoint we don't set the plan to complete.
Jim Ingham221d51c2013-05-08 00:35:16 +0000434
435 bool return_value;
Jim Inghamfbbfe6e2012-05-01 18:38:37 +0000436
Jim Inghamf02a2e92012-09-07 01:11:44 +0000437 if (m_virtual_step)
Jim Inghamfbbfe6e2012-05-01 18:38:37 +0000438 {
Jim Ingham221d51c2013-05-08 00:35:16 +0000439 return_value = true;
Jim Inghamfbbfe6e2012-05-01 18:38:37 +0000440 }
Jim Ingham221d51c2013-05-08 00:35:16 +0000441 else
442 {
Jim Ingham60c41182013-06-04 01:40:51 +0000443 StopInfoSP stop_info_sp = GetPrivateStopInfo ();
Jim Ingham221d51c2013-05-08 00:35:16 +0000444 if (stop_info_sp)
445 {
446 StopReason reason = stop_info_sp->GetStopReason();
447
448 switch (reason)
449 {
450 case eStopReasonBreakpoint:
451 if (NextRangeBreakpointExplainsStop(stop_info_sp))
452 {
453 return_value = true;
454 break;
455 }
456 case eStopReasonWatchpoint:
457 case eStopReasonSignal:
458 case eStopReasonException:
459 case eStopReasonExec:
460 case eStopReasonThreadExiting:
461 {
462 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
463 if (log)
464 log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
465 }
466 return_value = false;
467 break;
468 default:
469 return_value = true;
470 break;
471 }
472 }
473 else
474 return_value = true;
475 }
476
477 return return_value;
Jim Inghamfbbfe6e2012-05-01 18:38:37 +0000478}
Jim Ingham513c6bb2012-09-01 01:02:41 +0000479
480bool
Jim Ingham221d51c2013-05-08 00:35:16 +0000481ThreadPlanStepInRange::DoWillResume (lldb::StateType resume_state, bool current_plan)
Jim Ingham513c6bb2012-09-01 01:02:41 +0000482{
483 if (resume_state == eStateStepping && current_plan)
484 {
485 // See if we are about to step over a virtual inlined call.
486 bool step_without_resume = m_thread.DecrementCurrentInlinedDepth();
487 if (step_without_resume)
488 {
Greg Clayton5160ce52013-03-27 23:08:40 +0000489 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Ingham513c6bb2012-09-01 01:02:41 +0000490 if (log)
Jim Ingham221d51c2013-05-08 00:35:16 +0000491 log->Printf ("ThreadPlanStepInRange::DoWillResume: returning false, inline_depth: %d",
Jim Ingham513c6bb2012-09-01 01:02:41 +0000492 m_thread.GetCurrentInlinedDepth());
493 SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread));
Jim Inghamf02a2e92012-09-07 01:11:44 +0000494
495 // FIXME: Maybe it would be better to create a InlineStep stop reason, but then
496 // the whole rest of the world would have to handle that stop reason.
497 m_virtual_step = true;
Jim Ingham513c6bb2012-09-01 01:02:41 +0000498 }
499 return !step_without_resume;
500 }
Jim Ingham221d51c2013-05-08 00:35:16 +0000501 return true;
Jim Ingham513c6bb2012-09-01 01:02:41 +0000502}
Daniel Malea246cb612013-05-14 15:20:12 +0000503
504bool
505ThreadPlanStepInRange::IsVirtualStep()
506{
507 return m_virtual_step;
508}