Mesen-SX/Core/BreakpointManager.cpp

149 lines
3.9 KiB
C++
Raw Normal View History

2019-03-01 20:27:49 -05:00
#include "stdafx.h"
#include "BreakpointManager.h"
#include "DebugTypes.h"
#include "Debugger.h"
#include "Breakpoint.h"
2019-07-30 22:34:52 -04:00
#include "DebugUtilities.h"
2019-03-01 20:27:49 -05:00
#include "ExpressionEvaluator.h"
#include "EventManager.h"
2019-03-01 20:27:49 -05:00
2020-12-19 23:30:09 +03:00
BreakpointManager::BreakpointManager(Debugger* debugger, CpuType cpuType, IEventManager* eventManager)
2019-03-01 20:27:49 -05:00
{
_debugger = debugger;
_cpuType = cpuType;
_hasBreakpoint = false;
_eventManager = eventManager ? eventManager : debugger->GetEventManager(cpuType).get();
2019-03-01 20:27:49 -05:00
}
void BreakpointManager::SetBreakpoints(Breakpoint breakpoints[], uint32_t count)
{
_hasBreakpoint = false;
2020-12-19 23:30:09 +03:00
for (int i = 0; i < BreakpointManager::BreakpointTypeCount; i++)
{
_breakpoints[i].clear();
_rpnList[i].clear();
_hasBreakpointType[i] = false;
2019-03-01 20:27:49 -05:00
}
_bpExpEval.reset(new ExpressionEvaluator(_debugger, _cpuType));
2020-12-19 23:30:09 +03:00
for (uint32_t j = 0; j < count; j++)
{
Breakpoint& bp = breakpoints[j];
for (int i = 0; i < BreakpointManager::BreakpointTypeCount; i++)
{
2019-03-01 20:27:49 -05:00
BreakpointType bpType = (BreakpointType)i;
2020-12-19 23:30:09 +03:00
if ((bp.IsMarked() || bp.IsEnabled()) && bp.HasBreakpointType(bpType))
{
CpuType cpuType = bp.GetCpuType();
2020-12-19 23:30:09 +03:00
if (_cpuType != cpuType)
{
continue;
}
int curIndex = _breakpoints[i].size();
_breakpoints[i].insert(std::make_pair(curIndex, bp));
2019-03-01 20:27:49 -05:00
2020-12-19 23:30:09 +03:00
if (bp.HasCondition())
{
2019-03-01 20:27:49 -05:00
bool success = true;
ExpressionData data = _bpExpEval->GetRpnList(bp.GetCondition(), success);
_rpnList[i].insert(std::make_pair(curIndex, success ? data : ExpressionData()));
2020-12-19 23:30:09 +03:00
}
else
{
_rpnList[i].insert(std::make_pair(curIndex, ExpressionData()));
2019-03-01 20:27:49 -05:00
}
2020-12-19 23:30:09 +03:00
_hasBreakpoint = true;
_hasBreakpointType[i] = true;
2019-03-01 20:27:49 -05:00
}
}
}
}
void BreakpointManager::GetBreakpoints(Breakpoint* breakpoints, int& execs, int& reads, int& writes)
{
execs = _breakpoints[static_cast<int>(BreakpointType::Execute)].size();
reads = _breakpoints[static_cast<int>(BreakpointType::Read)].size();
writes = _breakpoints[static_cast<int>(BreakpointType::Write)].size();
2020-12-19 23:30:09 +03:00
if (breakpoints == NULL)
{
return;
}
int offset = 0;
2020-12-19 23:30:09 +03:00
for (auto it = _breakpoints[static_cast<int>(BreakpointType::Execute)].cbegin(); it != _breakpoints[static_cast<int>(
BreakpointType::Execute)].cend(); it++)
{
breakpoints[offset++] = it->second;
}
2020-12-19 23:30:09 +03:00
for (auto it = _breakpoints[static_cast<int>(BreakpointType::Read)].cbegin(); it != _breakpoints[static_cast<int>(
BreakpointType::Read)].cend(); it++)
{
breakpoints[offset++] = it->second;
}
2020-12-19 23:30:09 +03:00
for (auto it = _breakpoints[static_cast<int>(BreakpointType::Write)].cbegin(); it != _breakpoints[static_cast<int>(
BreakpointType::Write)].cend(); it++)
{
breakpoints[offset++] = it->second;
}
}
2019-03-01 20:27:49 -05:00
BreakpointType BreakpointManager::GetBreakpointType(MemoryOperationType type)
{
2020-12-19 23:30:09 +03:00
switch (type)
{
default:
case MemoryOperationType::ExecOperand:
case MemoryOperationType::ExecOpCode:
return BreakpointType::Execute;
case MemoryOperationType::DmaRead:
case MemoryOperationType::Read:
return BreakpointType::Read;
case MemoryOperationType::DmaWrite:
case MemoryOperationType::Write:
return BreakpointType::Write;
2019-03-01 20:27:49 -05:00
}
}
2020-12-19 23:30:09 +03:00
int BreakpointManager::InternalCheckBreakpoint(MemoryOperationInfo operationInfo, AddressInfo& address)
2019-03-01 20:27:49 -05:00
{
BreakpointType type = GetBreakpointType(operationInfo.Type);
2020-12-19 23:30:09 +03:00
if (!_hasBreakpointType[(int)type])
{
return -1;
2019-03-01 20:27:49 -05:00
}
DebugState state;
_debugger->GetState(state, false);
2019-03-01 20:27:49 -05:00
EvalResultType resultType;
2020-12-19 23:30:09 +03:00
unordered_map<int, Breakpoint>& breakpoints = _breakpoints[(int)type];
for (auto it = breakpoints.begin(); it != breakpoints.end(); it++)
{
if (it->second.Matches(operationInfo.Address, address))
{
if (!it->second.HasCondition() || _bpExpEval->Evaluate(_rpnList[(int)type][it->first], state, resultType,
operationInfo))
{
if (it->second.IsMarked())
{
_eventManager->AddEvent(DebugEventType::Breakpoint, operationInfo, it->first);
}
2020-12-19 23:30:09 +03:00
if (it->second.IsEnabled())
{
return it->first;
}
2019-03-01 20:27:49 -05:00
}
}
}
return -1;
2019-03-01 20:27:49 -05:00
}