From fb4b3c127f7c390358d7f4cadd2f58de116fec48 Mon Sep 17 00:00:00 2001 From: Liam Date: Mon, 30 May 2022 19:35:01 -0400 Subject: core/debugger: Implement new GDB stub debugger --- src/core/arm/arm_interface.cpp | 5 +++++ src/core/arm/arm_interface.h | 5 ++--- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 35 +++++++++++++++++++++++++------ src/core/arm/dynarmic/arm_dynarmic_32.h | 4 +++- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 32 +++++++++++++++++++++++----- src/core/arm/dynarmic/arm_dynarmic_64.h | 4 +++- 6 files changed, 69 insertions(+), 16 deletions(-) (limited to 'src/core/arm') diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp index c347e7ea7..1310f72bf 100644 --- a/src/core/arm/arm_interface.cpp +++ b/src/core/arm/arm_interface.cpp @@ -9,6 +9,7 @@ #include "core/arm/arm_interface.h" #include "core/arm/symbols.h" #include "core/core.h" +#include "core/debugger/debugger.h" #include "core/hle/kernel/k_process.h" #include "core/loader/loader.h" #include "core/memory.h" @@ -88,4 +89,8 @@ void ARM_Interface::LogBacktrace() const { } } +bool ARM_Interface::ShouldStep() const { + return system.DebuggerEnabled() && system.GetDebugger().IsStepping(); +} + } // namespace Core diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index 8ce973a77..7842c626b 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -66,9 +66,6 @@ public: /// Runs the CPU until an event happens virtual void Run() = 0; - /// Step CPU by one instruction - virtual void Step() = 0; - /// Clear all instruction cache virtual void ClearInstructionCache() = 0; @@ -194,6 +191,8 @@ public: void LogBacktrace() const; + bool ShouldStep() const; + protected: /// System context that this ARM interface is running under. System& system; diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 781a77f6f..894c1c527 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -17,6 +17,8 @@ #include "core/arm/dynarmic/arm_exclusive_monitor.h" #include "core/core.h" #include "core/core_timing.h" +#include "core/debugger/debugger.h" +#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/svc.h" #include "core/memory.h" @@ -26,6 +28,7 @@ using namespace Common::Literals; constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2; constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; +constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4; class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { public: @@ -78,11 +81,16 @@ public: } void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { + if (parent.system.DebuggerEnabled()) { + parent.breakpoint_pc = pc; + parent.jit.load()->HaltExecution(breakpoint); + return; + } + parent.LogBacktrace(); LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})", exception, pc, MemoryReadCode(pc), parent.IsInThumbMode()); - UNIMPLEMENTED(); } void CallSVC(u32 swi) override { @@ -234,20 +242,35 @@ std::shared_ptr ARM_Dynarmic_32::MakeJit(Common::PageTable* void ARM_Dynarmic_32::Run() { while (true) { - const auto hr = jit.load()->Run(); + const auto hr = ShouldStep() ? jit.load()->Step() : jit.load()->Run(); if (Has(hr, svc_call)) { Kernel::Svc::Call(system, svc_swi); } + + // Check to see if breakpoint is triggered. + // Recheck step condition in case stop is no longer desired. + Kernel::KThread* current_thread = system.Kernel().GetCurrentEmuThread(); + if (Has(hr, breakpoint)) { + jit.load()->Regs()[15] = breakpoint_pc; + + if (system.GetDebugger().NotifyThreadStopped(current_thread)) { + current_thread->RequestSuspend(Kernel::SuspendType::Debug); + } + break; + } + if (ShouldStep()) { + // When stepping, this should be the only thread running. + ASSERT(system.GetDebugger().NotifyThreadStopped(current_thread)); + current_thread->RequestSuspend(Kernel::SuspendType::Debug); + break; + } + if (Has(hr, break_loop) || !uses_wall_clock) { break; } } } -void ARM_Dynarmic_32::Step() { - jit.load()->Step(); -} - ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_) diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h index abfe76644..0557d5940 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.h +++ b/src/core/arm/dynarmic/arm_dynarmic_32.h @@ -42,7 +42,6 @@ public: u32 GetPSTATE() const override; void SetPSTATE(u32 pstate) override; void Run() override; - void Step() override; VAddr GetTlsAddress() const override; void SetTlsAddress(VAddr address) override; void SetTPIDR_EL0(u64 value) override; @@ -95,6 +94,9 @@ private: // SVC callback u32 svc_swi{}; + + // Debug restart address + u32 breakpoint_pc{}; }; } // namespace Core diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 1b1334598..1f596cfef 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -15,6 +15,7 @@ #include "core/arm/dynarmic/arm_exclusive_monitor.h" #include "core/core.h" #include "core/core_timing.h" +#include "core/debugger/debugger.h" #include "core/hardware_properties.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/svc.h" @@ -27,6 +28,7 @@ using namespace Common::Literals; constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2; constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; +constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4; class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { public: @@ -119,8 +121,13 @@ public: case Dynarmic::A64::Exception::SendEventLocal: case Dynarmic::A64::Exception::Yield: return; - case Dynarmic::A64::Exception::Breakpoint: default: + if (parent.system.DebuggerEnabled()) { + parent.breakpoint_pc = pc; + parent.jit.load()->HaltExecution(breakpoint); + return; + } + parent.LogBacktrace(); ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", static_cast(exception), pc, MemoryReadCode(pc)); @@ -299,16 +306,31 @@ void ARM_Dynarmic_64::Run() { if (Has(hr, svc_call)) { Kernel::Svc::Call(system, svc_swi); } + + // Check to see if breakpoint is triggered. + // Recheck step condition in case stop is no longer desired. + Kernel::KThread* current_thread = system.Kernel().GetCurrentEmuThread(); + if (Has(hr, breakpoint)) { + jit.load()->SetPC(breakpoint_pc); + + if (system.GetDebugger().NotifyThreadStopped(current_thread)) { + current_thread->RequestSuspend(Kernel::SuspendType::Debug); + } + break; + } + if (ShouldStep()) { + // When stepping, this should be the only thread running. + ASSERT(system.GetDebugger().NotifyThreadStopped(current_thread)); + current_thread->RequestSuspend(Kernel::SuspendType::Debug); + break; + } + if (Has(hr, break_loop) || !uses_wall_clock) { break; } } } -void ARM_Dynarmic_64::Step() { - jit.load()->Step(); -} - ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_) diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h index 01a7e4dad..aa7054e0c 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.h +++ b/src/core/arm/dynarmic/arm_dynarmic_64.h @@ -40,7 +40,6 @@ public: u32 GetPSTATE() const override; void SetPSTATE(u32 pstate) override; void Run() override; - void Step() override; VAddr GetTlsAddress() const override; void SetTlsAddress(VAddr address) override; void SetTPIDR_EL0(u64 value) override; @@ -88,6 +87,9 @@ private: // SVC callback u32 svc_swi{}; + + // Debug restart address + u64 breakpoint_pc{}; }; } // namespace Core -- cgit v1.2.3