Skip to content

aowlspt_inspect.h

Source: abi/aowlspt_inspect.h — 447 lines, 40 file-scope functions.

What this header owns

Reproduced verbatim from the header's own banner comment — these notes are frequently the only written record of why the subsystem is shaped the way it is.

text
 aowlspt_inspect.h -- the native half of the LIVE INSPECTOR / REPL.

WHY THIS EXISTS
---------------
Every client-side question on this build costs an edit, a full rebuild, a
deploy, a launch and ninety seconds to the menu -- and answers exactly ONE
log line, the one somebody had to predict in advance. Reflection is dead
here (`il2cpp_object_get_class`, `il2cpp_class_get_name`, `il2cpp_value_box`
and field iteration all fault), so the only way to learn anything about a
live object is to assert an offset and see whether it faults. That is the
whole reason the loop is slow: we cannot LOOK.

This header is the instrument that lets us look. It provides, to
`host/Aowlspt.Host.Il2Cpp/inspect.nim`:

  * a lock and a pending flag, so the host's tick thread can hand a batch of
    commands to Unity's main thread without a new socket, thread or port;
  * a BREADCRUMB -- a short string plus the pointer that was about to be
    dereferenced -- written before every hop, so a caught fault names WHERE
    it landed instead of only that it happened;
  * guarded byte reads and writes;
  * code-pointer verification: committed, executable, inside the `il2cpp`
    PE section (generated code does NOT live in `.text` on this build), and
    NOT already carrying somebody's detour;
  * generic direct-RVA call thunks in IL2CPP's convention.

THE CALLING CONVENTION, as the project has it disassembled (see
`abi/aowlspt_invoke2.h` for the evidence):

  instance:  RCX = this, RDX/R8/R9 = args, then a HIDDEN TRAILING
             `const MethodInfo*`;
  static:    RCX.. = args, then the same hidden trailing MethodInfo*;
  floats:    XMM0-3 BY POSITION -- so a C prototype that declares the
             argument as `double` in that position lands it in the right
             register with no assembly at all. That is why the thunks below
             are ordinary C functions: the ABI does the work.

A NULL MethodInfo* is fine for everything except SHARED GENERIC code, which
dereferences it (`AddComponent<T>` reads it at +0x38). So every thunk takes
the MethodInfo* as an explicit parameter rather than hardcoding NULL, and
the REPL's `call` grammar has a `mi=` token for the generic case.

WHAT IS DELIBERATELY NOT HERE
-----------------------------
No struct returns. `RectTransform::get_rect` returns a `Rect` by hidden
pointer and `Camera::WorldToScreenPoint` takes a `Vector3` by value; both
need a shape-specific prototype, and a generic thunk that guessed would
corrupt the stack. Those stay in `aowlspt_debugui.h` where they have real
prototypes. The REPL reports "unsupported signature" rather than trying.

Everything here is `static`, like the rest of `abi/`: these headers are
included into the single translation unit nimony emits per module.

Constants

  • AOWLSPT_INSPECT_H

Functions

SignatureLine
void aowl_insp_lock(void)75
void aowl_insp_unlock(void)80
int32_t aowl_insp_have(void)88
void aowl_insp_set_pending(int32_t v)91
void aowl_insp_mark(const char* what, void* p)115
char aowl_insp_crumb_get(void)125
void aowl_insp_crumb_ptr_get(void)126
int32_t aowl_insp_crumb_seq_get(void)127
int32_t aowl_insp_read_bytes(void* p, int32_t off, int32_t n, unsigned char* out)137
int32_t aowl_insp_readable_span(void* p, int32_t off, int32_t n)150
int32_t aowl_insp_write_bytes(void* p, int32_t off, int32_t n, const unsigned char* src)164
void aowl_insp_bounds(void)197
void aowl_insp_module_base(void)231
uint64_t aowl_insp_il2cpp_start(void)235
uint64_t aowl_insp_il2cpp_end(void)238
int32_t aowl_insp_last_reason(void)257
int32_t aowl_insp_is_detoured(const unsigned char* p)259
void aowl_insp_code(uint64_t rva)271
int32_t aowl_insp_prologue_ok(void* p, const char* hex)301
uint64_t aowl_insp_u_v(void* fn, void* mi)340
uint64_t aowl_insp_u_p(void* fn, void* a0, void* mi)344
uint64_t aowl_insp_u_pp(void* fn, void* a0, void* a1, void* mi)348
uint64_t aowl_insp_u_ppp(void* fn, void* a0, void* a1, void* a2, void* mi)353
uint64_t aowl_insp_u_pppp(void* fn, void* a0, void* a1, void* a2, void* a3, void* mi)359
uint64_t aowl_insp_u_pi(void* fn, void* a0, int32_t a1, void* mi)365
uint64_t aowl_insp_u_pl(void* fn, void* a0, int64_t a1, void* mi)370
uint64_t aowl_insp_u_pf(void* fn, void* a0, float a1, void* mi)378
uint64_t aowl_insp_u_pff(void* fn, void* a0, float a1, float a2, void* mi)383
uint64_t aowl_insp_u_i(void* fn, int32_t a0, void* mi)389
uint64_t aowl_insp_u_f(void* fn, float a0, void* mi)393
float aowl_insp_f_v(void* fn, void* mi)399
float aowl_insp_f_p(void* fn, void* a0, void* mi)403
float aowl_insp_f_pp(void* fn, void* a0, void* a1, void* mi)407
float aowl_insp_f_pi(void* fn, void* a0, int32_t a1, void* mi)411
float aowl_insp_f_pf(void* fn, void* a0, float a1, void* mi)416
float aowl_insp_f_i(void* fn, int32_t a0, void* mi)420
float aowl_insp_bits_to_f32(uint32_t b)433
double aowl_insp_bits_to_f64(uint64_t b)436
uint32_t aowl_insp_f32_to_bits(float v)439
uint64_t aowl_insp_f64_to_bits(double v)442

aoughwl — self-hosted platform for things n stuff. Contact / Support on Discord for access to the private backends.