Bug Summary

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