diff options
author | Itamar <itamar8910@gmail.com> | 2023-02-19 22:52:52 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-02-24 19:09:27 +0100 |
commit | 47f5a3ea9afeaade0295022c7e01fdc54401ef9f (patch) | |
tree | 800bff0439556de2e760c1734dc624ea3040fcee /Userland | |
parent | 91224d47d20ab149ddf41e681ea6367c50123323 (diff) | |
download | serenity-47f5a3ea9afeaade0295022c7e01fdc54401ef9f.zip |
HackStudio: Add 'pause debuggee' button
This button sends a SIGSTOP to the debugged process, which pauses it.
The debuggee can be resumed with the 'continue' button.
Diffstat (limited to 'Userland')
7 files changed, 44 insertions, 11 deletions
diff --git a/Userland/DevTools/HackStudio/Debugger/DebugInfoWidget.cpp b/Userland/DevTools/HackStudio/Debugger/DebugInfoWidget.cpp index ba03e124c4..788564e94b 100644 --- a/Userland/DevTools/HackStudio/Debugger/DebugInfoWidget.cpp +++ b/Userland/DevTools/HackStudio/Debugger/DebugInfoWidget.cpp @@ -40,12 +40,17 @@ ErrorOr<void> DebugInfoWidget::init_toolbar() Debugger::the().set_requested_debugger_action(Debugger::DebuggerAction::SourceStepOut); }); + m_pause_action = GUI::Action::create("Pause", {}, TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/debug-pause.png"sv)), [](auto&) { + Debugger::the().stop_debuggee(); + }); + m_toolbar->add_action(*m_continue_action); m_toolbar->add_action(*m_singlestep_action); m_toolbar->add_action(*m_step_in_action); m_toolbar->add_action(*m_step_out_action); + m_toolbar->add_action(*m_pause_action); - set_debug_actions_enabled(false); + set_debug_actions_enabled(false, {}); return {}; } @@ -193,12 +198,22 @@ void DebugInfoWidget::program_stopped() m_registers_view->set_model({}); } -void DebugInfoWidget::set_debug_actions_enabled(bool enabled) +void DebugInfoWidget::set_debug_actions_enabled(bool enabled, Optional<DebugActionsState> state) { - m_continue_action->set_enabled(enabled); - m_singlestep_action->set_enabled(enabled); - m_step_in_action->set_enabled(enabled); - m_step_out_action->set_enabled(enabled); + if (!enabled) { + m_continue_action->set_enabled(false); + m_singlestep_action->set_enabled(false); + m_step_in_action->set_enabled(false); + m_step_out_action->set_enabled(false); + m_pause_action->set_enabled(false); + return; + } + + m_continue_action->set_enabled(state == DebugActionsState::DebuggeeStopped); + m_singlestep_action->set_enabled(state == DebugActionsState::DebuggeeStopped); + m_step_in_action->set_enabled(state == DebugActionsState::DebuggeeStopped); + m_step_out_action->set_enabled(state == DebugActionsState::DebuggeeStopped); + m_pause_action->set_enabled(state == DebugActionsState::DebuggeeRunning); } } diff --git a/Userland/DevTools/HackStudio/Debugger/DebugInfoWidget.h b/Userland/DevTools/HackStudio/Debugger/DebugInfoWidget.h index 11759c649d..e08b23dfae 100644 --- a/Userland/DevTools/HackStudio/Debugger/DebugInfoWidget.h +++ b/Userland/DevTools/HackStudio/Debugger/DebugInfoWidget.h @@ -29,7 +29,12 @@ public: void update_state(Debug::ProcessInspector&, PtraceRegisters const&); void program_stopped(); - void set_debug_actions_enabled(bool enabled); + + enum class DebugActionsState { + DebuggeeRunning, + DebuggeeStopped, + }; + void set_debug_actions_enabled(bool enabled, Optional<DebugActionsState>); Function<void(Debug::DebugInfo::SourcePosition const&)> on_backtrace_frame_selection; @@ -51,6 +56,7 @@ private: RefPtr<GUI::Action> m_singlestep_action; RefPtr<GUI::Action> m_step_in_action; RefPtr<GUI::Action> m_step_out_action; + RefPtr<GUI::Action> m_pause_action; }; } diff --git a/Userland/DevTools/HackStudio/Debugger/Debugger.cpp b/Userland/DevTools/HackStudio/Debugger/Debugger.cpp index b1a97bae4c..2ab1a0cbc8 100644 --- a/Userland/DevTools/HackStudio/Debugger/Debugger.cpp +++ b/Userland/DevTools/HackStudio/Debugger/Debugger.cpp @@ -314,5 +314,9 @@ void Debugger::set_requested_debugger_action(DebuggerAction action) pthread_cond_signal(continue_cond()); pthread_mutex_unlock(continue_mutex()); } +void Debugger::stop_debuggee() +{ + return m_debug_session->stop_debuggee(); +} } diff --git a/Userland/DevTools/HackStudio/Debugger/Debugger.h b/Userland/DevTools/HackStudio/Debugger/Debugger.h index eafd7382ba..656d2983c4 100644 --- a/Userland/DevTools/HackStudio/Debugger/Debugger.h +++ b/Userland/DevTools/HackStudio/Debugger/Debugger.h @@ -64,6 +64,8 @@ public: void set_child_setup_callback(Function<ErrorOr<void>()> callback) { m_child_setup_callback = move(callback); } + void stop_debuggee(); + private: class DebuggingState { public: diff --git a/Userland/DevTools/HackStudio/HackStudioWidget.cpp b/Userland/DevTools/HackStudio/HackStudioWidget.cpp index 71d9eb486c..aa8b5be432 100644 --- a/Userland/DevTools/HackStudio/HackStudioWidget.cpp +++ b/Userland/DevTools/HackStudio/HackStudioWidget.cpp @@ -1055,7 +1055,7 @@ void HackStudioWidget::initialize_debugger() if (m_current_editor_in_execution) m_current_editor_in_execution->editor().set_execution_position(source_position.value().line_number - 1); m_debug_info_widget->update_state(*Debugger::the().session(), regs); - m_debug_info_widget->set_debug_actions_enabled(true); + m_debug_info_widget->set_debug_actions_enabled(true, DebugInfoWidget::DebugActionsState::DebuggeeStopped); m_disassembly_widget->update_state(*Debugger::the().session(), regs); HackStudioWidget::reveal_action_tab(*m_debug_info_widget); }); @@ -1065,7 +1065,7 @@ void HackStudioWidget::initialize_debugger() }, [this]() { GUI::Application::the()->event_loop().deferred_invoke([this] { - m_debug_info_widget->set_debug_actions_enabled(false); + m_debug_info_widget->set_debug_actions_enabled(true, DebugInfoWidget::DebugActionsState::DebuggeeRunning); if (m_current_editor_in_execution) m_current_editor_in_execution->editor().clear_execution_position(); }); @@ -1073,7 +1073,7 @@ void HackStudioWidget::initialize_debugger() }, [this]() { GUI::Application::the()->event_loop().deferred_invoke([this] { - m_debug_info_widget->set_debug_actions_enabled(false); + m_debug_info_widget->set_debug_actions_enabled(false, {}); if (m_current_editor_in_execution) m_current_editor_in_execution->editor().clear_execution_position(); m_debug_info_widget->program_stopped(); diff --git a/Userland/Libraries/LibDebug/DebugSession.cpp b/Userland/Libraries/LibDebug/DebugSession.cpp index 7ad41b67db..451d4a17a2 100644 --- a/Userland/Libraries/LibDebug/DebugSession.cpp +++ b/Userland/Libraries/LibDebug/DebugSession.cpp @@ -510,4 +510,9 @@ void DebugSession::update_loaded_libs() }); } +void DebugSession::stop_debuggee() +{ + kill(pid(), SIGSTOP); +} + } diff --git a/Userland/Libraries/LibDebug/DebugSession.h b/Userland/Libraries/LibDebug/DebugSession.h index 8997cea5dc..70b7ce43d3 100644 --- a/Userland/Libraries/LibDebug/DebugSession.h +++ b/Userland/Libraries/LibDebug/DebugSession.h @@ -100,6 +100,7 @@ public: Syscall, }; void continue_debuggee(ContinueType type = ContinueType::FreeRun); + void stop_debuggee(); // Returns the wstatus result of waitpid() int continue_debuggee_and_wait(ContinueType type = ContinueType::FreeRun); @@ -169,7 +170,7 @@ void DebugSession::run(DesiredInitialDebugeeState initial_debugee_state, Callbac // FIXME: This check actually only checks whether the debuggee // stopped because it hit a breakpoint/syscall/is in single stepping mode or not - if (WSTOPSIG(wstatus) != SIGTRAP) { + if (WSTOPSIG(wstatus) != SIGTRAP && WSTOPSIG(wstatus) != SIGSTOP) { callback(DebugBreakReason::Exited, Optional<PtraceRegisters>()); m_is_debuggee_dead = true; return true; |