Bug Summary

File:build/source/lldb/source/Target/ThreadPlanStepOut.cpp
Warning:line 484, column 11
Argument to 'delete' is offset by 16 bytes from the start of memory allocated by operator new

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ThreadPlanStepOut.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-17/lib/clang/17 -isystem /usr/include/libxml2 -D HAVE_ROUND -D _DEBUG -D _GLIBCXX_ASSERTIONS -D _GNU_SOURCE -D _LIBCPP_ENABLE_ASSERTIONS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/lldb/source/Target -I /build/source/lldb/source/Target -I /build/source/lldb/include -I tools/lldb/include -I include -I /build/source/llvm/include -I /usr/include/python3.9 -I /build/source/clang/include -I tools/lldb/../clang/include -I /build/source/lldb/source -I tools/lldb/source -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-17/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/source/= -fcoverage-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/source/= -source-date-epoch 1683717183 -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-stringop-truncation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/source/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/source/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2023-05-10-133810-16478-1 -x c++ /build/source/lldb/source/Target/ThreadPlanStepOut.cpp
1//===-- ThreadPlanStepOut.cpp ---------------------------------------------===//
2//
3// 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
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Target/ThreadPlanStepOut.h"
10#include "lldb/Breakpoint/Breakpoint.h"
11#include "lldb/Core/Value.h"
12#include "lldb/Core/ValueObjectConstResult.h"
13#include "lldb/Symbol/Block.h"
14#include "lldb/Symbol/Function.h"
15#include "lldb/Symbol/Symbol.h"
16#include "lldb/Symbol/Type.h"
17#include "lldb/Target/ABI.h"
18#include "lldb/Target/Process.h"
19#include "lldb/Target/RegisterContext.h"
20#include "lldb/Target/StopInfo.h"
21#include "lldb/Target/Target.h"
22#include "lldb/Target/ThreadPlanStepOverRange.h"
23#include "lldb/Target/ThreadPlanStepThrough.h"
24#include "lldb/Utility/LLDBLog.h"
25#include "lldb/Utility/Log.h"
26
27#include <memory>
28
29using namespace lldb;
30using namespace lldb_private;
31
32uint32_t ThreadPlanStepOut::s_default_flag_values = 0;
33
34// ThreadPlanStepOut: Step out of the current frame
35ThreadPlanStepOut::ThreadPlanStepOut(
36 Thread &thread, SymbolContext *context, bool first_insn, bool stop_others,
37 Vote report_stop_vote, Vote report_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, report_stop_vote,
41 report_run_vote),
42 ThreadPlanShouldStopHere(this), m_step_from_insn(LLDB_INVALID_ADDRESS(18446744073709551615UL)),
43 m_return_bp_id(LLDB_INVALID_BREAK_ID0),
44 m_return_addr(LLDB_INVALID_ADDRESS(18446744073709551615UL)), m_stop_others(stop_others),
45 m_immediate_step_from_function(nullptr),
46 m_calculate_return_value(gather_return_value) {
47 Log *log = GetLog(LLDBLog::Step);
48 SetFlagsToDefault();
49 SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
50
51 m_step_from_insn = thread.GetRegisterContext()->GetPC(0);
52
53 uint32_t return_frame_index = frame_idx + 1;
54 StackFrameSP return_frame_sp(thread.GetStackFrameAtIndex(return_frame_index));
55 StackFrameSP immediate_return_from_sp(thread.GetStackFrameAtIndex(frame_idx));
56
57 if (!return_frame_sp || !immediate_return_from_sp)
58 return; // we can't do anything here. ValidatePlan() will return false.
59
60 // While stepping out, behave as-if artificial frames are not present.
61 while (return_frame_sp->IsArtificial()) {
62 m_stepped_past_frames.push_back(return_frame_sp);
63
64 ++return_frame_index;
65 return_frame_sp = thread.GetStackFrameAtIndex(return_frame_index);
66
67 // We never expect to see an artificial frame without a regular ancestor.
68 // If this happens, log the issue and defensively refuse to step out.
69 if (!return_frame_sp) {
70 LLDB_LOG(log, "Can't step out of frame with artificial ancestors")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Format("lldb/source/Target/ThreadPlanStepOut.cpp"
, __func__, "Can't step out of frame with artificial ancestors"
); } while (0)
;
71 return;
72 }
73 }
74
75 m_step_out_to_id = return_frame_sp->GetStackID();
76 m_immediate_step_from_id = immediate_return_from_sp->GetStackID();
77
78 // If the frame directly below the one we are returning to is inlined, we
79 // have to be a little more careful. It is non-trivial to determine the real
80 // "return code address" for an inlined frame, so we have to work our way to
81 // that frame and then step out.
82 if (immediate_return_from_sp->IsInlined()) {
83 if (frame_idx > 0) {
84 // First queue a plan that gets us to this inlined frame, and when we get
85 // there we'll queue a second plan that walks us out of this frame.
86 m_step_out_to_inline_plan_sp = std::make_shared<ThreadPlanStepOut>(
87 thread, nullptr, false, stop_others, eVoteNoOpinion, eVoteNoOpinion,
88 frame_idx - 1, eLazyBoolNo, continue_to_next_branch);
89 static_cast<ThreadPlanStepOut *>(m_step_out_to_inline_plan_sp.get())
90 ->SetShouldStopHereCallbacks(nullptr, nullptr);
91 m_step_out_to_inline_plan_sp->SetPrivate(true);
92 } else {
93 // If we're already at the inlined frame we're stepping through, then
94 // just do that now.
95 QueueInlinedStepPlan(false);
96 }
97 } else {
98 // Find the return address and set a breakpoint there:
99 // FIXME - can we do this more securely if we know first_insn?
100
101 Address return_address(return_frame_sp->GetFrameCodeAddress());
102 if (continue_to_next_branch) {
103 SymbolContext return_address_sc;
104 AddressRange range;
105 Address return_address_decr_pc = return_address;
106 if (return_address_decr_pc.GetOffset() > 0)
107 return_address_decr_pc.Slide(-1);
108
109 return_address_decr_pc.CalculateSymbolContext(
110 &return_address_sc, lldb::eSymbolContextLineEntry);
111 if (return_address_sc.line_entry.IsValid()) {
112 const bool include_inlined_functions = false;
113 range = return_address_sc.line_entry.GetSameLineContiguousAddressRange(
114 include_inlined_functions);
115 if (range.GetByteSize() > 0) {
116 return_address = m_process.AdvanceAddressToNextBranchInstruction(
117 return_address, range);
118 }
119 }
120 }
121 m_return_addr = return_address.GetLoadAddress(&m_process.GetTarget());
122
123 if (m_return_addr == LLDB_INVALID_ADDRESS(18446744073709551615UL))
124 return;
125
126 // Perform some additional validation on the return address.
127 uint32_t permissions = 0;
128 if (!m_process.GetLoadAddressPermissions(m_return_addr, permissions)) {
129 LLDB_LOGF(log, "ThreadPlanStepOut(%p): Return address (0x%" PRIx64do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("ThreadPlanStepOut(%p): Return address (0x%"
"l" "x" ") permissions not found.", static_cast<void *>
(this), m_return_addr); } while (0)
130 ") permissions not found.", static_cast<void *>(this),do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("ThreadPlanStepOut(%p): Return address (0x%"
"l" "x" ") permissions not found.", static_cast<void *>
(this), m_return_addr); } while (0)
131 m_return_addr)do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("ThreadPlanStepOut(%p): Return address (0x%"
"l" "x" ") permissions not found.", static_cast<void *>
(this), m_return_addr); } while (0)
;
132 } else if (!(permissions & ePermissionsExecutable)) {
133 m_constructor_errors.Printf("Return address (0x%" PRIx64"l" "x"
134 ") did not point to executable memory.",
135 m_return_addr);
136 LLDB_LOGF(log, "ThreadPlanStepOut(%p): %s", static_cast<void *>(this),do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("ThreadPlanStepOut(%p): %s", static_cast
<void *>(this), m_constructor_errors.GetData()); } while
(0)
137 m_constructor_errors.GetData())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("ThreadPlanStepOut(%p): %s", static_cast
<void *>(this), m_constructor_errors.GetData()); } while
(0)
;
138 return;
139 }
140
141 Breakpoint *return_bp =
142 GetTarget().CreateBreakpoint(m_return_addr, true, false).get();
143
144 if (return_bp != nullptr) {
145 if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
146 m_could_not_resolve_hw_bp = true;
147 return_bp->SetThreadID(m_tid);
148 m_return_bp_id = return_bp->GetID();
149 return_bp->SetBreakpointKind("step-out");
150 }
151
152 if (immediate_return_from_sp) {
153 const SymbolContext &sc =
154 immediate_return_from_sp->GetSymbolContext(eSymbolContextFunction);
155 if (sc.function) {
156 m_immediate_step_from_function = sc.function;
157 }
158 }
159 }
160}
161
162void ThreadPlanStepOut::SetupAvoidNoDebug(
163 LazyBool step_out_avoids_code_without_debug_info) {
164 bool avoid_nodebug = true;
165 switch (step_out_avoids_code_without_debug_info) {
166 case eLazyBoolYes:
167 avoid_nodebug = true;
168 break;
169 case eLazyBoolNo:
170 avoid_nodebug = false;
171 break;
172 case eLazyBoolCalculate:
173 avoid_nodebug = GetThread().GetStepOutAvoidsNoDebug();
174 break;
175 }
176 if (avoid_nodebug)
177 GetFlags().Set(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
178 else
179 GetFlags().Clear(ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
180}
181
182void ThreadPlanStepOut::DidPush() {
183 Thread &thread = GetThread();
184 if (m_step_out_to_inline_plan_sp)
185 thread.QueueThreadPlan(m_step_out_to_inline_plan_sp, false);
186 else if (m_step_through_inline_plan_sp)
187 thread.QueueThreadPlan(m_step_through_inline_plan_sp, false);
188}
189
190ThreadPlanStepOut::~ThreadPlanStepOut() {
191 if (m_return_bp_id != LLDB_INVALID_BREAK_ID0)
192 GetTarget().RemoveBreakpointByID(m_return_bp_id);
193}
194
195void ThreadPlanStepOut::GetDescription(Stream *s,
196 lldb::DescriptionLevel level) {
197 if (level == lldb::eDescriptionLevelBrief)
198 s->Printf("step out");
199 else {
200 if (m_step_out_to_inline_plan_sp)
201 s->Printf("Stepping out to inlined frame so we can walk through it.");
202 else if (m_step_through_inline_plan_sp)
203 s->Printf("Stepping out by stepping through inlined function.");
204 else {
205 s->Printf("Stepping out from ");
206 Address tmp_address;
207 if (tmp_address.SetLoadAddress(m_step_from_insn, &GetTarget())) {
208 tmp_address.Dump(s, &m_process, Address::DumpStyleResolvedDescription,
209 Address::DumpStyleLoadAddress);
210 } else {
211 s->Printf("address 0x%" PRIx64"l" "x" "", (uint64_t)m_step_from_insn);
212 }
213
214 // FIXME: find some useful way to present the m_return_id, since there may
215 // be multiple copies of the
216 // same function on the stack.
217
218 s->Printf(" returning to frame at ");
219 if (tmp_address.SetLoadAddress(m_return_addr, &GetTarget())) {
220 tmp_address.Dump(s, &m_process, Address::DumpStyleResolvedDescription,
221 Address::DumpStyleLoadAddress);
222 } else {
223 s->Printf("address 0x%" PRIx64"l" "x" "", (uint64_t)m_return_addr);
224 }
225
226 if (level == eDescriptionLevelVerbose)
227 s->Printf(" using breakpoint site %d", m_return_bp_id);
228 }
229 }
230
231 if (m_stepped_past_frames.empty())
232 return;
233
234 s->Printf("\n");
235 for (StackFrameSP frame_sp : m_stepped_past_frames) {
236 s->Printf("Stepped out past: ");
237 frame_sp->DumpUsingSettingsFormat(s);
238 }
239}
240
241bool ThreadPlanStepOut::ValidatePlan(Stream *error) {
242 if (m_step_out_to_inline_plan_sp)
243 return m_step_out_to_inline_plan_sp->ValidatePlan(error);
244
245 if (m_step_through_inline_plan_sp)
246 return m_step_through_inline_plan_sp->ValidatePlan(error);
247
248 if (m_could_not_resolve_hw_bp) {
249 if (error)
250 error->PutCString(
251 "Could not create hardware breakpoint for thread plan.");
252 return false;
253 }
254
255 if (m_return_bp_id == LLDB_INVALID_BREAK_ID0) {
256 if (error) {
257 error->PutCString("Could not create return address breakpoint.");
258 if (m_constructor_errors.GetSize() > 0) {
259 error->PutCString(" ");
260 error->PutCString(m_constructor_errors.GetString());
261 }
262 }
263 return false;
264 }
265
266 return true;
267}
268
269bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) {
270 // If the step out plan is done, then we just need to step through the
271 // inlined frame.
272 if (m_step_out_to_inline_plan_sp) {
273 return m_step_out_to_inline_plan_sp->MischiefManaged();
274 } else if (m_step_through_inline_plan_sp) {
275 if (m_step_through_inline_plan_sp->MischiefManaged()) {
276 CalculateReturnValue();
277 SetPlanComplete();
278 return true;
279 } else
280 return false;
281 } else if (m_step_out_further_plan_sp) {
282 return m_step_out_further_plan_sp->MischiefManaged();
283 }
284
285 // We don't explain signals or breakpoints (breakpoints that handle stepping
286 // in or out will be handled by a child plan.
287
288 StopInfoSP stop_info_sp = GetPrivateStopInfo();
289 if (stop_info_sp) {
290 StopReason reason = stop_info_sp->GetStopReason();
291 if (reason == eStopReasonBreakpoint) {
292 // If this is OUR breakpoint, we're fine, otherwise we don't know why
293 // this happened...
294 BreakpointSiteSP site_sp(
295 m_process.GetBreakpointSiteList().FindByID(stop_info_sp->GetValue()));
296 if (site_sp && site_sp->IsBreakpointAtThisSite(m_return_bp_id)) {
297 bool done;
298
299 StackID frame_zero_id =
300 GetThread().GetStackFrameAtIndex(0)->GetStackID();
301
302 if (m_step_out_to_id == frame_zero_id)
303 done = true;
304 else if (m_step_out_to_id < frame_zero_id) {
305 // Either we stepped past the breakpoint, or the stack ID calculation
306 // was incorrect and we should probably stop.
307 done = true;
308 } else {
309 done = (m_immediate_step_from_id < frame_zero_id);
310 }
311
312 if (done) {
313 if (InvokeShouldStopHereCallback(eFrameCompareOlder, m_status)) {
314 CalculateReturnValue();
315 SetPlanComplete();
316 }
317 }
318
319 // If there was only one owner, then we're done. But if we also hit
320 // some user breakpoint on our way out, we should mark ourselves as
321 // done, but also not claim to explain the stop, since it is more
322 // important to report the user breakpoint than the step out
323 // completion.
324
325 if (site_sp->GetNumberOfOwners() == 1)
326 return true;
327 }
328 return false;
329 } else if (IsUsuallyUnexplainedStopReason(reason))
330 return false;
331 else
332 return true;
333 }
334 return true;
335}
336
337bool ThreadPlanStepOut::ShouldStop(Event *event_ptr) {
338 if (IsPlanComplete())
1
Assuming the condition is false
2
Taking false branch
339 return true;
340
341 bool done = false;
342 if (m_step_out_to_inline_plan_sp) {
3
Taking true branch
343 if (m_step_out_to_inline_plan_sp->MischiefManaged()) {
4
Assuming the condition is true
5
Taking true branch
344 // Now step through the inlined stack we are in:
345 if (QueueInlinedStepPlan(true)) {
6
Calling 'ThreadPlanStepOut::QueueInlinedStepPlan'
346 // If we can't queue a plan to do this, then just call ourselves done.
347 m_step_out_to_inline_plan_sp.reset();
348 SetPlanComplete(false);
349 return true;
350 } else
351 done = true;
352 } else
353 return m_step_out_to_inline_plan_sp->ShouldStop(event_ptr);
354 } else if (m_step_through_inline_plan_sp) {
355 if (m_step_through_inline_plan_sp->MischiefManaged())
356 done = true;
357 else
358 return m_step_through_inline_plan_sp->ShouldStop(event_ptr);
359 } else if (m_step_out_further_plan_sp) {
360 if (m_step_out_further_plan_sp->MischiefManaged())
361 m_step_out_further_plan_sp.reset();
362 else
363 return m_step_out_further_plan_sp->ShouldStop(event_ptr);
364 }
365
366 if (!done) {
367 StackID frame_zero_id = GetThread().GetStackFrameAtIndex(0)->GetStackID();
368 done = !(frame_zero_id < m_step_out_to_id);
369 }
370
371 // The normal step out computations think we are done, so all we need to do
372 // is consult the ShouldStopHere, and we are done.
373
374 if (done) {
375 if (InvokeShouldStopHereCallback(eFrameCompareOlder, m_status)) {
376 CalculateReturnValue();
377 SetPlanComplete();
378 } else {
379 m_step_out_further_plan_sp =
380 QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder, m_status);
381 done = false;
382 }
383 }
384
385 return done;
386}
387
388bool ThreadPlanStepOut::StopOthers() { return m_stop_others; }
389
390StateType ThreadPlanStepOut::GetPlanRunState() { return eStateRunning; }
391
392bool ThreadPlanStepOut::DoWillResume(StateType resume_state,
393 bool current_plan) {
394 if (m_step_out_to_inline_plan_sp || m_step_through_inline_plan_sp)
395 return true;
396
397 if (m_return_bp_id == LLDB_INVALID_BREAK_ID0)
398 return false;
399
400 if (current_plan) {
401 Breakpoint *return_bp = GetTarget().GetBreakpointByID(m_return_bp_id).get();
402 if (return_bp != nullptr)
403 return_bp->SetEnabled(true);
404 }
405 return true;
406}
407
408bool ThreadPlanStepOut::WillStop() {
409 if (m_return_bp_id != LLDB_INVALID_BREAK_ID0) {
410 Breakpoint *return_bp = GetTarget().GetBreakpointByID(m_return_bp_id).get();
411 if (return_bp != nullptr)
412 return_bp->SetEnabled(false);
413 }
414
415 return true;
416}
417
418bool ThreadPlanStepOut::MischiefManaged() {
419 if (IsPlanComplete()) {
420 // Did I reach my breakpoint? If so I'm done.
421 //
422 // I also check the stack depth, since if we've blown past the breakpoint
423 // for some
424 // reason and we're now stopping for some other reason altogether, then
425 // we're done with this step out operation.
426
427 Log *log = GetLog(LLDBLog::Step);
428 if (log)
429 LLDB_LOGF(log, "Completed step out plan.")do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("Completed step out plan."); } while
(0)
;
430 if (m_return_bp_id != LLDB_INVALID_BREAK_ID0) {
431 GetTarget().RemoveBreakpointByID(m_return_bp_id);
432 m_return_bp_id = LLDB_INVALID_BREAK_ID0;
433 }
434
435 ThreadPlan::MischiefManaged();
436 return true;
437 } else {
438 return false;
439 }
440}
441
442bool ThreadPlanStepOut::QueueInlinedStepPlan(bool queue_now) {
443 // Now figure out the range of this inlined block, and set up a "step through
444 // range" plan for that. If we've been provided with a context, then use the
445 // block in that context.
446 Thread &thread = GetThread();
447 StackFrameSP immediate_return_from_sp(thread.GetStackFrameAtIndex(0));
448 if (!immediate_return_from_sp)
7
Taking false branch
449 return false;
450
451 Log *log = GetLog(LLDBLog::Step);
452 if (log
7.1
'log' is null
) {
8
Taking false branch
453 StreamString s;
454 immediate_return_from_sp->Dump(&s, true, false);
455 LLDB_LOGF(log, "Queuing inlined frame to step past: %s.", s.GetData())do { ::lldb_private::Log *log_private = (log); if (log_private
) log_private->Printf("Queuing inlined frame to step past: %s."
, s.GetData()); } while (0)
;
456 }
457
458 Block *from_block = immediate_return_from_sp->GetFrameBlock();
459 if (from_block) {
9
Assuming 'from_block' is non-null
10
Taking true branch
460 Block *inlined_block = from_block->GetContainingInlinedBlock();
461 if (inlined_block) {
11
Assuming 'inlined_block' is non-null
12
Taking true branch
462 size_t num_ranges = inlined_block->GetNumRanges();
463 AddressRange inline_range;
464 if (inlined_block->GetRangeAtIndex(0, inline_range)) {
13
Assuming the condition is true
14
Taking true branch
465 SymbolContext inlined_sc;
466 inlined_block->CalculateSymbolContext(&inlined_sc);
467 inlined_sc.target_sp = GetTarget().shared_from_this();
468 RunMode run_mode =
469 m_stop_others ? lldb::eOnlyThisThread : lldb::eAllThreads;
15
Assuming field 'm_stop_others' is false
16
'?' condition is false
470 const LazyBool avoid_no_debug = eLazyBoolNo;
471
472 m_step_through_inline_plan_sp =
473 std::make_shared<ThreadPlanStepOverRange>(
474 thread, inline_range, inlined_sc, run_mode, avoid_no_debug);
475 ThreadPlanStepOverRange *step_through_inline_plan_ptr =
476 static_cast<ThreadPlanStepOverRange *>(
477 m_step_through_inline_plan_sp.get());
478 m_step_through_inline_plan_sp->SetPrivate(true);
479
480 step_through_inline_plan_ptr->SetOkayToDiscard(true);
481 StreamString errors;
482 if (!step_through_inline_plan_ptr->ValidatePlan(&errors)) {
17
Assuming the condition is true
18
Taking true branch
483 // FIXME: Log this failure.
484 delete step_through_inline_plan_ptr;
19
Argument to 'delete' is offset by 16 bytes from the start of memory allocated by operator new
485 return false;
486 }
487
488 for (size_t i = 1; i < num_ranges; i++) {
489 if (inlined_block->GetRangeAtIndex(i, inline_range))
490 step_through_inline_plan_ptr->AddRange(inline_range);
491 }
492
493 if (queue_now)
494 thread.QueueThreadPlan(m_step_through_inline_plan_sp, false);
495 return true;
496 }
497 }
498 }
499
500 return false;
501}
502
503void ThreadPlanStepOut::CalculateReturnValue() {
504 if (m_return_valobj_sp)
505 return;
506
507 if (!m_calculate_return_value)
508 return;
509
510 if (m_immediate_step_from_function != nullptr) {
511 CompilerType return_compiler_type =
512 m_immediate_step_from_function->GetCompilerType()
513 .GetFunctionReturnType();
514 if (return_compiler_type) {
515 lldb::ABISP abi_sp = m_process.GetABI();
516 if (abi_sp)
517 m_return_valobj_sp =
518 abi_sp->GetReturnValueObject(GetThread(), return_compiler_type);
519 }
520 }
521}
522
523bool ThreadPlanStepOut::IsPlanStale() {
524 // If we are still lower on the stack than the frame we are returning to,
525 // then there's something for us to do. Otherwise, we're stale.
526
527 StackID frame_zero_id = GetThread().GetStackFrameAtIndex(0)->GetStackID();
528 return !(frame_zero_id < m_step_out_to_id);
529}