Index: lldb/include/lldb/Target/Thread.h =================================================================== --- lldb/include/lldb/Target/Thread.h +++ lldb/include/lldb/Target/Thread.h @@ -539,9 +539,12 @@ /// This function is designed to be used by commands where the /// process is publicly stopped. /// + /// \param[in] frame_idx + /// The frame index to step out of. + /// /// \return /// An error that describes anything that went wrong - virtual Status StepOut(); + virtual Status StepOut(uint32_t frame_idx = 0); /// Retrieves the per-thread data area. /// Most OSs maintain a per-thread pointer (e.g. the FS register on @@ -836,7 +839,7 @@ /// See standard meanings for the stop & run votes in ThreadPlan.h. /// /// \param[in] frame_idx - /// The fame index. + /// The frame index. /// /// \param[out] status /// A status with an error if queuing failed. Index: lldb/source/Core/IOHandlerCursesGUI.cpp =================================================================== --- lldb/source/Core/IOHandlerCursesGUI.cpp +++ lldb/source/Core/IOHandlerCursesGUI.cpp @@ -6402,8 +6402,11 @@ if (exe_ctx.HasThreadScope()) { Process *process = exe_ctx.GetProcessPtr(); if (process && process->IsAlive() && - StateIsStoppedState(process->GetState(), true)) - exe_ctx.GetThreadRef().StepOut(); + StateIsStoppedState(process->GetState(), true)) { + Thread *thread = exe_ctx.GetThreadPtr(); + uint32_t frame_idx = thread->GetSelectedFrameIndex(); + exe_ctx.GetThreadRef().StepOut(frame_idx); + } } } return MenuActionResult::Handled; @@ -7361,7 +7364,9 @@ m_debugger.GetCommandInterpreter().GetExecutionContext(); if (exe_ctx.HasThreadScope() && StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) { - exe_ctx.GetThreadRef().StepOut(); + Thread *thread = exe_ctx.GetThreadPtr(); + uint32_t frame_idx = thread->GetSelectedFrameIndex(); + exe_ctx.GetThreadRef().StepOut(frame_idx); } } return eKeyHandled; Index: lldb/source/Target/Thread.cpp =================================================================== --- lldb/source/Target/Thread.cpp +++ lldb/source/Target/Thread.cpp @@ -1953,7 +1953,7 @@ return error; } -Status Thread::StepOut() { +Status Thread::StepOut(uint32_t frame_idx) { Status error; Process *process = GetProcess().get(); if (StateIsStoppedState(process->GetState(), true)) { @@ -1963,7 +1963,7 @@ ThreadPlanSP new_plan_sp(QueueThreadPlanForStepOut( abort_other_plans, nullptr, first_instruction, stop_other_threads, - eVoteYes, eVoteNoOpinion, 0, error)); + eVoteYes, eVoteNoOpinion, frame_idx, error)); new_plan_sp->SetIsControllingPlan(true); new_plan_sp->SetOkayToDiscard(false); Index: lldb/test/API/commands/gui/basicdebug/TestGuiBasicDebug.py =================================================================== --- lldb/test/API/commands/gui/basicdebug/TestGuiBasicDebug.py +++ lldb/test/API/commands/gui/basicdebug/TestGuiBasicDebug.py @@ -32,7 +32,7 @@ self.child.send("s") # step self.child.expect("return 1; // In function[^\r\n]+<<< Thread 1: step in") self.child.send("u") # up - self.child.expect_exact("func(); // Break here") + self.child.expect_exact("func(); // Break here") self.child.send("d") # down self.child.expect_exact("return 1; // In function") self.child.send("f") # finish @@ -40,7 +40,19 @@ self.child.send("s") # move onto the second one self.child.expect("<<< Thread 1: step in") self.child.send("n") # step over - self.child.expect("<<< Thread 1: step over") + self.child.expect("// Dummy command 1[^\r\n]+<<< Thread 1: step over") + self.child.send("n") + + # Test that 'up' + 'step out' steps out of the selected function. + self.child.send("s") # move into func_up() + self.child.expect("// In func_up") + self.child.send("s") # move into func_down() + self.child.expect("// In func_down") + self.child.send("u") # up + self.child.expect("// In func_up") + self.child.send("f") # finish + self.child.expect("// Dummy command 2[^\r\n]+<<< Thread 1: step out") + self.child.send("n") # Press escape to quit the gui self.child.send(escape_key) Index: lldb/test/API/commands/gui/basicdebug/func.c =================================================================== --- lldb/test/API/commands/gui/basicdebug/func.c +++ lldb/test/API/commands/gui/basicdebug/func.c @@ -1,3 +1,12 @@ int func() { return 1; // In function } + +void func_down() { + int dummy = 1; // In func_down + (void)dummy; +} + +void func_up() { + func_down(); // In func_up +} Index: lldb/test/API/commands/gui/basicdebug/main.c =================================================================== --- lldb/test/API/commands/gui/basicdebug/main.c +++ lldb/test/API/commands/gui/basicdebug/main.c @@ -1,7 +1,14 @@ extern int func(); +extern void func_up(); int main(int argc, char **argv) { - func(); // Break here - func(); // Second + int dummy; + func(); // Break here + func(); // Second + dummy = 1; // Dummy command 1 + + func_up(); // First func1 call + dummy = 2; // Dummy command 2 + return 0; }