When a thread reaches a breakpoint at the return address set by `ThreadPlanStepOut`, `ThreadPlanStepOut::ShouldStop()` calls `ThreadPlanShouldStopHere::InvokeShouldStopHereCallback()`, and if it returns `false`, `ThreadPlanShouldStopHere::QueueStepOutFromHerePlan()` is called to queue a new plan to skip the corresponding range. Once the new plan finishes, `ThreadPlanStepOut::ShouldStop()` should recheck the stop condition; however, there is no code path in the method that sets `done` to `true`. Before #126838, if `done` was `false`, the method checked if a suitable frame had been reached. After the patch, the check is only performed at a breakpoint; thus, the execution continues. This patch causes `ThreadPlanStepOut::ShouldStop()` to recheck the stop condition when `m_step_out_further_plan_sp` completes.
36 lines
1.1 KiB
Python
36 lines
1.1 KiB
Python
"""
|
|
Test stepping out of a function when the return location is an unsuitable
|
|
stopping point.
|
|
"""
|
|
|
|
|
|
import lldb
|
|
from lldbsuite.test.decorators import *
|
|
from lldbsuite.test.lldbtest import *
|
|
from lldbsuite.test import lldbutil
|
|
|
|
|
|
class ThreadStepOutLine0TestCase(TestBase):
|
|
def test(self):
|
|
self.build()
|
|
target, process, thread, _ = lldbutil.run_to_source_breakpoint(
|
|
self, "// Set breakpoint here", lldb.SBFileSpec("main.c")
|
|
)
|
|
correct_stepped_out_line = line_number("main.c", "// Should stop here")
|
|
return_statement_line = line_number("main.c", "// Ran too far")
|
|
safety_bp = target.BreakpointCreateByLocation(
|
|
lldb.SBFileSpec("main.c"), return_statement_line
|
|
)
|
|
self.assertTrue(safety_bp.IsValid())
|
|
|
|
error = lldb.SBError()
|
|
thread.StepOut(error)
|
|
self.assertTrue(error.Success())
|
|
|
|
frame = thread.GetSelectedFrame()
|
|
self.assertEqual(
|
|
frame.line_entry.GetLine(),
|
|
correct_stepped_out_line,
|
|
"Step-out lost control of execution, ran too far",
|
|
)
|