mirror of
https://github.com/xenia-project/xenia.git
synced 2025-12-06 07:12:03 +01:00
Merge 493af44de1 into 01ae24e46e
This commit is contained in:
commit
3c59473619
|
|
@ -44,6 +44,22 @@ bool BuiltinFunction::Call(ThreadState* thread_state, uint32_t return_address) {
|
|||
}
|
||||
|
||||
assert_not_null(handler_);
|
||||
|
||||
// Detect corrupted builtin argument pointers before calling the handler.
|
||||
// A very low non-null address (< 0x10000) is almost certainly invalid and
|
||||
// indicates memory corruption, likely from guest code buffer overflow.
|
||||
// This check helps identify the problem before it causes a crash in the
|
||||
// mutex operations within builtin handlers.
|
||||
if (arg0_ && reinterpret_cast<uintptr_t>(arg0_) < 0x10000) {
|
||||
XELOGE(
|
||||
"BuiltinFunction '{}' detected corrupted arg0 pointer: {:p}. "
|
||||
"This likely indicates memory corruption from guest code. "
|
||||
"The emulation cannot continue safely.",
|
||||
name(), arg0_);
|
||||
assert_always("BuiltinFunction arg0 corrupted - guest code memory corruption detected");
|
||||
return false;
|
||||
}
|
||||
|
||||
handler_(thread_state->context(), arg0_, arg1_);
|
||||
|
||||
if (original_thread_state != thread_state) {
|
||||
|
|
@ -129,8 +145,40 @@ bool GuestFunction::Call(ThreadState* thread_state, uint32_t return_address) {
|
|||
ThreadState::Bind(thread_state);
|
||||
}
|
||||
|
||||
// Validate PPCContext critical pointers before executing guest code.
|
||||
// This detects corruption that may have occurred from a previous function.
|
||||
auto ctx = thread_state->context();
|
||||
auto& expected_global_mutex = xe::global_critical_region::mutex();
|
||||
if (ctx->global_mutex != &expected_global_mutex) {
|
||||
uintptr_t corrupt_ptr = reinterpret_cast<uintptr_t>(ctx->global_mutex);
|
||||
XELOGE(
|
||||
"GuestFunction '{}' at 0x{:08X} called with corrupted PPCContext. "
|
||||
"global_mutex pointer is {:p} / 0x{:X} (expected {:p}). "
|
||||
"Corruption likely occurred in a previous function call.",
|
||||
name(), address(), ctx->global_mutex, corrupt_ptr,
|
||||
static_cast<void*>(&expected_global_mutex));
|
||||
assert_always(
|
||||
"PPCContext already corrupted before function execution. Previous "
|
||||
"guest function likely has buffer overflow.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = CallImpl(thread_state, return_address);
|
||||
|
||||
// Validate context after execution to catch corruption during this function.
|
||||
if (ctx->global_mutex != &expected_global_mutex) {
|
||||
uintptr_t corrupt_ptr = reinterpret_cast<uintptr_t>(ctx->global_mutex);
|
||||
XELOGE(
|
||||
"GuestFunction '{}' at 0x{:08X} CORRUPTED PPCContext during "
|
||||
"execution. global_mutex changed to {:p} / 0x{:X}. "
|
||||
"This function has a buffer overflow or invalid memory write.",
|
||||
name(), address(), ctx->global_mutex, corrupt_ptr);
|
||||
assert_always(
|
||||
"Memory corruption detected in guest function execution. "
|
||||
"The function has a buffer overflow bug.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (original_thread_state != thread_state) {
|
||||
ThreadState::Bind(original_thread_state);
|
||||
}
|
||||
|
|
@ -139,4 +187,4 @@ bool GuestFunction::Call(ThreadState* thread_state, uint32_t return_address) {
|
|||
}
|
||||
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
} // namespace xe
|
||||
|
|
@ -337,6 +337,31 @@ bool Processor::Execute(ThreadState* thread_state, uint32_t address) {
|
|||
|
||||
auto context = thread_state->context();
|
||||
|
||||
// Validate critical PPCContext pointers before executing guest code.
|
||||
// The global_mutex pointer is particularly susceptible to corruption from
|
||||
// guest code writing beyond array bounds (e.g., VMX register array overflow).
|
||||
// Detecting corruption here helps identify the source before crashes occur.
|
||||
auto& expected_global_mutex = xe::global_critical_region::mutex();
|
||||
if (context->global_mutex != &expected_global_mutex) {
|
||||
uintptr_t corrupt_ptr = reinterpret_cast<uintptr_t>(context->global_mutex);
|
||||
XELOGE(
|
||||
"PPCContext global_mutex pointer corrupted (expected {:p}, got {:p} / "
|
||||
"0x{:X}). This indicates guest code is writing beyond allocated "
|
||||
"boundaries. Common causes: VMX register overflow, stack corruption, or "
|
||||
"invalid memory access in translated code. Thread ID: {}",
|
||||
static_cast<void*>(&expected_global_mutex), context->global_mutex,
|
||||
corrupt_ptr, thread_state->thread_id());
|
||||
|
||||
// Log additional context for debugging
|
||||
XELOGE(" Function address: 0x{:08X}", address);
|
||||
XELOGE(" Stack pointer (r1): 0x{:08X}", context->r[1]);
|
||||
|
||||
assert_always(
|
||||
"PPCContext corruption detected - cannot continue safely. Check for "
|
||||
"guest code buffer overflows or emulator bugs in array bound checks.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pad out stack a bit, as some games seem to overwrite the caller by about
|
||||
// 16 to 32b.
|
||||
context->r[1] -= 64 + 112;
|
||||
|
|
@ -349,6 +374,23 @@ bool Processor::Execute(ThreadState* thread_state, uint32_t address) {
|
|||
// Execute the function.
|
||||
auto result = function->Call(thread_state, uint32_t(context->lr));
|
||||
|
||||
// Validate context integrity after execution to detect corruption during
|
||||
// the function call. This helps narrow down which guest functions cause
|
||||
// memory corruption.
|
||||
if (context->global_mutex != &expected_global_mutex) {
|
||||
uintptr_t corrupt_ptr = reinterpret_cast<uintptr_t>(context->global_mutex);
|
||||
XELOGE(
|
||||
"PPCContext global_mutex corrupted DURING function execution at "
|
||||
"0x{:08X}. Pointer changed from {:p} to {:p} / 0x{:X}. This "
|
||||
"indicates the executed function wrote beyond its allocated memory.",
|
||||
address, static_cast<void*>(&expected_global_mutex),
|
||||
context->global_mutex, corrupt_ptr);
|
||||
assert_always(
|
||||
"Memory corruption detected during function execution. The executed "
|
||||
"guest code has a buffer overflow or invalid memory write.");
|
||||
return false;
|
||||
}
|
||||
|
||||
context->lr = previous_lr;
|
||||
context->r[1] += 64 + 112;
|
||||
|
||||
|
|
@ -1302,4 +1344,4 @@ uint32_t Processor::CalculateNextGuestInstruction(ThreadDebugInfo* thread_info,
|
|||
}
|
||||
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
} // namespace xe
|
||||
Loading…
Reference in a new issue