diff --git a/src/xenia/cpu/backend/x64/x64_emitter.cc b/src/xenia/cpu/backend/x64/x64_emitter.cc index 5473a6a1a..558d3e53d 100644 --- a/src/xenia/cpu/backend/x64/x64_emitter.cc +++ b/src/xenia/cpu/backend/x64/x64_emitter.cc @@ -41,13 +41,14 @@ DEFINE_bool(debugprint_trap_log, false, "Log debugprint traps to the active debugger", "CPU"); -DEFINE_bool(audit_log_sub824F7800_args, false, - "Emit one XELOGKERNEL line per JIT-compiled entry to guest function " - "0x824F7800 (silph::WorkerCtx ctor's immediate caller; per audit-058 " - "fires exactly 1x after DiscImageDevice::ResolvePath). Dumps " - "r3..r10, LR, and 64 bytes at host(r3). Audit-059 round 7 probe — " - "off by default.", - "Auditing"); +DEFINE_uint32(audit_jit_prolog_pc, 0, + "Guest function entry PC at which to emit one XELOGKERNEL line " + "per JIT-compiled entry. When non-zero, the x64 emitter inserts " + "a CallNative to AuditLogJitPrologArgs at the start of the JIT " + "body of the matching guest function. Dumps r3..r10, LR, and 64 " + "bytes at host(r3). Zero (default) disables the probe. Audit-059 " + "round 7+ JIT-prolog probe — generic PC-configurable variant.", + "Auditing"); DEFINE_bool(ignore_undefined_externs, true, "Don't exit when an undefined extern is called.", "CPU"); DEFINE_bool(emit_source_annotations, false, @@ -277,14 +278,16 @@ bool X64Emitter::Emit(HIRBuilder* builder, EmitFunctionInfo& func_info) { count on no other code modifying it. mov(GetMembaseReg(), qword[GetContextReg() + offsetof(ppc::PPCContext, virtual_membase)]); */ - // Audit-059 round 7: one-shot dump of r3..r10/LR at entry to sub_824F7800. - // Compile-time gated on guest function address; runtime gated on the cvar. + // Audit-059: PC-configurable JIT-prolog probe. Runtime-gated on the cvar + // audit_jit_prolog_pc (uint32; 0 disables). When non-zero and the current + // guest function's entry PC matches, emit a single CallNative to + // AuditLogJitPrologArgs that dumps r3..r10, LR, and 64 bytes at host(r3). // Emits *before* any body instruction runs, so r3..r10 / LR in PPCContext // still reflect the caller's args (no LOAD/STORE_CONTEXT has executed yet). - if (cvars::audit_log_sub824F7800_args && - current_guest_function_ == 0x824F7800u) { - extern uint64_t AuditLogSub824F7800Args(void* raw_context, uint64_t arg0); - CallNative(AuditLogSub824F7800Args, 0); + if (cvars::audit_jit_prolog_pc != 0u && + current_guest_function_ == cvars::audit_jit_prolog_pc) { + extern uint64_t AuditLogJitPrologArgs(void* raw_context, uint64_t arg0); + CallNative(AuditLogJitPrologArgs, 0); } // Body. auto block = builder->first_block(); @@ -454,12 +457,14 @@ uint64_t TrapDebugBreak(void* raw_context, uint64_t address) { return 0; } -// Audit-059 round 7 probe: dump r3..r10, LR, and 64 bytes at host(r3) when -// the guest hits the JIT-compiled entry of sub_824F7800 (silph::WorkerCtx -// ctor's immediate caller). Per audit-058 this fires exactly once after the -// DiscImageDevice::ResolvePath(\dat\movie) sequence on canary. -uint64_t AuditLogSub824F7800Args(void* raw_context, uint64_t /*unused*/) { +// Audit-059 JIT-prolog probe: dump r3..r10, LR, and 64 bytes at host(r3) +// when the guest hits the JIT-compiled entry of the function whose entry PC +// matches cvars::audit_jit_prolog_pc. Generic PC-configurable variant of the +// round-7 sub_824F7800 hook. The hook logs the current guest PC so multiple +// instrumentation campaigns can share log output. +uint64_t AuditLogJitPrologArgs(void* raw_context, uint64_t /*unused*/) { auto* ctx = reinterpret_cast(raw_context); + uint32_t pc = static_cast(cvars::audit_jit_prolog_pc); uint32_t r3 = static_cast(ctx->r[3]); uint32_t r4 = static_cast(ctx->r[4]); uint32_t r5 = static_cast(ctx->r[5]); @@ -473,9 +478,9 @@ uint64_t AuditLogSub824F7800Args(void* raw_context, uint64_t /*unused*/) { uint32_t tid = ctx->thread_state ? ctx->thread_state->thread_id() : 0u; XELOGKERNEL( - "AUDIT-HLC sub_824F7800 entry tid={:08X} r3={:08X} r4={:08X} r5={:08X} " + "AUDIT-HLC JitProlog pc={:08X} tid={:08X} r3={:08X} r4={:08X} r5={:08X} " "r6={:08X} r7={:08X} r8={:08X} r9={:08X} r10={:08X} lr={:08X}", - tid, r3, r4, r5, r6, r7, r8, r9, r10, lr); + 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. if (r3 >= 0x10000 && r3 < 0xE0000000) { @@ -486,14 +491,17 @@ uint64_t AuditLogSub824F7800Args(void* raw_context, uint64_t /*unused*/) { uint32_t d1 = xe::load_and_swap(host + off + 4); uint32_t d2 = xe::load_and_swap(host + off + 8); uint32_t d3 = xe::load_and_swap(host + off + 12); - XELOGKERNEL("AUDIT-HLC sub_824F7800 r3+{:02X}: {:08X} {:08X} {:08X} {:08X}", - off, d0, d1, d2, d3); + XELOGKERNEL( + "AUDIT-HLC JitProlog pc={:08X} r3+{:02X}: {:08X} {:08X} {:08X} " + "{:08X}", + pc, off, d0, d1, d2, d3); } } else { - XELOGKERNEL("AUDIT-HLC sub_824F7800 r3 translate failed"); + XELOGKERNEL("AUDIT-HLC JitProlog pc={:08X} r3 translate failed", pc); } } else { - XELOGKERNEL("AUDIT-HLC sub_824F7800 r3 out of VA range, skipping dump"); + XELOGKERNEL("AUDIT-HLC JitProlog pc={:08X} r3 out of VA range, skipping dump", + pc); } return 0; }