[Audit] round 7: JIT-entry probe for sub_824F7800 args
Adds cvar audit_log_sub824F7800_args (off by default). When set, the x64 JIT emits one CallNative to AuditLogSub824F7800Args at the start of the JIT-compiled body of guest function 0x824F7800 (silph::WorkerCtx ctor's immediate caller per audit-058). The hook reads r3..r10, LR, and 64 bytes at host(r3) from PPCContext and writes them to XELOGKERNEL. The hook is placed *after* the JIT prolog (stack push, GUEST_RET_ADDR / GUEST_CALL_RET_ADDR setup, optional trace-functions block) and *before* the first HIR body instruction, so r3..r10 and lr in PPCContext still reflect the caller's args (no LOAD/STORE_CONTEXT has executed yet inside the callee). The compile-time gate `current_guest_function_ == 0x824F7800` makes this a zero-cost no-op for all other functions and a single extra CallNative for the one target. Audit-059 round 7 probe captures r3..r10 + LR for a-prime synthetic replay of sub_824F7800 from a host hook in xenia-rs. Run with: --audit_handle_lifecycle=true --audit_log_sub824F7800_args=true Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -41,6 +41,13 @@
|
||||
|
||||
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_bool(ignore_undefined_externs, true,
|
||||
"Don't exit when an undefined extern is called.", "CPU");
|
||||
DEFINE_bool(emit_source_annotations, false,
|
||||
@@ -270,6 +277,15 @@ 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.
|
||||
// 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);
|
||||
}
|
||||
// Body.
|
||||
auto block = builder->first_block();
|
||||
synchronize_stack_on_next_instruction_ = false;
|
||||
@@ -438,6 +454,50 @@ 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*/) {
|
||||
auto* ctx = reinterpret_cast<ppc::PPCContext_s*>(raw_context);
|
||||
uint32_t r3 = static_cast<uint32_t>(ctx->r[3]);
|
||||
uint32_t r4 = static_cast<uint32_t>(ctx->r[4]);
|
||||
uint32_t r5 = static_cast<uint32_t>(ctx->r[5]);
|
||||
uint32_t r6 = static_cast<uint32_t>(ctx->r[6]);
|
||||
uint32_t r7 = static_cast<uint32_t>(ctx->r[7]);
|
||||
uint32_t r8 = static_cast<uint32_t>(ctx->r[8]);
|
||||
uint32_t r9 = static_cast<uint32_t>(ctx->r[9]);
|
||||
uint32_t r10 = static_cast<uint32_t>(ctx->r[10]);
|
||||
uint32_t lr = static_cast<uint32_t>(ctx->lr);
|
||||
|
||||
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} "
|
||||
"r6={:08X} r7={:08X} r8={:08X} r9={:08X} r10={:08X} lr={:08X}",
|
||||
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) {
|
||||
uint8_t* host = ctx->TranslateVirtual(r3);
|
||||
if (host) {
|
||||
for (uint32_t off = 0; off < 0x40; off += 16) {
|
||||
uint32_t d0 = xe::load_and_swap<uint32_t>(host + off + 0);
|
||||
uint32_t d1 = xe::load_and_swap<uint32_t>(host + off + 4);
|
||||
uint32_t d2 = xe::load_and_swap<uint32_t>(host + off + 8);
|
||||
uint32_t d3 = xe::load_and_swap<uint32_t>(host + off + 12);
|
||||
XELOGKERNEL("AUDIT-HLC sub_824F7800 r3+{:02X}: {:08X} {:08X} {:08X} {:08X}",
|
||||
off, d0, d1, d2, d3);
|
||||
}
|
||||
} else {
|
||||
XELOGKERNEL("AUDIT-HLC sub_824F7800 r3 translate failed");
|
||||
}
|
||||
} else {
|
||||
XELOGKERNEL("AUDIT-HLC sub_824F7800 r3 out of VA range, skipping dump");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void X64Emitter::Trap(uint16_t trap_type) {
|
||||
switch (trap_type) {
|
||||
case 20:
|
||||
|
||||
Reference in New Issue
Block a user