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.
This commit is contained in:
Itamar 2023-02-19 22:52:52 +02:00 committed by Andreas Kling
parent 91224d47d2
commit 47f5a3ea9a
Notes: sideshowbarker 2024-07-17 04:32:07 +09:00
8 changed files with 44 additions and 11 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

View file

@ -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);
}
}

View file

@ -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;
};
}

View file

@ -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();
}
}

View file

@ -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:

View file

@ -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();

View file

@ -510,4 +510,9 @@ void DebugSession::update_loaded_libs()
});
}
void DebugSession::stop_debuggee()
{
kill(pid(), SIGSTOP);
}
}

View file

@ -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;