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/Value.h"
17 #include "lldb/Core/ValueObjectConstResult.h"
18 #include "lldb/Symbol/Block.h"
19 #include "lldb/Symbol/Function.h"
20 #include "lldb/Symbol/Symbol.h"
21 #include "lldb/Symbol/Type.h"
22 #include "lldb/Target/ABI.h"
23 #include "lldb/Target/Process.h"
24 #include "lldb/Target/RegisterContext.h"
25 #include "lldb/Target/StopInfo.h"
26 #include "lldb/Target/Target.h"
27 #include "lldb/Target/ThreadPlanStepOverRange.h"
28 #include "lldb/Target/ThreadPlanStepThrough.h"
29 #include "lldb/Utility/Log.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     Thread &thread, SymbolContext *context, bool first_insn, bool stop_others,
41     Vote stop_vote, Vote run_vote, uint32_t frame_idx,
42     LazyBool step_out_avoids_code_without_debug_info,
43     bool continue_to_next_branch, bool gather_return_value)
44     : ThreadPlan(ThreadPlan::eKindStepOut, "Step out", thread, stop_vote,
45                  run_vote),
46       ThreadPlanShouldStopHere(this), m_step_from_insn(LLDB_INVALID_ADDRESS),
47       m_return_bp_id(LLDB_INVALID_BREAK_ID),
48       m_return_addr(LLDB_INVALID_ADDRESS), m_stop_others(stop_others),
49       m_immediate_step_from_function(nullptr),
50       m_calculate_return_value(gather_return_value) {
51   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
52   SetFlagsToDefault();
53   SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
54 
55   m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0);
56 
57   uint32_t return_frame_index = frame_idx + 1;
58   StackFrameSP return_frame_sp(
59       m_thread.GetStackFrameAtIndex(return_frame_index));
60   StackFrameSP immediate_return_from_sp(
61       m_thread.GetStackFrameAtIndex(frame_idx));
62 
63   if (!return_frame_sp || !immediate_return_from_sp)
64     return; // we can't do anything here.  ValidatePlan() will return false.
65 
66   // While stepping out, behave as-if artificial frames are not present.
67   while (return_frame_sp->IsArtificial()) {
68     m_stepped_past_frames.push_back(return_frame_sp);
69 
70     ++return_frame_index;
71     return_frame_sp = m_thread.GetStackFrameAtIndex(return_frame_index);
72 
73     // We never expect to see an artificial frame without a regular ancestor.
74     // If this happens, log the issue and defensively refuse to step out.
75     if (!return_frame_sp) {
76       LLDB_LOG(log, "Can't step out of frame with artificial ancestors");
77       return;
78     }
79   }
80 
81   m_step_out_to_id = return_frame_sp->GetStackID();
82   m_immediate_step_from_id = immediate_return_from_sp->GetStackID();
83 
84   // If the frame directly below the one we are returning to is inlined, we
85   // have to be a little more careful.  It is non-trivial to determine the real
86   // "return code address" for an inlined frame, so we have to work our way to
87   // that frame and then step out.
88   if (immediate_return_from_sp->IsInlined()) {
89     if (frame_idx > 0) {
90       // First queue a plan that gets us to this inlined frame, and when we get
91       // there we'll queue a second plan that walks us out of this frame.
92       m_step_out_to_inline_plan_sp.reset(new ThreadPlanStepOut(
93           m_thread, nullptr, false, stop_others, eVoteNoOpinion, eVoteNoOpinion,
94           frame_idx - 1, eLazyBoolNo, continue_to_next_branch));
95       static_cast<ThreadPlanStepOut *>(m_step_out_to_inline_plan_sp.get())
96           ->SetShouldStopHereCallbacks(nullptr, nullptr);
97       m_step_out_to_inline_plan_sp->SetPrivate(true);
98     } else {
99       // If we're already at the inlined frame we're stepping through, then
100       // just do that now.
101       QueueInlinedStepPlan(false);
102     }
103   } else {
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       SymbolContext return_address_sc;
110       AddressRange range;
111       Address return_address_decr_pc = return_address;
112       if (return_address_decr_pc.GetOffset() > 0)
113         return_address_decr_pc.Slide(-1);
114 
115       return_address_decr_pc.CalculateSymbolContext(
116           &return_address_sc, lldb::eSymbolContextLineEntry);
117       if (return_address_sc.line_entry.IsValid()) {
118         range =
119             return_address_sc.line_entry.GetSameLineContiguousAddressRange();
120         if (range.GetByteSize() > 0) {
121           return_address =
122               m_thread.GetProcess()->AdvanceAddressToNextBranchInstruction(
123                   return_address, range);
124         }
125       }
126     }
127     m_return_addr =
128         return_address.GetLoadAddress(&m_thread.GetProcess()->GetTarget());
129 
130     if (m_return_addr == LLDB_INVALID_ADDRESS)
131       return;
132 
133     Breakpoint *return_bp = m_thread.CalculateTarget()
134                                 ->CreateBreakpoint(m_return_addr, true, false)
135                                 .get();
136     if (return_bp != nullptr) {
137       return_bp->SetThreadID(m_thread.GetID());
138       m_return_bp_id = return_bp->GetID();
139       return_bp->SetBreakpointKind("step-out");
140     }
141 
142     if (immediate_return_from_sp) {
143       const SymbolContext &sc =
144           immediate_return_from_sp->GetSymbolContext(eSymbolContextFunction);
145       if (sc.function) {
146         m_immediate_step_from_function = sc.function;
147       }
148     }
149   }
150 }
151 
152 void ThreadPlanStepOut::SetupAvoidNoDebug(
153     LazyBool step_out_avoids_code_without_debug_info) {
154   bool avoid_nodebug = true;
155   switch (step_out_avoids_code_without_debug_info) {
156   case eLazyBoolYes:
157     avoid_nodebug = true;
158     break;
159   case eLazyBoolNo:
160     avoid_nodebug = false;
161     break;
162   case eLazyBoolCalculate:
163     avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
164     break;
165   }
166   if (avoid_nodebug)
167     GetFlags().Set(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
168   else
169     GetFlags().Clear(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
170 }
171 
172 void ThreadPlanStepOut::DidPush() {
173   if (m_step_out_to_inline_plan_sp)
174     m_thread.QueueThreadPlan(m_step_out_to_inline_plan_sp, false);
175   else if (m_step_through_inline_plan_sp)
176     m_thread.QueueThreadPlan(m_step_through_inline_plan_sp, false);
177 }
178 
179 ThreadPlanStepOut::~ThreadPlanStepOut() {
180   if (m_return_bp_id != LLDB_INVALID_BREAK_ID)
181     m_thread.CalculateTarget()->RemoveBreakpointByID(m_return_bp_id);
182 }
183 
184 void ThreadPlanStepOut::GetDescription(Stream *s,
185                                        lldb::DescriptionLevel level) {
186   if (level == lldb::eDescriptionLevelBrief)
187     s->Printf("step out");
188   else {
189     if (m_step_out_to_inline_plan_sp)
190       s->Printf("Stepping out to inlined frame so we can walk through it.");
191     else if (m_step_through_inline_plan_sp)
192       s->Printf("Stepping out by stepping through inlined function.");
193     else {
194       s->Printf("Stepping out from ");
195       Address tmp_address;
196       if (tmp_address.SetLoadAddress(m_step_from_insn, &GetTarget())) {
197         tmp_address.Dump(s, &GetThread(), Address::DumpStyleResolvedDescription,
198                          Address::DumpStyleLoadAddress);
199       } else {
200         s->Printf("address 0x%" PRIx64 "", (uint64_t)m_step_from_insn);
201       }
202 
203       // FIXME: find some useful way to present the m_return_id, since there may
204       // be multiple copies of the
205       // same function on the stack.
206 
207       s->Printf(" returning to frame at ");
208       if (tmp_address.SetLoadAddress(m_return_addr, &GetTarget())) {
209         tmp_address.Dump(s, &GetThread(), Address::DumpStyleResolvedDescription,
210                          Address::DumpStyleLoadAddress);
211       } else {
212         s->Printf("address 0x%" PRIx64 "", (uint64_t)m_return_addr);
213       }
214 
215       if (level == eDescriptionLevelVerbose)
216         s->Printf(" using breakpoint site %d", m_return_bp_id);
217     }
218   }
219 
220   s->Printf("\n");
221   for (StackFrameSP frame_sp : m_stepped_past_frames) {
222     s->Printf("Stepped out past: ");
223     frame_sp->DumpUsingSettingsFormat(s);
224   }
225 }
226 
227 bool ThreadPlanStepOut::ValidatePlan(Stream *error) {
228   if (m_step_out_to_inline_plan_sp)
229     return m_step_out_to_inline_plan_sp->ValidatePlan(error);
230   else if (m_step_through_inline_plan_sp)
231     return m_step_through_inline_plan_sp->ValidatePlan(error);
232   else if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
233     if (error)
234       error->PutCString("Could not create return address breakpoint.");
235     return false;
236   } else
237     return true;
238 }
239 
240 bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) {
241   // If the step out plan is done, then we just need to step through the
242   // inlined frame.
243   if (m_step_out_to_inline_plan_sp) {
244     return m_step_out_to_inline_plan_sp->MischiefManaged();
245   } else if (m_step_through_inline_plan_sp) {
246     if (m_step_through_inline_plan_sp->MischiefManaged()) {
247       CalculateReturnValue();
248       SetPlanComplete();
249       return true;
250     } else
251       return false;
252   } else if (m_step_out_further_plan_sp) {
253     return m_step_out_further_plan_sp->MischiefManaged();
254   }
255 
256   // We don't explain signals or breakpoints (breakpoints that handle stepping
257   // in or out will be handled by a child plan.
258 
259   StopInfoSP stop_info_sp = GetPrivateStopInfo();
260   if (stop_info_sp) {
261     StopReason reason = stop_info_sp->GetStopReason();
262     if (reason == eStopReasonBreakpoint) {
263       // If this is OUR breakpoint, we're fine, otherwise we don't know why
264       // this happened...
265       BreakpointSiteSP site_sp(
266           m_thread.GetProcess()->GetBreakpointSiteList().FindByID(
267               stop_info_sp->GetValue()));
268       if (site_sp && site_sp->IsBreakpointAtThisSite(m_return_bp_id)) {
269         bool done;
270 
271         StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
272 
273         if (m_step_out_to_id == frame_zero_id)
274           done = true;
275         else if (m_step_out_to_id < frame_zero_id) {
276           // Either we stepped past the breakpoint, or the stack ID calculation
277           // was incorrect and we should probably stop.
278           done = true;
279         } else {
280           done = (m_immediate_step_from_id < frame_zero_id);
281         }
282 
283         if (done) {
284           if (InvokeShouldStopHereCallback(eFrameCompareOlder)) {
285             CalculateReturnValue();
286             SetPlanComplete();
287           }
288         }
289 
290         // If there was only one owner, then we're done.  But if we also hit
291         // some user breakpoint on our way out, we should mark ourselves as
292         // done, but also not claim to explain the stop, since it is more
293         // important to report the user breakpoint than the step out
294         // completion.
295 
296         if (site_sp->GetNumberOfOwners() == 1)
297           return true;
298       }
299       return false;
300     } else if (IsUsuallyUnexplainedStopReason(reason))
301       return false;
302     else
303       return true;
304   }
305   return true;
306 }
307 
308 bool ThreadPlanStepOut::ShouldStop(Event *event_ptr) {
309   if (IsPlanComplete())
310     return true;
311 
312   bool done = false;
313   if (m_step_out_to_inline_plan_sp) {
314     if (m_step_out_to_inline_plan_sp->MischiefManaged()) {
315       // Now step through the inlined stack we are in:
316       if (QueueInlinedStepPlan(true)) {
317         // If we can't queue a plan to do this, then just call ourselves done.
318         m_step_out_to_inline_plan_sp.reset();
319         SetPlanComplete(false);
320         return true;
321       } else
322         done = true;
323     } else
324       return m_step_out_to_inline_plan_sp->ShouldStop(event_ptr);
325   } else if (m_step_through_inline_plan_sp) {
326     if (m_step_through_inline_plan_sp->MischiefManaged())
327       done = true;
328     else
329       return m_step_through_inline_plan_sp->ShouldStop(event_ptr);
330   } else if (m_step_out_further_plan_sp) {
331     if (m_step_out_further_plan_sp->MischiefManaged())
332       m_step_out_further_plan_sp.reset();
333     else
334       return m_step_out_further_plan_sp->ShouldStop(event_ptr);
335   }
336 
337   if (!done) {
338     StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
339     done = !(frame_zero_id < m_step_out_to_id);
340   }
341 
342   // The normal step out computations think we are done, so all we need to do
343   // is consult the ShouldStopHere, and we are done.
344 
345   if (done) {
346     if (InvokeShouldStopHereCallback(eFrameCompareOlder)) {
347       CalculateReturnValue();
348       SetPlanComplete();
349     } else {
350       m_step_out_further_plan_sp =
351           QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder);
352       done = false;
353     }
354   }
355 
356   return done;
357 }
358 
359 bool ThreadPlanStepOut::StopOthers() { return m_stop_others; }
360 
361 StateType ThreadPlanStepOut::GetPlanRunState() { return eStateRunning; }
362 
363 bool ThreadPlanStepOut::DoWillResume(StateType resume_state,
364                                      bool current_plan) {
365   if (m_step_out_to_inline_plan_sp || m_step_through_inline_plan_sp)
366     return true;
367 
368   if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
369     return false;
370 
371   if (current_plan) {
372     Breakpoint *return_bp =
373         m_thread.CalculateTarget()->GetBreakpointByID(m_return_bp_id).get();
374     if (return_bp != nullptr)
375       return_bp->SetEnabled(true);
376   }
377   return true;
378 }
379 
380 bool ThreadPlanStepOut::WillStop() {
381   if (m_return_bp_id != LLDB_INVALID_BREAK_ID) {
382     Breakpoint *return_bp =
383         m_thread.CalculateTarget()->GetBreakpointByID(m_return_bp_id).get();
384     if (return_bp != nullptr)
385       return_bp->SetEnabled(false);
386   }
387 
388   return true;
389 }
390 
391 bool ThreadPlanStepOut::MischiefManaged() {
392   if (IsPlanComplete()) {
393     // Did I reach my breakpoint?  If so I'm done.
394     //
395     // I also check the stack depth, since if we've blown past the breakpoint
396     // for some
397     // reason and we're now stopping for some other reason altogether, then
398     // we're done with this step out operation.
399 
400     Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
401     if (log)
402       log->Printf("Completed step out plan.");
403     if (m_return_bp_id != LLDB_INVALID_BREAK_ID) {
404       m_thread.CalculateTarget()->RemoveBreakpointByID(m_return_bp_id);
405       m_return_bp_id = LLDB_INVALID_BREAK_ID;
406     }
407 
408     ThreadPlan::MischiefManaged();
409     return true;
410   } else {
411     return false;
412   }
413 }
414 
415 bool ThreadPlanStepOut::QueueInlinedStepPlan(bool queue_now) {
416   // Now figure out the range of this inlined block, and set up a "step through
417   // range" plan for that.  If we've been provided with a context, then use the
418   // block in that context.
419   StackFrameSP immediate_return_from_sp(m_thread.GetStackFrameAtIndex(0));
420   if (!immediate_return_from_sp)
421     return false;
422 
423   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
424   if (log) {
425     StreamString s;
426     immediate_return_from_sp->Dump(&s, true, false);
427     log->Printf("Queuing inlined frame to step past: %s.", s.GetData());
428   }
429 
430   Block *from_block = immediate_return_from_sp->GetFrameBlock();
431   if (from_block) {
432     Block *inlined_block = from_block->GetContainingInlinedBlock();
433     if (inlined_block) {
434       size_t num_ranges = inlined_block->GetNumRanges();
435       AddressRange inline_range;
436       if (inlined_block->GetRangeAtIndex(0, inline_range)) {
437         SymbolContext inlined_sc;
438         inlined_block->CalculateSymbolContext(&inlined_sc);
439         inlined_sc.target_sp = GetTarget().shared_from_this();
440         RunMode run_mode =
441             m_stop_others ? lldb::eOnlyThisThread : lldb::eAllThreads;
442         const LazyBool avoid_no_debug = eLazyBoolNo;
443 
444         m_step_through_inline_plan_sp.reset(new ThreadPlanStepOverRange(
445             m_thread, inline_range, inlined_sc, run_mode, avoid_no_debug));
446         ThreadPlanStepOverRange *step_through_inline_plan_ptr =
447             static_cast<ThreadPlanStepOverRange *>(
448                 m_step_through_inline_plan_sp.get());
449         m_step_through_inline_plan_sp->SetPrivate(true);
450 
451         step_through_inline_plan_ptr->SetOkayToDiscard(true);
452         StreamString errors;
453         if (!step_through_inline_plan_ptr->ValidatePlan(&errors)) {
454           // FIXME: Log this failure.
455           delete step_through_inline_plan_ptr;
456           return false;
457         }
458 
459         for (size_t i = 1; i < num_ranges; i++) {
460           if (inlined_block->GetRangeAtIndex(i, inline_range))
461             step_through_inline_plan_ptr->AddRange(inline_range);
462         }
463 
464         if (queue_now)
465           m_thread.QueueThreadPlan(m_step_through_inline_plan_sp, false);
466         return true;
467       }
468     }
469   }
470 
471   return false;
472 }
473 
474 void ThreadPlanStepOut::CalculateReturnValue() {
475   if (m_return_valobj_sp)
476     return;
477 
478   if (!m_calculate_return_value)
479     return;
480 
481   if (m_immediate_step_from_function != nullptr) {
482     CompilerType return_compiler_type =
483         m_immediate_step_from_function->GetCompilerType()
484             .GetFunctionReturnType();
485     if (return_compiler_type) {
486       lldb::ABISP abi_sp = m_thread.GetProcess()->GetABI();
487       if (abi_sp)
488         m_return_valobj_sp =
489             abi_sp->GetReturnValueObject(m_thread, return_compiler_type);
490     }
491   }
492 }
493 
494 bool ThreadPlanStepOut::IsPlanStale() {
495   // If we are still lower on the stack than the frame we are returning to,
496   // then there's something for us to do.  Otherwise, we're stale.
497 
498   StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
499   return !(frame_zero_id < m_step_out_to_id);
500 }
501