Mesen-SX/Core/CallstackManager.cpp

106 lines
2.3 KiB
C++
Raw Normal View History

2019-03-24 12:05:51 -04:00
#include "stdafx.h"
#include "CallstackManager.h"
#include "Debugger.h"
#include "DebugBreakHelper.h"
#include "Profiler.h"
2019-03-24 12:05:51 -04:00
CallstackManager::CallstackManager(Debugger* debugger)
{
_debugger = debugger;
_profiler.reset(new Profiler(debugger));
2019-03-24 12:05:51 -04:00
}
CallstackManager::~CallstackManager()
{
}
2020-12-19 23:30:09 +03:00
void CallstackManager::Push(AddressInfo& src, uint32_t srcAddr, AddressInfo& dest, uint32_t destAddr, AddressInfo& ret,
uint32_t returnAddress, StackFrameFlags flags)
2019-03-24 12:05:51 -04:00
{
2020-12-19 23:30:09 +03:00
if (_callstack.size() >= 511)
{
2019-03-24 12:05:51 -04:00
//Ensure callstack stays below 512 entries - games can use various tricks that could keep making the callstack grow
_callstack.pop_front();
}
StackFrameInfo stackFrame;
stackFrame.Source = srcAddr;
stackFrame.Target = destAddr;
stackFrame.Return = returnAddress;
stackFrame.AbsReturn = ret;
2019-03-24 12:05:51 -04:00
stackFrame.Flags = flags;
_callstack.push_back(stackFrame);
_profiler->StackFunction(dest, flags);
2019-03-24 12:05:51 -04:00
}
void CallstackManager::Pop(AddressInfo& dest, uint32_t destAddress)
2019-03-24 12:05:51 -04:00
{
2020-12-19 23:30:09 +03:00
if (_callstack.empty())
{
2019-03-24 12:05:51 -04:00
return;
}
StackFrameInfo prevFrame = _callstack.back();
2019-03-24 12:05:51 -04:00
_callstack.pop_back();
_profiler->UnstackFunction();
2019-03-24 12:05:51 -04:00
uint32_t returnAddr = prevFrame.Return;
2020-12-19 23:30:09 +03:00
if (!_callstack.empty() && destAddress != returnAddr)
{
2019-03-24 12:05:51 -04:00
//Mismatch, pop that stack frame and add the new one
bool foundMatch = false;
2020-12-19 23:30:09 +03:00
for (int i = (int)_callstack.size() - 1; i >= 0; i--)
{
if (destAddress == _callstack[i].Return)
{
2019-03-24 12:05:51 -04:00
//Found a matching stack frame, unstack until that point
foundMatch = true;
2020-12-19 23:30:09 +03:00
for (int j = (int)_callstack.size() - i - 1; j >= 0; j--)
{
2019-03-24 12:05:51 -04:00
_callstack.pop_back();
_profiler->UnstackFunction();
2019-03-24 12:05:51 -04:00
}
break;
}
}
2020-12-19 23:30:09 +03:00
if (!foundMatch)
{
2019-03-24 12:05:51 -04:00
//Couldn't find a matching frame, replace the current one
2020-12-19 23:30:09 +03:00
Push(prevFrame.AbsReturn, returnAddr, dest, destAddress, prevFrame.AbsReturn, returnAddr,
StackFrameFlags::None);
2019-03-24 12:05:51 -04:00
}
}
}
2020-12-19 23:30:09 +03:00
void CallstackManager::GetCallstack(StackFrameInfo* callstackArray, uint32_t& callstackSize)
2019-03-24 12:05:51 -04:00
{
DebugBreakHelper helper(_debugger);
int i = 0;
2020-12-19 23:30:09 +03:00
for (StackFrameInfo& info : _callstack)
{
2019-03-24 12:05:51 -04:00
callstackArray[i] = info;
i++;
}
callstackSize = i;
}
int32_t CallstackManager::GetReturnAddress()
{
DebugBreakHelper helper(_debugger);
2020-12-19 23:30:09 +03:00
if (_callstack.empty())
{
return -1;
}
return _callstack.back().Return;
}
Profiler* CallstackManager::GetProfiler()
{
return _profiler.get();
}