mirror of https://github.com/PCSX2/pcsx2.git
MipsStackWalk: clang-format
This commit is contained in:
parent
83c18d0cb6
commit
e19c9a967d
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue