mirror of
https://github.com/xenia-project/xenia.git
synced 2025-12-06 07:12:03 +01:00
[CPU] Detect and restore corrupted global_mutex pointer to prevent crashes
This commit is contained in:
parent
01ae24e46e
commit
23ec2a4c80
|
|
@ -44,6 +44,12 @@ bool BuiltinFunction::Call(ThreadState* thread_state, uint32_t return_address) {
|
|||
}
|
||||
|
||||
assert_not_null(handler_);
|
||||
// Detect corruption of builtin argument pointers (e.g., global mutex
|
||||
// accidentally overwritten by guest code). A very low non-null address is
|
||||
// almost certainly invalid here and has led to crashes in unlock().
|
||||
if (arg0_ && reinterpret_cast<uintptr_t>(arg0_) < 0x1000) {
|
||||
XELOGE("BuiltinFunction '{}' arg0 pointer appears corrupt: {:p}", name(), arg0_);
|
||||
}
|
||||
handler_(thread_state->context(), arg0_, arg1_);
|
||||
|
||||
if (original_thread_state != thread_state) {
|
||||
|
|
@ -129,6 +135,16 @@ bool GuestFunction::Call(ThreadState* thread_state, uint32_t return_address) {
|
|||
ThreadState::Bind(thread_state);
|
||||
}
|
||||
|
||||
// Validate the global mutex pointer before executing guest code to help
|
||||
// diagnose crashes where std::recursive_mutex::unlock() sees an invalid
|
||||
// 'this' (e.g., 0x1).
|
||||
auto ctx = thread_state->context();
|
||||
auto& expected_global_mutex = xe::global_critical_region::mutex();
|
||||
if (ctx->global_mutex != &expected_global_mutex) {
|
||||
XELOGE("GuestFunction '{}' executing with corrupted global_mutex {:p}; restoring", name(), ctx->global_mutex);
|
||||
ctx->global_mutex = &expected_global_mutex;
|
||||
}
|
||||
|
||||
bool result = CallImpl(thread_state, return_address);
|
||||
|
||||
if (original_thread_state != thread_state) {
|
||||
|
|
|
|||
|
|
@ -337,6 +337,16 @@ bool Processor::Execute(ThreadState* thread_state, uint32_t address) {
|
|||
|
||||
auto context = thread_state->context();
|
||||
|
||||
// Defensive: ensure the context's global mutex pointer hasn't been clobbered
|
||||
// by guest code scribbling over the red zone. A corrupt pointer (like 0x1)
|
||||
// leads to a crash when unlock() is invoked by translated code paths.
|
||||
auto& expected_global_mutex = xe::global_critical_region::mutex();
|
||||
if (context->global_mutex != &expected_global_mutex) {
|
||||
uintptr_t raw_ptr = reinterpret_cast<uintptr_t>(context->global_mutex);
|
||||
XELOGE("PPCContext global_mutex pointer corrupted (was {:p} / 0x{:X}), restoring", context->global_mutex, raw_ptr);
|
||||
context->global_mutex = &expected_global_mutex;
|
||||
}
|
||||
|
||||
// Pad out stack a bit, as some games seem to overwrite the caller by about
|
||||
// 16 to 32b.
|
||||
context->r[1] -= 64 + 112;
|
||||
|
|
|
|||
Loading…
Reference in a new issue