From b7ab7e966f7d45823d7c14fb4ea0b23249c2d1d1 Mon Sep 17 00:00:00 2001 From: emoose Date: Sun, 6 Oct 2024 04:47:59 +0100 Subject: [PATCH] [GDBStub] Prevent adding BP if other BP shares same host addr Fixes assert error with BPs set very close to each other (in IDA the failed BP will also show different color) --- src/xenia/debug/gdb/gdbstub.cc | 28 +++++++++++++++++++++------- src/xenia/debug/gdb/gdbstub.h | 2 +- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/xenia/debug/gdb/gdbstub.cc b/src/xenia/debug/gdb/gdbstub.cc index a0c8af71e..310a30439 100644 --- a/src/xenia/debug/gdb/gdbstub.cc +++ b/src/xenia/debug/gdb/gdbstub.cc @@ -692,7 +692,7 @@ std::string GDBStub::GetThreadStateReply(uint32_t thread_id, uint8_t signal) { return "S05"; } -void GDBStub::CreateCodeBreakpoint(uint64_t address) { +bool GDBStub::CreateCodeBreakpoint(uint64_t address) { #ifdef DEBUG debugging::DebugPrint("GDBStub: Adding breakpoint: {:X}\n", address); #endif @@ -705,16 +705,30 @@ void GDBStub::CreateCodeBreakpoint(uint64_t address) { OnBreakpointHit(breakpoint, thread_info); }); + // Fetch list of host addrs used by the new BP + std::vector host_addresses; + breakpoint->ForEachHostAddress([&host_addresses](uintptr_t host_address) { + host_addresses.push_back(host_address); + }); + auto& map = state.code_breakpoints_by_guest_address; - auto it = map.find(breakpoint->guest_address()); - if (it != map.end()) { - // Already exists! - return; + for (auto& kvp : map) { + if (kvp.first == breakpoint->guest_address()) { + return false; // Already exists! + } + for (auto& host_address : host_addresses) { + if (kvp.second->ContainsHostAddress(host_address)) { + return false; // Host addr is in use by another BP already + } + } } + map.emplace(breakpoint->guest_address(), breakpoint.get()); processor_->AddBreakpoint(breakpoint.get()); state.all_breakpoints.emplace_back(std::move(breakpoint)); + + return true; } void GDBStub::DeleteCodeBreakpoint(uint64_t address) { @@ -881,8 +895,8 @@ std::string GDBStub::HandleGDBCommand(const GDBCommand& command) { auto& hex_addr = cmd.data.substr(2); uint64_t addr = std::stoull(hex_addr.substr(0, hex_addr.find(',')), nullptr, 16); - CreateCodeBreakpoint(addr); - return kGdbReplyOK; + + return CreateCodeBreakpoint(addr) ? kGdbReplyOK : kGdbReplyError; }}, // Delete breakpoint {"z", diff --git a/src/xenia/debug/gdb/gdbstub.h b/src/xenia/debug/gdb/gdbstub.h index dc19e83b6..92394c613 100644 --- a/src/xenia/debug/gdb/gdbstub.h +++ b/src/xenia/debug/gdb/gdbstub.h @@ -73,7 +73,7 @@ class GDBStub : public cpu::DebugListener { std::string GetThreadStateReply(uint32_t thread_id, uint8_t signal); - void CreateCodeBreakpoint(uint64_t address); + bool CreateCodeBreakpoint(uint64_t address); void DeleteCodeBreakpoint(uint64_t address); void DeleteCodeBreakpoint(cpu::Breakpoint* breakpoint); cpu::Breakpoint* LookupBreakpointAtAddress(uint64_t address);