blob: 82b823be62e2f6183ebecffe3f6a81c051a39288 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- ThreadPlanStepOut.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
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
11// C++ Includes
12// Other libraries and framework includes
13// Project includes
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +000014#include "lldb/Target/ThreadPlanStepOut.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000015#include "lldb/Breakpoint/Breakpoint.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016#include "lldb/Core/Log.h"
Jim Ingham73ca05a2011-12-17 01:35:57 +000017#include "lldb/Core/Value.h"
18#include "lldb/Core/ValueObjectConstResult.h"
Greg Clayton1f746072012-08-29 21:13:06 +000019#include "lldb/Symbol/Block.h"
20#include "lldb/Symbol/Function.h"
Jason Molendafd4cea52016-01-08 21:40:11 +000021#include "lldb/Symbol/Symbol.h"
Greg Clayton1f746072012-08-29 21:13:06 +000022#include "lldb/Symbol/Type.h"
Zachary Turner32abc6e2015-03-03 19:23:09 +000023#include "lldb/Target/ABI.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000024#include "lldb/Target/Process.h"
25#include "lldb/Target/RegisterContext.h"
Greg Claytonf4b47e12010-08-04 01:40:35 +000026#include "lldb/Target/StopInfo.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000027#include "lldb/Target/Target.h"
Jim Inghama5ce6c82011-10-15 00:57:28 +000028#include "lldb/Target/ThreadPlanStepOverRange.h"
Jim Ingham4b4b2472014-03-13 02:47:14 +000029#include "lldb/Target/ThreadPlanStepThrough.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000030
31using namespace lldb;
32using namespace lldb_private;
33
Jim Ingham4b4b2472014-03-13 02:47:14 +000034uint32_t ThreadPlanStepOut::s_default_flag_values = 0;
35
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036//----------------------------------------------------------------------
37// ThreadPlanStepOut: Step out of the current frame
38//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +000039ThreadPlanStepOut::ThreadPlanStepOut
40(
41 Thread &thread,
42 SymbolContext *context,
43 bool first_insn,
44 bool stop_others,
45 Vote stop_vote,
Greg Clayton481cef22011-01-21 06:11:58 +000046 Vote run_vote,
Jim Ingham4b4b2472014-03-13 02:47:14 +000047 uint32_t frame_idx,
Jason Molendafd4cea52016-01-08 21:40:11 +000048 LazyBool step_out_avoids_code_without_debug_info,
49 bool continue_to_next_branch
Chris Lattner30fdc8d2010-06-08 16:52:24 +000050) :
Jim Inghamb01e7422010-06-19 04:45:32 +000051 ThreadPlan (ThreadPlan::eKindStepOut, "Step out", thread, stop_vote, run_vote),
Jim Ingham4b4b2472014-03-13 02:47:14 +000052 ThreadPlanShouldStopHere (this),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000053 m_step_from_insn (LLDB_INVALID_ADDRESS),
Benjamin Kramer1ee0d4f2010-07-16 12:32:33 +000054 m_return_bp_id (LLDB_INVALID_BREAK_ID),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055 m_return_addr (LLDB_INVALID_ADDRESS),
Jim Inghama5ce6c82011-10-15 00:57:28 +000056 m_stop_others (stop_others),
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +000057 m_immediate_step_from_function(nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000058{
Jim Ingham4b4b2472014-03-13 02:47:14 +000059 SetFlagsToDefault();
60 SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
61
Chris Lattner30fdc8d2010-06-08 16:52:24 +000062 m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0);
63
Jason Molendab57e4a12013-11-04 09:33:30 +000064 StackFrameSP return_frame_sp (m_thread.GetStackFrameAtIndex(frame_idx + 1));
65 StackFrameSP immediate_return_from_sp (m_thread.GetStackFrameAtIndex (frame_idx));
Jim Inghama5ce6c82011-10-15 00:57:28 +000066
Sean Callanan632d2f72012-03-13 16:34:56 +000067 if (!return_frame_sp || !immediate_return_from_sp)
68 return; // we can't do anything here. ValidatePlan() will return false.
69
Jim Inghamb5c0d1c2012-03-01 00:50:50 +000070 m_step_out_to_id = return_frame_sp->GetStackID();
71 m_immediate_step_from_id = immediate_return_from_sp->GetStackID();
72
73 StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
Jim Inghama5ce6c82011-10-15 00:57:28 +000074
75 // If the frame directly below the one we are returning to is inlined, we have to be
76 // a little more careful. It is non-trivial to determine the real "return code address" for
77 // an inlined frame, so we have to work our way to that frame and then step out.
78 if (immediate_return_from_sp && immediate_return_from_sp->IsInlined())
Chris Lattner30fdc8d2010-06-08 16:52:24 +000079 {
Jim Inghama5ce6c82011-10-15 00:57:28 +000080 if (frame_idx > 0)
81 {
82 // First queue a plan that gets us to this inlined frame, and when we get there we'll queue a second
83 // plan that walks us out of this frame.
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +000084 m_step_out_to_inline_plan_sp.reset(new ThreadPlanStepOut(m_thread,
85 nullptr,
86 false,
87 stop_others,
88 eVoteNoOpinion,
89 eVoteNoOpinion,
90 frame_idx - 1,
Jason Molendafd4cea52016-01-08 21:40:11 +000091 eLazyBoolNo,
92 continue_to_next_branch));
Jim Ingham4b4b2472014-03-13 02:47:14 +000093 static_cast<ThreadPlanStepOut *>(m_step_out_to_inline_plan_sp.get())->SetShouldStopHereCallbacks(nullptr, nullptr);
Jim Ingham2bdbfd52014-09-29 23:17:18 +000094 m_step_out_to_inline_plan_sp->SetPrivate(true);
Jim Inghama5ce6c82011-10-15 00:57:28 +000095 }
96 else
97 {
98 // If we're already at the inlined frame we're stepping through, then just do that now.
99 QueueInlinedStepPlan(false);
100 }
Jim Inghama5ce6c82011-10-15 00:57:28 +0000101 }
102 else if (return_frame_sp)
103 {
104 // Find the return address and set a breakpoint there:
105 // FIXME - can we do this more securely if we know first_insn?
106
Jason Molendafd4cea52016-01-08 21:40:11 +0000107 Address return_address (return_frame_sp->GetFrameCodeAddress());
108 if (continue_to_next_branch)
109 {
110 SymbolContext return_address_sc;
111 AddressRange range;
112 Address return_address_decr_pc = return_address;
113 if (return_address_decr_pc.GetOffset() > 0)
114 return_address_decr_pc.Slide (-1);
115
116 return_address_decr_pc.CalculateSymbolContext (&return_address_sc, lldb::eSymbolContextLineEntry);
117 if (return_address_sc.line_entry.IsValid())
118 {
119 range = return_address_sc.line_entry.GetSameLineContiguousAddressRange();
120 if (range.GetByteSize() > 0)
121 {
122 return_address = m_thread.GetProcess()->AdvanceAddressToNextBranchInstruction (return_address,
123 range);
124 }
125 }
126 }
127 m_return_addr = return_address.GetLoadAddress(&m_thread.GetProcess()->GetTarget());
Sean Callanan708709c2012-07-31 22:19:25 +0000128
129 if (m_return_addr == LLDB_INVALID_ADDRESS)
130 return;
131
Greg Claytoneb023e72013-10-11 19:48:25 +0000132 Breakpoint *return_bp = m_thread.CalculateTarget()->CreateBreakpoint (m_return_addr, true, false).get();
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +0000133 if (return_bp != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000134 {
135 return_bp->SetThreadID(m_thread.GetID());
136 m_return_bp_id = return_bp->GetID();
Jim Ingham29950772013-01-26 02:19:28 +0000137 return_bp->SetBreakpointKind ("step-out");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000138 }
Jim Ingham73ca05a2011-12-17 01:35:57 +0000139
140 if (immediate_return_from_sp)
141 {
142 const SymbolContext &sc = immediate_return_from_sp->GetSymbolContext(eSymbolContextFunction);
143 if (sc.function)
144 {
145 m_immediate_step_from_function = sc.function;
146 }
147 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000148 }
Jim Inghama5ce6c82011-10-15 00:57:28 +0000149}
150
151void
Jim Ingham4b4b2472014-03-13 02:47:14 +0000152ThreadPlanStepOut::SetupAvoidNoDebug(LazyBool step_out_avoids_code_without_debug_info)
153{
154 bool avoid_nodebug = true;
155 switch (step_out_avoids_code_without_debug_info)
156 {
157 case eLazyBoolYes:
158 avoid_nodebug = true;
159 break;
160 case eLazyBoolNo:
161 avoid_nodebug = false;
162 break;
163 case eLazyBoolCalculate:
164 avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
165 break;
166 }
167 if (avoid_nodebug)
168 GetFlags().Set (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
169 else
170 GetFlags().Clear (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
171}
172
173void
Jim Inghama5ce6c82011-10-15 00:57:28 +0000174ThreadPlanStepOut::DidPush()
175{
Jim Ingham4b4b2472014-03-13 02:47:14 +0000176 if (m_step_out_to_inline_plan_sp)
177 m_thread.QueueThreadPlan(m_step_out_to_inline_plan_sp, false);
Jim Inghama5ce6c82011-10-15 00:57:28 +0000178 else if (m_step_through_inline_plan_sp)
179 m_thread.QueueThreadPlan(m_step_through_inline_plan_sp, false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000180}
181
182ThreadPlanStepOut::~ThreadPlanStepOut ()
183{
184 if (m_return_bp_id != LLDB_INVALID_BREAK_ID)
Greg Clayton1ac04c32012-02-21 00:09:25 +0000185 m_thread.CalculateTarget()->RemoveBreakpointByID(m_return_bp_id);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000186}
187
188void
189ThreadPlanStepOut::GetDescription (Stream *s, lldb::DescriptionLevel level)
190{
191 if (level == lldb::eDescriptionLevelBrief)
192 s->Printf ("step out");
193 else
194 {
Jim Ingham4b4b2472014-03-13 02:47:14 +0000195 if (m_step_out_to_inline_plan_sp)
Jim Inghamb5c0d1c2012-03-01 00:50:50 +0000196 s->Printf ("Stepping out to inlined frame so we can walk through it.");
Jim Inghama5ce6c82011-10-15 00:57:28 +0000197 else if (m_step_through_inline_plan_sp)
198 s->Printf ("Stepping out by stepping through inlined function.");
199 else
Jim Ingham2bdbfd52014-09-29 23:17:18 +0000200 {
201 s->Printf ("Stepping out from ");
202 Address tmp_address;
203 if (tmp_address.SetLoadAddress (m_step_from_insn, &GetTarget()))
204 {
205 tmp_address.Dump(s, &GetThread(), Address::DumpStyleResolvedDescription, Address::DumpStyleLoadAddress);
206 }
207 else
208 {
209 s->Printf ("address 0x%" PRIx64 "", (uint64_t)m_step_from_insn);
210 }
211
212 // FIXME: find some useful way to present the m_return_id, since there may be multiple copies of the
213 // same function on the stack.
214
Jason Molendaafdf6cb2015-12-04 02:52:49 +0000215 s->Printf (" returning to frame at ");
Jim Ingham2bdbfd52014-09-29 23:17:18 +0000216 if (tmp_address.SetLoadAddress (m_return_addr, &GetTarget()))
217 {
218 tmp_address.Dump(s, &GetThread(), Address::DumpStyleResolvedDescription, Address::DumpStyleLoadAddress);
219 }
220 else
221 {
222 s->Printf ("address 0x%" PRIx64 "", (uint64_t)m_return_addr);
223 }
224
225 if (level == eDescriptionLevelVerbose)
226 s->Printf(" using breakpoint site %d", m_return_bp_id);
227 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000228 }
229}
230
231bool
232ThreadPlanStepOut::ValidatePlan (Stream *error)
233{
Jim Ingham4b4b2472014-03-13 02:47:14 +0000234 if (m_step_out_to_inline_plan_sp)
235 return m_step_out_to_inline_plan_sp->ValidatePlan (error);
Jim Inghama5ce6c82011-10-15 00:57:28 +0000236 else if (m_step_through_inline_plan_sp)
237 return m_step_through_inline_plan_sp->ValidatePlan (error);
238 else if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
239 {
Sean Callanan708709c2012-07-31 22:19:25 +0000240 if (error)
241 error->PutCString("Could not create return address breakpoint.");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000242 return false;
Jim Inghama5ce6c82011-10-15 00:57:28 +0000243 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000244 else
245 return true;
246}
247
248bool
Jim Ingham221d51c2013-05-08 00:35:16 +0000249ThreadPlanStepOut::DoPlanExplainsStop (Event *event_ptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000250{
Jim Ingham4b4b2472014-03-13 02:47:14 +0000251 // If the step out plan is done, then we just need to step through the inlined frame.
252 if (m_step_out_to_inline_plan_sp)
Jim Inghama5ce6c82011-10-15 00:57:28 +0000253 {
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +0000254 return m_step_out_to_inline_plan_sp->MischiefManaged();
Jim Ingham4b4b2472014-03-13 02:47:14 +0000255 }
256 else if (m_step_through_inline_plan_sp)
257 {
258 if (m_step_through_inline_plan_sp->MischiefManaged())
Jim Inghama5ce6c82011-10-15 00:57:28 +0000259 {
Jim Ingham73ca05a2011-12-17 01:35:57 +0000260 CalculateReturnValue();
Jim Inghama5ce6c82011-10-15 00:57:28 +0000261 SetPlanComplete();
262 return true;
263 }
264 else
265 return false;
266 }
Jim Ingham4b4b2472014-03-13 02:47:14 +0000267 else if (m_step_out_further_plan_sp)
Jim Inghama5ce6c82011-10-15 00:57:28 +0000268 {
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +0000269 return m_step_out_further_plan_sp->MischiefManaged();
Jim Inghama5ce6c82011-10-15 00:57:28 +0000270 }
271
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000272 // We don't explain signals or breakpoints (breakpoints that handle stepping in or
273 // out will be handled by a child plan.
Jim Inghama5ce6c82011-10-15 00:57:28 +0000274
Jim Ingham60c41182013-06-04 01:40:51 +0000275 StopInfoSP stop_info_sp = GetPrivateStopInfo ();
Jim Inghamb15bfc72010-10-20 00:39:53 +0000276 if (stop_info_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000277 {
Jim Inghamb15bfc72010-10-20 00:39:53 +0000278 StopReason reason = stop_info_sp->GetStopReason();
Jim Ingham9b03fa02015-07-23 19:55:02 +0000279 if (reason == eStopReasonBreakpoint)
Greg Claytonf4b47e12010-08-04 01:40:35 +0000280 {
281 // If this is OUR breakpoint, we're fine, otherwise we don't know why this happened...
Greg Clayton1ac04c32012-02-21 00:09:25 +0000282 BreakpointSiteSP site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByID (stop_info_sp->GetValue()));
Greg Claytonf4b47e12010-08-04 01:40:35 +0000283 if (site_sp && site_sp->IsBreakpointAtThisSite (m_return_bp_id))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000284 {
Jim Inghamb5c0d1c2012-03-01 00:50:50 +0000285 bool done;
286
287 StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
288
289 if (m_step_out_to_id == frame_zero_id)
290 done = true;
291 else if (m_step_out_to_id < frame_zero_id)
292 {
293 // Either we stepped past the breakpoint, or the stack ID calculation
294 // was incorrect and we should probably stop.
295 done = true;
296 }
297 else
298 {
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +0000299 done = (m_immediate_step_from_id < frame_zero_id);
Jim Inghamb5c0d1c2012-03-01 00:50:50 +0000300 }
301
302 if (done)
Jim Ingham73ca05a2011-12-17 01:35:57 +0000303 {
Jim Ingham4b4b2472014-03-13 02:47:14 +0000304 if (InvokeShouldStopHereCallback (eFrameCompareOlder))
305 {
306 CalculateReturnValue();
307 SetPlanComplete();
308 }
Jim Ingham73ca05a2011-12-17 01:35:57 +0000309 }
Greg Clayton481cef22011-01-21 06:11:58 +0000310
Greg Claytonf4b47e12010-08-04 01:40:35 +0000311 // If there was only one owner, then we're done. But if we also hit some
312 // user breakpoint on our way out, we should mark ourselves as done, but
313 // also not claim to explain the stop, since it is more important to report
314 // the user breakpoint than the step out completion.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000315
Greg Claytonf4b47e12010-08-04 01:40:35 +0000316 if (site_sp->GetNumberOfOwners() == 1)
317 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000318 }
Greg Claytonf4b47e12010-08-04 01:40:35 +0000319 return false;
320 }
Jim Ingham9b03fa02015-07-23 19:55:02 +0000321 else if (IsUsuallyUnexplainedStopReason(reason))
Greg Claytonf4b47e12010-08-04 01:40:35 +0000322 return false;
Jim Ingham9b03fa02015-07-23 19:55:02 +0000323 else
Greg Claytonf4b47e12010-08-04 01:40:35 +0000324 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000325 }
326 return true;
327}
328
329bool
330ThreadPlanStepOut::ShouldStop (Event *event_ptr)
331{
Jim Ingham4b4b2472014-03-13 02:47:14 +0000332 if (IsPlanComplete())
333 return true;
334
335 bool done = false;
336 if (m_step_out_to_inline_plan_sp)
337 {
338 if (m_step_out_to_inline_plan_sp->MischiefManaged())
339 {
340 // Now step through the inlined stack we are in:
341 if (QueueInlinedStepPlan(true))
342 {
343 // If we can't queue a plan to do this, then just call ourselves done.
344 m_step_out_to_inline_plan_sp.reset();
345 SetPlanComplete (false);
346 return true;
347 }
348 else
349 done = true;
350 }
351 else
352 return m_step_out_to_inline_plan_sp->ShouldStop(event_ptr);
353 }
354 else if (m_step_through_inline_plan_sp)
355 {
356 if (m_step_through_inline_plan_sp->MischiefManaged())
357 done = true;
358 else
359 return m_step_through_inline_plan_sp->ShouldStop(event_ptr);
360 }
361 else if (m_step_out_further_plan_sp)
362 {
363 if (m_step_out_further_plan_sp->MischiefManaged())
364 m_step_out_further_plan_sp.reset();
365 else
366 return m_step_out_further_plan_sp->ShouldStop(event_ptr);
367 }
368
369 if (!done)
370 {
Jim Inghamb5c0d1c2012-03-01 00:50:50 +0000371 StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +0000372 done = !(frame_zero_id < m_step_out_to_id);
Jim Ingham4b4b2472014-03-13 02:47:14 +0000373 }
374
375 // The normal step out computations think we are done, so all we need to do is consult the ShouldStopHere,
376 // and we are done.
377
378 if (done)
379 {
380 if (InvokeShouldStopHereCallback(eFrameCompareOlder))
Jim Inghama5ce6c82011-10-15 00:57:28 +0000381 {
Jim Ingham73ca05a2011-12-17 01:35:57 +0000382 CalculateReturnValue();
Jim Inghama5ce6c82011-10-15 00:57:28 +0000383 SetPlanComplete();
Jim Inghama5ce6c82011-10-15 00:57:28 +0000384 }
385 else
386 {
Jim Ingham4b4b2472014-03-13 02:47:14 +0000387 m_step_out_further_plan_sp = QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder);
388 done = false;
Jim Inghama5ce6c82011-10-15 00:57:28 +0000389 }
Jim Ingham4b4b2472014-03-13 02:47:14 +0000390 }
391
392 return done;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000393}
394
395bool
396ThreadPlanStepOut::StopOthers ()
397{
398 return m_stop_others;
399}
400
401StateType
Jim Ingham06e827c2010-11-11 19:26:09 +0000402ThreadPlanStepOut::GetPlanRunState ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000403{
404 return eStateRunning;
405}
406
407bool
Jim Ingham221d51c2013-05-08 00:35:16 +0000408ThreadPlanStepOut::DoWillResume (StateType resume_state, bool current_plan)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000409{
Jim Ingham4b4b2472014-03-13 02:47:14 +0000410 if (m_step_out_to_inline_plan_sp || m_step_through_inline_plan_sp)
Jim Inghama5ce6c82011-10-15 00:57:28 +0000411 return true;
412
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000413 if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
414 return false;
415
416 if (current_plan)
417 {
Greg Clayton1ac04c32012-02-21 00:09:25 +0000418 Breakpoint *return_bp = m_thread.CalculateTarget()->GetBreakpointByID(m_return_bp_id).get();
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +0000419 if (return_bp != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000420 return_bp->SetEnabled (true);
421 }
422 return true;
423}
424
425bool
426ThreadPlanStepOut::WillStop ()
427{
Jim Inghama5ce6c82011-10-15 00:57:28 +0000428 if (m_return_bp_id != LLDB_INVALID_BREAK_ID)
429 {
Greg Clayton1ac04c32012-02-21 00:09:25 +0000430 Breakpoint *return_bp = m_thread.CalculateTarget()->GetBreakpointByID(m_return_bp_id).get();
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +0000431 if (return_bp != nullptr)
Jim Inghama5ce6c82011-10-15 00:57:28 +0000432 return_bp->SetEnabled (false);
433 }
434
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000435 return true;
436}
437
438bool
439ThreadPlanStepOut::MischiefManaged ()
440{
Jim Inghama5ce6c82011-10-15 00:57:28 +0000441 if (IsPlanComplete())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000442 {
443 // Did I reach my breakpoint? If so I'm done.
444 //
445 // I also check the stack depth, since if we've blown past the breakpoint for some
446 // reason and we're now stopping for some other reason altogether, then we're done
447 // with this step out operation.
448
Greg Clayton5160ce52013-03-27 23:08:40 +0000449 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000450 if (log)
451 log->Printf("Completed step out plan.");
Jim Inghama5ce6c82011-10-15 00:57:28 +0000452 if (m_return_bp_id != LLDB_INVALID_BREAK_ID)
453 {
Greg Clayton1ac04c32012-02-21 00:09:25 +0000454 m_thread.CalculateTarget()->RemoveBreakpointByID (m_return_bp_id);
Jim Inghama5ce6c82011-10-15 00:57:28 +0000455 m_return_bp_id = LLDB_INVALID_BREAK_ID;
456 }
457
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000458 ThreadPlan::MischiefManaged ();
459 return true;
460 }
461 else
462 {
463 return false;
464 }
465}
466
Jim Inghama5ce6c82011-10-15 00:57:28 +0000467bool
468ThreadPlanStepOut::QueueInlinedStepPlan (bool queue_now)
469{
470 // Now figure out the range of this inlined block, and set up a "step through range"
471 // plan for that. If we've been provided with a context, then use the block in that
472 // context.
Jason Molendab57e4a12013-11-04 09:33:30 +0000473 StackFrameSP immediate_return_from_sp (m_thread.GetStackFrameAtIndex (0));
Jim Inghama5ce6c82011-10-15 00:57:28 +0000474 if (!immediate_return_from_sp)
475 return false;
476
Greg Clayton5160ce52013-03-27 23:08:40 +0000477 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
Jim Inghama5ce6c82011-10-15 00:57:28 +0000478 if (log)
479 {
480 StreamString s;
481 immediate_return_from_sp->Dump(&s, true, false);
482 log->Printf("Queuing inlined frame to step past: %s.", s.GetData());
483 }
484
485 Block *from_block = immediate_return_from_sp->GetFrameBlock();
486 if (from_block)
487 {
488 Block *inlined_block = from_block->GetContainingInlinedBlock();
489 if (inlined_block)
490 {
491 size_t num_ranges = inlined_block->GetNumRanges();
492 AddressRange inline_range;
493 if (inlined_block->GetRangeAtIndex(0, inline_range))
494 {
495 SymbolContext inlined_sc;
496 inlined_block->CalculateSymbolContext(&inlined_sc);
Jim Ingham5f1a4e12012-07-26 18:23:21 +0000497 inlined_sc.target_sp = GetTarget().shared_from_this();
Jim Inghama5ce6c82011-10-15 00:57:28 +0000498 RunMode run_mode = m_stop_others ? lldb::eOnlyThisThread : lldb::eAllThreads;
Jim Ingham4b4b2472014-03-13 02:47:14 +0000499 const LazyBool avoid_no_debug = eLazyBoolNo;
Jim Ingham2bdbfd52014-09-29 23:17:18 +0000500
501 m_step_through_inline_plan_sp.reset (new ThreadPlanStepOverRange(m_thread,
502 inline_range,
503 inlined_sc,
504 run_mode,
505 avoid_no_debug));
506 ThreadPlanStepOverRange *step_through_inline_plan_ptr
507 = static_cast<ThreadPlanStepOverRange *>(m_step_through_inline_plan_sp.get());
508 m_step_through_inline_plan_sp->SetPrivate(true);
509
Jim Inghama5ce6c82011-10-15 00:57:28 +0000510 step_through_inline_plan_ptr->SetOkayToDiscard(true);
511 StreamString errors;
512 if (!step_through_inline_plan_ptr->ValidatePlan(&errors))
513 {
514 //FIXME: Log this failure.
515 delete step_through_inline_plan_ptr;
516 return false;
517 }
518
519 for (size_t i = 1; i < num_ranges; i++)
520 {
521 if (inlined_block->GetRangeAtIndex (i, inline_range))
522 step_through_inline_plan_ptr->AddRange (inline_range);
523 }
Jim Ingham2bdbfd52014-09-29 23:17:18 +0000524
Jim Inghama5ce6c82011-10-15 00:57:28 +0000525 if (queue_now)
526 m_thread.QueueThreadPlan (m_step_through_inline_plan_sp, false);
527 return true;
528 }
529 }
530 }
531
532 return false;
533}
Jim Ingham73ca05a2011-12-17 01:35:57 +0000534
535void
536ThreadPlanStepOut::CalculateReturnValue ()
537{
538 if (m_return_valobj_sp)
539 return;
540
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +0000541 if (m_immediate_step_from_function != nullptr)
Jim Ingham73ca05a2011-12-17 01:35:57 +0000542 {
Bruce Mitchener3ad353f2015-09-24 03:54:50 +0000543 CompilerType return_compiler_type = m_immediate_step_from_function->GetCompilerType().GetFunctionReturnType();
544 if (return_compiler_type)
Jim Ingham73ca05a2011-12-17 01:35:57 +0000545 {
Greg Clayton1ac04c32012-02-21 00:09:25 +0000546 lldb::ABISP abi_sp = m_thread.GetProcess()->GetABI();
Jim Ingham73ca05a2011-12-17 01:35:57 +0000547 if (abi_sp)
Bruce Mitchener3ad353f2015-09-24 03:54:50 +0000548 m_return_valobj_sp = abi_sp->GetReturnValueObject(m_thread, return_compiler_type);
Jim Ingham73ca05a2011-12-17 01:35:57 +0000549 }
550 }
551}
Jim Ingham64e7ead2012-05-03 21:19:36 +0000552
553bool
554ThreadPlanStepOut::IsPlanStale()
555{
556 // If we are still lower on the stack than the frame we are returning to, then
557 // there's something for us to do. Otherwise, we're stale.
558
559 StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
Eugene Zelenkoe65b2cf2015-12-15 01:33:19 +0000560 return !(frame_zero_id < m_step_out_to_id);
Jim Ingham64e7ead2012-05-03 21:19:36 +0000561}