mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-13 07:14:49 +00:00
CPUThread: Split dump() info to separate methods
This commit is contained in:
parent
72c0aed4c1
commit
1231274e0f
@ -1505,7 +1505,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
|
||||
{
|
||||
if (!access_violation_recovered)
|
||||
{
|
||||
vm_log.notice("\n%s", cpu->dump());
|
||||
vm_log.notice("\n%s", cpu->dump_all());
|
||||
vm_log.error("Access violation %s location 0x%x (%s)", is_writing ? "writing" : "reading", addr, (is_writing && vm::check_addr(addr)) ? "read-only memory" : "unmapped memory");
|
||||
}
|
||||
|
||||
@ -1536,7 +1536,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
|
||||
|
||||
if (cpu && !access_violation_recovered)
|
||||
{
|
||||
vm_log.notice("\n%s", cpu->dump());
|
||||
vm_log.notice("\n%s", cpu->dump_all());
|
||||
}
|
||||
|
||||
// Note: a thread may access violate more than once after hack_alloc recovery
|
||||
@ -1617,7 +1617,7 @@ static LONG exception_filter(PEXCEPTION_POINTERS pExp) noexcept
|
||||
|
||||
if (const auto cpu = get_current_cpu_thread())
|
||||
{
|
||||
sys_log.notice("\n%s", cpu->dump());
|
||||
sys_log.notice("\n%s", cpu->dump_all());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1746,7 +1746,7 @@ static void signal_handler(int sig, siginfo_t* info, void* uct) noexcept
|
||||
|
||||
if (const auto cpu = get_current_cpu_thread())
|
||||
{
|
||||
sys_log.notice("\n%s", cpu->dump());
|
||||
sys_log.notice("\n%s", cpu->dump_all());
|
||||
}
|
||||
|
||||
std::string msg = fmt::format("Segfault %s location %p at %p.\n", cause, info->si_addr, RIP(context));
|
||||
|
@ -412,7 +412,7 @@ void cpu_thread::operator()()
|
||||
{
|
||||
if (_this)
|
||||
{
|
||||
sys_log.warning("CPU Thread '%s' terminated abnormally:\n%s", name, _this->dump());
|
||||
sys_log.warning("CPU Thread '%s' terminated abnormally:\n%s", name, _this->dump_all());
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
@ -599,7 +599,27 @@ std::string cpu_thread::get_name() const
|
||||
}
|
||||
}
|
||||
|
||||
std::string cpu_thread::dump() const
|
||||
std::string cpu_thread::dump_all() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string cpu_thread::dump_regs() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string cpu_thread::dump_callstack() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<u32> cpu_thread::dump_callstack_list() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string cpu_thread::dump_misc() const
|
||||
{
|
||||
return fmt::format("Type: %s\n" "State: %s\n", typeid(*this).name(), state.load());
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "../Utilities/Thread.h"
|
||||
#include "../Utilities/bit_set.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
// Thread state flags
|
||||
enum class cpu_flag : u32
|
||||
{
|
||||
@ -91,8 +93,20 @@ public:
|
||||
// Get thread name (as assigned to named_thread)
|
||||
std::string get_name() const;
|
||||
|
||||
// Get CPU state dump
|
||||
virtual std::string dump() const;
|
||||
// Get CPU state dump (everything)
|
||||
virtual std::string dump_all() const = 0;
|
||||
|
||||
// Get CPU register dump
|
||||
virtual std::string dump_regs() const;
|
||||
|
||||
// Get CPU call stack dump
|
||||
virtual std::string dump_callstack() const;
|
||||
|
||||
// Get CPU call stack list
|
||||
virtual std::vector<u32> dump_callstack_list() const;
|
||||
|
||||
// Get CPU dump of misc information
|
||||
virtual std::string dump_misc() const;
|
||||
|
||||
// Thread entry point function
|
||||
virtual void cpu_task() = 0;
|
||||
|
@ -58,6 +58,7 @@
|
||||
|
||||
#include <thread>
|
||||
#include <cfenv>
|
||||
#include <cctype>
|
||||
|
||||
const bool s_use_ssse3 = utils::has_ssse3();
|
||||
|
||||
@ -368,9 +369,96 @@ extern bool ppu_patch(u32 addr, u32 value)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string ppu_thread::dump() const
|
||||
std::string ppu_thread::dump_all() const
|
||||
{
|
||||
std::string ret = cpu_thread::dump();
|
||||
std::string ret = cpu_thread::dump_misc() + '\n';
|
||||
|
||||
ret += dump_misc() + '\n';
|
||||
ret += dump_regs() + '\n';
|
||||
ret += dump_callstack();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string ppu_thread::dump_regs() const
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
for (uint i = 0; i < 32; ++i) fmt::append(ret, "GPR[%d] = 0x%llx\n", i, gpr[i]);
|
||||
for (uint i = 0; i < 32; ++i) fmt::append(ret, "FPR[%d] = %.6G\n", i, fpr[i]);
|
||||
for (uint i = 0; i < 32; ++i) fmt::append(ret, "VR[%d] = %s [x: %g y: %g z: %g w: %g]\n", i, vr[i], vr[i]._f[3], vr[i]._f[2], vr[i]._f[1], vr[i]._f[0]);
|
||||
|
||||
fmt::append(ret, "CR = 0x%08x\n", cr.pack());
|
||||
fmt::append(ret, "LR = 0x%llx\n", lr);
|
||||
fmt::append(ret, "CTR = 0x%llx\n", ctr);
|
||||
fmt::append(ret, "VRSAVE = 0x%08x\n", vrsave);
|
||||
fmt::append(ret, "XER = [CA=%u | OV=%u | SO=%u | CNT=%u]\n", xer.ca, xer.ov, xer.so, xer.cnt);
|
||||
fmt::append(ret, "VSCR = [SAT=%u | NJ=%u]\n", sat, nj);
|
||||
fmt::append(ret, "FPSCR = [FL=%u | FG=%u | FE=%u | FU=%u]\n", fpscr.fl, fpscr.fg, fpscr.fe, fpscr.fu);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string ppu_thread::dump_callstack() const
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
fmt::append(ret, "Call stack:\n=========\n0x%08x (0x0) called\n", cia);
|
||||
|
||||
for (u32 sp : dump_callstack_list())
|
||||
{
|
||||
// TODO: function addresses too
|
||||
fmt::append(ret, "> from 0x%04llx (0x0)\n", vm::read64(static_cast<u32>(sp + 16)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<u32> ppu_thread::dump_callstack_list() const
|
||||
{
|
||||
//std::shared_lock rlock(vm::g_mutex); // Needs optimizations
|
||||
|
||||
// Determine stack range
|
||||
const u32 stack_ptr = static_cast<u32>(gpr[1]);
|
||||
|
||||
if (!vm::check_addr(stack_ptr, 1, vm::page_writable))
|
||||
{
|
||||
// Normally impossible unless the code does not follow ABI rules
|
||||
return {};
|
||||
}
|
||||
|
||||
u32 stack_min = stack_ptr & ~0xfff;
|
||||
u32 stack_max = stack_min + 4096;
|
||||
|
||||
while (stack_min && vm::check_addr(stack_min - 4096, 4096, vm::page_writable))
|
||||
{
|
||||
stack_min -= 4096;
|
||||
}
|
||||
|
||||
while (stack_max + 4096 && vm::check_addr(stack_max, 4096, vm::page_writable))
|
||||
{
|
||||
stack_max += 4096;
|
||||
}
|
||||
|
||||
std::vector<u32> call_stack_list;
|
||||
|
||||
for (
|
||||
u64 sp = *vm::get_super_ptr<u64>(stack_ptr);
|
||||
sp >= stack_min && std::max(sp, sp + 0x200) < stack_max;
|
||||
sp = *vm::get_super_ptr<u64>(static_cast<u32>(sp))
|
||||
)
|
||||
{
|
||||
// TODO: function addresses too
|
||||
call_stack_list.push_back(*vm::get_super_ptr<u64>(static_cast<u32>(sp + 16)));
|
||||
}
|
||||
|
||||
return call_stack_list;
|
||||
}
|
||||
|
||||
std::string ppu_thread::dump_misc() const
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
fmt::append(ret, "Priority: %d\n", +prio);
|
||||
fmt::append(ret, "Stack: 0x%x..0x%x\n", stack_addr, stack_addr + stack_size - 1);
|
||||
fmt::append(ret, "Joiner: %s\n", joiner.load());
|
||||
@ -411,51 +499,6 @@ std::string ppu_thread::dump() const
|
||||
{
|
||||
ret += '\n';
|
||||
}
|
||||
|
||||
ret += "\nRegisters:\n=========\n";
|
||||
for (uint i = 0; i < 32; ++i) fmt::append(ret, "GPR[%d] = 0x%llx\n", i, gpr[i]);
|
||||
for (uint i = 0; i < 32; ++i) fmt::append(ret, "FPR[%d] = %.6G\n", i, fpr[i]);
|
||||
for (uint i = 0; i < 32; ++i) fmt::append(ret, "VR[%d] = %s [x: %g y: %g z: %g w: %g]\n", i, vr[i], vr[i]._f[3], vr[i]._f[2], vr[i]._f[1], vr[i]._f[0]);
|
||||
|
||||
fmt::append(ret, "CR = 0x%08x\n", cr.pack());
|
||||
fmt::append(ret, "LR = 0x%llx\n", lr);
|
||||
fmt::append(ret, "CTR = 0x%llx\n", ctr);
|
||||
fmt::append(ret, "VRSAVE = 0x%08x\n", vrsave);
|
||||
fmt::append(ret, "XER = [CA=%u | OV=%u | SO=%u | CNT=%u]\n", xer.ca, xer.ov, xer.so, xer.cnt);
|
||||
fmt::append(ret, "VSCR = [SAT=%u | NJ=%u]\n", sat, nj);
|
||||
fmt::append(ret, "FPSCR = [FL=%u | FG=%u | FE=%u | FU=%u]\n", fpscr.fl, fpscr.fg, fpscr.fe, fpscr.fu);
|
||||
fmt::append(ret, "\nCall stack:\n=========\n0x%08x (0x0) called\n", cia);
|
||||
|
||||
//std::shared_lock rlock(vm::g_mutex); // Needs optimizations
|
||||
|
||||
// Determine stack range
|
||||
u32 stack_ptr = static_cast<u32>(gpr[1]);
|
||||
|
||||
if (!vm::check_addr(stack_ptr, 1, vm::page_writable))
|
||||
{
|
||||
// Normally impossible unless the code does not follow ABI rules
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 stack_min = stack_ptr & ~0xfff;
|
||||
u32 stack_max = stack_min + 4096;
|
||||
|
||||
while (stack_min && vm::check_addr(stack_min - 4096, 4096, vm::page_writable))
|
||||
{
|
||||
stack_min -= 4096;
|
||||
}
|
||||
|
||||
while (stack_max + 4096 && vm::check_addr(stack_max, 4096, vm::page_writable))
|
||||
{
|
||||
stack_max += 4096;
|
||||
}
|
||||
|
||||
for (u64 sp = *vm::get_super_ptr<u64>(stack_ptr); sp >= stack_min && std::max(sp, sp + 0x200) < stack_max; sp = *vm::get_super_ptr<u64>(static_cast<u32>(sp)))
|
||||
{
|
||||
// TODO: print also function addresses
|
||||
fmt::append(ret, "> from 0x%08llx (0x0)\n", *vm::get_super_ptr<u64>(static_cast<u32>(sp + 16)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,11 @@ public:
|
||||
static const u32 id_step = 1;
|
||||
static const u32 id_count = 2048;
|
||||
|
||||
virtual std::string dump() const override;
|
||||
virtual std::string dump_all() const override;
|
||||
virtual std::string dump_regs() const override;
|
||||
virtual std::string dump_callstack() const override;
|
||||
virtual std::vector<u32> dump_callstack_list() const override;
|
||||
virtual std::string dump_misc() const override;
|
||||
virtual void cpu_task() override final;
|
||||
virtual void cpu_sleep() override;
|
||||
virtual void cpu_mem() override;
|
||||
|
@ -1009,9 +1009,41 @@ spu_imm_table_t::spu_imm_table_t()
|
||||
}
|
||||
}
|
||||
|
||||
std::string spu_thread::dump() const
|
||||
std::string spu_thread::dump_all() const
|
||||
{
|
||||
std::string ret = cpu_thread::dump();
|
||||
std::string ret = cpu_thread::dump_misc() + '\n';
|
||||
|
||||
ret += dump_misc() + '\n';
|
||||
ret += dump_regs();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string spu_thread::dump_regs() const
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
for (u32 i = 0; i < 128; i++)
|
||||
{
|
||||
fmt::append(ret, "\nGPR[%d] = %s", i, gpr[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string spu_thread::dump_callstack() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<u32> spu_thread::dump_callstack_list() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string spu_thread::dump_misc() const
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
fmt::append(ret, "\nBlock Weight: %u (Retreats: %u)", block_counter, block_failure);
|
||||
|
||||
@ -1028,7 +1060,6 @@ std::string spu_thread::dump() const
|
||||
// Print chunk address from lowest 16 bits
|
||||
fmt::append(ret, "...chunk-0x%05x", (name & 0xffff) * 4);
|
||||
}
|
||||
|
||||
fmt::append(ret, "\n[%s]", ch_mfc_cmd);
|
||||
fmt::append(ret, "\nLocal Storage: 0x%08x..0x%08x", offset, offset + 0x3ffff);
|
||||
fmt::append(ret, "\nTag Mask: 0x%08x", ch_tag_mask);
|
||||
@ -1047,13 +1078,6 @@ std::string spu_thread::dump() const
|
||||
}
|
||||
}
|
||||
|
||||
ret += "\nRegisters:\n=========";
|
||||
|
||||
for (u32 i = 0; i < 128; i++)
|
||||
{
|
||||
fmt::append(ret, "\nGPR[%d] = %s", i, gpr[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -498,7 +498,11 @@ public:
|
||||
class spu_thread : public cpu_thread
|
||||
{
|
||||
public:
|
||||
virtual std::string dump() const override;
|
||||
virtual std::string dump_all() const override;
|
||||
virtual std::string dump_regs() const override;
|
||||
virtual std::string dump_callstack() const override;
|
||||
virtual std::vector<u32> dump_callstack_list() const override;
|
||||
virtual std::string dump_misc() const override;
|
||||
virtual void cpu_task() override final;
|
||||
virtual void cpu_mem() override;
|
||||
virtual void cpu_unmem() override;
|
||||
|
Loading…
x
Reference in New Issue
Block a user