mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-04 03:46:42 +01:00
Merge pull request #8940 from RenaKunisaki/master
add Break On Hit and Log On Hit for instruction breakpoints
This commit is contained in:
commit
76b955e090
@ -30,6 +30,19 @@ bool BreakPoints::IsTempBreakPoint(u32 address) const
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BreakPoints::IsBreakPointBreakOnHit(u32 address) const
|
||||||
|
{
|
||||||
|
return std::any_of(m_breakpoints.begin(), m_breakpoints.end(), [address](const auto& bp) {
|
||||||
|
return bp.address == address && bp.break_on_hit;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BreakPoints::IsBreakPointLogOnHit(u32 address) const
|
||||||
|
{
|
||||||
|
return std::any_of(m_breakpoints.begin(), m_breakpoints.end(),
|
||||||
|
[address](const auto& bp) { return bp.address == address && bp.log_on_hit; });
|
||||||
|
}
|
||||||
|
|
||||||
BreakPoints::TBreakPointsStr BreakPoints::GetStrings() const
|
BreakPoints::TBreakPointsStr BreakPoints::GetStrings() const
|
||||||
{
|
{
|
||||||
TBreakPointsStr bp_strings;
|
TBreakPointsStr bp_strings;
|
||||||
@ -38,7 +51,8 @@ BreakPoints::TBreakPointsStr BreakPoints::GetStrings() const
|
|||||||
if (!bp.is_temporary)
|
if (!bp.is_temporary)
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
ss << std::hex << bp.address << " " << (bp.is_enabled ? "n" : "");
|
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());
|
bp_strings.push_back(ss.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,6 +69,8 @@ void BreakPoints::AddFromStrings(const TBreakPointsStr& bp_strings)
|
|||||||
ss << std::hex << bp_string;
|
ss << std::hex << bp_string;
|
||||||
ss >> bp.address;
|
ss >> bp.address;
|
||||||
bp.is_enabled = bp_string.find('n') != bp_string.npos;
|
bp.is_enabled = bp_string.find('n') != bp_string.npos;
|
||||||
|
bp.log_on_hit = bp_string.find('l') != bp_string.npos;
|
||||||
|
bp.break_on_hit = bp_string.find('b') != bp_string.npos;
|
||||||
bp.is_temporary = false;
|
bp.is_temporary = false;
|
||||||
Add(bp);
|
Add(bp);
|
||||||
}
|
}
|
||||||
@ -71,6 +87,11 @@ void BreakPoints::Add(const TBreakPoint& bp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BreakPoints::Add(u32 address, bool temp)
|
void BreakPoints::Add(u32 address, bool temp)
|
||||||
|
{
|
||||||
|
BreakPoints::Add(address, temp, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakPoints::Add(u32 address, bool temp, bool break_on_hit, bool log_on_hit)
|
||||||
{
|
{
|
||||||
// Only add new addresses
|
// Only add new addresses
|
||||||
if (IsAddressBreakPoint(address))
|
if (IsAddressBreakPoint(address))
|
||||||
@ -79,6 +100,8 @@ void BreakPoints::Add(u32 address, bool temp)
|
|||||||
TBreakPoint bp; // breakpoint settings
|
TBreakPoint bp; // breakpoint settings
|
||||||
bp.is_enabled = true;
|
bp.is_enabled = true;
|
||||||
bp.is_temporary = temp;
|
bp.is_temporary = temp;
|
||||||
|
bp.break_on_hit = break_on_hit;
|
||||||
|
bp.log_on_hit = log_on_hit;
|
||||||
bp.address = address;
|
bp.address = address;
|
||||||
|
|
||||||
m_breakpoints.push_back(bp);
|
m_breakpoints.push_back(bp);
|
||||||
@ -154,7 +177,7 @@ void MemChecks::AddFromStrings(const TMemChecksStr& mc_strings)
|
|||||||
mc.is_break_on_read = mc_string.find('r') != 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.is_break_on_write = mc_string.find('w') != mc_string.npos;
|
||||||
mc.log_on_hit = mc_string.find('l') != mc_string.npos;
|
mc.log_on_hit = mc_string.find('l') != mc_string.npos;
|
||||||
mc.break_on_hit = mc_string.find('p') != mc_string.npos;
|
mc.break_on_hit = mc_string.find('b') != mc_string.npos;
|
||||||
if (mc.is_ranged)
|
if (mc.is_ranged)
|
||||||
ss >> mc.end_address;
|
ss >> mc.end_address;
|
||||||
else
|
else
|
||||||
|
@ -20,6 +20,8 @@ struct TBreakPoint
|
|||||||
u32 address = 0;
|
u32 address = 0;
|
||||||
bool is_enabled = false;
|
bool is_enabled = false;
|
||||||
bool is_temporary = false;
|
bool is_temporary = false;
|
||||||
|
bool log_on_hit = false;
|
||||||
|
bool break_on_hit = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TMemCheck
|
struct TMemCheck
|
||||||
@ -56,8 +58,11 @@ public:
|
|||||||
// is address breakpoint
|
// is address breakpoint
|
||||||
bool IsAddressBreakPoint(u32 address) const;
|
bool IsAddressBreakPoint(u32 address) const;
|
||||||
bool IsTempBreakPoint(u32 address) const;
|
bool IsTempBreakPoint(u32 address) const;
|
||||||
|
bool IsBreakPointBreakOnHit(u32 address) const;
|
||||||
|
bool IsBreakPointLogOnHit(u32 address) const;
|
||||||
|
|
||||||
// Add BreakPoint
|
// Add BreakPoint
|
||||||
|
void Add(u32 address, bool temp, bool break_on_hit, bool log_on_hit);
|
||||||
void Add(u32 address, bool temp = false);
|
void Add(u32 address, bool temp = false);
|
||||||
void Add(const TBreakPoint& bp);
|
void Add(const TBreakPoint& bp);
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "Core/PowerPC/Interpreter/Interpreter.h"
|
#include "Core/PowerPC/Interpreter/Interpreter.h"
|
||||||
#include "Core/PowerPC/JitInterface.h"
|
#include "Core/PowerPC/JitInterface.h"
|
||||||
#include "Core/PowerPC/MMU.h"
|
#include "Core/PowerPC/MMU.h"
|
||||||
|
#include "Core/PowerPC/PPCSymbolDB.h"
|
||||||
|
|
||||||
namespace PowerPC
|
namespace PowerPC
|
||||||
{
|
{
|
||||||
@ -603,7 +604,14 @@ void CheckBreakPoints()
|
|||||||
{
|
{
|
||||||
if (PowerPC::breakpoints.IsAddressBreakPoint(PC))
|
if (PowerPC::breakpoints.IsAddressBreakPoint(PC))
|
||||||
{
|
{
|
||||||
|
if (PowerPC::breakpoints.IsBreakPointBreakOnHit(PC))
|
||||||
CPU::Break();
|
CPU::Break();
|
||||||
|
if (PowerPC::breakpoints.IsBreakPointLogOnHit(PC))
|
||||||
|
{
|
||||||
|
NOTICE_LOG(MEMMAP, "BP %08x %s(%08x %08x %08x %08x %08x %08x %08x %08x %08x %08x) LR=%08x",
|
||||||
|
PC, g_symbolDB.GetDescription(PC).c_str(), 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))
|
if (PowerPC::breakpoints.IsTempBreakPoint(PC))
|
||||||
PowerPC::breakpoints.Remove(PC);
|
PowerPC::breakpoints.Remove(PC);
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,15 @@ void BreakpointWidget::Update()
|
|||||||
m_table->setItem(i, 3,
|
m_table->setItem(i, 3,
|
||||||
create_item(QStringLiteral("%1").arg(bp.address, 8, 16, QLatin1Char('0'))));
|
create_item(QStringLiteral("%1").arg(bp.address, 8, 16, QLatin1Char('0'))));
|
||||||
|
|
||||||
m_table->setItem(i, 4, create_item());
|
QString flags;
|
||||||
|
|
||||||
|
if (bp.break_on_hit)
|
||||||
|
flags.append(QLatin1Char{'b'});
|
||||||
|
|
||||||
|
if (bp.log_on_hit)
|
||||||
|
flags.append(QLatin1Char{'l'});
|
||||||
|
|
||||||
|
m_table->setItem(i, 4, create_item(flags));
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -308,7 +316,12 @@ void BreakpointWidget::OnSave()
|
|||||||
|
|
||||||
void BreakpointWidget::AddBP(u32 addr)
|
void BreakpointWidget::AddBP(u32 addr)
|
||||||
{
|
{
|
||||||
PowerPC::breakpoints.Add(addr);
|
AddBP(addr, false, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BreakpointWidget::AddBP(u32 addr, bool temp, bool break_on_hit, bool log_on_hit)
|
||||||
|
{
|
||||||
|
PowerPC::breakpoints.Add(addr, temp, break_on_hit, log_on_hit);
|
||||||
|
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ public:
|
|||||||
~BreakpointWidget();
|
~BreakpointWidget();
|
||||||
|
|
||||||
void AddBP(u32 addr);
|
void AddBP(u32 addr);
|
||||||
|
void AddBP(u32 addr, bool temp, bool break_on_hit, bool log_on_hit);
|
||||||
void AddAddressMBP(u32 addr, bool on_read = true, bool on_write = true, bool do_log = true,
|
void AddAddressMBP(u32 addr, bool on_read = true, bool on_write = true, bool do_log = true,
|
||||||
bool do_break = true);
|
bool do_break = true);
|
||||||
void AddRangedMBP(u32 from, u32 to, bool do_read = true, bool do_write = true, bool do_log = true,
|
void AddRangedMBP(u32 from, u32 to, bool do_read = true, bool do_write = true, bool do_log = true,
|
||||||
|
@ -62,12 +62,12 @@ void NewBreakpointDialog::CreateWidgets()
|
|||||||
m_memory_on_read_and_write = new QRadioButton(tr("Read or Write"));
|
m_memory_on_read_and_write = new QRadioButton(tr("Read or Write"));
|
||||||
m_memory_on_write->setChecked(true);
|
m_memory_on_write->setChecked(true);
|
||||||
// i18n: This is a selectable action when adding a breakpoint
|
// i18n: This is a selectable action when adding a breakpoint
|
||||||
m_memory_do_log = new QRadioButton(tr("Write to Log"));
|
m_do_log = new QRadioButton(tr("Write to Log"));
|
||||||
// i18n: This is a selectable action when adding a breakpoint
|
// i18n: This is a selectable action when adding a breakpoint
|
||||||
m_memory_do_break = new QRadioButton(tr("Break"));
|
m_do_break = new QRadioButton(tr("Break"));
|
||||||
// i18n: This is a selectable action when adding a breakpoint
|
// i18n: This is a selectable action when adding a breakpoint
|
||||||
m_memory_do_log_and_break = new QRadioButton(tr("Write to Log and Break"));
|
m_do_log_and_break = new QRadioButton(tr("Write to Log and Break"));
|
||||||
m_memory_do_log_and_break->setChecked(true);
|
m_do_log_and_break->setChecked(true);
|
||||||
|
|
||||||
auto* memory_layout = new QGridLayout;
|
auto* memory_layout = new QGridLayout;
|
||||||
m_memory_box->setLayout(memory_layout);
|
m_memory_box->setLayout(memory_layout);
|
||||||
@ -89,10 +89,9 @@ void NewBreakpointDialog::CreateWidgets()
|
|||||||
QGroupBox* action_box = new QGroupBox(tr("Action"));
|
QGroupBox* action_box = new QGroupBox(tr("Action"));
|
||||||
auto* action_layout = new QHBoxLayout;
|
auto* action_layout = new QHBoxLayout;
|
||||||
action_box->setLayout(action_layout);
|
action_box->setLayout(action_layout);
|
||||||
memory_layout->addWidget(action_box, 3, 0, 1, -1);
|
action_layout->addWidget(m_do_log);
|
||||||
action_layout->addWidget(m_memory_do_log);
|
action_layout->addWidget(m_do_break);
|
||||||
action_layout->addWidget(m_memory_do_break);
|
action_layout->addWidget(m_do_log_and_break);
|
||||||
action_layout->addWidget(m_memory_do_log_and_break);
|
|
||||||
|
|
||||||
auto* layout = new QVBoxLayout;
|
auto* layout = new QVBoxLayout;
|
||||||
|
|
||||||
@ -100,6 +99,7 @@ void NewBreakpointDialog::CreateWidgets()
|
|||||||
layout->addWidget(m_instruction_box);
|
layout->addWidget(m_instruction_box);
|
||||||
layout->addWidget(m_memory_bp);
|
layout->addWidget(m_memory_bp);
|
||||||
layout->addWidget(m_memory_box);
|
layout->addWidget(m_memory_box);
|
||||||
|
layout->addWidget(action_box);
|
||||||
layout->addWidget(m_buttons);
|
layout->addWidget(m_buttons);
|
||||||
|
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
@ -150,8 +150,8 @@ void NewBreakpointDialog::accept()
|
|||||||
bool on_write = m_memory_on_write->isChecked() || m_memory_on_read_and_write->isChecked();
|
bool on_write = m_memory_on_write->isChecked() || m_memory_on_read_and_write->isChecked();
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
bool do_log = m_memory_do_log->isChecked() || m_memory_do_log_and_break->isChecked();
|
bool do_log = m_do_log->isChecked() || m_do_log_and_break->isChecked();
|
||||||
bool do_break = m_memory_do_break->isChecked() || m_memory_do_log_and_break->isChecked();
|
bool do_break = m_do_break->isChecked() || m_do_log_and_break->isChecked();
|
||||||
|
|
||||||
bool good;
|
bool good;
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ void NewBreakpointDialog::accept()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_parent->AddBP(address);
|
m_parent->AddBP(address, false, do_break, do_log);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -48,9 +48,11 @@ private:
|
|||||||
QRadioButton* m_memory_on_read;
|
QRadioButton* m_memory_on_read;
|
||||||
QRadioButton* m_memory_on_read_and_write;
|
QRadioButton* m_memory_on_read_and_write;
|
||||||
QRadioButton* m_memory_on_write;
|
QRadioButton* m_memory_on_write;
|
||||||
QRadioButton* m_memory_do_log;
|
|
||||||
QRadioButton* m_memory_do_break;
|
// Action
|
||||||
QRadioButton* m_memory_do_log_and_break;
|
QRadioButton* m_do_log;
|
||||||
|
QRadioButton* m_do_break;
|
||||||
|
QRadioButton* m_do_log_and_break;
|
||||||
|
|
||||||
QDialogButtonBox* m_buttons;
|
QDialogButtonBox* m_buttons;
|
||||||
BreakpointWidget* m_parent;
|
BreakpointWidget* m_parent;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user