[Debugger] Add unaligned write breakpoints

This commit is contained in:
zilmar 2018-02-02 04:28:08 +11:00
parent deada521bb
commit 076280b9ba
11 changed files with 167 additions and 13 deletions

View File

@ -26,6 +26,10 @@ __interface CDebugger
virtual void FrameDrawn(void) = 0;
virtual void WaitForStep(void) = 0;
virtual bool ExecutionBP(uint32_t address) = 0;
virtual bool WriteBP8(uint32_t address) = 0;
virtual bool WriteBP16(uint32_t address) = 0;
virtual bool WriteBP32(uint32_t address) = 0;
virtual bool WriteBP64(uint32_t address) = 0;
virtual void CPUStepStarted(void) = 0;
virtual void CPUStep(void) = 0;

View File

@ -18,6 +18,7 @@
#include <Project64-core/N64System/Mips/OpcodeName.h>
#include <Project64-core/N64System/Interpreter/InterpreterCPU.h>
#include <Project64-core/Logging.h>
#include <Project64-core/Debugger.h>
#include <float.h>
#include <math.h>
@ -1237,6 +1238,10 @@ void R4300iOp::LWU()
void R4300iOp::SB()
{
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if (HaveWriteBP() && g_Debugger->WriteBP8(Address) && MemoryBreakpoint())
{
return;
}
if (!g_MMU->SB_VAddr(Address, _GPR[m_Opcode.rt].UB[0]))
{
if (HaveDebugger())
@ -1257,6 +1262,10 @@ void R4300iOp::SH()
{
ADDRESS_ERROR_EXCEPTION(Address, false);
}
if (HaveWriteBP() && g_Debugger->WriteBP16(Address) && MemoryBreakpoint())
{
return;
}
if (!g_MMU->SH_VAddr(Address, _GPR[m_Opcode.rt].UHW[0]))
{
if (HaveDebugger())
@ -1275,6 +1284,10 @@ void R4300iOp::SWL()
uint32_t Offset, Address, Value;
Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if (HaveWriteBP() && g_Debugger->WriteBP32(Address) && MemoryBreakpoint())
{
return;
}
Offset = Address & 3;
if (!g_MMU->LW_VAddr((Address & ~3), Value))
@ -1313,6 +1326,10 @@ void R4300iOp::SW()
{
ADDRESS_ERROR_EXCEPTION(Address, false);
}
if (HaveWriteBP() && g_Debugger->WriteBP32(Address) && MemoryBreakpoint())
{
return;
}
if (GenerateLog())
{
Log_SW((*_PROGRAM_COUNTER), Address, _GPR[m_Opcode.rt].UW[0]);
@ -1346,6 +1363,10 @@ void R4300iOp::SDL()
uint64_t Value;
Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if (HaveWriteBP() && g_Debugger->WriteBP64(Address) && MemoryBreakpoint())
{
return;
}
Offset = Address & 7;
if (!g_MMU->LD_VAddr((Address & ~7), Value))
@ -1394,6 +1415,10 @@ void R4300iOp::SDR()
uint64_t Value;
Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if (HaveWriteBP() && g_Debugger->WriteBP64(Address) && MemoryBreakpoint())
{
return;
}
Offset = Address & 7;
if (!g_MMU->LD_VAddr((Address & ~7), Value))
@ -1430,6 +1455,10 @@ void R4300iOp::SWR()
uint32_t Offset, Address, Value;
Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
if (HaveWriteBP() && g_Debugger->WriteBP32(Address) && MemoryBreakpoint())
{
return;
}
Offset = Address & 3;
if (!g_MMU->LW_VAddr((Address & ~3), Value))
@ -1518,6 +1547,10 @@ void R4300iOp::SC()
{
ADDRESS_ERROR_EXCEPTION(Address, false);
}
if (HaveWriteBP() && g_Debugger->WriteBP32(Address) && MemoryBreakpoint())
{
return;
}
Log_SW((*_PROGRAM_COUNTER), Address, _GPR[m_Opcode.rt].UW[0]);
if ((*_LLBit) == 1)
{
@ -1590,6 +1623,10 @@ void R4300iOp::SWC1()
{
ADDRESS_ERROR_EXCEPTION(Address, false);
}
if (HaveWriteBP() && g_Debugger->WriteBP32(Address) && MemoryBreakpoint())
{
return;
}
if (!g_MMU->SW_VAddr(Address, *(uint32_t *)_FPR_S[m_Opcode.ft]))
{
@ -1609,6 +1646,11 @@ void R4300iOp::SDC1()
uint32_t Address = _GPR[m_Opcode.base].UW[0] + (int16_t)m_Opcode.offset;
TEST_COP1_USABLE_EXCEPTION();
if (HaveWriteBP() && g_Debugger->WriteBP64(Address) && MemoryBreakpoint())
{
return;
}
if ((Address & 7) != 0)
{
ADDRESS_ERROR_EXCEPTION(Address, false);
@ -1633,6 +1675,10 @@ void R4300iOp::SD()
{
ADDRESS_ERROR_EXCEPTION(Address, false);
}
if (HaveWriteBP() && g_Debugger->WriteBP64(Address) && MemoryBreakpoint())
{
return;
}
if (!g_MMU->SD_VAddr(Address, _GPR[m_Opcode.rt].UDW))
{
if (HaveDebugger())
@ -2913,3 +2959,16 @@ void R4300iOp::UnknownOpcode()
}
#endif
}
bool R4300iOp::MemoryBreakpoint()
{
g_Settings->SaveBool(Debugger_SteppingOps, true);
g_Debugger->WaitForStep();
if (SkipOp())
{
// Skip command if instructed by the debugger
g_Settings->SaveBool(Debugger_SkipOp, false);
return true;
}
return false;
}

View File

@ -225,6 +225,8 @@ protected:
static void COP1_W();
static void COP1_L();
static bool MemoryBreakpoint();
static Func Jump_Opcode[64];
static Func Jump_Special[64];
static Func Jump_Regimm[32];

View File

@ -25,6 +25,7 @@ bool CDebugSettings::m_bShowTLBMisses = false;
bool CDebugSettings::m_bShowDivByZero = false;
bool CDebugSettings::m_RecordExecutionTimes = false;
bool CDebugSettings::m_HaveExecutionBP = false;
bool CDebugSettings::m_HaveWriteBP = false;
CDebugSettings::CDebugSettings()
{
@ -40,6 +41,7 @@ CDebugSettings::CDebugSettings()
g_Settings->RegisterChangeCB(Debugger_SteppingOps, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
g_Settings->RegisterChangeCB(Debugger_SkipOp, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
g_Settings->RegisterChangeCB(Debugger_HaveExecutionBP, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
g_Settings->RegisterChangeCB(Debugger_WriteBPExists, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
g_Settings->RegisterChangeCB(Debugger_WaitingForStep, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
RefreshSettings();
@ -59,6 +61,7 @@ CDebugSettings::~CDebugSettings()
g_Settings->UnregisterChangeCB(Debugger_SteppingOps, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
g_Settings->UnregisterChangeCB(Debugger_SkipOp, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
g_Settings->UnregisterChangeCB(Debugger_HaveExecutionBP, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
g_Settings->UnregisterChangeCB(Debugger_WriteBPExists, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
g_Settings->UnregisterChangeCB(Debugger_WaitingForStep, this, (CSettings::SettingChangedFunc)StaticRefreshSettings);
}
}
@ -69,11 +72,12 @@ void CDebugSettings::RefreshSettings()
m_bRecordRecompilerAsm = m_HaveDebugger && g_Settings->LoadBool(Debugger_RecordRecompilerAsm);
m_bShowTLBMisses = m_HaveDebugger && g_Settings->LoadBool(Debugger_ShowTLBMisses);
m_bShowDivByZero = m_HaveDebugger && g_Settings->LoadBool(Debugger_ShowDivByZero);
m_RecordExecutionTimes = g_Settings->LoadBool(Debugger_RecordExecutionTimes);
m_Stepping = g_Settings->LoadBool(Debugger_SteppingOps);
m_SkipOp = g_Settings->LoadBool(Debugger_SkipOp);
m_RecordExecutionTimes = m_HaveDebugger && g_Settings->LoadBool(Debugger_RecordExecutionTimes);
m_Stepping = m_HaveDebugger && g_Settings->LoadBool(Debugger_SteppingOps);
m_SkipOp = m_HaveDebugger && g_Settings->LoadBool(Debugger_SkipOp);
m_WaitingForStep = g_Settings->LoadBool(Debugger_WaitingForStep);
m_HaveExecutionBP = g_Settings->LoadBool(Debugger_HaveExecutionBP);
m_HaveExecutionBP = m_HaveDebugger && g_Settings->LoadBool(Debugger_HaveExecutionBP);
m_HaveWriteBP = m_HaveDebugger && g_Settings->LoadBool(Debugger_WriteBPExists);
m_Debugging = m_HaveDebugger && (m_HaveExecutionBP || m_WaitingForStep);
m_Debugging = m_HaveDebugger && (m_HaveExecutionBP || m_WaitingForStep || m_HaveWriteBP);
}

View File

@ -28,6 +28,7 @@ public:
static inline bool bShowDivByZero(void) { return m_bShowDivByZero; }
static inline bool bRecordExecutionTimes(void) { return m_RecordExecutionTimes; }
static inline bool HaveExecutionBP(void) { return m_HaveExecutionBP; }
static inline bool HaveWriteBP(void) { return m_HaveWriteBP; }
private:
static void StaticRefreshSettings(CDebugSettings * _this)
@ -47,6 +48,7 @@ private:
static bool m_bShowDivByZero;
static bool m_RecordExecutionTimes;
static bool m_HaveExecutionBP;
static bool m_HaveWriteBP;
static int32_t m_RefCount;
static bool m_Registered;

View File

@ -232,6 +232,7 @@ enum SettingID
Debugger_SteppingOps,
Debugger_SkipOp,
Debugger_HaveExecutionBP,
Debugger_WriteBPExists,
Debugger_WaitingForStep,
//Trace

View File

@ -317,6 +317,7 @@ void CSettings::AddHowToHandleSetting(const char * BaseDirectory)
AddHandler(Debugger_SteppingOps, new CSettingTypeTempBool(false));
AddHandler(Debugger_SkipOp, new CSettingTypeTempBool(false));
AddHandler(Debugger_HaveExecutionBP, new CSettingTypeTempBool(false));
AddHandler(Debugger_WriteBPExists, new CSettingTypeTempBool(false));
AddHandler(Debugger_WaitingForStep, new CSettingTypeTempBool(false));
AddHandler(Debugger_DebugLanguage, new CSettingTypeApplication("Debugger", "Debug Language", false));
AddHandler(Debugger_ShowDivByZero, new CSettingTypeApplication("Debugger", "Show Div by zero", false));

View File

@ -36,6 +36,11 @@ bool CBreakpoints::WBPAdd(uint32_t address)
if (!WriteBPExists8(address))
{
m_WriteMem.insert(breakpoints_t::value_type(address, false));
UpdateAlignedWriteBP();
if (!HaveWriteBP())
{
g_Settings->SaveBool(Debugger_WriteBPExists, true);
}
return true;
}
return false;
@ -71,6 +76,11 @@ void CBreakpoints::WBPRemove(uint32_t address)
if (itr != m_WriteMem.end())
{
m_WriteMem.erase(itr);
UpdateAlignedWriteBP();
if (m_Execution.size() == 0)
{
g_Settings->SaveBool(Debugger_WriteBPExists, false);
}
}
}
@ -119,6 +129,8 @@ void CBreakpoints::RBPClear()
void CBreakpoints::WBPClear()
{
m_WriteMem.clear();
UpdateAlignedWriteBP();
g_Settings->SaveBool(Debugger_WriteBPExists, false);
}
void CBreakpoints::EBPClear()
@ -153,6 +165,36 @@ CBreakpoints::BPSTATE CBreakpoints::WriteBPExists8(uint32_t address)
return BP_NOT_SET;
}
CBreakpoints::BPSTATE CBreakpoints::WriteBPExists16(uint32_t address)
{
breakpoints_t::const_iterator itr = m_WriteMem16.find(address);
if (itr != m_WriteMem16.end())
{
return BP_SET;
}
return BP_NOT_SET;
}
CBreakpoints::BPSTATE CBreakpoints::WriteBPExists32(uint32_t address)
{
breakpoints_t::const_iterator itr = m_WriteMem16.find(address);
if (itr != m_WriteMem16.end())
{
return BP_SET;
}
return BP_NOT_SET;
}
CBreakpoints::BPSTATE CBreakpoints::WriteBPExists64(uint32_t address)
{
breakpoints_t::const_iterator itr = m_WriteMem16.find(address);
if (itr != m_WriteMem16.end())
{
return BP_SET;
}
return BP_NOT_SET;
}
CBreakpoints::BPSTATE CBreakpoints::ExecutionBPExists(uint32_t address, bool bRemoveTemp)
{
breakpoints_t::const_iterator itr = m_Execution.find(address);
@ -170,3 +212,17 @@ CBreakpoints::BPSTATE CBreakpoints::ExecutionBPExists(uint32_t address, bool bRe
}
return BP_NOT_SET;
}
void CBreakpoints::UpdateAlignedWriteBP()
{
m_WriteMem16.clear();
m_WriteMem32.clear();
m_WriteMem64.clear();
for (breakpoints_t::const_iterator itr = m_WriteMem.begin(); itr != m_WriteMem.end(); itr++)
{
m_WriteMem16.insert(breakpoints_t::value_type((itr->first & ~0x1), false));
m_WriteMem32.insert(breakpoints_t::value_type((itr->first & ~0x3), false));
m_WriteMem64.insert(breakpoints_t::value_type((itr->first & ~0x7), false));
}
}

View File

@ -34,6 +34,9 @@ public:
BPSTATE ReadBPExists(uint32_t address);
BPSTATE WriteBPExists8(uint32_t address);
BPSTATE WriteBPExists16(uint32_t address);
BPSTATE WriteBPExists32(uint32_t address);
BPSTATE WriteBPExists64(uint32_t address);
BPSTATE ExecutionBPExists(uint32_t address, bool bRemoveTemp = false);
bool RBPAdd(uint32_t address);
@ -54,7 +57,9 @@ public:
void BPClear();
private:
void UpdateAlignedWriteBP(void);
breakpoints_t m_ReadMem;
breakpoints_t m_WriteMem;
breakpoints_t m_WriteMem, m_WriteMem16, m_WriteMem32, m_WriteMem64;
breakpoints_t m_Execution;
};

View File

@ -414,11 +414,6 @@ void CDebuggerUI::CPUStepStarted()
{
m_ScriptSystem->HookCPUWrite()->InvokeByParamInRange(memoryAddress);
if (m_Breakpoints->WriteBPExists8(memoryAddress))
{
goto breakpoint_hit;
}
// Catch cart -> rdram dma
if (memoryAddress == 0xA460000C) // PI_WR_LEN_REG
{
@ -539,3 +534,24 @@ bool CDebuggerUI::ExecutionBP(uint32_t address)
{
return m_Breakpoints != NULL && m_Breakpoints->ExecutionBPExists(address, true) != CBreakpoints::BP_NOT_SET;
}
bool CDebuggerUI::WriteBP8(uint32_t address)
{
return m_Breakpoints != NULL && m_Breakpoints->WriteBPExists8(address) != CBreakpoints::BP_NOT_SET;
}
bool CDebuggerUI::WriteBP16(uint32_t address)
{
return m_Breakpoints != NULL && m_Breakpoints->WriteBPExists16(address) != CBreakpoints::BP_NOT_SET;
}
bool CDebuggerUI::WriteBP32(uint32_t address)
{
return m_Breakpoints != NULL && m_Breakpoints->WriteBPExists32(address) != CBreakpoints::BP_NOT_SET;
}
bool CDebuggerUI::WriteBP64(uint32_t address)
{
return m_Breakpoints != NULL && m_Breakpoints->WriteBPExists64(address) != CBreakpoints::BP_NOT_SET;
}

View File

@ -59,6 +59,10 @@ public:
void OpenDMALogWindow(void);
bool ExecutionBP(uint32_t address);
bool WriteBP8(uint32_t address);
bool WriteBP16(uint32_t address);
bool WriteBP32(uint32_t address);
bool WriteBP64(uint32_t address);
void WaitForStep(void);
CBreakpoints* Breakpoints();