blob: 7581ccea625af074300abf0c78e77b7a82bc99bd [file] [log] [blame]
Raphael Isemann80814282020-01-24 07:23:271//===-- ThreadPlanStepOut.cpp ---------------------------------------------===//
Chris Lattner30fdc8d2010-06-08 16:52:242//
Chandler Carruth2946cd72019-01-19 08:50:563// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Chris Lattner30fdc8d2010-06-08 16:52:246//
7//===----------------------------------------------------------------------===//
8
Eugene Zelenkoe65b2cf2015-12-15 01:33:199#include "lldb/Target/ThreadPlanStepOut.h"
Chris Lattner30fdc8d2010-06-08 16:52:2410#include "lldb/Breakpoint/Breakpoint.h"
Jim Ingham73ca05a2011-12-17 01:35:5711#include "lldb/Core/Value.h"
12#include "lldb/Core/ValueObjectConstResult.h"
Greg Clayton1f746072012-08-29 21:13:0613#include "lldb/Symbol/Block.h"
14#include "lldb/Symbol/Function.h"
Jason Molendafd4cea52016-01-08 21:40:1115#include "lldb/Symbol/Symbol.h"
Greg Clayton1f746072012-08-29 21:13:0616#include "lldb/Symbol/Type.h"
Zachary Turner32abc6e2015-03-03 19:23:0917#include "lldb/Target/ABI.h"
Chris Lattner30fdc8d2010-06-08 16:52:2418#include "lldb/Target/Process.h"
19#include "lldb/Target/RegisterContext.h"
Greg Claytonf4b47e12010-08-04 01:40:3520#include "lldb/Target/StopInfo.h"
Chris Lattner30fdc8d2010-06-08 16:52:2421#include "lldb/Target/Target.h"
Jim Inghama5ce6c82011-10-15 00:57:2822#include "lldb/Target/ThreadPlanStepOverRange.h"
Jim Ingham4b4b2472014-03-13 02:47:1423#include "lldb/Target/ThreadPlanStepThrough.h"
Zachary Turner6f9e6902017-03-03 20:56:2824#include "lldb/Utility/Log.h"
Chris Lattner30fdc8d2010-06-08 16:52:2425
Jonas Devlieghere796ac802019-02-11 23:13:0826#include <memory>
27
Chris Lattner30fdc8d2010-06-08 16:52:2428using namespace lldb;
29using namespace lldb_private;
30
Jim Ingham4b4b2472014-03-13 02:47:1431uint32_t ThreadPlanStepOut::s_default_flag_values = 0;
32
Chris Lattner30fdc8d2010-06-08 16:52:2433// ThreadPlanStepOut: Step out of the current frame
Kate Stoneb9c1b512016-09-06 20:57:5034ThreadPlanStepOut::ThreadPlanStepOut(
35 Thread &thread, SymbolContext *context, bool first_insn, bool stop_others,
36 Vote stop_vote, Vote run_vote, uint32_t frame_idx,
Jason Molendafd4cea52016-01-08 21:40:1137 LazyBool step_out_avoids_code_without_debug_info,
Kate Stoneb9c1b512016-09-06 20:57:5038 bool continue_to_next_branch, bool gather_return_value)
39 : ThreadPlan(ThreadPlan::eKindStepOut, "Step out", thread, stop_vote,
40 run_vote),
41 ThreadPlanShouldStopHere(this), m_step_from_insn(LLDB_INVALID_ADDRESS),
42 m_return_bp_id(LLDB_INVALID_BREAK_ID),
43 m_return_addr(LLDB_INVALID_ADDRESS), m_stop_others(stop_others),
44 m_immediate_step_from_function(nullptr),
45 m_calculate_return_value(gather_return_value) {
Vedant Kumar4b36f792018-10-05 23:23:1546 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
Kate Stoneb9c1b512016-09-06 20:57:5047 SetFlagsToDefault();
48 SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
Chris Lattner30fdc8d2010-06-08 16:52:2449
Kate Stoneb9c1b512016-09-06 20:57:5050 m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0);
Jim Inghama5ce6c82011-10-15 00:57:2851
Vedant Kumar4b36f792018-10-05 23:23:1552 uint32_t return_frame_index = frame_idx + 1;
53 StackFrameSP return_frame_sp(
54 m_thread.GetStackFrameAtIndex(return_frame_index));
Kate Stoneb9c1b512016-09-06 20:57:5055 StackFrameSP immediate_return_from_sp(
56 m_thread.GetStackFrameAtIndex(frame_idx));
57
58 if (!return_frame_sp || !immediate_return_from_sp)
59 return; // we can't do anything here. ValidatePlan() will return false.
60
Vedant Kumar4b36f792018-10-05 23:23:1561 // While stepping out, behave as-if artificial frames are not present.
62 while (return_frame_sp->IsArtificial()) {
63 m_stepped_past_frames.push_back(return_frame_sp);
64
65 ++return_frame_index;
66 return_frame_sp = m_thread.GetStackFrameAtIndex(return_frame_index);
67
68 // We never expect to see an artificial frame without a regular ancestor.
69 // If this happens, log the issue and defensively refuse to step out.
70 if (!return_frame_sp) {
71 LLDB_LOG(log, "Can't step out of frame with artificial ancestors");
72 return;
73 }
74 }
75
Kate Stoneb9c1b512016-09-06 20:57:5076 m_step_out_to_id = return_frame_sp->GetStackID();
77 m_immediate_step_from_id = immediate_return_from_sp->GetStackID();
78
Adrian Prantl05097242018-04-30 16:49:0479 // If the frame directly below the one we are returning to is inlined, we
80 // have to be a little more careful. It is non-trivial to determine the real
81 // "return code address" for an inlined frame, so we have to work our way to
82 // that frame and then step out.
Vedant Kumar4b36f792018-10-05 23:23:1583 if (immediate_return_from_sp->IsInlined()) {
Kate Stoneb9c1b512016-09-06 20:57:5084 if (frame_idx > 0) {
85 // First queue a plan that gets us to this inlined frame, and when we get
Adrian Prantl05097242018-04-30 16:49:0486 // there we'll queue a second plan that walks us out of this frame.
Jonas Devlieghere796ac802019-02-11 23:13:0887 m_step_out_to_inline_plan_sp = std::make_shared<ThreadPlanStepOut>(
Kate Stoneb9c1b512016-09-06 20:57:5088 m_thread, nullptr, false, stop_others, eVoteNoOpinion, eVoteNoOpinion,
Jonas Devlieghere796ac802019-02-11 23:13:0889 frame_idx - 1, eLazyBoolNo, continue_to_next_branch);
Kate Stoneb9c1b512016-09-06 20:57:5090 static_cast<ThreadPlanStepOut *>(m_step_out_to_inline_plan_sp.get())
91 ->SetShouldStopHereCallbacks(nullptr, nullptr);
92 m_step_out_to_inline_plan_sp->SetPrivate(true);
93 } else {
Adrian Prantl05097242018-04-30 16:49:0494 // If we're already at the inlined frame we're stepping through, then
95 // just do that now.
Kate Stoneb9c1b512016-09-06 20:57:5096 QueueInlinedStepPlan(false);
Jim Inghama5ce6c82011-10-15 00:57:2897 }
Vedant Kumar4b36f792018-10-05 23:23:1598 } else {
Kate Stoneb9c1b512016-09-06 20:57:5099 // Find the return address and set a breakpoint there:
100 // FIXME - can we do this more securely if we know first_insn?
Jim Inghama5ce6c82011-10-15 00:57:28101
Kate Stoneb9c1b512016-09-06 20:57:50102 Address return_address(return_frame_sp->GetFrameCodeAddress());
103 if (continue_to_next_branch) {
104 SymbolContext return_address_sc;
105 AddressRange range;
106 Address return_address_decr_pc = return_address;
107 if (return_address_decr_pc.GetOffset() > 0)
108 return_address_decr_pc.Slide(-1);
Jason Molendafd4cea52016-01-08 21:40:11109
Kate Stoneb9c1b512016-09-06 20:57:50110 return_address_decr_pc.CalculateSymbolContext(
111 &return_address_sc, lldb::eSymbolContextLineEntry);
112 if (return_address_sc.line_entry.IsValid()) {
Greg Clayton8a777922019-05-06 20:01:21113 const bool include_inlined_functions = false;
114 range = return_address_sc.line_entry.GetSameLineContiguousAddressRange(
115 include_inlined_functions);
Kate Stoneb9c1b512016-09-06 20:57:50116 if (range.GetByteSize() > 0) {
117 return_address =
118 m_thread.GetProcess()->AdvanceAddressToNextBranchInstruction(
119 return_address, range);
Jason Molendafd4cea52016-01-08 21:40:11120 }
Kate Stoneb9c1b512016-09-06 20:57:50121 }
Chris Lattner30fdc8d2010-06-08 16:52:24122 }
Kate Stoneb9c1b512016-09-06 20:57:50123 m_return_addr =
124 return_address.GetLoadAddress(&m_thread.GetProcess()->GetTarget());
125
126 if (m_return_addr == LLDB_INVALID_ADDRESS)
127 return;
128
Jim Ingham2a42a5a2019-12-20 19:00:11129 // Perform some additional validation on the return address.
130 uint32_t permissions = 0;
131 if (!m_thread.GetProcess()->GetLoadAddressPermissions(m_return_addr,
132 permissions)) {
Ted Woodward6fd818c2020-02-10 19:40:17133 LLDB_LOGF(log, "ThreadPlanStepOut(%p): Return address (0x%" PRIx64
134 ") permissions not found.", static_cast<void *>(this),
135 m_return_addr);
Jim Ingham2a42a5a2019-12-20 19:00:11136 } else if (!(permissions & ePermissionsExecutable)) {
137 m_constructor_errors.Printf("Return address (0x%" PRIx64
138 ") did not point to executable memory.",
139 m_return_addr);
140 LLDB_LOGF(log, "ThreadPlanStepOut(%p): %s", static_cast<void *>(this),
141 m_constructor_errors.GetData());
142 return;
143 }
144
Kate Stoneb9c1b512016-09-06 20:57:50145 Breakpoint *return_bp = m_thread.CalculateTarget()
146 ->CreateBreakpoint(m_return_addr, true, false)
147 .get();
Jonas Devliegheree103ae92018-11-15 01:18:15148
Kate Stoneb9c1b512016-09-06 20:57:50149 if (return_bp != nullptr) {
Jonas Devliegheree103ae92018-11-15 01:18:15150 if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
151 m_could_not_resolve_hw_bp = true;
Kate Stoneb9c1b512016-09-06 20:57:50152 return_bp->SetThreadID(m_thread.GetID());
153 m_return_bp_id = return_bp->GetID();
154 return_bp->SetBreakpointKind("step-out");
155 }
156
157 if (immediate_return_from_sp) {
158 const SymbolContext &sc =
159 immediate_return_from_sp->GetSymbolContext(eSymbolContextFunction);
160 if (sc.function) {
161 m_immediate_step_from_function = sc.function;
162 }
163 }
164 }
Jim Inghama5ce6c82011-10-15 00:57:28165}
166
Kate Stoneb9c1b512016-09-06 20:57:50167void ThreadPlanStepOut::SetupAvoidNoDebug(
168 LazyBool step_out_avoids_code_without_debug_info) {
169 bool avoid_nodebug = true;
170 switch (step_out_avoids_code_without_debug_info) {
171 case eLazyBoolYes:
172 avoid_nodebug = true;
173 break;
174 case eLazyBoolNo:
175 avoid_nodebug = false;
176 break;
177 case eLazyBoolCalculate:
178 avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
179 break;
180 }
181 if (avoid_nodebug)
182 GetFlags().Set(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
183 else
184 GetFlags().Clear(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
Jim Ingham4b4b2472014-03-13 02:47:14185}
186
Kate Stoneb9c1b512016-09-06 20:57:50187void ThreadPlanStepOut::DidPush() {
188 if (m_step_out_to_inline_plan_sp)
189 m_thread.QueueThreadPlan(m_step_out_to_inline_plan_sp, false);
190 else if (m_step_through_inline_plan_sp)
191 m_thread.QueueThreadPlan(m_step_through_inline_plan_sp, false);
192}
193
194ThreadPlanStepOut::~ThreadPlanStepOut() {
195 if (m_return_bp_id != LLDB_INVALID_BREAK_ID)
196 m_thread.CalculateTarget()->RemoveBreakpointByID(m_return_bp_id);
197}
198
199void ThreadPlanStepOut::GetDescription(Stream *s,
200 lldb::DescriptionLevel level) {
201 if (level == lldb::eDescriptionLevelBrief)
202 s->Printf("step out");
203 else {
Jim Ingham4b4b2472014-03-13 02:47:14204 if (m_step_out_to_inline_plan_sp)
Kate Stoneb9c1b512016-09-06 20:57:50205 s->Printf("Stepping out to inlined frame so we can walk through it.");
Jim Inghama5ce6c82011-10-15 00:57:28206 else if (m_step_through_inline_plan_sp)
Kate Stoneb9c1b512016-09-06 20:57:50207 s->Printf("Stepping out by stepping through inlined function.");
208 else {
209 s->Printf("Stepping out from ");
210 Address tmp_address;
211 if (tmp_address.SetLoadAddress(m_step_from_insn, &GetTarget())) {
212 tmp_address.Dump(s, &GetThread(), Address::DumpStyleResolvedDescription,
213 Address::DumpStyleLoadAddress);
214 } else {
215 s->Printf("address 0x%" PRIx64 "", (uint64_t)m_step_from_insn);
216 }
217
218 // FIXME: find some useful way to present the m_return_id, since there may
219 // be multiple copies of the
220 // same function on the stack.
221
222 s->Printf(" returning to frame at ");
223 if (tmp_address.SetLoadAddress(m_return_addr, &GetTarget())) {
224 tmp_address.Dump(s, &GetThread(), Address::DumpStyleResolvedDescription,
225 Address::DumpStyleLoadAddress);
226 } else {
227 s->Printf("address 0x%" PRIx64 "", (uint64_t)m_return_addr);
228 }
229
230 if (level == eDescriptionLevelVerbose)
231 s->Printf(" using breakpoint site %d", m_return_bp_id);
232 }
233 }
Vedant Kumar4b36f792018-10-05 23:23:15234
235 s->Printf("\n");
236 for (StackFrameSP frame_sp : m_stepped_past_frames) {
237 s->Printf("Stepped out past: ");
238 frame_sp->DumpUsingSettingsFormat(s);
239 }
Chris Lattner30fdc8d2010-06-08 16:52:24240}
241
Kate Stoneb9c1b512016-09-06 20:57:50242bool ThreadPlanStepOut::ValidatePlan(Stream *error) {
243 if (m_step_out_to_inline_plan_sp)
244 return m_step_out_to_inline_plan_sp->ValidatePlan(error);
Jonas Devliegheree103ae92018-11-15 01:18:15245
246 if (m_step_through_inline_plan_sp)
Kate Stoneb9c1b512016-09-06 20:57:50247 return m_step_through_inline_plan_sp->ValidatePlan(error);
Jonas Devliegheree103ae92018-11-15 01:18:15248
249 if (m_could_not_resolve_hw_bp) {
250 if (error)
251 error->PutCString(
252 "Could not create hardware breakpoint for thread plan.");
253 return false;
254 }
255
256 if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
Jim Ingham2a42a5a2019-12-20 19:00:11257 if (error) {
Kate Stoneb9c1b512016-09-06 20:57:50258 error->PutCString("Could not create return address breakpoint.");
Jim Ingham2a42a5a2019-12-20 19:00:11259 if (m_constructor_errors.GetSize() > 0) {
260 error->PutCString(" ");
261 error->PutCString(m_constructor_errors.GetString());
262 }
263 }
Jim Inghama5ce6c82011-10-15 00:57:28264 return false;
Jonas Devliegheree103ae92018-11-15 01:18:15265 }
266
267 return true;
Jim Inghama5ce6c82011-10-15 00:57:28268}
Jim Ingham73ca05a2011-12-17 01:35:57269
Kate Stoneb9c1b512016-09-06 20:57:50270bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) {
Adrian Prantl05097242018-04-30 16:49:04271 // If the step out plan is done, then we just need to step through the
272 // inlined frame.
Kate Stoneb9c1b512016-09-06 20:57:50273 if (m_step_out_to_inline_plan_sp) {
274 return m_step_out_to_inline_plan_sp->MischiefManaged();
275 } else if (m_step_through_inline_plan_sp) {
276 if (m_step_through_inline_plan_sp->MischiefManaged()) {
277 CalculateReturnValue();
278 SetPlanComplete();
279 return true;
280 } else
281 return false;
282 } else if (m_step_out_further_plan_sp) {
283 return m_step_out_further_plan_sp->MischiefManaged();
284 }
285
286 // We don't explain signals or breakpoints (breakpoints that handle stepping
Adrian Prantl05097242018-04-30 16:49:04287 // in or out will be handled by a child plan.
Kate Stoneb9c1b512016-09-06 20:57:50288
289 StopInfoSP stop_info_sp = GetPrivateStopInfo();
290 if (stop_info_sp) {
291 StopReason reason = stop_info_sp->GetStopReason();
292 if (reason == eStopReasonBreakpoint) {
Adrian Prantl05097242018-04-30 16:49:04293 // If this is OUR breakpoint, we're fine, otherwise we don't know why
294 // this happened...
Kate Stoneb9c1b512016-09-06 20:57:50295 BreakpointSiteSP site_sp(
296 m_thread.GetProcess()->GetBreakpointSiteList().FindByID(
297 stop_info_sp->GetValue()));
298 if (site_sp && site_sp->IsBreakpointAtThisSite(m_return_bp_id)) {
299 bool done;
300
301 StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
302
303 if (m_step_out_to_id == frame_zero_id)
304 done = true;
305 else if (m_step_out_to_id < frame_zero_id) {
306 // Either we stepped past the breakpoint, or the stack ID calculation
307 // was incorrect and we should probably stop.
308 done = true;
309 } else {
310 done = (m_immediate_step_from_id < frame_zero_id);
Jim Ingham73ca05a2011-12-17 01:35:57311 }
Kate Stoneb9c1b512016-09-06 20:57:50312
313 if (done) {
Jonas Devliegheree103ae92018-11-15 01:18:15314 if (InvokeShouldStopHereCallback(eFrameCompareOlder, m_status)) {
Kate Stoneb9c1b512016-09-06 20:57:50315 CalculateReturnValue();
316 SetPlanComplete();
317 }
318 }
319
320 // If there was only one owner, then we're done. But if we also hit
Adrian Prantl05097242018-04-30 16:49:04321 // some user breakpoint on our way out, we should mark ourselves as
322 // done, but also not claim to explain the stop, since it is more
323 // important to report the user breakpoint than the step out
324 // completion.
Kate Stoneb9c1b512016-09-06 20:57:50325
326 if (site_sp->GetNumberOfOwners() == 1)
327 return true;
328 }
329 return false;
330 } else if (IsUsuallyUnexplainedStopReason(reason))
331 return false;
332 else
333 return true;
334 }
335 return true;
Jim Ingham73ca05a2011-12-17 01:35:57336}
Jim Ingham64e7ead2012-05-03 21:19:36337
Kate Stoneb9c1b512016-09-06 20:57:50338bool ThreadPlanStepOut::ShouldStop(Event *event_ptr) {
339 if (IsPlanComplete())
340 return true;
341
342 bool done = false;
343 if (m_step_out_to_inline_plan_sp) {
344 if (m_step_out_to_inline_plan_sp->MischiefManaged()) {
345 // Now step through the inlined stack we are in:
346 if (QueueInlinedStepPlan(true)) {
347 // If we can't queue a plan to do this, then just call ourselves done.
348 m_step_out_to_inline_plan_sp.reset();
349 SetPlanComplete(false);
350 return true;
351 } else
352 done = true;
353 } else
354 return m_step_out_to_inline_plan_sp->ShouldStop(event_ptr);
355 } else if (m_step_through_inline_plan_sp) {
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 } else if (m_step_out_further_plan_sp) {
361 if (m_step_out_further_plan_sp->MischiefManaged())
362 m_step_out_further_plan_sp.reset();
363 else
364 return m_step_out_further_plan_sp->ShouldStop(event_ptr);
365 }
366
367 if (!done) {
Jim Ingham64e7ead2012-05-03 21:19:36368 StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
Kate Stoneb9c1b512016-09-06 20:57:50369 done = !(frame_zero_id < m_step_out_to_id);
370 }
371
Adrian Prantl05097242018-04-30 16:49:04372 // The normal step out computations think we are done, so all we need to do
373 // is consult the ShouldStopHere, and we are done.
Kate Stoneb9c1b512016-09-06 20:57:50374
375 if (done) {
Jonas Devliegheree103ae92018-11-15 01:18:15376 if (InvokeShouldStopHereCallback(eFrameCompareOlder, m_status)) {
Kate Stoneb9c1b512016-09-06 20:57:50377 CalculateReturnValue();
378 SetPlanComplete();
379 } else {
380 m_step_out_further_plan_sp =
Jonas Devliegheree103ae92018-11-15 01:18:15381 QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder, m_status);
Kate Stoneb9c1b512016-09-06 20:57:50382 done = false;
383 }
384 }
385
386 return done;
387}
388
389bool ThreadPlanStepOut::StopOthers() { return m_stop_others; }
390
391StateType ThreadPlanStepOut::GetPlanRunState() { return eStateRunning; }
392
393bool ThreadPlanStepOut::DoWillResume(StateType resume_state,
394 bool current_plan) {
395 if (m_step_out_to_inline_plan_sp || m_step_through_inline_plan_sp)
396 return true;
397
398 if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
399 return false;
400
401 if (current_plan) {
402 Breakpoint *return_bp =
403 m_thread.CalculateTarget()->GetBreakpointByID(m_return_bp_id).get();
404 if (return_bp != nullptr)
405 return_bp->SetEnabled(true);
406 }
407 return true;
408}
409
410bool ThreadPlanStepOut::WillStop() {
411 if (m_return_bp_id != LLDB_INVALID_BREAK_ID) {
412 Breakpoint *return_bp =
413 m_thread.CalculateTarget()->GetBreakpointByID(m_return_bp_id).get();
414 if (return_bp != nullptr)
415 return_bp->SetEnabled(false);
416 }
417
418 return true;
419}
420
421bool ThreadPlanStepOut::MischiefManaged() {
422 if (IsPlanComplete()) {
423 // Did I reach my breakpoint? If so I'm done.
424 //
425 // I also check the stack depth, since if we've blown past the breakpoint
426 // for some
427 // reason and we're now stopping for some other reason altogether, then
Adrian Prantl05097242018-04-30 16:49:04428 // we're done with this step out operation.
Kate Stoneb9c1b512016-09-06 20:57:50429
430 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
431 if (log)
Jonas Devlieghere63e5fb72019-07-24 17:56:10432 LLDB_LOGF(log, "Completed step out plan.");
Kate Stoneb9c1b512016-09-06 20:57:50433 if (m_return_bp_id != LLDB_INVALID_BREAK_ID) {
434 m_thread.CalculateTarget()->RemoveBreakpointByID(m_return_bp_id);
435 m_return_bp_id = LLDB_INVALID_BREAK_ID;
436 }
437
438 ThreadPlan::MischiefManaged();
439 return true;
440 } else {
441 return false;
442 }
443}
444
445bool ThreadPlanStepOut::QueueInlinedStepPlan(bool queue_now) {
446 // Now figure out the range of this inlined block, and set up a "step through
Adrian Prantl05097242018-04-30 16:49:04447 // range" plan for that. If we've been provided with a context, then use the
448 // block in that context.
Kate Stoneb9c1b512016-09-06 20:57:50449 StackFrameSP immediate_return_from_sp(m_thread.GetStackFrameAtIndex(0));
450 if (!immediate_return_from_sp)
451 return false;
452
453 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
454 if (log) {
455 StreamString s;
456 immediate_return_from_sp->Dump(&s, true, false);
Jonas Devlieghere63e5fb72019-07-24 17:56:10457 LLDB_LOGF(log, "Queuing inlined frame to step past: %s.", s.GetData());
Kate Stoneb9c1b512016-09-06 20:57:50458 }
459
460 Block *from_block = immediate_return_from_sp->GetFrameBlock();
461 if (from_block) {
462 Block *inlined_block = from_block->GetContainingInlinedBlock();
463 if (inlined_block) {
464 size_t num_ranges = inlined_block->GetNumRanges();
465 AddressRange inline_range;
466 if (inlined_block->GetRangeAtIndex(0, inline_range)) {
467 SymbolContext inlined_sc;
468 inlined_block->CalculateSymbolContext(&inlined_sc);
469 inlined_sc.target_sp = GetTarget().shared_from_this();
470 RunMode run_mode =
471 m_stop_others ? lldb::eOnlyThisThread : lldb::eAllThreads;
472 const LazyBool avoid_no_debug = eLazyBoolNo;
473
Jonas Devlieghere796ac802019-02-11 23:13:08474 m_step_through_inline_plan_sp =
475 std::make_shared<ThreadPlanStepOverRange>(
476 m_thread, inline_range, inlined_sc, run_mode, avoid_no_debug);
Kate Stoneb9c1b512016-09-06 20:57:50477 ThreadPlanStepOverRange *step_through_inline_plan_ptr =
478 static_cast<ThreadPlanStepOverRange *>(
479 m_step_through_inline_plan_sp.get());
480 m_step_through_inline_plan_sp->SetPrivate(true);
481
482 step_through_inline_plan_ptr->SetOkayToDiscard(true);
483 StreamString errors;
484 if (!step_through_inline_plan_ptr->ValidatePlan(&errors)) {
485 // FIXME: Log this failure.
486 delete step_through_inline_plan_ptr;
487 return false;
488 }
489
490 for (size_t i = 1; i < num_ranges; i++) {
491 if (inlined_block->GetRangeAtIndex(i, inline_range))
492 step_through_inline_plan_ptr->AddRange(inline_range);
493 }
494
495 if (queue_now)
496 m_thread.QueueThreadPlan(m_step_through_inline_plan_sp, false);
497 return true;
498 }
499 }
500 }
501
502 return false;
503}
504
505void ThreadPlanStepOut::CalculateReturnValue() {
506 if (m_return_valobj_sp)
507 return;
508
509 if (!m_calculate_return_value)
510 return;
511
512 if (m_immediate_step_from_function != nullptr) {
513 CompilerType return_compiler_type =
514 m_immediate_step_from_function->GetCompilerType()
515 .GetFunctionReturnType();
516 if (return_compiler_type) {
517 lldb::ABISP abi_sp = m_thread.GetProcess()->GetABI();
518 if (abi_sp)
519 m_return_valobj_sp =
520 abi_sp->GetReturnValueObject(m_thread, return_compiler_type);
521 }
522 }
523}
524
525bool ThreadPlanStepOut::IsPlanStale() {
Adrian Prantl05097242018-04-30 16:49:04526 // If we are still lower on the stack than the frame we are returning to,
527 // then there's something for us to do. Otherwise, we're stale.
Kate Stoneb9c1b512016-09-06 20:57:50528
529 StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID();
530 return !(frame_zero_id < m_step_out_to_id);
Jim Ingham64e7ead2012-05-03 21:19:36531}