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