mirror of https://github.com/PCSX2/pcsx2.git
Merge pull request #279 from Kingcom/StackFrames
Add stack trace and step out
This commit is contained in:
commit
cee80eb5f4
|
@ -282,6 +282,7 @@ set(pcsx2DebugToolsSources
|
|||
DebugTools/MIPSAnalyst.cpp
|
||||
DebugTools/MipsAssembler.cpp
|
||||
DebugTools/MipsAssemblerTables.cpp
|
||||
DebugTools/MipsStackWalk.cpp
|
||||
DebugTools/Breakpoints.cpp
|
||||
DebugTools/SymbolMap.cpp
|
||||
DebugTools/DisR3000A.cpp
|
||||
|
@ -298,6 +299,7 @@ set(pcsx2DebugToolsHeaders
|
|||
DebugTools/MIPSAnalyst.h
|
||||
DebugTools/MipsAssembler.h
|
||||
DebugTools/MipsAssemblerTables.h
|
||||
DebugTools/MipsStackWalk.h
|
||||
DebugTools/Breakpoints.h
|
||||
DebugTools/SymbolMap.h
|
||||
DebugTools/Debug.h
|
||||
|
|
|
@ -43,7 +43,7 @@ enum {
|
|||
|
||||
struct EEThread
|
||||
{
|
||||
u32 tid;
|
||||
int tid;
|
||||
EEInternalThread data;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
#include "MipsStackWalk.h"
|
||||
#include "SymbolMap.h"
|
||||
#include "MIPSAnalyst.h"
|
||||
#include "DebugInterface.h"
|
||||
#include "../R5900OpcodeTables.h"
|
||||
|
||||
#define _RS ((rawOp >> 21) & 0x1F)
|
||||
#define _RT ((rawOp >> 16) & 0x1F)
|
||||
#define _RD ((rawOp >> 11) & 0x1F)
|
||||
#define _IMM16 ((signed short)(rawOp & 0xFFFF))
|
||||
#define MIPS_REG_SP 29
|
||||
#define MIPS_REG_FP 30
|
||||
#define MIPS_REG_RA 31
|
||||
|
||||
#define INVALIDTARGET 0xFFFFFFFF
|
||||
|
||||
namespace MipsStackWalk {
|
||||
// In the worst case, we scan this far above the pc for an entry.
|
||||
const int MAX_FUNC_SIZE = 32768 * 4;
|
||||
// After this we assume we're stuck.
|
||||
const size_t MAX_DEPTH = 1024;
|
||||
|
||||
static u32 GuessEntry(u32 pc) {
|
||||
SymbolInfo info;
|
||||
if (symbolMap.GetSymbolInfo(&info, pc)) {
|
||||
return info.address;
|
||||
}
|
||||
return INVALIDTARGET;
|
||||
}
|
||||
|
||||
bool IsSWInstr(const R5900::OPCODE& op) {
|
||||
if ((op.flags & IS_MEMORY) && (op.flags & IS_STORE))
|
||||
{
|
||||
u32 type = op.flags & MEMTYPE_MASK;
|
||||
switch (op.flags & MEMTYPE_MASK)
|
||||
{
|
||||
case MEMTYPE_WORD:
|
||||
case MEMTYPE_DWORD:
|
||||
case MEMTYPE_QWORD:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsAddImmInstr(const R5900::OPCODE& op) {
|
||||
if (op.flags & IS_ALU)
|
||||
return (op.flags & ALUTYPE_MASK) == ALUTYPE_ADDI;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsMovRegsInstr(const R5900::OPCODE& op, u32 rawOp) {
|
||||
if (op.flags & IS_ALU)
|
||||
return (op.flags & ALUTYPE_MASK) == ALUTYPE_ADDI && (_RS == 0 || _RT == 0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScanForAllocaSignature(DebugInterface* cpu, u32 pc) {
|
||||
// In God Eater Burst, for example, after 0880E750, there's what looks like an alloca().
|
||||
// It's surrounded by "mov fp, sp" and "mov sp, fp", which is unlikely to be used for other reasons.
|
||||
|
||||
// It ought to be pretty close.
|
||||
u32 stop = pc - 32 * 4;
|
||||
for (; cpu->isValidAddress(pc) && pc >= stop; pc -= 4) {
|
||||
u32 rawOp = cpu->read32(pc);
|
||||
const R5900::OPCODE& op = R5900::GetInstruction(rawOp);
|
||||
|
||||
// We're looking for a "mov fp, sp" close by a "addiu sp, sp, -N".
|
||||
if (IsMovRegsInstr(op,rawOp) && _RD == MIPS_REG_FP && (_RS == MIPS_REG_SP || _RT == MIPS_REG_SP)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScanForEntry(DebugInterface* cpu, StackFrame &frame, u32 entry, u32 &ra) {
|
||||
// Let's hope there are no > 1MB functions on the PSP, for the sake of humanity...
|
||||
const u32 LONGEST_FUNCTION = 1024 * 1024;
|
||||
// TODO: Check if found entry is in the same symbol? Might be wrong sometimes...
|
||||
|
||||
int ra_offset = -1;
|
||||
const u32 start = frame.pc;
|
||||
u32 stop = entry;
|
||||
if (entry == INVALIDTARGET) {
|
||||
/* if (start >= PSP_GetUserMemoryBase()) {
|
||||
stop = PSP_GetUserMemoryBase();
|
||||
} else if (start >= PSP_GetKernelMemoryBase()) {
|
||||
stop = PSP_GetKernelMemoryBase();
|
||||
} else if (start >= PSP_GetScratchpadMemoryBase()) {
|
||||
stop = PSP_GetScratchpadMemoryBase();
|
||||
}*/
|
||||
stop = 0x80000;
|
||||
}
|
||||
if (stop < start - LONGEST_FUNCTION) {
|
||||
stop = start - LONGEST_FUNCTION;
|
||||
}
|
||||
for (u32 pc = start; cpu->isValidAddress(pc) && pc >= stop; pc -= 4) {
|
||||
u32 rawOp = cpu->read32(pc);
|
||||
const R5900::OPCODE& op = R5900::GetInstruction(rawOp);
|
||||
|
||||
// Here's where they store the ra address.
|
||||
if (IsSWInstr(op) && _RT == MIPS_REG_RA && _RS == MIPS_REG_SP) {
|
||||
ra_offset = _IMM16;
|
||||
}
|
||||
|
||||
if (IsAddImmInstr(op) && _RT == MIPS_REG_SP && _RS == MIPS_REG_SP) {
|
||||
// A positive imm either means alloca() or we went too far.
|
||||
if (_IMM16 > 0) {
|
||||
// TODO: Maybe check for any alloca() signature and bail?
|
||||
continue;
|
||||
}
|
||||
if (ScanForAllocaSignature(cpu,pc)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
frame.entry = pc;
|
||||
frame.stackSize = -_IMM16;
|
||||
if (ra_offset != -1 && cpu->isValidAddress(frame.sp + ra_offset)) {
|
||||
ra = cpu->read32(frame.sp + ra_offset);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DetermineFrameInfo(DebugInterface* cpu, StackFrame &frame, u32 possibleEntry, u32 threadEntry, u32 &ra) {
|
||||
if (ScanForEntry(cpu, frame, possibleEntry, ra)) {
|
||||
// Awesome, found one that looks right.
|
||||
return true;
|
||||
} else if (ra != INVALIDTARGET && possibleEntry != INVALIDTARGET) {
|
||||
// Let's just assume it's a leaf.
|
||||
frame.entry = possibleEntry;
|
||||
frame.stackSize = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Okay, we failed to get one. Our possibleEntry could be wrong, it often is.
|
||||
// Let's just scan upward.
|
||||
u32 newPossibleEntry = frame.pc > threadEntry ? threadEntry : frame.pc - MAX_FUNC_SIZE;
|
||||
if (ScanForEntry(cpu, frame, newPossibleEntry, ra)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<StackFrame> Walk(DebugInterface* cpu, u32 pc, u32 ra, u32 sp, u32 threadEntry, u32 threadStackTop) {
|
||||
std::vector<StackFrame> frames;
|
||||
StackFrame current;
|
||||
current.pc = pc;
|
||||
current.sp = sp;
|
||||
current.entry = INVALIDTARGET;
|
||||
current.stackSize = -1;
|
||||
|
||||
u32 prevEntry = INVALIDTARGET;
|
||||
while (pc != threadEntry) {
|
||||
u32 possibleEntry = GuessEntry(current.pc);
|
||||
if (DetermineFrameInfo(cpu, current, possibleEntry, threadEntry, ra)) {
|
||||
frames.push_back(current);
|
||||
if (current.entry == threadEntry || GuessEntry(current.entry) == threadEntry) {
|
||||
break;
|
||||
}
|
||||
if (current.entry == prevEntry || frames.size() >= MAX_DEPTH) {
|
||||
// Recursion, means we're screwed. Let's just give up.
|
||||
break;
|
||||
}
|
||||
prevEntry = current.entry;
|
||||
|
||||
current.pc = ra;
|
||||
current.sp += current.stackSize;
|
||||
ra = INVALIDTARGET;
|
||||
current.entry = INVALIDTARGET;
|
||||
current.stackSize = -1;
|
||||
} else {
|
||||
// Well, we got as far as we could.
|
||||
current.entry = possibleEntry;
|
||||
current.stackSize = 0;
|
||||
frames.push_back(current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return frames;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "Pcsx2Types.h"
|
||||
|
||||
class DebugInterface;
|
||||
|
||||
namespace MipsStackWalk {
|
||||
struct StackFrame {
|
||||
// Beginning of function symbol (may be estimated.)
|
||||
u32 entry;
|
||||
// Next position within function.
|
||||
u32 pc;
|
||||
// Value of SP inside this function (assuming no alloca()...)
|
||||
u32 sp;
|
||||
// Size of stack frame in bytes.
|
||||
int stackSize;
|
||||
};
|
||||
|
||||
std::vector<StackFrame> Walk(DebugInterface* cpu, u32 pc, u32 ra, u32 sp, u32 threadEntry, u32 threadStackTop);
|
||||
};
|
|
@ -889,11 +889,17 @@ void CtrlDisassemblyView::keydownEvent(wxKeyEvent& evt)
|
|||
}
|
||||
scanFunctions();
|
||||
break;
|
||||
case WXK_F8:
|
||||
postEvent(debEVT_STEPOUT,0);
|
||||
break;
|
||||
case WXK_F10:
|
||||
postEvent(debEVT_STEPOVER,0);
|
||||
return;
|
||||
case WXK_F11:
|
||||
postEvent(debEVT_STEPINTO,0);
|
||||
if (evt.ShiftDown())
|
||||
postEvent(debEVT_STEPOUT,0);
|
||||
else
|
||||
postEvent(debEVT_STEPINTO,0);
|
||||
return;
|
||||
default:
|
||||
evt.Skip();
|
||||
|
|
|
@ -24,6 +24,7 @@ DEFINE_LOCAL_EVENT_TYPE( debEVT_RUNTOPOS )
|
|||
DEFINE_LOCAL_EVENT_TYPE( debEVT_MAPLOADED )
|
||||
DEFINE_LOCAL_EVENT_TYPE( debEVT_STEPOVER )
|
||||
DEFINE_LOCAL_EVENT_TYPE( debEVT_STEPINTO )
|
||||
DEFINE_LOCAL_EVENT_TYPE( debEVT_STEPOUT )
|
||||
DEFINE_LOCAL_EVENT_TYPE( debEVT_UPDATE )
|
||||
DEFINE_LOCAL_EVENT_TYPE( debEVT_BREAKPOINTWINDOW )
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ DECLARE_LOCAL_EVENT_TYPE( debEVT_RUNTOPOS, wxNewEventType() )
|
|||
DECLARE_LOCAL_EVENT_TYPE( debEVT_MAPLOADED, wxNewEventType() )
|
||||
DECLARE_LOCAL_EVENT_TYPE( debEVT_STEPOVER, wxNewEventType() )
|
||||
DECLARE_LOCAL_EVENT_TYPE( debEVT_STEPINTO, wxNewEventType() )
|
||||
DECLARE_LOCAL_EVENT_TYPE( debEVT_STEPOUT, wxNewEventType() )
|
||||
DECLARE_LOCAL_EVENT_TYPE( debEVT_UPDATE, wxNewEventType() )
|
||||
DECLARE_LOCAL_EVENT_TYPE( debEVT_BREAKPOINTWINDOW, wxNewEventType() )
|
||||
|
||||
|
|
|
@ -612,3 +612,108 @@ void ThreadList::onDoubleClick(int itemIndex, const wxPoint& point)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EEThread ThreadList::getRunningThread()
|
||||
{
|
||||
for (size_t i = 0; i < threads.size(); i++)
|
||||
{
|
||||
if (threads[i].data.status == THS_RUN)
|
||||
return threads[i];
|
||||
}
|
||||
|
||||
EEThread thread;
|
||||
memset(&thread,0,sizeof(thread));
|
||||
thread.tid = -1;
|
||||
return thread;
|
||||
}
|
||||
|
||||
//
|
||||
// StackFramesList
|
||||
//
|
||||
|
||||
enum { SF_ENTRY, SF_ENTRYNAME, SF_CURPC, SF_CUROPCODE, SF_CURSP, SF_FRAMESIZE, SF_COLUMNCOUNT };
|
||||
|
||||
GenericListViewColumn stackFrameolumns[SF_COLUMNCOUNT] = {
|
||||
{ L"Entry", 0.12f },
|
||||
{ L"Name", 0.24f },
|
||||
{ L"PC", 0.12f },
|
||||
{ L"Opcode", 0.28f },
|
||||
{ L"SP", 0.12f },
|
||||
{ L"Frame Size", 0.12f }
|
||||
};
|
||||
|
||||
StackFramesList::StackFramesList(wxWindow* parent, DebugInterface* _cpu, CtrlDisassemblyView* _disassembly)
|
||||
: GenericListView(parent,stackFrameolumns,SF_COLUMNCOUNT), cpu(_cpu), disassembly(_disassembly)
|
||||
{
|
||||
#ifdef __linux__
|
||||
// On linux wx failed to resize properly the page. I don't know why so for the moment I just create a static size page
|
||||
// Far from ideal but at least I can use the memory window!
|
||||
this->SetSize(wxSize(1000, 200));
|
||||
#endif
|
||||
}
|
||||
|
||||
void StackFramesList::loadStackFrames(EEThread& currentThread)
|
||||
{
|
||||
frames = MipsStackWalk::Walk(cpu,cpu->getPC(),cpu->getRegister(0,31),cpu->getRegister(0,29),
|
||||
currentThread.data.entry_init,currentThread.data.stack);
|
||||
update();
|
||||
}
|
||||
|
||||
int StackFramesList::getRowCount()
|
||||
{
|
||||
return frames.size();
|
||||
}
|
||||
|
||||
wxString StackFramesList::getColumnText(int item, int col) const
|
||||
{
|
||||
if (item < 0 || item >= (int)frames.size())
|
||||
return L"";
|
||||
|
||||
FastFormatUnicode dest;
|
||||
const MipsStackWalk::StackFrame& frame = frames[item];
|
||||
|
||||
switch (col)
|
||||
{
|
||||
case SF_ENTRY:
|
||||
dest.Write("0x%08X",frame.entry);
|
||||
break;
|
||||
case SF_ENTRYNAME:
|
||||
{
|
||||
const std::string sym = symbolMap.GetLabelString(frame.entry);
|
||||
if (!sym.empty()) {
|
||||
dest.Write("%s",sym.c_str());
|
||||
} else {
|
||||
dest.Write("-");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SF_CURPC:
|
||||
dest.Write("0x%08X",frame.pc);
|
||||
break;
|
||||
case SF_CUROPCODE:
|
||||
{
|
||||
char temp[512];
|
||||
disassembly->getOpcodeText(frame.pc,temp);
|
||||
dest.Write("%s",temp);
|
||||
}
|
||||
break;
|
||||
case SF_CURSP:
|
||||
dest.Write("0x%08X",frame.sp);
|
||||
break;
|
||||
case SF_FRAMESIZE:
|
||||
dest.Write("0x%08X",frame.stackSize);
|
||||
break;
|
||||
default:
|
||||
return L"Invalid";
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void StackFramesList::onDoubleClick(int itemIndex, const wxPoint& point)
|
||||
{
|
||||
if (itemIndex < 0 || itemIndex >= (int)frames.size())
|
||||
return;
|
||||
|
||||
postEvent(debEVT_GOTOINDISASM,frames[itemIndex].pc);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "DebugTools/DebugInterface.h"
|
||||
#include "DebugTools/Breakpoints.h"
|
||||
#include "DebugTools/BiosDebugData.h"
|
||||
#include "DebugTools/MipsStackWalk.h"
|
||||
#include "CtrlDisassemblyView.h"
|
||||
|
||||
struct GenericListViewColumn
|
||||
|
@ -88,6 +89,7 @@ class ThreadList: public GenericListView
|
|||
public:
|
||||
ThreadList(wxWindow* parent, DebugInterface* _cpu);
|
||||
void reloadThreads();
|
||||
EEThread getRunningThread();
|
||||
protected:
|
||||
void onPopupClick(wxCommandEvent& evt);
|
||||
|
||||
|
@ -98,3 +100,20 @@ private:
|
|||
DebugInterface* cpu;
|
||||
std::vector<EEThread> threads;
|
||||
};
|
||||
|
||||
class StackFramesList: public GenericListView
|
||||
{
|
||||
public:
|
||||
StackFramesList(wxWindow* parent, DebugInterface* _cpu, CtrlDisassemblyView* _disassembly);
|
||||
void loadStackFrames(EEThread& currentThread);
|
||||
protected:
|
||||
void onPopupClick(wxCommandEvent& evt);
|
||||
|
||||
virtual wxString getColumnText(int row, int col) const;
|
||||
virtual int getRowCount();
|
||||
virtual void onDoubleClick(int itemIndex, const wxPoint& point);
|
||||
private:
|
||||
DebugInterface* cpu;
|
||||
CtrlDisassemblyView* disassembly;
|
||||
std::vector<MipsStackWalk::StackFrame> frames;
|
||||
};
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "DebugTools/DebugInterface.h"
|
||||
#include "DebugTools/DisassemblyManager.h"
|
||||
#include "DebugTools/Breakpoints.h"
|
||||
#include "DebugTools/MipsStackWalk.h"
|
||||
#include "BreakpointWindow.h"
|
||||
#include "PathDefs.h"
|
||||
|
||||
|
@ -34,6 +35,7 @@ BEGIN_EVENT_TABLE(DisassemblyDialog, wxFrame)
|
|||
EVT_COMMAND( wxID_ANY, debEVT_GOTOINDISASM, DisassemblyDialog::onDebuggerEvent )
|
||||
EVT_COMMAND( wxID_ANY, debEVT_STEPOVER, DisassemblyDialog::onDebuggerEvent )
|
||||
EVT_COMMAND( wxID_ANY, debEVT_STEPINTO, DisassemblyDialog::onDebuggerEvent )
|
||||
EVT_COMMAND( wxID_ANY, debEVT_STEPOUT, DisassemblyDialog::onDebuggerEvent )
|
||||
EVT_COMMAND( wxID_ANY, debEVT_UPDATE, DisassemblyDialog::onDebuggerEvent )
|
||||
EVT_COMMAND( wxID_ANY, debEVT_BREAKPOINTWINDOW, DisassemblyDialog::onDebuggerEvent )
|
||||
EVT_COMMAND( wxID_ANY, debEVT_MAPLOADED, DisassemblyDialog::onDebuggerEvent )
|
||||
|
@ -109,10 +111,14 @@ CpuTabPage::CpuTabPage(wxWindow* parent, DebugInterface* _cpu)
|
|||
bottomTabs->AddPage(breakpointList,L"Breakpoints");
|
||||
|
||||
threadList = NULL;
|
||||
stackFrames = NULL;
|
||||
if (cpu == &r5900Debug)
|
||||
{
|
||||
threadList = new ThreadList(bottomTabs,cpu);
|
||||
bottomTabs->AddPage(threadList,L"Threads");
|
||||
|
||||
stackFrames = new StackFramesList(bottomTabs,cpu,disassembly);
|
||||
bottomTabs->AddPage(stackFrames,L"Stack frames");
|
||||
}
|
||||
|
||||
mainSizer->Add(bottomTabs,1,wxEXPAND);
|
||||
|
@ -171,8 +177,13 @@ void CpuTabPage::update()
|
|||
breakpointList->reloadBreakpoints();
|
||||
|
||||
if (threadList != NULL)
|
||||
{
|
||||
threadList->reloadThreads();
|
||||
|
||||
EEThread thread = threadList->getRunningThread();
|
||||
if (thread.tid != -1)
|
||||
stackFrames->loadStackFrames(thread);
|
||||
}
|
||||
Refresh();
|
||||
}
|
||||
|
||||
|
@ -186,6 +197,22 @@ void CpuTabPage::loadCycles()
|
|||
lastCycles = cycles;
|
||||
}
|
||||
|
||||
u32 CpuTabPage::getStepOutAddress()
|
||||
{
|
||||
if (threadList == NULL)
|
||||
return (u32)-1;
|
||||
|
||||
EEThread currentThread = threadList->getRunningThread();
|
||||
std::vector<MipsStackWalk::StackFrame> frames =
|
||||
MipsStackWalk::Walk(cpu,cpu->getPC(),cpu->getRegister(0,31),cpu->getRegister(0,29),
|
||||
currentThread.data.entry_init,currentThread.data.stack);
|
||||
|
||||
if (frames.size() < 2)
|
||||
return (u32)-1;
|
||||
|
||||
return frames[1].pc;
|
||||
}
|
||||
|
||||
DisassemblyDialog::DisassemblyDialog(wxWindow* parent):
|
||||
wxFrame( parent, wxID_ANY, L"Debugger", wxDefaultPosition,wxDefaultSize,wxRESIZE_BORDER|wxCLOSE_BOX|wxCAPTION|wxSYSTEM_MENU ),
|
||||
currentCpu(NULL)
|
||||
|
@ -215,6 +242,7 @@ DisassemblyDialog::DisassemblyDialog(wxWindow* parent):
|
|||
|
||||
stepOutButton = new wxButton( panel, wxID_ANY, L"Step Out" );
|
||||
stepOutButton->Enable(false);
|
||||
Connect( stepOutButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DisassemblyDialog::onStepOutClicked ) );
|
||||
topRowSizer->Add(stepOutButton,0,wxRIGHT,8);
|
||||
|
||||
breakpointButton = new wxButton( panel, wxID_ANY, L"Breakpoint" );
|
||||
|
@ -297,6 +325,11 @@ void DisassemblyDialog::onStepIntoClicked(wxCommandEvent& evt)
|
|||
stepInto();
|
||||
}
|
||||
|
||||
void DisassemblyDialog::onStepOutClicked(wxCommandEvent& evt)
|
||||
{
|
||||
stepOut();
|
||||
}
|
||||
|
||||
void DisassemblyDialog::onPageChanging(wxCommandEvent& evt)
|
||||
{
|
||||
wxNotebook* notebook = (wxNotebook*)wxWindow::FindWindowById(evt.GetId());
|
||||
|
@ -404,6 +437,18 @@ void DisassemblyDialog::stepInto()
|
|||
r5900Debug.resumeCpu();
|
||||
}
|
||||
|
||||
void DisassemblyDialog::stepOut()
|
||||
{
|
||||
if (!r5900Debug.isAlive() || !r5900Debug.isCpuPaused() || currentCpu == NULL)
|
||||
return;
|
||||
|
||||
u32 addr = currentCpu->getStepOutAddress();
|
||||
if (addr == (u32)-1)
|
||||
return;
|
||||
|
||||
CBreakPoints::AddBreakPoint(addr,true);
|
||||
r5900Debug.resumeCpu();
|
||||
}
|
||||
|
||||
void DisassemblyDialog::onBreakpointClick(wxCommandEvent& evt)
|
||||
{
|
||||
|
@ -475,6 +520,10 @@ void DisassemblyDialog::onDebuggerEvent(wxCommandEvent& evt)
|
|||
{
|
||||
eeTab->reloadSymbolMap();
|
||||
iopTab->reloadSymbolMap();
|
||||
} else if (type == debEVT_STEPOUT)
|
||||
{
|
||||
if (currentCpu != NULL)
|
||||
stepOut();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,6 +575,7 @@ void DisassemblyDialog::setDebugMode(bool debugMode, bool switchPC)
|
|||
|
||||
stepOverButton->Enable(true);
|
||||
stepIntoButton->Enable(true);
|
||||
stepOutButton->Enable(currentCpu == eeTab);
|
||||
|
||||
if (switchPC || CBreakPoints::GetBreakpointTriggered())
|
||||
gotoPc();
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
void showMemoryView() { setBottomTabPage(memory); };
|
||||
void loadCycles();
|
||||
void reloadSymbolMap();
|
||||
u32 getStepOutAddress();
|
||||
|
||||
void listBoxHandler(wxCommandEvent& event);
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
@ -60,6 +61,7 @@ private:
|
|||
BreakpointList* breakpointList;
|
||||
wxStaticText* cyclesText;
|
||||
ThreadList* threadList;
|
||||
StackFramesList* stackFrames;
|
||||
u32 lastCycles;
|
||||
};
|
||||
|
||||
|
@ -85,12 +87,14 @@ protected:
|
|||
void onBreakRunClicked(wxCommandEvent& evt);
|
||||
void onStepOverClicked(wxCommandEvent& evt);
|
||||
void onStepIntoClicked(wxCommandEvent& evt);
|
||||
void onStepOutClicked(wxCommandEvent& evt);
|
||||
void onDebuggerEvent(wxCommandEvent& evt);
|
||||
void onPageChanging(wxCommandEvent& evt);
|
||||
void onBreakpointClick(wxCommandEvent& evt);
|
||||
void onClose(wxCloseEvent& evt);
|
||||
void stepOver();
|
||||
void stepInto();
|
||||
void stepOut();
|
||||
void gotoPc();
|
||||
private:
|
||||
CpuTabPage* eeTab;
|
||||
|
|
|
@ -179,6 +179,7 @@
|
|||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(RootDir)%(Directory)\%(Filename).h</Outputs>
|
||||
</CustomBuild>
|
||||
<ClCompile Include="..\..\CDVD\CompressedFileReader.cpp" />
|
||||
<ClCompile Include="..\..\DebugTools\MipsStackWalk.cpp" />
|
||||
<ClCompile Include="..\..\gui\Debugger\DebuggerLists.cpp" />
|
||||
<None Include="..\..\gui\Debugger\DebuggerLists.h" />
|
||||
<None Include="..\..\Utilities\folderdesc.txt" />
|
||||
|
@ -718,6 +719,7 @@
|
|||
<ClInclude Include="..\..\DebugTools\MIPSAnalyst.h" />
|
||||
<ClInclude Include="..\..\DebugTools\MipsAssembler.h" />
|
||||
<ClInclude Include="..\..\DebugTools\MipsAssemblerTables.h" />
|
||||
<ClInclude Include="..\..\DebugTools\MipsStackWalk.h" />
|
||||
<ClInclude Include="..\..\DebugTools\SymbolMap.h" />
|
||||
<ClInclude Include="..\..\GameDatabase.h" />
|
||||
<ClInclude Include="..\..\Gif_Unit.h" />
|
||||
|
@ -935,4 +937,4 @@
|
|||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -856,6 +856,9 @@
|
|||
<ClCompile Include="..\..\CDVD\CompressedFileReader.cpp">
|
||||
<Filter>System\ISO</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\DebugTools\MipsStackWalk.cpp">
|
||||
<Filter>System\Ps2\Debug</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\Patch.h">
|
||||
|
@ -1269,6 +1272,9 @@
|
|||
<ClInclude Include="..\..\CDVD\zlib_indexed.h">
|
||||
<Filter>System\ISO</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\DebugTools\MipsStackWalk.h">
|
||||
<Filter>System\Ps2\Debug</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\..\3rdparty\wxWidgets\include\wx\msw\wx.rc">
|
||||
|
@ -1351,4 +1357,4 @@
|
|||
<Filter>AppHost\Resources</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -416,6 +416,7 @@
|
|||
<ClCompile Include="..\..\DebugTools\MIPSAnalyst.cpp" />
|
||||
<ClCompile Include="..\..\DebugTools\MipsAssembler.cpp" />
|
||||
<ClCompile Include="..\..\DebugTools\MipsAssemblerTables.cpp" />
|
||||
<ClCompile Include="..\..\DebugTools\MipsStackWalk.cpp" />
|
||||
<ClCompile Include="..\..\DebugTools\SymbolMap.cpp" />
|
||||
<ClCompile Include="..\..\GameDatabase.cpp" />
|
||||
<ClCompile Include="..\..\Gif_Logger.cpp" />
|
||||
|
@ -704,6 +705,7 @@
|
|||
<ClInclude Include="..\..\DebugTools\MIPSAnalyst.h" />
|
||||
<ClInclude Include="..\..\DebugTools\MipsAssembler.h" />
|
||||
<ClInclude Include="..\..\DebugTools\MipsAssemblerTables.h" />
|
||||
<ClInclude Include="..\..\DebugTools\MipsStackWalk.h" />
|
||||
<ClInclude Include="..\..\DebugTools\SymbolMap.h" />
|
||||
<ClInclude Include="..\..\GameDatabase.h" />
|
||||
<ClInclude Include="..\..\Gif_Unit.h" />
|
||||
|
@ -940,4 +942,4 @@
|
|||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -853,6 +853,9 @@
|
|||
<ClCompile Include="..\..\CDVD\CompressedFileReader.cpp">
|
||||
<Filter>System\ISO</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\DebugTools\MipsStackWalk.cpp">
|
||||
<Filter>System\Ps2\Debug</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\Patch.h">
|
||||
|
@ -1269,6 +1272,9 @@
|
|||
<ClInclude Include="..\..\CDVD\zlib_indexed.h">
|
||||
<Filter>System\ISO</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\DebugTools\MipsStackWalk.h">
|
||||
<Filter>System\Ps2\Debug</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\..\3rdparty\wxWidgets\include\wx\msw\wx.rc">
|
||||
|
@ -1351,4 +1357,4 @@
|
|||
<Filter>AppHost\Resources</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
|
@ -416,6 +416,7 @@
|
|||
<ClCompile Include="..\..\DebugTools\MIPSAnalyst.cpp" />
|
||||
<ClCompile Include="..\..\DebugTools\MipsAssembler.cpp" />
|
||||
<ClCompile Include="..\..\DebugTools\MipsAssemblerTables.cpp" />
|
||||
<ClCompile Include="..\..\DebugTools\MipsStackWalk.cpp" />
|
||||
<ClCompile Include="..\..\DebugTools\SymbolMap.cpp" />
|
||||
<ClCompile Include="..\..\GameDatabase.cpp" />
|
||||
<ClCompile Include="..\..\Gif_Logger.cpp" />
|
||||
|
@ -704,6 +705,7 @@
|
|||
<ClInclude Include="..\..\DebugTools\MIPSAnalyst.h" />
|
||||
<ClInclude Include="..\..\DebugTools\MipsAssembler.h" />
|
||||
<ClInclude Include="..\..\DebugTools\MipsAssemblerTables.h" />
|
||||
<ClInclude Include="..\..\DebugTools\MipsStackWalk.h" />
|
||||
<ClInclude Include="..\..\DebugTools\SymbolMap.h" />
|
||||
<ClInclude Include="..\..\GameDatabase.h" />
|
||||
<ClInclude Include="..\..\Gif_Unit.h" />
|
||||
|
|
|
@ -853,6 +853,9 @@
|
|||
<ClCompile Include="..\..\DebugTools\BiosDebugData.cpp">
|
||||
<Filter>System\Ps2\Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\DebugTools\MipsStackWalk.cpp">
|
||||
<Filter>System\Ps2\Debug</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\Patch.h">
|
||||
|
@ -1269,6 +1272,9 @@
|
|||
<ClInclude Include="..\..\DebugTools\BiosDebugData.h">
|
||||
<Filter>System\Ps2\Debug</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\DebugTools\MipsStackWalk.h">
|
||||
<Filter>System\Ps2\Debug</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\..\..\3rdparty\wxWidgets\include\wx\msw\wx.rc">
|
||||
|
|
Loading…
Reference in New Issue