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"
|
2019-10-18 20:09:08 -04:00
|
|
|
#include "EventManager.h"
|
2019-03-01 20:27:49 -05:00
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
BreakpointManager::BreakpointManager(Debugger *debugger, CpuType cpuType, IEventManager* eventManager)
|
2019-03-01 20:27:49 -05:00
|
|
|
{
|
|
|
|
_debugger = debugger;
|
2019-10-11 16:07:30 -04:00
|
|
|
_cpuType = cpuType;
|
|
|
|
_hasBreakpoint = false;
|
2020-06-18 00:58:22 -04:00
|
|
|
_eventManager = eventManager ? eventManager : debugger->GetEventManager(cpuType).get();
|
2019-03-01 20:27:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void BreakpointManager::SetBreakpoints(Breakpoint breakpoints[], uint32_t count)
|
|
|
|
{
|
2019-10-11 16:07:30 -04:00
|
|
|
_hasBreakpoint = false;
|
2021-03-10 11:13:28 -05:00
|
|
|
for(int i = 0; i < BreakpointManager::BreakpointTypeCount; i++) {
|
2019-10-11 16:07:30 -04:00
|
|
|
_breakpoints[i].clear();
|
|
|
|
_rpnList[i].clear();
|
|
|
|
_hasBreakpointType[i] = false;
|
2019-03-01 20:27:49 -05:00
|
|
|
}
|
|
|
|
|
2019-10-11 16:07:30 -04:00
|
|
|
_bpExpEval.reset(new ExpressionEvaluator(_debugger, _cpuType));
|
2019-04-07 14:38:22 -04:00
|
|
|
|
2021-03-10 11:13:28 -05: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;
|
2021-03-10 11:13:28 -05:00
|
|
|
if((bp.IsMarked() || bp.IsEnabled()) && bp.HasBreakpointType(bpType)) {
|
2019-07-25 22:22:09 -04:00
|
|
|
CpuType cpuType = bp.GetCpuType();
|
2021-03-10 11:13:28 -05:00
|
|
|
if(_cpuType != cpuType) {
|
2019-10-11 16:07:30 -04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-10-29 02:19:23 +03:00
|
|
|
int curIndex = _breakpoints[i].size();
|
|
|
|
_breakpoints[i].insert(std::make_pair(curIndex, bp));
|
2019-03-01 20:27:49 -05:00
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(bp.HasCondition()) {
|
2019-03-01 20:27:49 -05:00
|
|
|
bool success = true;
|
2019-10-11 16:07:30 -04:00
|
|
|
ExpressionData data = _bpExpEval->GetRpnList(bp.GetCondition(), success);
|
2020-10-29 02:19:23 +03:00
|
|
|
_rpnList[i].insert(std::make_pair(curIndex, success ? data : ExpressionData()));
|
2021-03-10 11:13:28 -05:00
|
|
|
} else {
|
2020-10-29 02:19:23 +03:00
|
|
|
_rpnList[i].insert(std::make_pair(curIndex, ExpressionData()));
|
2019-03-01 20:27:49 -05:00
|
|
|
}
|
2021-03-10 11:13:28 -05:00
|
|
|
|
2019-10-11 16:07:30 -04:00
|
|
|
_hasBreakpoint = true;
|
|
|
|
_hasBreakpointType[i] = true;
|
2019-03-01 20:27:49 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-01 16:52:30 +03: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();
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if (breakpoints == NULL) {
|
2020-11-01 16:52:30 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int offset = 0;
|
2021-03-10 11:13:28 -05:00
|
|
|
for (auto it = _breakpoints[static_cast<int>(BreakpointType::Execute)].cbegin(); it != _breakpoints[static_cast<int>(BreakpointType::Execute)].cend(); it++) {
|
2020-11-01 16:52:30 +03:00
|
|
|
breakpoints[offset++] = it->second;
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
for (auto it = _breakpoints[static_cast<int>(BreakpointType::Read)].cbegin(); it != _breakpoints[static_cast<int>(BreakpointType::Read)].cend(); it++) {
|
2020-11-01 16:52:30 +03:00
|
|
|
breakpoints[offset++] = it->second;
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
for (auto it = _breakpoints[static_cast<int>(BreakpointType::Write)].cbegin(); it != _breakpoints[static_cast<int>(BreakpointType::Write)].cend(); it++) {
|
2020-11-01 16:52:30 +03:00
|
|
|
breakpoints[offset++] = it->second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-01 20:27:49 -05:00
|
|
|
BreakpointType BreakpointManager::GetBreakpointType(MemoryOperationType type)
|
|
|
|
{
|
2021-03-10 11:13:28 -05: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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
int BreakpointManager::InternalCheckBreakpoint(MemoryOperationInfo operationInfo, AddressInfo &address)
|
2019-03-01 20:27:49 -05:00
|
|
|
{
|
|
|
|
BreakpointType type = GetBreakpointType(operationInfo.Type);
|
|
|
|
|
2021-03-10 11:13:28 -05:00
|
|
|
if(!_hasBreakpointType[(int)type]) {
|
2019-05-07 20:06:04 -04:00
|
|
|
return -1;
|
2019-03-01 20:27:49 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
DebugState state;
|
2019-07-14 21:45:12 -04:00
|
|
|
_debugger->GetState(state, false);
|
2019-03-01 20:27:49 -05:00
|
|
|
EvalResultType resultType;
|
2021-03-10 11:13:28 -05: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()) {
|
2020-10-29 02:19:23 +03:00
|
|
|
_eventManager->AddEvent(DebugEventType::Breakpoint, operationInfo, it->first);
|
2019-10-18 20:09:08 -04:00
|
|
|
}
|
2021-03-10 11:13:28 -05:00
|
|
|
if (it->second.IsEnabled()) {
|
2020-10-29 02:19:23 +03:00
|
|
|
return it->first;
|
2019-10-18 20:09:08 -04:00
|
|
|
}
|
2019-03-01 20:27:49 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-07 20:06:04 -04:00
|
|
|
return -1;
|
2019-03-01 20:27:49 -05:00
|
|
|
}
|