mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 00:57:36 +00:00
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:
parent
91224d47d2
commit
47f5a3ea9a
8 changed files with 44 additions and 11 deletions
BIN
Base/res/icons/16x16/debug-pause.png
Normal file
BIN
Base/res/icons/16x16/debug-pause.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
|
@ -40,12 +40,17 @@ ErrorOr<void> DebugInfoWidget::init_toolbar()
|
||||||
Debugger::the().set_requested_debugger_action(Debugger::DebuggerAction::SourceStepOut);
|
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_continue_action);
|
||||||
m_toolbar->add_action(*m_singlestep_action);
|
m_toolbar->add_action(*m_singlestep_action);
|
||||||
m_toolbar->add_action(*m_step_in_action);
|
m_toolbar->add_action(*m_step_in_action);
|
||||||
m_toolbar->add_action(*m_step_out_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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -193,12 +198,22 @@ void DebugInfoWidget::program_stopped()
|
||||||
m_registers_view->set_model({});
|
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);
|
if (!enabled) {
|
||||||
m_singlestep_action->set_enabled(enabled);
|
m_continue_action->set_enabled(false);
|
||||||
m_step_in_action->set_enabled(enabled);
|
m_singlestep_action->set_enabled(false);
|
||||||
m_step_out_action->set_enabled(enabled);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,12 @@ public:
|
||||||
|
|
||||||
void update_state(Debug::ProcessInspector&, PtraceRegisters const&);
|
void update_state(Debug::ProcessInspector&, PtraceRegisters const&);
|
||||||
void program_stopped();
|
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;
|
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_singlestep_action;
|
||||||
RefPtr<GUI::Action> m_step_in_action;
|
RefPtr<GUI::Action> m_step_in_action;
|
||||||
RefPtr<GUI::Action> m_step_out_action;
|
RefPtr<GUI::Action> m_step_out_action;
|
||||||
|
RefPtr<GUI::Action> m_pause_action;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -314,5 +314,9 @@ void Debugger::set_requested_debugger_action(DebuggerAction action)
|
||||||
pthread_cond_signal(continue_cond());
|
pthread_cond_signal(continue_cond());
|
||||||
pthread_mutex_unlock(continue_mutex());
|
pthread_mutex_unlock(continue_mutex());
|
||||||
}
|
}
|
||||||
|
void Debugger::stop_debuggee()
|
||||||
|
{
|
||||||
|
return m_debug_session->stop_debuggee();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,8 @@ public:
|
||||||
|
|
||||||
void set_child_setup_callback(Function<ErrorOr<void>()> callback) { m_child_setup_callback = move(callback); }
|
void set_child_setup_callback(Function<ErrorOr<void>()> callback) { m_child_setup_callback = move(callback); }
|
||||||
|
|
||||||
|
void stop_debuggee();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class DebuggingState {
|
class DebuggingState {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1055,7 +1055,7 @@ void HackStudioWidget::initialize_debugger()
|
||||||
if (m_current_editor_in_execution)
|
if (m_current_editor_in_execution)
|
||||||
m_current_editor_in_execution->editor().set_execution_position(source_position.value().line_number - 1);
|
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->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);
|
m_disassembly_widget->update_state(*Debugger::the().session(), regs);
|
||||||
HackStudioWidget::reveal_action_tab(*m_debug_info_widget);
|
HackStudioWidget::reveal_action_tab(*m_debug_info_widget);
|
||||||
});
|
});
|
||||||
|
@ -1065,7 +1065,7 @@ void HackStudioWidget::initialize_debugger()
|
||||||
},
|
},
|
||||||
[this]() {
|
[this]() {
|
||||||
GUI::Application::the()->event_loop().deferred_invoke([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)
|
if (m_current_editor_in_execution)
|
||||||
m_current_editor_in_execution->editor().clear_execution_position();
|
m_current_editor_in_execution->editor().clear_execution_position();
|
||||||
});
|
});
|
||||||
|
@ -1073,7 +1073,7 @@ void HackStudioWidget::initialize_debugger()
|
||||||
},
|
},
|
||||||
[this]() {
|
[this]() {
|
||||||
GUI::Application::the()->event_loop().deferred_invoke([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)
|
if (m_current_editor_in_execution)
|
||||||
m_current_editor_in_execution->editor().clear_execution_position();
|
m_current_editor_in_execution->editor().clear_execution_position();
|
||||||
m_debug_info_widget->program_stopped();
|
m_debug_info_widget->program_stopped();
|
||||||
|
|
|
@ -510,4 +510,9 @@ void DebugSession::update_loaded_libs()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebugSession::stop_debuggee()
|
||||||
|
{
|
||||||
|
kill(pid(), SIGSTOP);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,6 +100,7 @@ public:
|
||||||
Syscall,
|
Syscall,
|
||||||
};
|
};
|
||||||
void continue_debuggee(ContinueType type = ContinueType::FreeRun);
|
void continue_debuggee(ContinueType type = ContinueType::FreeRun);
|
||||||
|
void stop_debuggee();
|
||||||
|
|
||||||
// Returns the wstatus result of waitpid()
|
// Returns the wstatus result of waitpid()
|
||||||
int continue_debuggee_and_wait(ContinueType type = ContinueType::FreeRun);
|
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
|
// FIXME: This check actually only checks whether the debuggee
|
||||||
// stopped because it hit a breakpoint/syscall/is in single stepping mode or not
|
// 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>());
|
callback(DebugBreakReason::Exited, Optional<PtraceRegisters>());
|
||||||
m_is_debuggee_dead = true;
|
m_is_debuggee_dead = true;
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue