From 33dee75c03b9873fea8523d0bfc6a98573893d2d Mon Sep 17 00:00:00 2001 From: MechaCat02 Date: Sun, 7 Jun 2026 19:39:26 +0200 Subject: [PATCH] [Audit] --audit-r3-dump-bytes: dump N bytes at r3 when probe fires MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AUDIT-059 round 15 — diagnostic. New cvar `audit_jit_prolog_r3_bytes` (default 64 = existing behaviour, capped at 256, rounded up to 16B multiple) controls how many bytes are dumped at host(r3) when the audit_jit_prolog_pc probe fires. Set to 80 to capture audit-051's stack-local struct at sub_82452DC0's r31+96. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/xenia/cpu/backend/x64/x64_emitter.cc | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/xenia/cpu/backend/x64/x64_emitter.cc b/src/xenia/cpu/backend/x64/x64_emitter.cc index d9d984e11..ef04f0c3c 100644 --- a/src/xenia/cpu/backend/x64/x64_emitter.cc +++ b/src/xenia/cpu/backend/x64/x64_emitter.cc @@ -58,6 +58,13 @@ DEFINE_uint32(audit_jit_prolog_mem_dump, 0, "and its vtable[0] (first virtual method = bctrl target at " "sub_822F1AA8+0x90). Zero (default) disables.", "Auditing"); +DEFINE_uint32(audit_jit_prolog_r3_bytes, 0x40, + "Audit-052 — number of bytes to dump from host(r3) on every " + "audit_jit_prolog_pc fire (capped at 256, 16-byte aligned). " + "Default 64 (existing behaviour). Set to 80 to capture the " + "audit-051 stack-local struct at sub_82452DC0's r31+96 " + "(probe sub_8245B000 entry where r3 IS the struct ptr).", + "Auditing"); DEFINE_bool(ignore_undefined_externs, true, "Don't exit when an undefined extern is called.", "CPU"); DEFINE_bool(emit_source_annotations, false, @@ -491,11 +498,16 @@ uint64_t AuditLogJitPrologArgs(void* raw_context, uint64_t /*unused*/) { "r6={:08X} r7={:08X} r8={:08X} r9={:08X} r10={:08X} lr={:08X}", pc, tid, r3, r4, r5, r6, r7, r8, r9, r10, lr); - // Dump 64 bytes at host(r3) if r3 looks like a plausible guest VA. + // Dump N bytes at host(r3) if r3 looks like a plausible guest VA. + // N comes from cvar `audit_jit_prolog_r3_bytes` (default 64 = existing + // behaviour). Round up to a 16-byte multiple; cap at 256. + uint32_t r3_dump_bytes = static_cast(cvars::audit_jit_prolog_r3_bytes); + if (r3_dump_bytes > 256) r3_dump_bytes = 256; + r3_dump_bytes = (r3_dump_bytes + 15) & ~15u; if (r3 >= 0x10000 && r3 < 0xE0000000) { uint8_t* host = ctx->TranslateVirtual(r3); if (host) { - for (uint32_t off = 0; off < 0x40; off += 16) { + for (uint32_t off = 0; off < r3_dump_bytes; off += 16) { uint32_t d0 = xe::load_and_swap(host + off + 0); uint32_t d1 = xe::load_and_swap(host + off + 4); uint32_t d2 = xe::load_and_swap(host + off + 8);