Port stack walker from PPSSPP

This commit is contained in:
Kingcom 2014-08-25 17:01:17 +02:00
parent b9fba8005a
commit 4768f293bf
10 changed files with 242 additions and 5 deletions

View File

@ -276,6 +276,7 @@ set(pcsx2DebugToolsSources
DebugTools/MIPSAnalyst.cpp
DebugTools/MipsAssembler.cpp
DebugTools/MipsAssemblerTables.cpp
DebugTools/MipsStackWalk.cpp
DebugTools/Breakpoints.cpp
DebugTools/SymbolMap.cpp
DebugTools/DisR3000A.cpp
@ -292,6 +293,7 @@ set(pcsx2DebugToolsHeaders
DebugTools/MIPSAnalyst.h
DebugTools/MipsAssembler.h
DebugTools/MipsAssemblerTables.h
DebugTools/MipsStackWalk.h
DebugTools/Breakpoints.h
DebugTools/SymbolMap.h
DebugTools/Debug.h

View File

@ -43,7 +43,7 @@ enum {
struct EEThread
{
u32 tid;
int tid;
EEInternalThread data;
};

View File

@ -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;
}
};

View File

@ -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);
};

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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" />

View File

@ -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">