diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/unicorn/arm_unicorn.cpp | 2 | ||||
| -rw-r--r-- | src/core/core.cpp | 5 | ||||
| -rw-r--r-- | src/core/core.h | 11 | ||||
| -rw-r--r-- | src/core/gdbstub/gdbstub.cpp | 10 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_debug.ui | 7 |
5 files changed, 26 insertions, 9 deletions
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp index 4c11f35a4..6bc349460 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) { | |||
| 203 | } | 203 | } |
| 204 | Kernel::Thread* thread = Kernel::GetCurrentThread(); | 204 | Kernel::Thread* thread = Kernel::GetCurrentThread(); |
| 205 | SaveContext(thread->context); | 205 | SaveContext(thread->context); |
| 206 | if (last_bkpt_hit || (num_instructions == 1)) { | 206 | if (last_bkpt_hit || GDBStub::GetCpuStepFlag()) { |
| 207 | last_bkpt_hit = false; | 207 | last_bkpt_hit = false; |
| 208 | GDBStub::Break(); | 208 | GDBStub::Break(); |
| 209 | GDBStub::SendTrap(thread, 5); | 209 | GDBStub::SendTrap(thread, 5); |
diff --git a/src/core/core.cpp b/src/core/core.cpp index e01c45cdd..085ba68d0 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -62,7 +62,6 @@ System::ResultStatus System::RunLoop(bool tight_loop) { | |||
| 62 | // execute. Otherwise, get out of the loop function. | 62 | // execute. Otherwise, get out of the loop function. |
| 63 | if (GDBStub::GetCpuHaltFlag()) { | 63 | if (GDBStub::GetCpuHaltFlag()) { |
| 64 | if (GDBStub::GetCpuStepFlag()) { | 64 | if (GDBStub::GetCpuStepFlag()) { |
| 65 | GDBStub::SetCpuStepFlag(false); | ||
| 66 | tight_loop = false; | 65 | tight_loop = false; |
| 67 | } else { | 66 | } else { |
| 68 | return ResultStatus::Success; | 67 | return ResultStatus::Success; |
| @@ -78,6 +77,10 @@ System::ResultStatus System::RunLoop(bool tight_loop) { | |||
| 78 | } | 77 | } |
| 79 | } | 78 | } |
| 80 | 79 | ||
| 80 | if (GDBStub::IsServerEnabled()) { | ||
| 81 | GDBStub::SetCpuStepFlag(false); | ||
| 82 | } | ||
| 83 | |||
| 81 | return status; | 84 | return status; |
| 82 | } | 85 | } |
| 83 | 86 | ||
diff --git a/src/core/core.h b/src/core/core.h index a3be88aa8..c8ca4b247 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -82,6 +82,17 @@ public: | |||
| 82 | */ | 82 | */ |
| 83 | ResultStatus SingleStep(); | 83 | ResultStatus SingleStep(); |
| 84 | 84 | ||
| 85 | /** | ||
| 86 | * Invalidate the CPU instruction caches | ||
| 87 | * This function should only be used by GDB Stub to support breakpoints, memory updates and | ||
| 88 | * step/continue commands. | ||
| 89 | */ | ||
| 90 | void InvalidateCpuInstructionCaches() { | ||
| 91 | for (auto& cpu : cpu_cores) { | ||
| 92 | cpu->ArmInterface().ClearInstructionCache(); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 85 | /// Shutdown the emulated system. | 96 | /// Shutdown the emulated system. |
| 86 | void Shutdown(); | 97 | void Shutdown(); |
| 87 | 98 | ||
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 884e64e99..332e5c3d0 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp | |||
| @@ -173,6 +173,7 @@ struct Breakpoint { | |||
| 173 | bool active; | 173 | bool active; |
| 174 | VAddr addr; | 174 | VAddr addr; |
| 175 | u64 len; | 175 | u64 len; |
| 176 | std::array<u8, 4> inst; | ||
| 176 | }; | 177 | }; |
| 177 | 178 | ||
| 178 | using BreakpointMap = std::map<VAddr, Breakpoint>; | 179 | using BreakpointMap = std::map<VAddr, Breakpoint>; |
| @@ -453,6 +454,8 @@ static void RemoveBreakpoint(BreakpointType type, VAddr addr) { | |||
| 453 | 454 | ||
| 454 | LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}", | 455 | LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}", |
| 455 | bp->second.len, bp->second.addr, static_cast<int>(type)); | 456 | bp->second.len, bp->second.addr, static_cast<int>(type)); |
| 457 | Memory::WriteBlock(bp->second.addr, bp->second.inst.data(), bp->second.inst.size()); | ||
| 458 | Core::System::GetInstance().InvalidateCpuInstructionCaches(); | ||
| 456 | p.erase(addr); | 459 | p.erase(addr); |
| 457 | } | 460 | } |
| 458 | 461 | ||
| @@ -937,6 +940,7 @@ static void WriteMemory() { | |||
| 937 | 940 | ||
| 938 | GdbHexToMem(data.data(), len_pos + 1, len); | 941 | GdbHexToMem(data.data(), len_pos + 1, len); |
| 939 | Memory::WriteBlock(addr, data.data(), len); | 942 | Memory::WriteBlock(addr, data.data(), len); |
| 943 | Core::System::GetInstance().InvalidateCpuInstructionCaches(); | ||
| 940 | SendReply("OK"); | 944 | SendReply("OK"); |
| 941 | } | 945 | } |
| 942 | 946 | ||
| @@ -956,6 +960,7 @@ static void Step() { | |||
| 956 | step_loop = true; | 960 | step_loop = true; |
| 957 | halt_loop = true; | 961 | halt_loop = true; |
| 958 | send_trap = true; | 962 | send_trap = true; |
| 963 | Core::System::GetInstance().InvalidateCpuInstructionCaches(); | ||
| 959 | } | 964 | } |
| 960 | 965 | ||
| 961 | /// Tell the CPU if we hit a memory breakpoint. | 966 | /// Tell the CPU if we hit a memory breakpoint. |
| @@ -972,6 +977,7 @@ static void Continue() { | |||
| 972 | memory_break = false; | 977 | memory_break = false; |
| 973 | step_loop = false; | 978 | step_loop = false; |
| 974 | halt_loop = false; | 979 | halt_loop = false; |
| 980 | Core::System::GetInstance().InvalidateCpuInstructionCaches(); | ||
| 975 | } | 981 | } |
| 976 | 982 | ||
| 977 | /** | 983 | /** |
| @@ -988,6 +994,10 @@ static bool CommitBreakpoint(BreakpointType type, VAddr addr, u64 len) { | |||
| 988 | breakpoint.active = true; | 994 | breakpoint.active = true; |
| 989 | breakpoint.addr = addr; | 995 | breakpoint.addr = addr; |
| 990 | breakpoint.len = len; | 996 | breakpoint.len = len; |
| 997 | Memory::ReadBlock(addr, breakpoint.inst.data(), breakpoint.inst.size()); | ||
| 998 | static constexpr std::array<u8, 4> btrap{{0xd4, 0x20, 0x7d, 0x0}}; | ||
| 999 | Memory::WriteBlock(addr, btrap.data(), btrap.size()); | ||
| 1000 | Core::System::GetInstance().InvalidateCpuInstructionCaches(); | ||
| 991 | p.insert({addr, breakpoint}); | 1001 | p.insert({addr, breakpoint}); |
| 992 | 1002 | ||
| 993 | LOG_DEBUG(Debug_GDBStub, "gdb: added {} breakpoint: {:016X} bytes at {:016X}", | 1003 | LOG_DEBUG(Debug_GDBStub, "gdb: added {} breakpoint: {:016X} bytes at {:016X}", |
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 118e91cf1..5ae7276bd 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui | |||
| @@ -23,13 +23,6 @@ | |||
| 23 | </property> | 23 | </property> |
| 24 | <layout class="QVBoxLayout" name="verticalLayout_3"> | 24 | <layout class="QVBoxLayout" name="verticalLayout_3"> |
| 25 | <item> | 25 | <item> |
| 26 | <widget class="QLabel" name="label_1"> | ||
| 27 | <property name="text"> | ||
| 28 | <string>The GDB Stub only works correctly when the CPU JIT is off.</string> | ||
| 29 | </property> | ||
| 30 | </widget> | ||
| 31 | </item> | ||
| 32 | <item> | ||
| 33 | <layout class="QHBoxLayout" name="horizontalLayout_1"> | 26 | <layout class="QHBoxLayout" name="horizontalLayout_1"> |
| 34 | <item> | 27 | <item> |
| 35 | <widget class="QCheckBox" name="toggle_gdbstub"> | 28 | <widget class="QCheckBox" name="toggle_gdbstub"> |