[Audit] handle-lifecycle: one-shot silph::WorkerCtx hexdump on first KeSetEvent
Adds a 41-LOC cvar-gated probe (audit_handle_lifecycle) that emits a one-shot 0x300-byte hexdump of the silph::WorkerCtx context the first time KeSetEvent fires into the silph UI PKEVENT cluster (0xBCE25200..0xBCE25300 in current builds). Recovers ctx_base by anchoring on the canonical layout (events at ctx+0x54/+0x64/+0x74/+0x84 with 16-byte stride; ctx_base = ev_addr - (ev_addr - 0xBCE251C0)). Also emits an explicit per-slot summary of the 8 candidate KEVENT headers at +0x54..+0xC4 for sanity. Produces 48 DUMP rows + 8 slot rows in canary.log on the first triggering KeSetEvent. Guarded by std::atomic_bool so subsequent fires are silent. Used by iterate 2.BF context-replication in ours: we need the live [ctx+0] vtable pointer and the 4 quiet/4 active KEVENT slot config to synthesize a matching WorkerCtx and spawn the four sub_82506xxx entries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_threading.h"
|
||||
#include <atomic>
|
||||
#include "xenia/base/atomic.h"
|
||||
#include "xenia/base/clock.h"
|
||||
#include "xenia/base/platform.h"
|
||||
@@ -23,6 +24,9 @@ namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
|
||||
// AUDIT-HLC: one-shot guard for silph::WorkerCtx context dump (round5).
|
||||
static std::atomic<bool> g_audit_silph_ctx_dumped{false};
|
||||
|
||||
// r13 + 0x100: pointer to thread local state
|
||||
// Thread local state:
|
||||
// 0x058: kernel time
|
||||
@@ -552,6 +556,43 @@ dword_result_t KeSetEvent_entry(pointer_t<X_KEVENT> event_ptr,
|
||||
uint32_t lr = static_cast<uint32_t>(cpu::ThreadState::Get()->context()->lr);
|
||||
XELOGKERNEL("AUDIT-HLC KeSetEvent guest_ptr={:08X} lr={:08X}",
|
||||
uint32_t(event_ptr.guest_address()), lr);
|
||||
// AUDIT-HLC round5: one-shot hexdump of the silph::WorkerCtx context when
|
||||
// KeSetEvent first fires into the silph UI PKEVENT cluster
|
||||
// (0xBCE25214/24/34/44 in current builds; widened a bit for allocator
|
||||
// drift). Used by iterate 2.BF context-replication.
|
||||
uint32_t ev_addr = uint32_t(event_ptr.guest_address());
|
||||
if (ev_addr >= 0xBCE25200 && ev_addr < 0xBCE25300) {
|
||||
if (!g_audit_silph_ctx_dumped.exchange(true)) {
|
||||
// Events live at ctx+0x54, +0x64, +0x74, +0x84 (16-byte stride).
|
||||
// Compute ctx_base assuming the canonical layout (lowest event at
|
||||
// ctx+0x54 → ctx_base = 0xBCE251C0 when ev_addr == 0xBCE25214).
|
||||
uint32_t event_offset_in_ctx = ev_addr - 0xBCE251C0;
|
||||
uint32_t ctx_base = ev_addr - event_offset_in_ctx;
|
||||
auto* ctx = cpu::ThreadState::Get()->context();
|
||||
uint8_t* host = ctx->TranslateVirtual(ctx_base);
|
||||
XELOGKERNEL(
|
||||
"AUDIT-HLC silph_ctx_dump ctx_base={:08X} (event {:08X} at +{:02X})",
|
||||
ctx_base, ev_addr, event_offset_in_ctx);
|
||||
for (uint32_t off = 0; off < 0x300; 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 DUMP {:08X}: {:08X} {:08X} {:08X} {:08X}",
|
||||
ctx_base + off, d0, d1, d2, d3);
|
||||
}
|
||||
XELOGKERNEL("AUDIT-HLC silph_ctx event-slots:");
|
||||
for (uint32_t i = 0; i < 8; ++i) {
|
||||
uint32_t ev_off = 0x54 + i * 0x10;
|
||||
uint32_t hdr = xe::load_and_swap<uint32_t>(host + ev_off + 0);
|
||||
uint32_t state = xe::load_and_swap<uint32_t>(host + ev_off + 4);
|
||||
XELOGKERNEL(
|
||||
"AUDIT-HLC slot[{}] off=+{:02X} addr={:08X} hdr={:08X} "
|
||||
"state={:08X}",
|
||||
i, ev_off, ctx_base + ev_off, hdr, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return xeKeSetEvent(event_ptr, increment, wait);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user