1 //===-- 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 
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/Target/ThreadPlanStepOut.h"
15 #include "lldb/Breakpoint/Breakpoint.h"
16 #include "lldb/Core/Log.h"
17 #include "lldb/Core/Value.h"
18 #include "lldb/Core/ValueObjectConstResult.h"
19 #include "lldb/Symbol/Block.h"
20 #include "lldb/Symbol/Function.h"
21 #include "lldb/Symbol/Symbol.h"
22 #include "lldb/Symbol/Type.h"
23 #include "lldb/Target/ABI.h"
24 #include "lldb/Target/Process.h"
25 #include "lldb/Target/RegisterContext.h"
26 #include "lldb/Target/StopInfo.h"
27 #include "lldb/Target/Target.h"
28 #include "lldb/Target/ThreadPlanStepOverRange.h"
29 #include "lldb/Target/ThreadPlanStepThrough.h"
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 
34 uint32_t ThreadPlanStepOut::s_default_flag_values = 0;
35 
36 //----------------------------------------------------------------------
37 // ThreadPlanStepOut: Step out of the current frame
38 //----------------------------------------------------------------------
39 ThreadPlanStepOut::ThreadPlanStepOut
40 (
41     Thread &thread,
42     SymbolContext *context,
43     bool first_insn,
44     bool stop_others,
45     Vote stop_vote,
46     Vote run_vote,
47     uint32_t frame_idx,
48     LazyBool step_out_avoids_code_without_debug_info,
49     bool continue_to_next_branch
50 ) :
51     ThreadPlan (ThreadPlan::eKindStepOut, "Step out", thread, stop_vote, run_vote),
52     ThreadPlanShouldStopHere (this),
53     m_step_from_insn (LLDB_INVALID_ADDRESS),
54     m_return_bp_id (LLDB_INVALID_BREAK_ID),
55     m_return_addr (LLDB_INVALID_ADDRESS),
56     m_stop_others (stop_others),
57     m_immediate_step_from_function(nullptr)
58 {
59     SetFlagsToDefault();
60     SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
61 
62     m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0);
63 
64     StackFrameSP return_frame_sp (m_thread.GetStackFrameAtIndex(frame_idx + 1));
65     StackFrameSP immediate_return_from_sp (m_thread.GetStackFrameAtIndex (frame_idx));
66 
67     if (!return_frame_sp || !immediate_return_from_sp)
68         return; // we can't do anything here.  ValidatePlan() will return false.
69 
70     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();
74 
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())
79     {
80         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.
84             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,
91                                                                      eLazyBoolNo,
92                                                                      continue_to_next_branch));
93             static_cast<ThreadPlanStepOut *>(m_step_out_to_inline_plan_sp.get())->SetShouldStopHereCallbacks(nullptr, nullptr);
94             m_step_out_to_inline_plan_sp->SetPrivate(true);
95         }
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         }
101     }
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 
107         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());
128 
129         if (m_return_addr == LLDB_INVALID_ADDRESS)
130             return;
131 
132         Breakpoint *return_bp = m_thread.CalculateTarget()->CreateBreakpoint (m_return_addr, true, false).get();
133         if (return_bp != nullptr)
134         {
135             return_bp->SetThreadID(m_thread.GetID());
136             m_return_bp_id = return_bp->GetID();
137             return_bp->SetBreakpointKind ("step-out");
138         }
139 
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         }
148     }
149 }
150 
151 void
152 ThreadPlanStepOut::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 
173 void
174 ThreadPlanStepOut::DidPush()
175 {
176     if (m_step_out_to_inline_plan_sp)
177         m_thread.QueueThreadPlan(m_step_out_to_inline_plan_sp, false);
178     else if (m_step_through_inline_plan_sp)
179         m_thread.QueueThreadPlan(m_step_through_inline_plan_sp, false);
180 }
181 
182 ThreadPlanStepOut::~ThreadPlanStepOut ()
183 {
184     if (m_return_bp_id != LLDB_INVALID_BREAK_ID)
185         m_thread.CalculateTarget()->RemoveBreakpointByID(m_return_bp_id);
186 }
187 
188 void
189 ThreadPlanStepOut::GetDescription (Stream *s, lldb::DescriptionLevel level)
190 {
191     if (level == lldb::eDescriptionLevelBrief)
192         s->Printf ("step out");
193     else
194     {
195         if (m_step_out_to_inline_plan_sp)
196             s->Printf ("Stepping out to inlined frame so we can walk through it.");
197         else if (m_step_through_inline_plan_sp)
198             s->Printf ("Stepping out by stepping through inlined function.");
199         else
200         {
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 
215             s->Printf (" returning to frame at ");
216             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         }
228     }
229 }
230 
231 bool
232 ThreadPlanStepOut::ValidatePlan (Stream *error)
233 {
234     if (m_step_out_to_inline_plan_sp)
235         return m_step_out_to_inline_plan_sp->ValidatePlan (error);
236     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     {
240         if (error)
241             error->PutCString("Could not create return address breakpoint.");
242         return false;
243     }
244     else
245         return true;
246 }
247 
248 bool
249 ThreadPlanStepOut::DoPlanExplainsStop (Event *event_ptr)
250 {
251     // 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)
253     {
254         return m_step_out_to_inline_plan_sp->MischiefManaged();
255     }
256     else if (m_step_through_inline_plan_sp)
257     {
258         if (m_step_through_inline_plan_sp->MischiefManaged())
259         {
260             CalculateReturnValue();
261             SetPlanComplete();
262             return true;
263         }
264         else
265             return false;
266     }
267     else if (m_step_out_further_plan_sp)
268     {
269         return m_step_out_further_plan_sp->MischiefManaged();
270     }
271 
272     // We don't explain signals or breakpoints (breakpoints that handle stepping in or
273     // out will be handled by a child plan.
274 
275     StopInfoSP stop_info_sp = GetPrivateStopInfo ();
276     if (stop_info_sp)
277     {
278         StopReason reason = stop_info_sp->GetStopReason();
279         if (reason == eStopReasonBreakpoint)
280         {
281             // If this is OUR breakpoint, we're fine, otherwise we don't know why this happened...
282             BreakpointSiteSP site_sp (m_thread.GetProcess()->GetBreakpointSiteList().FindByID (stop_info_sp->GetValue()));
283             if (site_sp && site_sp->IsBreakpointAtThisSite (m_return_bp_id))
284             {
285                 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                 {
299                     done = (m_immediate_step_from_id < frame_zero_id);
300                 }
301 
302                 if (done)
303                 {
304                     if (InvokeShouldStopHereCallback (eFrameCompareOlder))
305                     {
306                         CalculateReturnValue();
307                         SetPlanComplete();
308                     }
309                 }
310 
311                 // 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.
315 
316                 if (site_sp->GetNumberOfOwners() == 1)
317                     return true;
318             }
319             return false;
320         }
321         else if (IsUsuallyUnexplainedStopReason(reason))
322             return false;
323         else
324             return true;
325     }
326     return true;
327 }
328 
329 bool
330 ThreadPlanStepOut::ShouldStop (Event *event_ptr)
331 {
332     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     {
371         StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
372         done = !(frame_zero_id < m_step_out_to_id);
373     }
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))
381         {
382             CalculateReturnValue();
383             SetPlanComplete();
384         }
385         else
386         {
387             m_step_out_further_plan_sp = QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder);
388             done = false;
389         }
390     }
391 
392     return done;
393 }
394 
395 bool
396 ThreadPlanStepOut::StopOthers ()
397 {
398     return m_stop_others;
399 }
400 
401 StateType
402 ThreadPlanStepOut::GetPlanRunState ()
403 {
404     return eStateRunning;
405 }
406 
407 bool
408 ThreadPlanStepOut::DoWillResume (StateType resume_state, bool current_plan)
409 {
410     if (m_step_out_to_inline_plan_sp || m_step_through_inline_plan_sp)
411         return true;
412 
413     if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
414         return false;
415 
416     if (current_plan)
417     {
418         Breakpoint *return_bp = m_thread.CalculateTarget()->GetBreakpointByID(m_return_bp_id).get();
419         if (return_bp != nullptr)
420             return_bp->SetEnabled (true);
421     }
422     return true;
423 }
424 
425 bool
426 ThreadPlanStepOut::WillStop ()
427 {
428     if (m_return_bp_id != LLDB_INVALID_BREAK_ID)
429     {
430         Breakpoint *return_bp = m_thread.CalculateTarget()->GetBreakpointByID(m_return_bp_id).get();
431         if (return_bp != nullptr)
432             return_bp->SetEnabled (false);
433     }
434 
435     return true;
436 }
437 
438 bool
439 ThreadPlanStepOut::MischiefManaged ()
440 {
441     if (IsPlanComplete())
442     {
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 
449         Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
450         if (log)
451             log->Printf("Completed step out plan.");
452         if (m_return_bp_id != LLDB_INVALID_BREAK_ID)
453         {
454             m_thread.CalculateTarget()->RemoveBreakpointByID (m_return_bp_id);
455             m_return_bp_id = LLDB_INVALID_BREAK_ID;
456         }
457 
458         ThreadPlan::MischiefManaged ();
459         return true;
460     }
461     else
462     {
463         return false;
464     }
465 }
466 
467 bool
468 ThreadPlanStepOut::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.
473     StackFrameSP immediate_return_from_sp (m_thread.GetStackFrameAtIndex (0));
474     if (!immediate_return_from_sp)
475         return false;
476 
477     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
478     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);
497                 inlined_sc.target_sp = GetTarget().shared_from_this();
498                 RunMode run_mode = m_stop_others ? lldb::eOnlyThisThread : lldb::eAllThreads;
499                 const LazyBool avoid_no_debug = eLazyBoolNo;
500 
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 
510                 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                 }
524 
525                 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 }
534 
535 void
536 ThreadPlanStepOut::CalculateReturnValue ()
537 {
538     if (m_return_valobj_sp)
539         return;
540 
541     if (m_immediate_step_from_function != nullptr)
542     {
543         CompilerType return_compiler_type = m_immediate_step_from_function->GetCompilerType().GetFunctionReturnType();
544         if (return_compiler_type)
545         {
546             lldb::ABISP abi_sp = m_thread.GetProcess()->GetABI();
547             if (abi_sp)
548                 m_return_valobj_sp = abi_sp->GetReturnValueObject(m_thread, return_compiler_type);
549         }
550     }
551 }
552 
553 bool
554 ThreadPlanStepOut::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();
560     return !(frame_zero_id < m_step_out_to_id);
561 }
562