Compare commits
2 Commits
dde48f287b
...
5427f14f1b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5427f14f1b | ||
|
|
a594f95f77 |
@@ -49,6 +49,15 @@ DEFINE_uint32(audit_jit_prolog_pc, 0,
|
||||
"bytes at host(r3). Zero (default) disables the probe. Audit-059 "
|
||||
"round 7+ JIT-prolog probe — generic PC-configurable variant.",
|
||||
"Auditing");
|
||||
DEFINE_uint32(audit_jit_prolog_mem_dump, 0,
|
||||
"Audit-059 round 14 — paired memory-dump VA. When non-zero "
|
||||
"AND audit_jit_prolog_pc fires, dereference the guest VA 3 "
|
||||
"levels deep and emit one XELOGKERNEL line: addr -> val "
|
||||
"(singleton instance), val -> vtable, vtable -> vtable[0] / "
|
||||
"vtable[24]. Reads the singleton at [0x828E1F08], its vtable, "
|
||||
"and its vtable[0] (first virtual method = bctrl target at "
|
||||
"sub_822F1AA8+0x90). Zero (default) disables.",
|
||||
"Auditing");
|
||||
DEFINE_bool(ignore_undefined_externs, true,
|
||||
"Don't exit when an undefined extern is called.", "CPU");
|
||||
DEFINE_bool(emit_source_annotations, false,
|
||||
@@ -503,6 +512,28 @@ uint64_t AuditLogJitPrologArgs(void* raw_context, uint64_t /*unused*/) {
|
||||
XELOGKERNEL("AUDIT-HLC JitProlog pc={:08X} r3 out of VA range, skipping dump",
|
||||
pc);
|
||||
}
|
||||
|
||||
// Audit-059 round 14 — paired 3-level dereference. When
|
||||
// `audit_jit_prolog_mem_dump` is set, read the singleton at that VA,
|
||||
// its vtable, vtable[0] (first virtual method = bctrl target), and
|
||||
// vtable[24] (slot 6 = silph chain method per round 9).
|
||||
uint32_t mem_addr = static_cast<uint32_t>(cvars::audit_jit_prolog_mem_dump);
|
||||
if (mem_addr != 0u && mem_addr >= 0x10000 && mem_addr < 0xE0000000) {
|
||||
auto load_be32 = [&](uint32_t va) -> uint32_t {
|
||||
if (va < 0x10000 || va >= 0xE0000000) return 0u;
|
||||
uint8_t* h = ctx->TranslateVirtual(va);
|
||||
if (!h) return 0u;
|
||||
return xe::load_and_swap<uint32_t>(h);
|
||||
};
|
||||
uint32_t val = load_be32(mem_addr);
|
||||
uint32_t vtable = val != 0u ? load_be32(val) : 0u;
|
||||
uint32_t m0 = vtable != 0u ? load_be32(vtable) : 0u;
|
||||
uint32_t m6 = vtable != 0u ? load_be32(vtable + 24u) : 0u;
|
||||
XELOGKERNEL(
|
||||
"AUDIT-MEM-READ addr={:08X} val={:08X} vtable={:08X} vtable[0]={:08X} "
|
||||
"vtable[24]={:08X} pc={:08X} tid={:08X}",
|
||||
mem_addr, val, vtable, m0, m6, pc, tid);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1379,6 +1379,40 @@ void KernelState::EmulateCPInterruptDPC(uint32_t interrupt_callback,
|
||||
"AUDIT-HLC EmulateCPInterruptDPC callback={:08X} data={:08X} source={} "
|
||||
"cpu={}",
|
||||
interrupt_callback, interrupt_callback_data, source, cpu);
|
||||
|
||||
// AUDIT-2BF round 14 — one-shot singleton + vtable dump. Resolves
|
||||
// the silph init chain bctrl target at PC 0x822F1B4C (vtable[0] of
|
||||
// ANON_Class_2D56F86D at [0x828E1F08]). Dereferences 3 deep:
|
||||
// [0x828E1F08] (singleton) → vtable → vtable[0] (=first virtual
|
||||
// method, the bctrl target) and vtable[24] (=slot 6, canary's silph
|
||||
// chain target sub_821B55D8). Done once per process via atomic
|
||||
// flag. Defensive null-checks at each level.
|
||||
static std::atomic<bool> g_audit_singleton_dumped{false};
|
||||
bool expected = false;
|
||||
if (g_audit_singleton_dumped.compare_exchange_strong(expected, true)) {
|
||||
const uint32_t addr = 0x828E1F08;
|
||||
uint32_t val = 0, vtable = 0, m0 = 0, m6 = 0;
|
||||
auto* host_addr = memory()->TranslateVirtual<uint32_t*>(addr);
|
||||
if (host_addr) {
|
||||
val = xe::load_and_swap<uint32_t>(host_addr);
|
||||
}
|
||||
if (val) {
|
||||
auto* host_val = memory()->TranslateVirtual<uint32_t*>(val);
|
||||
if (host_val) {
|
||||
vtable = xe::load_and_swap<uint32_t>(host_val);
|
||||
}
|
||||
}
|
||||
if (vtable) {
|
||||
auto* host_vt0 = memory()->TranslateVirtual<uint32_t*>(vtable);
|
||||
auto* host_vt6 = memory()->TranslateVirtual<uint32_t*>(vtable + 24);
|
||||
if (host_vt0) m0 = xe::load_and_swap<uint32_t>(host_vt0);
|
||||
if (host_vt6) m6 = xe::load_and_swap<uint32_t>(host_vt6);
|
||||
}
|
||||
XELOGKERNEL(
|
||||
"AUDIT-HLC singleton[0x828E1F08]={:08X} vtable={:08X} "
|
||||
"vtable[0]={:08X} vtable[24]={:08X}",
|
||||
val, vtable, m0, m6);
|
||||
}
|
||||
}
|
||||
|
||||
auto thread = kernel::XThread::GetCurrentThread();
|
||||
|
||||
@@ -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