GDBStub works with both Unicorn and Dynarmic now (#941)
* GDBStub works with both Unicorn and Dynarmic now * Tidy up
This commit is contained in:
parent
e218d79cc2
commit
e2b74f6354
5 changed files with 26 additions and 9 deletions
|
@ -203,7 +203,7 @@ void ARM_Unicorn::ExecuteInstructions(int num_instructions) {
|
||||||
}
|
}
|
||||||
Kernel::Thread* thread = Kernel::GetCurrentThread();
|
Kernel::Thread* thread = Kernel::GetCurrentThread();
|
||||||
SaveContext(thread->context);
|
SaveContext(thread->context);
|
||||||
if (last_bkpt_hit || (num_instructions == 1)) {
|
if (last_bkpt_hit || GDBStub::GetCpuStepFlag()) {
|
||||||
last_bkpt_hit = false;
|
last_bkpt_hit = false;
|
||||||
GDBStub::Break();
|
GDBStub::Break();
|
||||||
GDBStub::SendTrap(thread, 5);
|
GDBStub::SendTrap(thread, 5);
|
||||||
|
|
|
@ -62,7 +62,6 @@ System::ResultStatus System::RunLoop(bool tight_loop) {
|
||||||
// execute. Otherwise, get out of the loop function.
|
// execute. Otherwise, get out of the loop function.
|
||||||
if (GDBStub::GetCpuHaltFlag()) {
|
if (GDBStub::GetCpuHaltFlag()) {
|
||||||
if (GDBStub::GetCpuStepFlag()) {
|
if (GDBStub::GetCpuStepFlag()) {
|
||||||
GDBStub::SetCpuStepFlag(false);
|
|
||||||
tight_loop = false;
|
tight_loop = false;
|
||||||
} else {
|
} else {
|
||||||
return ResultStatus::Success;
|
return ResultStatus::Success;
|
||||||
|
@ -78,6 +77,10 @@ System::ResultStatus System::RunLoop(bool tight_loop) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GDBStub::IsServerEnabled()) {
|
||||||
|
GDBStub::SetCpuStepFlag(false);
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,17 @@ public:
|
||||||
*/
|
*/
|
||||||
ResultStatus SingleStep();
|
ResultStatus SingleStep();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate the CPU instruction caches
|
||||||
|
* This function should only be used by GDB Stub to support breakpoints, memory updates and
|
||||||
|
* step/continue commands.
|
||||||
|
*/
|
||||||
|
void InvalidateCpuInstructionCaches() {
|
||||||
|
for (auto& cpu : cpu_cores) {
|
||||||
|
cpu->ArmInterface().ClearInstructionCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Shutdown the emulated system.
|
/// Shutdown the emulated system.
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,7 @@ struct Breakpoint {
|
||||||
bool active;
|
bool active;
|
||||||
VAddr addr;
|
VAddr addr;
|
||||||
u64 len;
|
u64 len;
|
||||||
|
std::array<u8, 4> inst;
|
||||||
};
|
};
|
||||||
|
|
||||||
using BreakpointMap = std::map<VAddr, Breakpoint>;
|
using BreakpointMap = std::map<VAddr, Breakpoint>;
|
||||||
|
@ -453,6 +454,8 @@ static void RemoveBreakpoint(BreakpointType type, VAddr addr) {
|
||||||
|
|
||||||
LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}",
|
LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}",
|
||||||
bp->second.len, bp->second.addr, static_cast<int>(type));
|
bp->second.len, bp->second.addr, static_cast<int>(type));
|
||||||
|
Memory::WriteBlock(bp->second.addr, bp->second.inst.data(), bp->second.inst.size());
|
||||||
|
Core::System::GetInstance().InvalidateCpuInstructionCaches();
|
||||||
p.erase(addr);
|
p.erase(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -937,6 +940,7 @@ static void WriteMemory() {
|
||||||
|
|
||||||
GdbHexToMem(data.data(), len_pos + 1, len);
|
GdbHexToMem(data.data(), len_pos + 1, len);
|
||||||
Memory::WriteBlock(addr, data.data(), len);
|
Memory::WriteBlock(addr, data.data(), len);
|
||||||
|
Core::System::GetInstance().InvalidateCpuInstructionCaches();
|
||||||
SendReply("OK");
|
SendReply("OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -956,6 +960,7 @@ static void Step() {
|
||||||
step_loop = true;
|
step_loop = true;
|
||||||
halt_loop = true;
|
halt_loop = true;
|
||||||
send_trap = true;
|
send_trap = true;
|
||||||
|
Core::System::GetInstance().InvalidateCpuInstructionCaches();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tell the CPU if we hit a memory breakpoint.
|
/// Tell the CPU if we hit a memory breakpoint.
|
||||||
|
@ -972,6 +977,7 @@ static void Continue() {
|
||||||
memory_break = false;
|
memory_break = false;
|
||||||
step_loop = false;
|
step_loop = false;
|
||||||
halt_loop = false;
|
halt_loop = false;
|
||||||
|
Core::System::GetInstance().InvalidateCpuInstructionCaches();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -988,6 +994,10 @@ static bool CommitBreakpoint(BreakpointType type, VAddr addr, u64 len) {
|
||||||
breakpoint.active = true;
|
breakpoint.active = true;
|
||||||
breakpoint.addr = addr;
|
breakpoint.addr = addr;
|
||||||
breakpoint.len = len;
|
breakpoint.len = len;
|
||||||
|
Memory::ReadBlock(addr, breakpoint.inst.data(), breakpoint.inst.size());
|
||||||
|
static constexpr std::array<u8, 4> btrap{{0xd4, 0x20, 0x7d, 0x0}};
|
||||||
|
Memory::WriteBlock(addr, btrap.data(), btrap.size());
|
||||||
|
Core::System::GetInstance().InvalidateCpuInstructionCaches();
|
||||||
p.insert({addr, breakpoint});
|
p.insert({addr, breakpoint});
|
||||||
|
|
||||||
LOG_DEBUG(Debug_GDBStub, "gdb: added {} breakpoint: {:016X} bytes at {:016X}",
|
LOG_DEBUG(Debug_GDBStub, "gdb: added {} breakpoint: {:016X} bytes at {:016X}",
|
||||||
|
|
|
@ -22,13 +22,6 @@
|
||||||
<string>GDB</string>
|
<string>GDB</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_1">
|
|
||||||
<property name="text">
|
|
||||||
<string>The GDB Stub only works correctly when the CPU JIT is off.</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_1">
|
<layout class="QHBoxLayout" name="horizontalLayout_1">
|
||||||
<item>
|
<item>
|
||||||
|
|
Loading…
Reference in a new issue