diff --git a/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp b/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp index 4ef9432ff..ff7eed2c3 100644 --- a/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp +++ b/stratosphere/dmnt.gen2/source/dmnt2_debug_process.cpp @@ -273,25 +273,31 @@ namespace ams::dmnt { /* Note that we're stepping. */ m_stepping = true; - /* Determine where we're stepping to. */ - u64 current_pc = ctx.pc; - u64 step_target = 0; - this->GetBranchTarget(ctx, thread_id, current_pc, step_target); + if (m_use_hardware_single_step) { + /* Set thread single step. */ + R_TRY(this->SetThreadContext(std::addressof(ctx), thread_id, svc::ThreadContextFlag_SetSingleStep)); + } else { + /* Determine where we're stepping to. */ + u64 current_pc = ctx.pc; + u64 step_target = 0; + this->GetBranchTarget(ctx, thread_id, current_pc, step_target); - /* Ensure we end with valid breakpoints. */ - auto bp_guard = SCOPE_GUARD { this->ClearStep(); }; + /* Ensure we end with valid breakpoints. */ + auto bp_guard = SCOPE_GUARD { this->ClearStep(); }; - /* Set step breakpoint on current pc. */ - /* TODO: aarch32 breakpoints. */ - if (current_pc) { - R_TRY(m_step_breakpoints.SetBreakPoint(current_pc, sizeof(u32), true)); + /* Set step breakpoint on current pc. */ + /* TODO: aarch32 breakpoints. */ + if (current_pc) { + R_TRY(m_step_breakpoints.SetBreakPoint(current_pc, sizeof(u32), true)); + } + + if (step_target) { + R_TRY(m_step_breakpoints.SetBreakPoint(step_target, sizeof(u32), true)); + } + + bp_guard.Cancel(); } - if (step_target) { - R_TRY(m_step_breakpoints.SetBreakPoint(step_target, sizeof(u32), true)); - } - - bp_guard.Cancel(); return ResultSuccess(); } diff --git a/stratosphere/dmnt.gen2/source/dmnt2_debug_process.hpp b/stratosphere/dmnt.gen2/source/dmnt2_debug_process.hpp index 8b18345ba..e7ea9a461 100644 --- a/stratosphere/dmnt.gen2/source/dmnt2_debug_process.hpp +++ b/stratosphere/dmnt.gen2/source/dmnt2_debug_process.hpp @@ -52,6 +52,7 @@ namespace ams::dmnt { u64 m_continue_thread_id{}; GdbSignal m_last_signal{}; bool m_stepping{false}; + bool m_use_hardware_single_step{false}; bool m_thread_valid[ThreadCountMax]{}; u64 m_thread_ids[ThreadCountMax]{}; osdbg::ThreadInfo m_thread_infos[ThreadCountMax]{}; @@ -64,8 +65,12 @@ namespace ams::dmnt { size_t m_module_count{}; size_t m_main_module{}; public: - /* TODO: ifdef for hardware breakpoints. */ - DebugProcess() : m_software_breakpoints(this), m_hardware_breakpoints(this), m_hardware_watchpoints(this), m_step_breakpoints(m_software_breakpoints) { /* ... */ } + DebugProcess() : m_software_breakpoints(this), m_hardware_breakpoints(this), m_hardware_watchpoints(this), m_step_breakpoints(m_software_breakpoints) { + if (svc::IsKernelMesosphere()) { + uint64_t value = 0; + m_use_hardware_single_step = R_SUCCEEDED(::ams::svc::GetInfo(std::addressof(value), ::ams::svc::InfoType_MesosphereMeta, ::ams::svc::InvalidHandle, ::ams::svc::MesosphereMetaInfo_IsSingleStepEnabled)) && value != 0; + } + } ~DebugProcess() { this->Detach(); } svc::Handle GetHandle() const { return m_debug_handle; }