From 350870a498867a76b62ebeaac67f561c68d5d8f9 Mon Sep 17 00:00:00 2001 From: Jarek Syrylak Date: Mon, 6 Aug 2018 13:36:55 +0100 Subject: [PATCH] GDBStub works with both Unicorn and Dynarmic now --- src/core/arm/dynarmic/arm_dynarmic.cpp | 13 +++++++++++++ src/core/arm/unicorn/arm_unicorn.cpp | 2 +- src/core/core.cpp | 6 +++++- src/core/gdbstub/gdbstub.cpp | 19 +++++++++++++++++++ src/core/gdbstub/gdbstub.h | 6 ++++++ src/yuzu/configuration/configure_debug.ui | 7 ------- 6 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index ceb3f76835..18faf23226 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -10,6 +10,7 @@ #include "core/arm/dynarmic/arm_dynarmic.h" #include "core/core.h" #include "core/core_timing.h" +#include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/svc.h" #include "core/memory.h" @@ -131,10 +132,22 @@ std::unique_ptr ARM_Dynarmic::MakeJit() const { void ARM_Dynarmic::Run() { ASSERT(Memory::GetCurrentPageTable() == current_page_table); + if (GDBStub::IsServerEnabled()) { + if (!GDBStub::GetInstCacheValidity()) { + ClearInstructionCache(); + } + } + jit->Run(); } void ARM_Dynarmic::Step() { + if (GDBStub::IsServerEnabled()) { + if (!GDBStub::GetInstCacheValidity()) { + ClearInstructionCache(); + } + } + cb->InterpreterFallback(jit->GetPC(), 1); } diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp index 4c11f35a49..6bc3494601 100644 --- a/src/core/arm/unicorn/arm_unicorn.cpp +++ b/src/core/arm/unicorn/arm_unicorn.cpp @@ -203,7 +203,7 @@ void ARM_Unicorn::ExecuteInstructions(int num_instructions) { } Kernel::Thread* thread = Kernel::GetCurrentThread(); SaveContext(thread->context); - if (last_bkpt_hit || (num_instructions == 1)) { + if (last_bkpt_hit || GDBStub::GetCpuStepFlag()) { last_bkpt_hit = false; GDBStub::Break(); GDBStub::SendTrap(thread, 5); diff --git a/src/core/core.cpp b/src/core/core.cpp index e01c45cddc..4ac22e44f6 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -62,7 +62,6 @@ System::ResultStatus System::RunLoop(bool tight_loop) { // execute. Otherwise, get out of the loop function. if (GDBStub::GetCpuHaltFlag()) { if (GDBStub::GetCpuStepFlag()) { - GDBStub::SetCpuStepFlag(false); tight_loop = false; } else { return ResultStatus::Success; @@ -78,6 +77,11 @@ System::ResultStatus System::RunLoop(bool tight_loop) { } } + if (GDBStub::IsServerEnabled()) { + GDBStub::SetCpuStepFlag(false); + GDBStub::SetInstCacheValidity(true); + } + return status; } diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 884e64e994..ba7efb2c01 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -160,6 +160,7 @@ u16 gdbstub_port = 24689; bool halt_loop = true; bool step_loop = false; bool send_trap = false; +static bool inst_cache_valid = true; // If set to false, the server will never be started and no // gdbstub-related functions will be executed. @@ -173,6 +174,7 @@ struct Breakpoint { bool active; VAddr addr; u64 len; + u8 inst[4]; }; using BreakpointMap = std::map; @@ -453,6 +455,8 @@ static void RemoveBreakpoint(BreakpointType type, VAddr addr) { LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}", bp->second.len, bp->second.addr, static_cast(type)); + Memory::WriteBlock(bp->second.addr, bp->second.inst, 4); + GDBStub::SetInstCacheValidity(false); p.erase(addr); } @@ -937,6 +941,7 @@ static void WriteMemory() { GdbHexToMem(data.data(), len_pos + 1, len); Memory::WriteBlock(addr, data.data(), len); + GDBStub::SetInstCacheValidity(false); SendReply("OK"); } @@ -956,6 +961,7 @@ static void Step() { step_loop = true; halt_loop = true; send_trap = true; + GDBStub::SetInstCacheValidity(false); } /// Tell the CPU if we hit a memory breakpoint. @@ -972,6 +978,7 @@ static void Continue() { memory_break = false; step_loop = false; halt_loop = false; + GDBStub::SetInstCacheValidity(false); } /** @@ -988,6 +995,10 @@ static bool CommitBreakpoint(BreakpointType type, VAddr addr, u64 len) { breakpoint.active = true; breakpoint.addr = addr; breakpoint.len = len; + Memory::ReadBlock(addr, breakpoint.inst, 4); + static const u8 btrap[] = {0xd4, 0x20, 0x7d, 0x00}; + Memory::WriteBlock(addr, btrap, 4); + GDBStub::SetInstCacheValidity(false); p.insert({addr, breakpoint}); LOG_DEBUG(Debug_GDBStub, "gdb: added {} breakpoint: {:016X} bytes at {:016X}", @@ -1305,4 +1316,12 @@ void SendTrap(Kernel::Thread* thread, int trap) { send_trap = false; } } + +void SetInstCacheValidity(bool validity) { + inst_cache_valid = validity; +} + +bool GetInstCacheValidity() { + return inst_cache_valid; +} }; // namespace GDBStub diff --git a/src/core/gdbstub/gdbstub.h b/src/core/gdbstub/gdbstub.h index 5a36524b2e..0e516a4af8 100644 --- a/src/core/gdbstub/gdbstub.h +++ b/src/core/gdbstub/gdbstub.h @@ -104,4 +104,10 @@ void SetCpuStepFlag(bool is_step); * @param trap Trap no. */ void SendTrap(Kernel::Thread* thread, int trap); + +/// Set instruction cache validity. +void SetInstCacheValidity(bool validity); + +/// Get instruction cache validity. +bool GetInstCacheValidity(); } // namespace GDBStub diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 118e91cf1b..5ae7276bd2 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui @@ -22,13 +22,6 @@ GDB - - - - The GDB Stub only works correctly when the CPU JIT is off. - - -