blob: f4339a45cd41618e1edaf463848ef40b831ac0ea [file] [log] [blame]
Chris Lattner24943d22010-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"
19#include "lldb/Core/Stream.h"
Jim Ingham809ab9b2010-07-10 02:27:39 +000020#include "lldb/Symbol/Symbol.h"
Jim Ingham0e81b642010-09-16 00:58:09 +000021#include "lldb/Symbol/Function.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/Target/Process.h"
23#include "lldb/Target/RegisterContext.h"
Greg Clayton395fc332011-02-15 21:59:32 +000024#include "lldb/Target/Target.h"
Chris Lattner24943d22010-06-08 16:52:24 +000025#include "lldb/Target/Thread.h"
26#include "lldb/Target/ThreadPlanStepOut.h"
27#include "lldb/Target/ThreadPlanStepThrough.h"
Jim Ingham809ab9b2010-07-10 02:27:39 +000028#include "lldb/Core/RegularExpression.h"
Chris Lattner24943d22010-06-08 16:52:24 +000029
30using namespace lldb;
31using namespace lldb_private;
32
33uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eAvoidNoDebug;
34
35//----------------------------------------------------------------------
36// ThreadPlanStepInRange: Step through a stack range, either stepping over or into
37// based on the value of \a type.
38//----------------------------------------------------------------------
39
40ThreadPlanStepInRange::ThreadPlanStepInRange
41(
42 Thread &thread,
43 const AddressRange &range,
44 const SymbolContext &addr_context,
45 lldb::RunMode stop_others
46) :
Jim Ingham5a47e8b2010-06-19 04:45:32 +000047 ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others),
Jim Ingham0e81b642010-09-16 00:58:09 +000048 ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL),
Jim Ingham45bc4a22012-09-07 01:11:44 +000049 m_step_past_prologue (true),
50 m_virtual_step (false)
Chris Lattner24943d22010-06-08 16:52:24 +000051{
52 SetFlagsToDefault ();
53}
54
55ThreadPlanStepInRange::~ThreadPlanStepInRange ()
56{
57}
58
59void
60ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
61{
62 if (level == lldb::eDescriptionLevelBrief)
63 s->Printf("step in");
64 else
65 {
66 s->Printf ("Stepping through range (stepping into functions): ");
Jim Ingham76e55f72011-10-15 00:24:48 +000067 DumpRanges(s);
Chris Lattner24943d22010-06-08 16:52:24 +000068 }
69}
70
71bool
72ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
73{
Greg Claytone005f2c2010-11-06 01:53:30 +000074 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner24943d22010-06-08 16:52:24 +000075 m_no_more_plans = false;
76
77 if (log)
78 {
79 StreamString s;
Greg Clayton395fc332011-02-15 21:59:32 +000080 s.Address (m_thread.GetRegisterContext()->GetPC(),
Greg Claytonf4124de2012-02-21 00:09:25 +000081 m_thread.CalculateTarget()->GetArchitecture().GetAddressByteSize());
Chris Lattner24943d22010-06-08 16:52:24 +000082 log->Printf("ThreadPlanStepInRange reached %s.", s.GetData());
83 }
84
Jim Inghamad382c52011-12-03 01:52:59 +000085 if (IsPlanComplete())
86 return true;
87
Chris Lattner24943d22010-06-08 16:52:24 +000088 ThreadPlan* new_plan = NULL;
89
Jim Ingham45bc4a22012-09-07 01:11:44 +000090 if (m_virtual_step)
Jim Ingham4f385f12010-11-05 00:18:21 +000091 {
Jim Ingham45bc4a22012-09-07 01:11:44 +000092 // If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise
93 // we're done.
Chris Lattner24943d22010-06-08 16:52:24 +000094 new_plan = InvokeShouldStopHereCallback();
Jim Ingham45bc4a22012-09-07 01:11:44 +000095 }
96 else
Chris Lattner24943d22010-06-08 16:52:24 +000097 {
Jim Ingham23f21942012-10-25 22:30:09 +000098 // Stepping through should be done running other threads in general, since we're setting a breakpoint and
99 // continuing. So only stop others if we are explicitly told to do so.
Jim Ingham45bc4a22012-09-07 01:11:44 +0000100
101 bool stop_others;
Jim Ingham23f21942012-10-25 22:30:09 +0000102 if (m_stop_others == lldb::eOnlyThisThread)
Jim Ingham45bc4a22012-09-07 01:11:44 +0000103 stop_others = false;
Jim Ingham23f21942012-10-25 22:30:09 +0000104 else
105 stop_others = true;
Jim Ingham45bc4a22012-09-07 01:11:44 +0000106
107 FrameComparison frame_order = CompareCurrentFrameToStartFrame();
108
109 if (frame_order == eFrameCompareOlder)
Jim Ingham0e81b642010-09-16 00:58:09 +0000110 {
Jim Ingham45bc4a22012-09-07 01:11:44 +0000111 // If we're in an older frame then we should stop.
112 //
113 // A caveat to this is if we think the frame is older but we're actually in a trampoline.
114 // I'm going to make the assumption that you wouldn't RETURN to a trampoline. So if we are
115 // in a trampoline we think the frame is older because the trampoline confused the backtracer.
116 new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others);
117 if (new_plan == NULL)
118 return true;
119 else if (log)
Jim Ingham0e81b642010-09-16 00:58:09 +0000120 {
Jim Ingham45bc4a22012-09-07 01:11:44 +0000121 log->Printf("Thought I stepped out, but in fact arrived at a trampoline.");
Jim Ingham0e81b642010-09-16 00:58:09 +0000122 }
Jim Ingham45bc4a22012-09-07 01:11:44 +0000123
124 }
125 else if (frame_order == eFrameCompareEqual && InSymbol())
126 {
127 // If we are not in a place we should step through, we're done.
128 // One tricky bit here is that some stubs don't push a frame, so we have to check
129 // both the case of a frame that is younger, or the same as this frame.
130 // However, if the frame is the same, and we are still in the symbol we started
131 // in, the we don't need to do this. This first check isn't strictly necessary,
132 // but it is more efficient.
Jim Ingham0e81b642010-09-16 00:58:09 +0000133
Jim Ingham45bc4a22012-09-07 01:11:44 +0000134 // If we're still in the range, keep going, either by running to the next branch breakpoint, or by
135 // stepping.
136 if (InRange())
Jim Ingham0e81b642010-09-16 00:58:09 +0000137 {
Jim Ingham45bc4a22012-09-07 01:11:44 +0000138 SetNextBranchBreakpoint();
139 return false;
140 }
141
142 SetPlanComplete();
143 return true;
144 }
145
146 // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it:
147 ClearNextBranchBreakpoint();
148
149 // We may have set the plan up above in the FrameIsOlder section:
150
151 if (new_plan == NULL)
152 new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others);
153
154 if (log)
155 {
156 if (new_plan != NULL)
157 log->Printf ("Found a step through plan: %s", new_plan->GetName());
158 else
159 log->Printf ("No step through plan found.");
160 }
161
162 // If not, give the "should_stop" callback a chance to push a plan to get us out of here.
163 // But only do that if we actually have stepped in.
164 if (!new_plan && frame_order == eFrameCompareYounger)
165 new_plan = InvokeShouldStopHereCallback();
166
167 // If we've stepped in and we are going to stop here, check to see if we were asked to
168 // run past the prologue, and if so do that.
169
170 if (new_plan == NULL && frame_order == eFrameCompareYounger && m_step_past_prologue)
171 {
172 lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0);
173 if (curr_frame)
174 {
175 size_t bytes_to_skip = 0;
176 lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC();
177 Address func_start_address;
178
179 SymbolContext sc = curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextSymbol);
180
181 if (sc.function)
182 {
183 func_start_address = sc.function->GetAddressRange().GetBaseAddress();
184 if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get()))
185 bytes_to_skip = sc.function->GetPrologueByteSize();
186 }
187 else if (sc.symbol)
188 {
189 func_start_address = sc.symbol->GetAddress();
190 if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get()))
191 bytes_to_skip = sc.symbol->GetPrologueByteSize();
192 }
193
194 if (bytes_to_skip != 0)
195 {
196 func_start_address.Slide (bytes_to_skip);
197 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
198 if (log)
199 log->Printf ("Pushing past prologue ");
200
201 new_plan = m_thread.QueueThreadPlanForRunToAddress(false, func_start_address,true);
202 }
Jim Ingham0e81b642010-09-16 00:58:09 +0000203 }
204 }
Jim Ingham45bc4a22012-09-07 01:11:44 +0000205 }
Jim Ingham0e81b642010-09-16 00:58:09 +0000206
207 if (new_plan == NULL)
208 {
Chris Lattner24943d22010-06-08 16:52:24 +0000209 m_no_more_plans = true;
210 SetPlanComplete();
211 return true;
212 }
213 else
214 {
215 m_no_more_plans = false;
216 return false;
217 }
218}
219
220void
221ThreadPlanStepInRange::SetFlagsToDefault ()
222{
223 GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values);
224}
225
Jim Ingham809ab9b2010-07-10 02:27:39 +0000226void
227ThreadPlanStepInRange::SetAvoidRegexp(const char *name)
228{
229 if (m_avoid_regexp_ap.get() == NULL)
230 m_avoid_regexp_ap.reset (new RegularExpression(name));
231
232 m_avoid_regexp_ap->Compile (name);
233}
234
Chris Lattner24943d22010-06-08 16:52:24 +0000235void
236ThreadPlanStepInRange::SetDefaultFlagValue (uint32_t new_value)
237{
238 // TODO: Should we test this for sanity?
239 ThreadPlanStepInRange::s_default_flag_values = new_value;
240}
241
Jim Ingham809ab9b2010-07-10 02:27:39 +0000242bool
243ThreadPlanStepInRange::FrameMatchesAvoidRegexp ()
244{
245 StackFrame *frame = GetThread().GetStackFrameAtIndex(0).get();
246
Greg Clayton73844aa2012-08-22 17:17:09 +0000247 const RegularExpression *avoid_regexp_to_use = m_avoid_regexp_ap.get();
Jim Ingham20594b12010-09-08 03:14:33 +0000248 if (avoid_regexp_to_use == NULL)
249 avoid_regexp_to_use = GetThread().GetSymbolsToAvoidRegexp();
250
251 if (avoid_regexp_to_use != NULL)
Jim Ingham809ab9b2010-07-10 02:27:39 +0000252 {
Greg Clayton002b3cf2012-07-13 00:19:40 +0000253 SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
Jim Ingham809ab9b2010-07-10 02:27:39 +0000254 if (sc.symbol != NULL)
255 {
Greg Clayton002b3cf2012-07-13 00:19:40 +0000256 const char *frame_function_name = sc.GetFunctionName().GetCString();
257 if (frame_function_name)
258 return avoid_regexp_to_use->Execute(frame_function_name);
Jim Ingham809ab9b2010-07-10 02:27:39 +0000259 }
260 }
261 return false;
262}
263
Chris Lattner24943d22010-06-08 16:52:24 +0000264ThreadPlan *
265ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton)
266{
Jim Ingham809ab9b2010-07-10 02:27:39 +0000267 bool should_step_out = false;
268 StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
269
Greg Claytonf3d0b0c2010-10-27 03:32:59 +0000270 if (flags.Test(eAvoidNoDebug))
Chris Lattner24943d22010-06-08 16:52:24 +0000271 {
Chris Lattner24943d22010-06-08 16:52:24 +0000272 if (!frame->HasDebugInformation())
Jim Inghame4b8aeb2010-09-15 00:06:51 +0000273 {
Jim Ingham0c8fa2d2012-09-01 01:02:41 +0000274 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Inghame4b8aeb2010-09-15 00:06:51 +0000275 if (log)
276 log->Printf ("Stepping out of frame with no debug info");
277
Jim Ingham809ab9b2010-07-10 02:27:39 +0000278 should_step_out = true;
Jim Inghame4b8aeb2010-09-15 00:06:51 +0000279 }
Jim Ingham809ab9b2010-07-10 02:27:39 +0000280 }
281
282 if (!should_step_out)
283 {
284 if (current_plan->GetKind() == eKindStepInRange)
Chris Lattner24943d22010-06-08 16:52:24 +0000285 {
Jim Ingham809ab9b2010-07-10 02:27:39 +0000286 ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
287 should_step_out = step_in_range_plan->FrameMatchesAvoidRegexp ();
Chris Lattner24943d22010-06-08 16:52:24 +0000288 }
289 }
Jim Ingham809ab9b2010-07-10 02:27:39 +0000290
291 if (should_step_out)
292 {
293 // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions.
Jim Ingham23f21942012-10-25 22:30:09 +0000294 // We really should have all plans take the tri-state for "stop others" so we can do the right
295 // thing. For now let's be safe and always run others when we are likely to run arbitrary code.
296 const bool stop_others = false;
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000297 return current_plan->GetThread().QueueThreadPlanForStepOut (false,
298 NULL,
299 true,
Jim Ingham23f21942012-10-25 22:30:09 +0000300 stop_others,
Greg Clayton1ebdcc72011-01-21 06:11:58 +0000301 eVoteNo,
302 eVoteNoOpinion,
303 0); // Frame index
Jim Ingham809ab9b2010-07-10 02:27:39 +0000304 }
Chris Lattner24943d22010-06-08 16:52:24 +0000305
306 return NULL;
307}
Jim Ingham707b7a82012-05-01 18:38:37 +0000308
309bool
310ThreadPlanStepInRange::PlanExplainsStop ()
311{
312 // We always explain a stop. Either we've just done a single step, in which
313 // case we'll do our ordinary processing, or we stopped for some
314 // reason that isn't handled by our sub-plans, in which case we want to just stop right
315 // away.
316 // We also set ourselves complete when we stop for this sort of unintended reason, but mark
317 // success as false so we don't end up being the reason for the stop.
318 //
319 // The only variation is that if we are doing "step by running to next branch" in which case
320 // if we hit our branch breakpoint we don't set the plan to complete.
321
Jim Ingham45bc4a22012-09-07 01:11:44 +0000322 if (m_virtual_step)
323 return true;
324
Jim Ingham707b7a82012-05-01 18:38:37 +0000325 StopInfoSP stop_info_sp = GetPrivateStopReason();
326 if (stop_info_sp)
327 {
328 StopReason reason = stop_info_sp->GetStopReason();
329
330 switch (reason)
331 {
332 case eStopReasonBreakpoint:
333 if (NextRangeBreakpointExplainsStop(stop_info_sp))
334 return true;
335 case eStopReasonWatchpoint:
336 case eStopReasonSignal:
337 case eStopReasonException:
Greg Clayton0bce9a22012-12-05 00:16:59 +0000338 case eStopReasonExec:
Jim Ingham0c8fa2d2012-09-01 01:02:41 +0000339 {
340 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
341 if (log)
342 log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
343 SetPlanComplete(false);
344 }
Jim Ingham707b7a82012-05-01 18:38:37 +0000345 break;
346 default:
347 break;
348 }
349 }
350 return true;
351}
Jim Ingham0c8fa2d2012-09-01 01:02:41 +0000352
353bool
354ThreadPlanStepInRange::WillResume (lldb::StateType resume_state, bool current_plan)
355{
356 if (resume_state == eStateStepping && current_plan)
357 {
358 // See if we are about to step over a virtual inlined call.
359 bool step_without_resume = m_thread.DecrementCurrentInlinedDepth();
360 if (step_without_resume)
361 {
362 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
363 if (log)
364 log->Printf ("ThreadPlanStepInRange::WillResume: returning false, inline_depth: %d",
365 m_thread.GetCurrentInlinedDepth());
366 SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread));
Jim Ingham45bc4a22012-09-07 01:11:44 +0000367
368 // FIXME: Maybe it would be better to create a InlineStep stop reason, but then
369 // the whole rest of the world would have to handle that stop reason.
370 m_virtual_step = true;
Jim Ingham0c8fa2d2012-09-01 01:02:41 +0000371 }
372 return !step_without_resume;
373 }
374 else
375 return ThreadPlan::WillResume(resume_state, current_plan);
376
377}