From 47f5a3ea9afeaade0295022c7e01fdc54401ef9f Mon Sep 17 00:00:00 2001 From: Itamar Date: Sun, 19 Feb 2023 22:52:52 +0200 Subject: [PATCH] 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. --- Base/res/icons/16x16/debug-pause.png | Bin 0 -> 4979 bytes .../HackStudio/Debugger/DebugInfoWidget.cpp | 27 ++++++++++++++---- .../HackStudio/Debugger/DebugInfoWidget.h | 8 +++++- .../DevTools/HackStudio/Debugger/Debugger.cpp | 4 +++ .../DevTools/HackStudio/Debugger/Debugger.h | 2 ++ .../DevTools/HackStudio/HackStudioWidget.cpp | 6 ++-- Userland/Libraries/LibDebug/DebugSession.cpp | 5 ++++ Userland/Libraries/LibDebug/DebugSession.h | 3 +- 8 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 Base/res/icons/16x16/debug-pause.png diff --git a/Base/res/icons/16x16/debug-pause.png b/Base/res/icons/16x16/debug-pause.png new file mode 100644 index 0000000000000000000000000000000000000000..a93a815ea314f3a81a5c8de02983f4ca10a0933a GIT binary patch literal 4979 zcmeHKc~leU77tdUhJXvANL^ykR-a~1$np}lge7PoMyf!uI+>Y-k!&Ud1XM~9d7>gn zDMi7uiJ~kPYFpXVx?roop?F-_Dn&(G6-sH*Rtj$tP~p7(<2kSYnVgx-+~s%g{eAbl zlSz>W`q>j)2sj+hUg|GVV8630$8+G=_wIEYiDK-d0yz4`o!kftSo!!T`i$lU$yAa!y(pS?{9?X zKk^IXn!rUspSN<`{5G3!hf@yLW$yopz35YF;h8TMej`s;M+r_%m4Mz+K}V=%xh|rw zbGCoAu%Bw&c+YV4c(iy#=iMCjEE+yu+YmFPyPN#5;?F^@@AXQf@4PnKOu=L6k@s>4 z!vyc9;v2Xy&&Gtsif{RIk_$^$g%z}Iweu~O5Nq)Kt(k~?bCtqYa;3|VbRj%6Yu$2V z58)kY=R!6wAOpWR^yk8^8F?WQlpGBwl5_cLYWLNoEvFB6Uj*ED0{g3-_LP105z4y-N=e_sY`^ySGhwau0{}RrCW>XBmrFSeodV2`B zVs_RLPCNyF-X-O@ryJ9cJXhf*$D{ME*b>v9cH%OQ_~W=&O-S7wq`FF-ZU30pcs}V< z((KM<-;u8I(?(JPzZbXdi}~SschSbY9S(ECe_5L3+*^=cBvBWpEo~@aTrMjNtjDLG zJj{MKFj0K{c)GGRQ_&p4ay2$|EO6k@rz*k+jwQ|6mlbUEc^;@S~G*ooS{?GGy>gG4h=x6fjA{^GiyhaNo`bTc|^NyD_V@0(p{$Bu!*&|RDc z*Qrf+F9kJwI=}6=MHonEX%X_j2xuOFbVilq0gnM~Lbm>HK!nNw!^>`+n7k6R)Mw<_eX*^-j`_N5||>7OgA4sL{j2z>T)ek*x*l$Fu+V zB(sWrvDkM3b+2Y!O+c#0k=9nl;f@=z7yeTy*Jm~ib(gF;oSi#xueK-R!u*@LRfEfJ z=b}#%W_9csY6{%-*rw{TLsfii`*QoaTXVj9nw{M5cS(%zQXPz|{PfJ%i+fRi`KhJy z4)Cco_2{9JYSo|V4-b9b;TS0TDm!dbbH%ZuTwlX#N>9dt{HV^V+ZRuIxJPbnyIxv( z=J@TV>U+ym)ZOPAbn&+C{XrRV^)0MOG^IB7FgN^n`UeH!&o9+=t)Trm>D=X!Y>IvC9}5f z-mqvb^{>Qt?4^766?KOhegP|g?(Qio-Bn7O9-nZghPSfDKV>wMKv4>LeOGF?r`5(J z$X7AC`kbes7b`OcvNM~@0ydqRH7j`!KwR1A_5kAB+!=^U!)@*_6kZ$c%q!Y>t(`dC z|I!zYrx*6v_xvQga<49EbyZ^F>^#S`P}Hl(ucCDExoyqdknTf;p9C~J?z^Non|i}d zWxM9x&&UTNYP|mNZU<8b=c((1fu`-h&QGptxXQeRIFJwctoBNt>f|(cUE;14<@l9u z8K;*F4$Nc^GpmD*PTzc6nZQI>*n2!%GTe8wSr%xP7C5*3(NnX;)$a|n=(ko%AS!=+CIu0lFFdG0c5=Kc%SdHjJMBfLH? zFc^%B1o;rz!<`^B3ormJi~=OHR--cs%p$TCSAbnx#56L=YJx_J$RRR0Nvt=*BsP^z zrBi&&NHmk|P9O=5kV>GC_>MzhcOr5GiW&qoT1-p~HHJmi8`U%hpU}^Z zu{snmQ*tPDUo_#b0Y|=*=LD(l6)}gKwAt3Ojzah$~v6cgYG*|;` zF;f#3l`$!#pHwD)>0zNjjc5&4FO2L-mMEfnMb@O;EE;P$6BEJQU*b-(eo?#C7_*Ye z1QI12CVW1Ob4;0#$S#?8Z~FVb%mF zsm_D~IuN!%Vc=8*!%=d15L?CLQaBtp6@|^gu6T5aP2odK7Msb2`3x>N0V2qVU|k7l zCT3-Uf-oo+i>u^ulza-P;<{1T5X_<|RS=iLP`NQ+7N&yvTq_g=3ViiOEr2a2q6O42 z&7f0T6&At;UUI33%%sv^N#q&;RbdVy@>)a}WqzdyMzrvH6tJ+#aO1l1SbPSZ!Dq2J zJjN@d4Y1LKb)p56L8r3Da4pLsz>2|$1uT7v0a!h-S_EPv44`^ruwJhbku52aES}c( zCJDzD#UC+Y7O|F&AMg3~@V2qLu`QrMtSS=8+O`4!91CIsqG8Ay2=g0Lff0aC4P*Oz zyrEvmk-u3iJ{^SkN(M$QU4<={k^@lqd>)g+gXnZV1L86`Y|dnKlU{|!07lqLja7KVAG2Ba$JpbW})#P{EV-~KNtaneiP)i_YXdfW3M>{SS_T;nIfjat6>^~XQPBr^>Dp(Y&8 z&e3w%;11_HW5Q{uROU17!4${2?>GhA@O_AhmP;jG!MtnW7H8X#Z@lrzqisau=(d4_ lHjc$vsV;P9qO&cLi2LCI-c`8wLOJGulllZoD!jKO{uh>uju!v` literal 0 HcmV?d00001 diff --git a/Userland/DevTools/HackStudio/Debugger/DebugInfoWidget.cpp b/Userland/DevTools/HackStudio/Debugger/DebugInfoWidget.cpp index ba03e124c47..788564e94b9 100644 --- a/Userland/DevTools/HackStudio/Debugger/DebugInfoWidget.cpp +++ b/Userland/DevTools/HackStudio/Debugger/DebugInfoWidget.cpp @@ -40,12 +40,17 @@ ErrorOr 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 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 11759c649d0..e08b23dfaed 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); Function on_backtrace_frame_selection; @@ -51,6 +56,7 @@ private: RefPtr m_singlestep_action; RefPtr m_step_in_action; RefPtr m_step_out_action; + RefPtr m_pause_action; }; } diff --git a/Userland/DevTools/HackStudio/Debugger/Debugger.cpp b/Userland/DevTools/HackStudio/Debugger/Debugger.cpp index b1a97bae4c7..2ab1a0cbc89 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 eafd7382ba9..656d2983c40 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()> 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 71d9eb486c3..aa8b5be432e 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 7ad41b67db9..451d4a17a23 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 8997cea5dc7..70b7ce43d37 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()); m_is_debuggee_dead = true; return true;