[Audit] round 12: ExCreateThread + XThread::Execute probes
Two cvar-gated AUDIT-HLC probes for thread-spawn lineage attribution: 1. ExCreateThread_entry shim logs (start_address, start_context, xapi, flags, kernel lr, guest_lr). guest_lr is recovered via the same one-frame-up PPC back-chain walk used by the NtWaitForSingleObjectEx probe (lr saved at [back2 - 8]). 2. XThread::Execute emits (tid, start_address, start_context, xapi) at the very top so each running thread can be matched back to its creating ExCreateThread entry by (start_address, start_context). Gated on the existing cvars::audit_handle_lifecycle; no new cvar. Pulled in xenia/kernel/kernel_flags.h from xthread.cc to expose the cvar declaration there. Used by audit-059 round 12 to enumerate the 23 thread spawns in canary's 35 s boot, attribute each to its guest_lr caller, and cross- reference against ours' 10 spawns to identify the 7 missing spawner functions (including sub_824F7800 which spawns the 4 silph PKEVENT workers at entry=0x82506528/58/88/B8 via guest_lr=0x824F7B24). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -162,6 +162,30 @@ dword_result_t ExCreateThread_entry(lpdword_t handle_ptr, dword_t stack_size,
|
||||
lpvoid_t start_address,
|
||||
lpvoid_t start_context,
|
||||
dword_t creation_flags) {
|
||||
if (cvars::audit_handle_lifecycle) {
|
||||
auto* ctx = cpu::ThreadState::Get()->context();
|
||||
uint32_t lr = static_cast<uint32_t>(ctx->lr);
|
||||
// Walk one PPC stack frame up from the shim's frame to recover the GUEST
|
||||
// caller's LR (lr_enter is just the kernel-internal shim's return
|
||||
// address; we want the function that called *it*). Same convention as
|
||||
// the NtWaitForSingleObjectEx probe above.
|
||||
uint32_t guest_lr = 0;
|
||||
uint32_t sp = static_cast<uint32_t>(ctx->r[1]);
|
||||
uint32_t back1 = xe::load_and_swap<uint32_t>(ctx->TranslateVirtual(sp));
|
||||
if (back1) {
|
||||
uint32_t back2 =
|
||||
xe::load_and_swap<uint32_t>(ctx->TranslateVirtual(back1));
|
||||
if (back2) {
|
||||
guest_lr =
|
||||
xe::load_and_swap<uint32_t>(ctx->TranslateVirtual(back2 - 8));
|
||||
}
|
||||
}
|
||||
XELOGKERNEL(
|
||||
"AUDIT-HLC ExCreateThread entry={:08X} start_ctx={:08X} xapi={:08X} "
|
||||
"flags={:08X} lr={:08X} guest_lr={:08X}",
|
||||
uint32_t(start_address), uint32_t(start_context),
|
||||
uint32_t(xapi_thread_startup), uint32_t(creation_flags), lr, guest_lr);
|
||||
}
|
||||
return ExCreateThread(handle_ptr, stack_size, thread_id_ptr,
|
||||
xapi_thread_startup, start_address, start_context,
|
||||
creation_flags);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "xenia/base/threading.h"
|
||||
#include "xenia/cpu/processor.h"
|
||||
#include "xenia/emulator.h"
|
||||
#include "xenia/kernel/kernel_flags.h"
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/user_module.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_threading.h"
|
||||
@@ -544,6 +545,13 @@ X_STATUS XThread::Terminate(int exit_code) {
|
||||
void XThread::Execute() {
|
||||
XELOGKERNEL("XThread::Execute thid {} (handle={:08X}, '{}', native={:08X})",
|
||||
thread_id_, handle(), thread_name_, thread_->system_id());
|
||||
if (cvars::audit_handle_lifecycle) {
|
||||
XELOGKERNEL(
|
||||
"AUDIT-HLC XThread::Execute tid={} start_address={:08X} "
|
||||
"start_context={:08X} xapi={:08X}",
|
||||
thread_id_, creation_params_.start_address,
|
||||
creation_params_.start_context, creation_params_.xapi_thread_startup);
|
||||
}
|
||||
// Let the kernel know we are starting.
|
||||
kernel_state()->OnThreadExecute(this);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user