blob: c4cb9aba1b3e08e55d60969bf102141adf57b131 [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:
Jim Inghama786e532014-01-23 21:57:53 +0000282 bool libraries_say_avoid = false;
283
Jim Ingham4da62062014-01-23 21:52:47 +0000284 FileSpecList libraries_to_avoid (GetThread().GetLibrariesToAvoid());
285 size_t num_libraries = libraries_to_avoid.GetSize();
Jim Inghama786e532014-01-23 21:57:53 +0000286 if (num_libraries > 0)
Jim Ingham4da62062014-01-23 21:52:47 +0000287 {
Jim Inghama786e532014-01-23 21:57:53 +0000288 SymbolContext sc(frame->GetSymbolContext(eSymbolContextModule));
289 FileSpec frame_library(sc.module_sp->GetFileSpec());
290
291 if (frame_library)
Jim Ingham4da62062014-01-23 21:52:47 +0000292 {
Jim Inghama786e532014-01-23 21:57:53 +0000293 for (size_t i = 0; i < num_libraries; i++)
Jim Ingham4da62062014-01-23 21:52:47 +0000294 {
Jim Inghama786e532014-01-23 21:57:53 +0000295 const FileSpec &file_spec(libraries_to_avoid.GetFileSpecAtIndex(i));
296 if (FileSpec::Equal (file_spec, frame_library, false))
297 {
298 libraries_say_avoid = true;
299 break;
300 }
Jim Ingham4da62062014-01-23 21:52:47 +0000301 }
302 }
303 }
304 if (libraries_say_avoid)
305 return true;
306
Greg Clayton67cc0632012-08-22 17:17:09 +0000307 const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get();
Jim Inghamee8aea12010-09-08 03:14:33 +0000308 if (avoid_regexp_to_use == NULL)
309 avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp();
310
311 if (avoid_regexp_to_use != NULL)
Jim Inghama56c8002010-07-10 02:27:39 +0000312 {
Greg Clayton4592cbc2012-07-13 00:19:40 +0000313 SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
Jim Inghama56c8002010-07-10 02:27:39 +0000314 if (sc.symbol != NULL)
315 {
Greg Clayton4592cbc2012-07-13 00:19:40 +0000316 const char *frame_function_name = sc.GetFunctionName().GetCString();
317 if (frame_function_name)
Jim Ingham3101ba32013-03-14 21:44:36 +0000318 {
Jim Inghamcf2667c2013-03-14 22:00:18 +0000319 size_t num_matches = 0;
Greg Clayton5160ce52013-03-27 23:08:40 +0000320 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Inghamcf2667c2013-03-14 22:00:18 +0000321 if (log)
322 num_matches = 1;
Greg Claytonbc43cab2013-04-03 21:37:16 +0000323
324 RegularExpression::Match regex_match(num_matches);
325
326 bool return_value = avoid_regexp_to_use->Execute(frame_function_name, &regex_match);
Jim Ingham3101ba32013-03-14 21:44:36 +0000327 if (return_value)
328 {
Jim Ingham3101ba32013-03-14 21:44:36 +0000329 if (log)
Jim Inghamcf2667c2013-03-14 22:00:18 +0000330 {
331 std::string match;
Greg Claytonbc43cab2013-04-03 21:37:16 +0000332 regex_match.GetMatchAtIndex(frame_function_name,0, match);
Jim Inghamcf2667c2013-03-14 22:00:18 +0000333 log->Printf ("Stepping out of function \"%s\" because it matches the avoid regexp \"%s\" - match substring: \"%s\".",
Jim Ingham3101ba32013-03-14 21:44:36 +0000334 frame_function_name,
Jim Inghamcf2667c2013-03-14 22:00:18 +0000335 avoid_regexp_to_use->GetText(),
336 match.c_str());
337 }
Jim Ingham3101ba32013-03-14 21:44:36 +0000338
339 }
340 return return_value;
341 }
Jim Inghama56c8002010-07-10 02:27:39 +0000342 }
343 }
344 return false;
345}
346
Jim Ingham4d56e9c2013-07-18 21:48:26 +0000347ThreadPlanSP
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000348ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton)
349{
Jim Inghama56c8002010-07-10 02:27:39 +0000350 bool should_step_out = false;
Jason Molendab57e4a12013-11-04 09:33:30 +0000351 StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
Greg Clayton5160ce52013-03-27 23:08:40 +0000352 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Inghama56c8002010-07-10 02:27:39 +0000353
Greg Clayton73b472d2010-10-27 03:32:59 +0000354 if (flags.Test(eAvoidNoDebug))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000355 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000356 if (!frame->HasDebugInformation())
Jim Inghamaf0f1752010-09-15 00:06:51 +0000357 {
358 if (log)
359 log->Printf ("Stepping out of frame with no debug info");
360
Jim Inghama56c8002010-07-10 02:27:39 +0000361 should_step_out = true;
Jim Inghamaf0f1752010-09-15 00:06:51 +0000362 }
Jim Inghama56c8002010-07-10 02:27:39 +0000363 }
364
Jim Inghamc6276822012-12-12 19:58:40 +0000365 if (current_plan->GetKind() == eKindStepInRange)
Jim Inghama56c8002010-07-10 02:27:39 +0000366 {
Jim Inghamc6276822012-12-12 19:58:40 +0000367 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
368 if (step_in_range_plan->m_step_into_target)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000369 {
Jim Inghamc6276822012-12-12 19:58:40 +0000370 SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
371 if (sc.symbol != NULL)
372 {
373 // First try an exact match, since that's cheap with ConstStrings. Then do a strstr compare.
374 if (step_in_range_plan->m_step_into_target == sc.GetFunctionName())
375 {
376 should_step_out = false;
377 }
378 else
379 {
380 const char *target_name = step_in_range_plan->m_step_into_target.AsCString();
381 const char *function_name = sc.GetFunctionName().AsCString();
382
383 if (function_name == NULL)
384 should_step_out = true;
385 else if (strstr (function_name, target_name) == NULL)
386 should_step_out = true;
387 }
Jim Ingham3101ba32013-03-14 21:44:36 +0000388 if (log && should_step_out)
389 log->Printf("Stepping out of frame %s which did not match step into target %s.",
390 sc.GetFunctionName().AsCString(),
391 step_in_range_plan->m_step_into_target.AsCString());
Jim Inghamc6276822012-12-12 19:58:40 +0000392 }
393 }
394
395 if (!should_step_out)
396 {
Jim Ingham3101ba32013-03-14 21:44:36 +0000397 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
Jim Ingham4da62062014-01-23 21:52:47 +0000398 // Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidCriteria.
399 should_step_out = step_in_range_plan->FrameMatchesAvoidCriteria ();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000400 }
401 }
Jim Inghama56c8002010-07-10 02:27:39 +0000402
Jim Inghamc6276822012-12-12 19:58:40 +0000403
Jim Inghama56c8002010-07-10 02:27:39 +0000404 if (should_step_out)
405 {
406 // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions.
Jim Ingham4a58e962012-10-25 22:30:09 +0000407 // We really should have all plans take the tri-state for "stop others" so we can do the right
408 // thing. For now let's be safe and always run others when we are likely to run arbitrary code.
409 const bool stop_others = false;
Greg Clayton481cef22011-01-21 06:11:58 +0000410 return current_plan->GetThread().QueueThreadPlanForStepOut (false,
411 NULL,
412 true,
Jim Ingham4a58e962012-10-25 22:30:09 +0000413 stop_others,
Greg Clayton481cef22011-01-21 06:11:58 +0000414 eVoteNo,
415 eVoteNoOpinion,
416 0); // Frame index
Jim Inghama56c8002010-07-10 02:27:39 +0000417 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000418
Jim Ingham4d56e9c2013-07-18 21:48:26 +0000419 return ThreadPlanSP();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000420}
Jim Inghamfbbfe6e2012-05-01 18:38:37 +0000421
422bool
Jim Ingham221d51c2013-05-08 00:35:16 +0000423ThreadPlanStepInRange::DoPlanExplainsStop (Event *event_ptr)
Jim Inghamfbbfe6e2012-05-01 18:38:37 +0000424{
425 // We always explain a stop. Either we've just done a single step, in which
426 // case we'll do our ordinary processing, or we stopped for some
427 // reason that isn't handled by our sub-plans, in which case we want to just stop right
428 // away.
Jim Inghamc6276822012-12-12 19:58:40 +0000429 // In general, we don't want to mark the plan as complete for unexplained stops.
430 // For instance, if you step in to some code with no debug info, so you step out
431 // and in the course of that hit a breakpoint, then you want to stop & show the user
432 // the breakpoint, but not unship the step in plan, since you still may want to complete that
433 // plan when you continue. This is particularly true when doing "step in to target function."
434 // stepping.
Jim Inghamfbbfe6e2012-05-01 18:38:37 +0000435 //
436 // The only variation is that if we are doing "step by running to next branch" in which case
437 // if we hit our branch breakpoint we don't set the plan to complete.
Jim Ingham221d51c2013-05-08 00:35:16 +0000438
439 bool return_value;
Jim Inghamfbbfe6e2012-05-01 18:38:37 +0000440
Jim Inghamf02a2e92012-09-07 01:11:44 +0000441 if (m_virtual_step)
Jim Inghamfbbfe6e2012-05-01 18:38:37 +0000442 {
Jim Ingham221d51c2013-05-08 00:35:16 +0000443 return_value = true;
Jim Inghamfbbfe6e2012-05-01 18:38:37 +0000444 }
Jim Ingham221d51c2013-05-08 00:35:16 +0000445 else
446 {
Jim Ingham60c41182013-06-04 01:40:51 +0000447 StopInfoSP stop_info_sp = GetPrivateStopInfo ();
Jim Ingham221d51c2013-05-08 00:35:16 +0000448 if (stop_info_sp)
449 {
450 StopReason reason = stop_info_sp->GetStopReason();
451
452 switch (reason)
453 {
454 case eStopReasonBreakpoint:
455 if (NextRangeBreakpointExplainsStop(stop_info_sp))
456 {
457 return_value = true;
458 break;
459 }
460 case eStopReasonWatchpoint:
461 case eStopReasonSignal:
462 case eStopReasonException:
463 case eStopReasonExec:
464 case eStopReasonThreadExiting:
465 {
466 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
467 if (log)
468 log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
469 }
470 return_value = false;
471 break;
472 default:
473 return_value = true;
474 break;
475 }
476 }
477 else
478 return_value = true;
479 }
480
481 return return_value;
Jim Inghamfbbfe6e2012-05-01 18:38:37 +0000482}
Jim Ingham513c6bb2012-09-01 01:02:41 +0000483
484bool
Jim Ingham221d51c2013-05-08 00:35:16 +0000485ThreadPlanStepInRange::DoWillResume (lldb::StateType resume_state, bool current_plan)
Jim Ingham513c6bb2012-09-01 01:02:41 +0000486{
487 if (resume_state == eStateStepping && current_plan)
488 {
489 // See if we are about to step over a virtual inlined call.
490 bool step_without_resume = m_thread.DecrementCurrentInlinedDepth();
491 if (step_without_resume)
492 {
Greg Clayton5160ce52013-03-27 23:08:40 +0000493 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Ingham513c6bb2012-09-01 01:02:41 +0000494 if (log)
Jim Ingham221d51c2013-05-08 00:35:16 +0000495 log->Printf ("ThreadPlanStepInRange::DoWillResume: returning false, inline_depth: %d",
Jim Ingham513c6bb2012-09-01 01:02:41 +0000496 m_thread.GetCurrentInlinedDepth());
497 SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread));
Jim Inghamf02a2e92012-09-07 01:11:44 +0000498
499 // FIXME: Maybe it would be better to create a InlineStep stop reason, but then
500 // the whole rest of the world would have to handle that stop reason.
501 m_virtual_step = true;
Jim Ingham513c6bb2012-09-01 01:02:41 +0000502 }
503 return !step_without_resume;
504 }
Jim Ingham221d51c2013-05-08 00:35:16 +0000505 return true;
Jim Ingham513c6bb2012-09-01 01:02:41 +0000506}
Daniel Malea246cb612013-05-14 15:20:12 +0000507
508bool
509ThreadPlanStepInRange::IsVirtualStep()
510{
511 return m_virtual_step;
512}