core/debugger: Implement new GDB stub debugger
This commit is contained in:
parent
f6c47df671
commit
fb4b3c127f
27 changed files with 1500 additions and 42 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<Dynarmic::A32::Jit> 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_)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<std::size_t>(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_)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue