1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 12:12:50 +01:00

Debugger: Implement SPU callstack, fix PPU callstack

This commit is contained in:
Eladash 2020-11-07 18:12:52 +02:00 committed by Ivan
parent fd7ea82965
commit 3cb5fd8ebc
3 changed files with 86 additions and 8 deletions

View File

@ -538,7 +538,7 @@ std::string ppu_thread::dump_callstack() const
for (const auto& sp : dump_callstack_list())
{
// TODO: function addresses too
fmt::append(ret, "> from 0x%08x (r1=0x%08x)\n", sp.first, sp.second);
fmt::append(ret, "> from 0x%08x (sp=0x%08x)\n", sp.first, sp.second);
}
return ret;
@ -579,17 +579,39 @@ std::vector<std::pair<u32, u32>> ppu_thread::dump_callstack_list() const
std::vector<std::pair<u32, u32>> call_stack_list;
bool first = true;
for (
u64 sp = *vm::get_super_ptr<u64>(stack_ptr);
u64 sp = r1;
sp % 0x10 == 0u && sp >= stack_min && sp <= stack_max - ppu_stack_start_offset;
sp = *vm::get_super_ptr<u64>(static_cast<u32>(sp))
)
{
const u64 addr = *vm::get_super_ptr<u64>(static_cast<u32>(sp + 16));
u64 addr = *vm::get_super_ptr<u64>(static_cast<u32>(sp + 16));
if (addr > UINT32_MAX || addr % 4 || !vm::check_addr(static_cast<u32>(addr), 1, vm::page_executable))
auto is_invalid = [](u64 addr)
{
break;
return (addr > UINT32_MAX || addr % 4 || !vm::check_addr(static_cast<u32>(addr), 1, vm::page_executable));
};
if (is_invalid(addr))
{
if (std::exchange(first, false))
{
// Function hasn't saved LR, could be because it's a leaf function
// Use LR directly instead
addr = lr;
if (is_invalid(addr))
{
// Skip it, workaround
continue;
}
}
else
{
break;
}
}
// TODO: function addresses too

View File

@ -1245,12 +1245,68 @@ std::string spu_thread::dump_regs() const
std::string spu_thread::dump_callstack() const
{
return {};
std::string ret;
fmt::append(ret, "Call stack:\n=========\n0x%08x (0x0) called\n", pc);
for (const auto& sp : dump_callstack_list())
{
// TODO: function addresses too
fmt::append(ret, "> from 0x%08x (sp=0x%08x)\n", sp.first, sp.second);
}
return ret;
}
std::vector<std::pair<u32, u32>> spu_thread::dump_callstack_list() const
{
return {};
std::vector<std::pair<u32, u32>> call_stack_list;
bool first = true;
// Declare first 128-bytes as invalid for stack (common values such as 0 do not make sense here)
for (u32 sp = gpr[1]._u32[3]; (sp & ~0x3FFF0) == 0u && sp >= 0x80u; sp = _ref<u32>(sp))
{
v128 lr = _ref<v128>(sp + 16);
auto is_invalid = [](v128 v)
{
const u32 addr = v._u32[3];
if (v != v128::from32r(addr))
{
// Non-zero lower words are invalid (because BRSL-like instructions generate only zeroes)
return true;
}
return !!(addr & ~0x3FFFC);
};
if (is_invalid(lr))
{
if (std::exchange(first, false))
{
// Function hasn't saved LR, could be because it's a leaf function
// Use LR directly instead
lr = gpr[0];
if (is_invalid(lr))
{
// Skip it, workaround
continue;
}
}
else
{
break;
}
}
// TODO: function addresses too
call_stack_list.emplace_back(lr._u32[3], sp);
}
return call_stack_list;
}
std::string spu_thread::dump_misc() const

View File

@ -792,7 +792,7 @@ public:
template<typename T>
to_be_t<T>* _ptr(u32 lsa) const
{
return reinterpret_cast<to_be_t<T>*>(ls + lsa);
return reinterpret_cast<to_be_t<T>*>(ls + (lsa % SPU_LS_SIZE));
}
// Convert specified SPU LS address to a reference of specified (possibly converted to BE) type