From 4935e9b560a380deb3f293c35a4ab558ccf0d56b Mon Sep 17 00:00:00 2001 From: InusualZ Date: Sun, 28 Feb 2021 08:04:50 +0000 Subject: [PATCH] Allow to disable/enable breakpoints Added `ToggleBreakPoint` to both interface BreakPoints/MemChecks. this would allow us to toggle the state of the breakpoint. Also the TMemCheck::is_ranged is not longer serialized to string, since can be deduce by comparing the TMemCheck::start_address and TMemCheck::end_address --- Source/Core/Core/PowerPC/BreakPoints.cpp | 72 ++++++++++++++++++------ Source/Core/Core/PowerPC/BreakPoints.h | 7 +++ Source/Core/Core/PowerPC/PowerPC.cpp | 26 ++++----- 3 files changed, 75 insertions(+), 30 deletions(-) diff --git a/Source/Core/Core/PowerPC/BreakPoints.cpp b/Source/Core/Core/PowerPC/BreakPoints.cpp index b6fa3fc147..9b78b2a490 100644 --- a/Source/Core/Core/PowerPC/BreakPoints.cpp +++ b/Source/Core/Core/PowerPC/BreakPoints.cpp @@ -23,6 +23,12 @@ bool BreakPoints::IsAddressBreakPoint(u32 address) const [address](const auto& bp) { return bp.address == address; }); } +bool BreakPoints::IsBreakPointEnable(u32 address) const +{ + return std::any_of(m_breakpoints.begin(), m_breakpoints.end(), + [address](const auto& bp) { return bp.is_enabled && bp.address == address; }); +} + bool BreakPoints::IsTempBreakPoint(u32 address) const { return std::any_of(m_breakpoints.begin(), m_breakpoints.end(), [address](const auto& bp) { @@ -51,6 +57,8 @@ BreakPoints::TBreakPointsStr BreakPoints::GetStrings() const if (!bp.is_temporary) { std::ostringstream ss; + ss.imbue(std::locale::classic()); + ss << std::hex << bp.address << " " << (bp.is_enabled ? "n" : "") << (bp.log_on_hit ? "l" : "") << (bp.break_on_hit ? "b" : ""); bp_strings.push_back(ss.str()); @@ -67,6 +75,8 @@ void BreakPoints::AddFromStrings(const TBreakPointsStr& bp_strings) TBreakPoint bp; std::string flags; std::istringstream iss(bp_string); + iss.imbue(std::locale::classic()); + iss >> std::hex >> bp.address; iss >> flags; bp.is_enabled = flags.find('n') != flags.npos; @@ -110,6 +120,18 @@ void BreakPoints::Add(u32 address, bool temp, bool break_on_hit, bool log_on_hit JitInterface::InvalidateICache(address, 4, true); } +bool BreakPoints::ToggleBreakPoint(u32 address) +{ + auto iter = std::find_if(m_breakpoints.begin(), m_breakpoints.end(), + [address](const auto& bp) { return bp.address == address; }); + + if (iter == m_breakpoints.end()) + return false; + + iter->is_enabled = !iter->is_enabled; + return true; +} + void BreakPoints::Remove(u32 address) { const auto iter = std::find_if(m_breakpoints.begin(), m_breakpoints.end(), @@ -155,11 +177,11 @@ MemChecks::TMemChecksStr MemChecks::GetStrings() const for (const TMemCheck& mc : m_mem_checks) { std::ostringstream ss; - ss << std::hex << mc.start_address; - ss << " " << (mc.is_ranged ? mc.end_address : mc.start_address) << " " - << (mc.is_ranged ? "n" : "") << (mc.is_break_on_read ? "r" : "") - << (mc.is_break_on_write ? "w" : "") << (mc.log_on_hit ? "l" : "") - << (mc.break_on_hit ? "b" : ""); + ss.imbue(std::locale::classic()); + + ss << std::hex << mc.start_address << " " << mc.end_address << " " << (mc.is_enabled ? "n" : "") + << (mc.is_break_on_read ? "r" : "") << (mc.is_break_on_write ? "w" : "") + << (mc.log_on_hit ? "l" : "") << (mc.break_on_hit ? "b" : ""); mc_strings.push_back(ss.str()); } @@ -171,18 +193,19 @@ void MemChecks::AddFromStrings(const TMemChecksStr& mc_strings) for (const std::string& mc_string : mc_strings) { TMemCheck mc; - std::stringstream ss; - ss << std::hex << mc_string; - ss >> mc.start_address; - mc.is_ranged = mc_string.find('n') != mc_string.npos; - mc.is_break_on_read = mc_string.find('r') != mc_string.npos; - mc.is_break_on_write = mc_string.find('w') != mc_string.npos; - mc.log_on_hit = mc_string.find('l') != mc_string.npos; - mc.break_on_hit = mc_string.find('b') != mc_string.npos; - if (mc.is_ranged) - ss >> mc.end_address; - else - mc.end_address = mc.start_address; + std::istringstream iss(mc_string); + iss.imbue(std::locale::classic()); + + std::string flags; + iss >> std::hex >> mc.start_address >> mc.end_address >> flags; + + mc.is_ranged = mc.start_address != mc.end_address; + mc.is_enabled = flags.find('n') != flags.npos; + mc.is_break_on_read = flags.find('r') != flags.npos; + mc.is_break_on_write = flags.find('w') != flags.npos; + mc.log_on_hit = flags.find('l') != flags.npos; + mc.break_on_hit = flags.find('b') != flags.npos; + Add(mc); } } @@ -203,6 +226,18 @@ void MemChecks::Add(const TMemCheck& memory_check) }); } +bool MemChecks::ToggleBreakPoint(u32 address) +{ + auto iter = std::find_if(m_mem_checks.begin(), m_mem_checks.end(), + [address](const auto& bp) { return bp.start_address == address; }); + + if (iter == m_mem_checks.end()) + return false; + + iter->is_enabled = !iter->is_enabled; + return true; +} + void MemChecks::Remove(u32 address) { const auto iter = @@ -262,6 +297,9 @@ bool MemChecks::OverlapsMemcheck(u32 address, u32 length) const bool TMemCheck::Action(Common::DebugInterface* debug_interface, u32 value, u32 addr, bool write, size_t size, u32 pc) { + if (!is_enabled) + return false; + if ((write && is_break_on_write) || (!write && is_break_on_read)) { if (log_on_hit) diff --git a/Source/Core/Core/PowerPC/BreakPoints.h b/Source/Core/Core/PowerPC/BreakPoints.h index 571427f47d..4d86261af6 100644 --- a/Source/Core/Core/PowerPC/BreakPoints.h +++ b/Source/Core/Core/PowerPC/BreakPoints.h @@ -29,6 +29,7 @@ struct TMemCheck u32 start_address = 0; u32 end_address = 0; + bool is_enabled = true; bool is_ranged = false; bool is_break_on_read = false; @@ -57,6 +58,7 @@ public: // is address breakpoint bool IsAddressBreakPoint(u32 address) const; + bool IsBreakPointEnable(u32 adresss) const; bool IsTempBreakPoint(u32 address) const; bool IsBreakPointBreakOnHit(u32 address) const; bool IsBreakPointLogOnHit(u32 address) const; @@ -66,6 +68,9 @@ public: void Add(u32 address, bool temp = false); void Add(const TBreakPoint& bp); + // Modify Breakpoint + bool ToggleBreakPoint(u32 address); + // Remove Breakpoint void Remove(u32 address); void Clear(); @@ -88,6 +93,8 @@ public: void Add(const TMemCheck& memory_check); + bool ToggleBreakPoint(u32 address); + // memory breakpoint TMemCheck* GetMemCheck(u32 address, size_t size = 1); bool OverlapsMemcheck(u32 address, u32 length) const; diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index 6a20d6a345..4388a6ce5f 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -602,21 +602,21 @@ void CheckExternalExceptions() void CheckBreakPoints() { - if (PowerPC::breakpoints.IsAddressBreakPoint(PC)) + if (!PowerPC::breakpoints.IsBreakPointEnable(PC)) + return; + + if (PowerPC::breakpoints.IsBreakPointBreakOnHit(PC)) + CPU::Break(); + if (PowerPC::breakpoints.IsBreakPointLogOnHit(PC)) { - if (PowerPC::breakpoints.IsBreakPointBreakOnHit(PC)) - CPU::Break(); - if (PowerPC::breakpoints.IsBreakPointLogOnHit(PC)) - { - NOTICE_LOG_FMT(MEMMAP, - "BP {:08x} {}({:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} " - "{:08x}) LR={:08x}", - PC, g_symbolDB.GetDescription(PC), GPR(3), GPR(4), GPR(5), GPR(6), GPR(7), - GPR(8), GPR(9), GPR(10), GPR(11), GPR(12), LR); - } - if (PowerPC::breakpoints.IsTempBreakPoint(PC)) - PowerPC::breakpoints.Remove(PC); + NOTICE_LOG_FMT(MEMMAP, + "BP {:08x} {}({:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} {:08x} " + "{:08x}) LR={:08x}", + PC, g_symbolDB.GetDescription(PC), GPR(3), GPR(4), GPR(5), GPR(6), GPR(7), + GPR(8), GPR(9), GPR(10), GPR(11), GPR(12), LR); } + if (PowerPC::breakpoints.IsTempBreakPoint(PC)) + PowerPC::breakpoints.Remove(PC); } void PowerPCState::SetSR(u32 index, u32 value)