diff options
| author | 2022-05-30 19:35:01 -0400 | |
|---|---|---|
| committer | 2022-06-01 00:01:25 -0400 | |
| commit | fb4b3c127f7c390358d7f4cadd2f58de116fec48 (patch) | |
| tree | e2588a859d364a32be0cd9e0401a345c6492d1a7 /src/core/arm/dynarmic | |
| parent | Merge pull request #8368 from german77/seventimes (diff) | |
| download | yuzu-fb4b3c127f7c390358d7f4cadd2f58de116fec48.tar.gz yuzu-fb4b3c127f7c390358d7f4cadd2f58de116fec48.tar.xz yuzu-fb4b3c127f7c390358d7f4cadd2f58de116fec48.zip | |
core/debugger: Implement new GDB stub debugger
Diffstat (limited to 'src/core/arm/dynarmic')
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 35 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.h | 4 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.cpp | 32 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.h | 4 |
4 files changed, 62 insertions, 13 deletions
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 @@ | |||
| 17 | #include "core/arm/dynarmic/arm_exclusive_monitor.h" | 17 | #include "core/arm/dynarmic/arm_exclusive_monitor.h" |
| 18 | #include "core/core.h" | 18 | #include "core/core.h" |
| 19 | #include "core/core_timing.h" | 19 | #include "core/core_timing.h" |
| 20 | #include "core/debugger/debugger.h" | ||
| 21 | #include "core/hle/kernel/k_process.h" | ||
| 20 | #include "core/hle/kernel/svc.h" | 22 | #include "core/hle/kernel/svc.h" |
| 21 | #include "core/memory.h" | 23 | #include "core/memory.h" |
| 22 | 24 | ||
| @@ -26,6 +28,7 @@ using namespace Common::Literals; | |||
| 26 | 28 | ||
| 27 | constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2; | 29 | constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2; |
| 28 | constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; | 30 | constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; |
| 31 | constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4; | ||
| 29 | 32 | ||
| 30 | class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { | 33 | class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { |
| 31 | public: | 34 | public: |
| @@ -78,11 +81,16 @@ public: | |||
| 78 | } | 81 | } |
| 79 | 82 | ||
| 80 | void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { | 83 | void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { |
| 84 | if (parent.system.DebuggerEnabled()) { | ||
| 85 | parent.breakpoint_pc = pc; | ||
| 86 | parent.jit.load()->HaltExecution(breakpoint); | ||
| 87 | return; | ||
| 88 | } | ||
| 89 | |||
| 81 | parent.LogBacktrace(); | 90 | parent.LogBacktrace(); |
| 82 | LOG_CRITICAL(Core_ARM, | 91 | LOG_CRITICAL(Core_ARM, |
| 83 | "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})", | 92 | "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})", |
| 84 | exception, pc, MemoryReadCode(pc), parent.IsInThumbMode()); | 93 | exception, pc, MemoryReadCode(pc), parent.IsInThumbMode()); |
| 85 | UNIMPLEMENTED(); | ||
| 86 | } | 94 | } |
| 87 | 95 | ||
| 88 | void CallSVC(u32 swi) override { | 96 | void CallSVC(u32 swi) override { |
| @@ -234,20 +242,35 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 234 | 242 | ||
| 235 | void ARM_Dynarmic_32::Run() { | 243 | void ARM_Dynarmic_32::Run() { |
| 236 | while (true) { | 244 | while (true) { |
| 237 | const auto hr = jit.load()->Run(); | 245 | const auto hr = ShouldStep() ? jit.load()->Step() : jit.load()->Run(); |
| 238 | if (Has(hr, svc_call)) { | 246 | if (Has(hr, svc_call)) { |
| 239 | Kernel::Svc::Call(system, svc_swi); | 247 | Kernel::Svc::Call(system, svc_swi); |
| 240 | } | 248 | } |
| 249 | |||
| 250 | // Check to see if breakpoint is triggered. | ||
| 251 | // Recheck step condition in case stop is no longer desired. | ||
| 252 | Kernel::KThread* current_thread = system.Kernel().GetCurrentEmuThread(); | ||
| 253 | if (Has(hr, breakpoint)) { | ||
| 254 | jit.load()->Regs()[15] = breakpoint_pc; | ||
| 255 | |||
| 256 | if (system.GetDebugger().NotifyThreadStopped(current_thread)) { | ||
| 257 | current_thread->RequestSuspend(Kernel::SuspendType::Debug); | ||
| 258 | } | ||
| 259 | break; | ||
| 260 | } | ||
| 261 | if (ShouldStep()) { | ||
| 262 | // When stepping, this should be the only thread running. | ||
| 263 | ASSERT(system.GetDebugger().NotifyThreadStopped(current_thread)); | ||
| 264 | current_thread->RequestSuspend(Kernel::SuspendType::Debug); | ||
| 265 | break; | ||
| 266 | } | ||
| 267 | |||
| 241 | if (Has(hr, break_loop) || !uses_wall_clock) { | 268 | if (Has(hr, break_loop) || !uses_wall_clock) { |
| 242 | break; | 269 | break; |
| 243 | } | 270 | } |
| 244 | } | 271 | } |
| 245 | } | 272 | } |
| 246 | 273 | ||
| 247 | void ARM_Dynarmic_32::Step() { | ||
| 248 | jit.load()->Step(); | ||
| 249 | } | ||
| 250 | |||
| 251 | ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, | 274 | ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, |
| 252 | bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, | 275 | bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, |
| 253 | std::size_t core_index_) | 276 | 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: | |||
| 42 | u32 GetPSTATE() const override; | 42 | u32 GetPSTATE() const override; |
| 43 | void SetPSTATE(u32 pstate) override; | 43 | void SetPSTATE(u32 pstate) override; |
| 44 | void Run() override; | 44 | void Run() override; |
| 45 | void Step() override; | ||
| 46 | VAddr GetTlsAddress() const override; | 45 | VAddr GetTlsAddress() const override; |
| 47 | void SetTlsAddress(VAddr address) override; | 46 | void SetTlsAddress(VAddr address) override; |
| 48 | void SetTPIDR_EL0(u64 value) override; | 47 | void SetTPIDR_EL0(u64 value) override; |
| @@ -95,6 +94,9 @@ private: | |||
| 95 | 94 | ||
| 96 | // SVC callback | 95 | // SVC callback |
| 97 | u32 svc_swi{}; | 96 | u32 svc_swi{}; |
| 97 | |||
| 98 | // Debug restart address | ||
| 99 | u32 breakpoint_pc{}; | ||
| 98 | }; | 100 | }; |
| 99 | 101 | ||
| 100 | } // namespace Core | 102 | } // 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 @@ | |||
| 15 | #include "core/arm/dynarmic/arm_exclusive_monitor.h" | 15 | #include "core/arm/dynarmic/arm_exclusive_monitor.h" |
| 16 | #include "core/core.h" | 16 | #include "core/core.h" |
| 17 | #include "core/core_timing.h" | 17 | #include "core/core_timing.h" |
| 18 | #include "core/debugger/debugger.h" | ||
| 18 | #include "core/hardware_properties.h" | 19 | #include "core/hardware_properties.h" |
| 19 | #include "core/hle/kernel/k_process.h" | 20 | #include "core/hle/kernel/k_process.h" |
| 20 | #include "core/hle/kernel/svc.h" | 21 | #include "core/hle/kernel/svc.h" |
| @@ -27,6 +28,7 @@ using namespace Common::Literals; | |||
| 27 | 28 | ||
| 28 | constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2; | 29 | constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2; |
| 29 | constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; | 30 | constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; |
| 31 | constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4; | ||
| 30 | 32 | ||
| 31 | class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { | 33 | class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { |
| 32 | public: | 34 | public: |
| @@ -119,8 +121,13 @@ public: | |||
| 119 | case Dynarmic::A64::Exception::SendEventLocal: | 121 | case Dynarmic::A64::Exception::SendEventLocal: |
| 120 | case Dynarmic::A64::Exception::Yield: | 122 | case Dynarmic::A64::Exception::Yield: |
| 121 | return; | 123 | return; |
| 122 | case Dynarmic::A64::Exception::Breakpoint: | ||
| 123 | default: | 124 | default: |
| 125 | if (parent.system.DebuggerEnabled()) { | ||
| 126 | parent.breakpoint_pc = pc; | ||
| 127 | parent.jit.load()->HaltExecution(breakpoint); | ||
| 128 | return; | ||
| 129 | } | ||
| 130 | |||
| 124 | parent.LogBacktrace(); | 131 | parent.LogBacktrace(); |
| 125 | ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", | 132 | ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", |
| 126 | static_cast<std::size_t>(exception), pc, MemoryReadCode(pc)); | 133 | static_cast<std::size_t>(exception), pc, MemoryReadCode(pc)); |
| @@ -299,16 +306,31 @@ void ARM_Dynarmic_64::Run() { | |||
| 299 | if (Has(hr, svc_call)) { | 306 | if (Has(hr, svc_call)) { |
| 300 | Kernel::Svc::Call(system, svc_swi); | 307 | Kernel::Svc::Call(system, svc_swi); |
| 301 | } | 308 | } |
| 309 | |||
| 310 | // Check to see if breakpoint is triggered. | ||
| 311 | // Recheck step condition in case stop is no longer desired. | ||
| 312 | Kernel::KThread* current_thread = system.Kernel().GetCurrentEmuThread(); | ||
| 313 | if (Has(hr, breakpoint)) { | ||
| 314 | jit.load()->SetPC(breakpoint_pc); | ||
| 315 | |||
| 316 | if (system.GetDebugger().NotifyThreadStopped(current_thread)) { | ||
| 317 | current_thread->RequestSuspend(Kernel::SuspendType::Debug); | ||
| 318 | } | ||
| 319 | break; | ||
| 320 | } | ||
| 321 | if (ShouldStep()) { | ||
| 322 | // When stepping, this should be the only thread running. | ||
| 323 | ASSERT(system.GetDebugger().NotifyThreadStopped(current_thread)); | ||
| 324 | current_thread->RequestSuspend(Kernel::SuspendType::Debug); | ||
| 325 | break; | ||
| 326 | } | ||
| 327 | |||
| 302 | if (Has(hr, break_loop) || !uses_wall_clock) { | 328 | if (Has(hr, break_loop) || !uses_wall_clock) { |
| 303 | break; | 329 | break; |
| 304 | } | 330 | } |
| 305 | } | 331 | } |
| 306 | } | 332 | } |
| 307 | 333 | ||
| 308 | void ARM_Dynarmic_64::Step() { | ||
| 309 | jit.load()->Step(); | ||
| 310 | } | ||
| 311 | |||
| 312 | ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, | 334 | ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, |
| 313 | bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, | 335 | bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, |
| 314 | std::size_t core_index_) | 336 | 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: | |||
| 40 | u32 GetPSTATE() const override; | 40 | u32 GetPSTATE() const override; |
| 41 | void SetPSTATE(u32 pstate) override; | 41 | void SetPSTATE(u32 pstate) override; |
| 42 | void Run() override; | 42 | void Run() override; |
| 43 | void Step() override; | ||
| 44 | VAddr GetTlsAddress() const override; | 43 | VAddr GetTlsAddress() const override; |
| 45 | void SetTlsAddress(VAddr address) override; | 44 | void SetTlsAddress(VAddr address) override; |
| 46 | void SetTPIDR_EL0(u64 value) override; | 45 | void SetTPIDR_EL0(u64 value) override; |
| @@ -88,6 +87,9 @@ private: | |||
| 88 | 87 | ||
| 89 | // SVC callback | 88 | // SVC callback |
| 90 | u32 svc_swi{}; | 89 | u32 svc_swi{}; |
| 90 | |||
| 91 | // Debug restart address | ||
| 92 | u64 breakpoint_pc{}; | ||
| 91 | }; | 93 | }; |
| 92 | 94 | ||
| 93 | } // namespace Core | 95 | } // namespace Core |