re: two trigger appenders -- built-in 19's node carries the handler routine

Resolves the puzzle the previous commit left open: payload+28 is a 1-12 index, yet
the drain hands it to a spawner that wants a code offset.  The cause is that built-in
25 is not the only thing that appends a trigger node.

Searching for functions that write a double at +16 AND a word at +28 of the same
register finds exactly two: sub_8226A0D8 (built-in 25, vtable slot 28) which fills the
payload inline, and sub_8226E160, a free-list recycling variant whose sole caller
sub_82269ED0 is vtable slot 68 = BUILT-IN 19.

Built-in 19 passes local[4] -> node+0 (the unit), local[12] -> +4, local[24] -> +16 as
a double, and local[32] -> +28.  That last one is the field the drain spawns from, and
it is a genuine code offset:

  over all 79 call sites disc-wide
    land on the instruction stream    79 / 79 = 100.0%
    control, random 4-aligned offsets           27.8%
    values 12164 .. 111080, 73 distinct

Large, distinct, and every one resolves against a control that resolves barely a
quarter of the time.  So built-in 19 registers a trigger whose handler is a routine,
and the drain's `base + payload+28` spawn is that handler.  The two builders simply
put different things in the same slot.

Observed alongside: built-in 25 writes +24 = 1 and built-in 19 writes +24 = 0, which
is kind-tag shaped -- but the drain was not shown branching on it, so that is recorded
as an observation and not a reading.

All artefacts regenerate byte-identical; documentation only.

Still open: whether +24 selects between the node kinds, and this STILL does not
explain the unreached code -- 0 of the 79 handler offsets are unreached run-starts.
This commit is contained in:
Sylpheed RE agent
2026-08-27 07:38:24 +00:00
parent 9ee32f7940
commit 6402a34d9b
2 changed files with 65 additions and 3 deletions

View File

@@ -119,6 +119,22 @@ unknown, what evidence exists, and what the first step would be. Move an item in
earlier. The drain does operate on the container — what `sub_8226E458` does to
it stays unread. 🟡 What starts the ~15 % of unreached code: still open, not this.
***(2026-08-27) RESOLVED — TWO trigger appenders, and built-in 19's carries the
handler routine. [structures/isl-trigger-node](structures/isl-trigger-node.md).**
Last iteration's puzzle (`payload+28` is a 112 index, yet the drain spawns
`base + payload+28`) had a simple cause: **built-in 25 is not the only appender**.
Searching for functions writing a double at `+16` AND a word at `+28` of the same
register finds exactly two — `sub_8226A0D8` (built-in 25, slot 28) and
`sub_8226E160`, whose sole caller `sub_82269ED0` is **vtable slot 68 =
built-in 19**. Built-in 19 passes `local[4]`→+0, `local[12]`→+4, `local[24]`→+16
(double), **`local[32]`→+28**. 🔑 **Those ARE code offsets: 79/79 land on the
instruction stream vs a 27.8 % control**, values 12 164111 080, 73 distinct. So
**built-in 19 registers a trigger whose handler is a routine**, and the drain's
spawn is that handler. Observed: built-in 25 writes `+24 = 1`, built-in 19 writes
`+24 = 0` — kind-tag shaped, 🟡 but the drain was not shown branching on it.
🟡 **Still does not explain the unreached code** — 0 of the 79 handler offsets are
unreached run-starts.
## ✅✅ SOLVED — the mission freeze was a modal sign-in dialog (2026-08-26)
`XamShowSigninUI` opens a modal dialog and `xeXamDispatchDialog` blocks the