MipsStackWalk: clang-format

This commit is contained in:
Ziemas 2023-10-24 22:59:34 +02:00 committed by refractionpcsx2
parent 83c18d0cb6
commit e19c9a967d
1 changed files with 62 additions and 33 deletions

View File

@ -35,21 +35,25 @@
#define INVALIDTARGET 0xFFFFFFFF #define INVALIDTARGET 0xFFFFFFFF
namespace MipsStackWalk { namespace MipsStackWalk
{
// In the worst case, we scan this far above the pc for an entry. // In the worst case, we scan this far above the pc for an entry.
const int MAX_FUNC_SIZE = 32768 * 4; const int MAX_FUNC_SIZE = 32768 * 4;
// After this we assume we're stuck. // After this we assume we're stuck.
const size_t MAX_DEPTH = 1024; const size_t MAX_DEPTH = 1024;
static u32 GuessEntry(DebugInterface* cpu, u32 pc) { static u32 GuessEntry(DebugInterface* cpu, u32 pc)
{
SymbolInfo info; SymbolInfo info;
if (cpu->GetSymbolMap().GetSymbolInfo(&info, pc)) { if (cpu->GetSymbolMap().GetSymbolInfo(&info, pc))
{
return info.address; return info.address;
} }
return INVALIDTARGET; return INVALIDTARGET;
} }
bool IsSWInstr(const R5900::OPCODE& op) { bool IsSWInstr(const R5900::OPCODE& op)
{
if ((op.flags & IS_MEMORY) && (op.flags & IS_STORE)) if ((op.flags & IS_MEMORY) && (op.flags & IS_STORE))
{ {
switch (op.flags & MEMTYPE_MASK) switch (op.flags & MEMTYPE_MASK)
@ -64,39 +68,45 @@ namespace MipsStackWalk {
return false; return false;
} }
bool IsAddImmInstr(const R5900::OPCODE& op) { bool IsAddImmInstr(const R5900::OPCODE& op)
{
if (op.flags & IS_ALU) if (op.flags & IS_ALU)
return (op.flags & ALUTYPE_MASK) == ALUTYPE_ADDI; return (op.flags & ALUTYPE_MASK) == ALUTYPE_ADDI;
return false; return false;
} }
bool IsMovRegsInstr(const R5900::OPCODE& op, u32 rawOp) { bool IsMovRegsInstr(const R5900::OPCODE& op, u32 rawOp)
{
if (op.flags & IS_ALU) if (op.flags & IS_ALU)
return (op.flags & ALUTYPE_MASK) == ALUTYPE_ADDI && (_RS == 0 || _RT == 0); return (op.flags & ALUTYPE_MASK) == ALUTYPE_ADDI && (_RS == 0 || _RT == 0);
return false; return false;
} }
bool ScanForAllocaSignature(DebugInterface* cpu, u32 pc) { bool ScanForAllocaSignature(DebugInterface* cpu, u32 pc)
{
// In God Eater Burst, for example, after 0880E750, there's what looks like an alloca(). // 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'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. // It ought to be pretty close.
u32 stop = pc - 32 * 4; u32 stop = pc - 32 * 4;
for (; cpu->isValidAddress(pc) && pc >= stop; pc -= 4) { for (; cpu->isValidAddress(pc) && pc >= stop; pc -= 4)
{
u32 rawOp = cpu->read32(pc); u32 rawOp = cpu->read32(pc);
const R5900::OPCODE& op = R5900::GetInstruction(rawOp); const R5900::OPCODE& op = R5900::GetInstruction(rawOp);
// We're looking for a "mov fp, sp" close by a "addiu sp, sp, -N". // 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)) { if (IsMovRegsInstr(op, rawOp) && _RD == MIPS_REG_FP && (_RS == MIPS_REG_SP || _RT == MIPS_REG_SP))
{
return true; return true;
} }
} }
return false; return false;
} }
bool ScanForEntry(DebugInterface* cpu, StackFrame &frame, u32 entry, u32 &ra) { 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... // Let's hope there are no > 1MB functions on the PSP, for the sake of humanity...
const u32 LONGEST_FUNCTION = 1024 * 1024; const u32 LONGEST_FUNCTION = 1024 * 1024;
// TODO: Check if found entry is in the same symbol? Might be wrong sometimes... // TODO: Check if found entry is in the same symbol? Might be wrong sometimes...
@ -104,7 +114,8 @@ namespace MipsStackWalk {
int ra_offset = -1; int ra_offset = -1;
const u32 start = frame.pc; const u32 start = frame.pc;
u32 stop = entry; u32 stop = entry;
if (entry == INVALIDTARGET) { if (entry == INVALIDTARGET)
{
/* if (start >= PSP_GetUserMemoryBase()) { /* if (start >= PSP_GetUserMemoryBase()) {
stop = PSP_GetUserMemoryBase(); stop = PSP_GetUserMemoryBase();
} else if (start >= PSP_GetKernelMemoryBase()) { } else if (start >= PSP_GetKernelMemoryBase()) {
@ -114,31 +125,38 @@ namespace MipsStackWalk {
}*/ }*/
stop = 0x80000; stop = 0x80000;
} }
if (stop < start - LONGEST_FUNCTION) { if (stop < start - LONGEST_FUNCTION)
{
stop = start - LONGEST_FUNCTION; stop = start - LONGEST_FUNCTION;
} }
for (u32 pc = start; cpu->isValidAddress(pc) && pc >= stop; pc -= 4) { for (u32 pc = start; cpu->isValidAddress(pc) && pc >= stop; pc -= 4)
{
u32 rawOp = cpu->read32(pc); u32 rawOp = cpu->read32(pc);
const R5900::OPCODE& op = R5900::GetInstruction(rawOp); const R5900::OPCODE& op = R5900::GetInstruction(rawOp);
// Here's where they store the ra address. // Here's where they store the ra address.
if (IsSWInstr(op) && _RT == MIPS_REG_RA && _RS == MIPS_REG_SP) { if (IsSWInstr(op) && _RT == MIPS_REG_RA && _RS == MIPS_REG_SP)
{
ra_offset = _IMM16; ra_offset = _IMM16;
} }
if (IsAddImmInstr(op) && _RT == MIPS_REG_SP && _RS == MIPS_REG_SP) { if (IsAddImmInstr(op) && _RT == MIPS_REG_SP && _RS == MIPS_REG_SP)
{
// A positive imm either means alloca() or we went too far. // A positive imm either means alloca() or we went too far.
if (_IMM16 > 0) { if (_IMM16 > 0)
{
// TODO: Maybe check for any alloca() signature and bail? // TODO: Maybe check for any alloca() signature and bail?
continue; continue;
} }
if (ScanForAllocaSignature(cpu,pc)) { if (ScanForAllocaSignature(cpu, pc))
{
continue; continue;
} }
frame.entry = pc; frame.entry = pc;
frame.stackSize = -_IMM16; frame.stackSize = -_IMM16;
if (ra_offset != -1 && cpu->isValidAddress(frame.sp + ra_offset)) { if (ra_offset != -1 && cpu->isValidAddress(frame.sp + ra_offset))
{
ra = cpu->read32(frame.sp + ra_offset); ra = cpu->read32(frame.sp + ra_offset);
} }
return true; return true;
@ -147,11 +165,15 @@ namespace MipsStackWalk {
return false; return false;
} }
bool DetermineFrameInfo(DebugInterface* cpu, StackFrame &frame, u32 possibleEntry, u32 threadEntry, u32 &ra) { bool DetermineFrameInfo(DebugInterface* cpu, StackFrame& frame, u32 possibleEntry, u32 threadEntry, u32& ra)
if (ScanForEntry(cpu, frame, possibleEntry, ra)) { {
if (ScanForEntry(cpu, frame, possibleEntry, ra))
{
// Awesome, found one that looks right. // Awesome, found one that looks right.
return true; return true;
} else if (ra != INVALIDTARGET && possibleEntry != INVALIDTARGET) { }
else if (ra != INVALIDTARGET && possibleEntry != INVALIDTARGET)
{
// Let's just assume it's a leaf. // Let's just assume it's a leaf.
frame.entry = possibleEntry; frame.entry = possibleEntry;
frame.stackSize = 0; frame.stackSize = 0;
@ -164,7 +186,8 @@ namespace MipsStackWalk {
return ScanForEntry(cpu, frame, newPossibleEntry, ra); return ScanForEntry(cpu, frame, newPossibleEntry, ra);
} }
std::vector<StackFrame> Walk(DebugInterface* cpu, u32 pc, u32 ra, u32 sp, u32 threadEntry, u32 threadStackTop) { std::vector<StackFrame> Walk(DebugInterface* cpu, u32 pc, u32 ra, u32 sp, u32 threadEntry, u32 threadStackTop)
{
std::vector<StackFrame> frames; std::vector<StackFrame> frames;
StackFrame current; StackFrame current;
current.pc = pc; current.pc = pc;
@ -173,14 +196,18 @@ namespace MipsStackWalk {
current.stackSize = -1; current.stackSize = -1;
u32 prevEntry = INVALIDTARGET; u32 prevEntry = INVALIDTARGET;
while (pc != threadEntry) { while (pc != threadEntry)
{
u32 possibleEntry = GuessEntry(cpu, current.pc); u32 possibleEntry = GuessEntry(cpu, current.pc);
if (DetermineFrameInfo(cpu, current, possibleEntry, threadEntry, ra)) { if (DetermineFrameInfo(cpu, current, possibleEntry, threadEntry, ra))
{
frames.push_back(current); frames.push_back(current);
if (current.entry == threadEntry || GuessEntry(cpu, current.entry) == threadEntry) { if (current.entry == threadEntry || GuessEntry(cpu, current.entry) == threadEntry)
{
break; break;
} }
if (current.entry == prevEntry || frames.size() >= MAX_DEPTH) { if (current.entry == prevEntry || frames.size() >= MAX_DEPTH)
{
// Recursion, means we're screwed. Let's just give up. // Recursion, means we're screwed. Let's just give up.
break; break;
} }
@ -191,7 +218,9 @@ namespace MipsStackWalk {
ra = INVALIDTARGET; ra = INVALIDTARGET;
current.entry = INVALIDTARGET; current.entry = INVALIDTARGET;
current.stackSize = -1; current.stackSize = -1;
} else { }
else
{
// Well, we got as far as we could. // Well, we got as far as we could.
current.entry = possibleEntry; current.entry = possibleEntry;
current.stackSize = 0; current.stackSize = 0;
@ -202,4 +231,4 @@ namespace MipsStackWalk {
return frames; return frames;
} }
}; }; // namespace MipsStackWalk