diff --git a/docs/re/BACKLOG.md b/docs/re/BACKLOG.md index 6cbbc4c4..36f7e7e7 100644 --- a/docs/re/BACKLOG.md +++ b/docs/re/BACKLOG.md @@ -35,8 +35,22 @@ unknown, what evidence exists, and what the first step would be. Move an item in which is what an engine-entered abort handler should look like. ⚠️ First seeding attempt moved NOTHING (85.0 %→85.0 %, 5→5) because `dominating_conditions()` builds its own entry set — fix-the-instance again. - 🟡 Still open: reach only 85.0 %→**85.2 %**, so what starts the other ~15 % is - unknown; `entry_a` is unidentified; 6 of 88 values do not land on an instruction. + ✅ **(2026-08-27) `entry_a` IDENTIFIED — and it is NOT an entry point.** It is the + offset where the phase's CODE ends and a trailing **DATA table** begins: 8-byte + typed records, tag `0x19` = int, tag `0x1A` = IEEE float, and the dispatcher only + has 25 opcodes (`cmplwi 0x18`). **44 of 44 phases: the first opcode > 0x18 is + exactly `entry_a`, zero exceptions**; only tags 0x19 (1394) and 0x1A (675) occur. + So the record is `0x1883, base, size, 0, code_end, force_end_handler`. ⚠️ This + also retires the earlier "93.2 % land on a valid instruction" test as TOO WEAK — a + data record has length 8 and passes "nonzero, even". 🔧 `isl.linear_offsets` was + decoding all **2069** data records as instructions (1.23 %); now stops per phase + at the boundary: **168251 → 166182**, op>0x18 **2069 → 0**, call-site coverage + held at **25705/25705**, exits still 0 unreachable, conditions unchanged at 400. + ⚠️ The first attempt at that fix cost **36 %** of the stream (168251→107596, + exits 0→74) because the walk is global and stopped at phase 1's table — it must + SKIP and resume per phase. 🟡 Still open: the table's contents are undecoded (its + int values hit the stream 46/51 vs 29.5 % chance but **0 are unreached + run-starts**), and what starts the other ~15 % of code is still unknown. ## ✅✅ SOLVED — the mission freeze was a modal sign-in dialog (2026-08-26) diff --git a/docs/re/data/isl-phase-guards-all.txt b/docs/re/data/isl-phase-guards-all.txt index 84249560..901bf770 100644 --- a/docs/re/data/isl-phase-guards-all.txt +++ b/docs/re/data/isl-phase-guards-all.txt @@ -7,7 +7,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 8256 of 9879 instructions (83.6%). +CFG reached 8083 of 9706 instructions (83.3%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -68,7 +68,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 15821 of 18739 instructions (84.4%). +CFG reached 15650 of 18568 instructions (84.3%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -174,7 +174,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 8482 of 11105 instructions (76.4%). +CFG reached 8272 of 10895 instructions (75.9%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -286,7 +286,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 3688 of 4377 instructions (84.3%). +CFG reached 3605 of 4294 instructions (84.0%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -358,7 +358,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 4316 of 5194 instructions (83.1%). +CFG reached 4230 of 5108 instructions (82.8%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -419,7 +419,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 8409 of 9514 instructions (88.4%). +CFG reached 8286 of 9391 instructions (88.2%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -520,7 +520,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 7254 of 8026 instructions (90.4%). +CFG reached 7195 of 7967 instructions (90.3%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -621,7 +621,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 6642 of 7610 instructions (87.3%). +CFG reached 6526 of 7494 instructions (87.1%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -684,7 +684,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 9008 of 10053 instructions (89.6%). +CFG reached 8894 of 9939 instructions (89.5%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -803,7 +803,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 2578 of 2749 instructions (93.8%). +CFG reached 2544 of 2715 instructions (93.7%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -839,7 +839,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 6805 of 7253 instructions (93.8%). +CFG reached 6728 of 7176 instructions (93.8%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -903,7 +903,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 6202 of 6628 instructions (93.6%). +CFG reached 6141 of 6567 instructions (93.5%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -939,7 +939,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 4302 of 5258 instructions (81.8%). +CFG reached 4217 of 5173 instructions (81.5%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -980,7 +980,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 3305 of 3709 instructions (89.1%). +CFG reached 3228 of 3632 instructions (88.9%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -1037,7 +1037,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 6767 of 8106 instructions (83.5%). +CFG reached 6624 of 7963 instructions (83.2%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -1089,7 +1089,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 836 of 1179 instructions (70.9%). +CFG reached 775 of 1118 instructions (69.3%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -1123,7 +1123,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 881 of 925 instructions (95.2%). +CFG reached 871 of 915 instructions (95.2%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -1144,7 +1144,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 528 of 560 instructions (94.3%). +CFG reached 518 of 550 instructions (94.2%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -1165,7 +1165,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 811 of 846 instructions (95.9%). +CFG reached 801 of 836 instructions (95.8%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -1186,7 +1186,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 378 of 411 instructions (92.0%). +CFG reached 368 of 401 instructions (91.8%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -1207,7 +1207,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 706 of 738 instructions (95.7%). +CFG reached 696 of 728 instructions (95.6%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -1228,7 +1228,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 374 of 406 instructions (92.1%). +CFG reached 364 of 396 instructions (91.9%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -1249,7 +1249,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 4027 of 4235 instructions (95.1%). +CFG reached 3984 of 4192 instructions (95.0%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -1306,7 +1306,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 9577 of 9936 instructions (96.4%). +CFG reached 9525 of 9884 instructions (96.4%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -1341,7 +1341,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 3896 of 5604 instructions (69.5%). +CFG reached 3820 of 5528 instructions (69.1%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -1382,7 +1382,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 2468 of 3031 instructions (81.4%). +CFG reached 2410 of 2973 instructions (81.1%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -1440,7 +1440,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 2193 of 2401 instructions (91.3%). +CFG reached 2168 of 2376 instructions (91.2%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. @@ -1476,7 +1476,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 14840 of 19779 instructions (75.0%). +CFG reached 14758 of 19697 instructions (74.9%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. diff --git a/docs/re/data/isl-stage02-phase-guards.txt b/docs/re/data/isl-stage02-phase-guards.txt index aacfab7c..09429b64 100644 --- a/docs/re/data/isl-stage02-phase-guards.txt +++ b/docs/re/data/isl-stage02-phase-guards.txt @@ -7,7 +7,7 @@ entry to that `END_PHASE` passes through it, so it is NECESSARY for the phase to end that way. Reachability alone is the wrong query here — in a poll loop both successors reach the exit. -CFG reached 15821 of 18739 instructions (84.4%). +CFG reached 15650 of 18568 instructions (84.3%). `precond` = necessary: the exit cannot happen unless it holds. `TRIGGER` = also SUFFICIENT: once it holds the exit is unavoidable. diff --git a/docs/re/isl-stream-entry-points.md b/docs/re/isl-stream-entry-points.md index 756cf660..92a717bb 100644 --- a/docs/re/isl-stream-entry-points.md +++ b/docs/re/isl-stream-entry-points.md @@ -1,4 +1,4 @@ -# ✅ The mission-level `0x1883` record carries two ENTRY POINTS — and they were the missing exits +# ✅ The mission-level `0x1883` record: one entry point and one code/data boundary Every phase exit in all 28 stages is now reachable. `data/isl-phase-guards-all.txt` went from **5 of 177 exits unreachable** to **0**. @@ -33,9 +33,12 @@ one per phase, whose operand is the phase's code base, and notes they each end 0x1883, base_delta, size, 0, entry_a, entry_b ; entries PHASE-RELATIVE ``` -**Measured over all 28 stages: 82 of 88 of those values land on a valid -instruction — 93.2 %, against a 38.6 % chance rate for a random 4-aligned -offset.** +~~**Measured over all 28 stages: 82 of 88 of those values land on a valid +instruction — 93.2 %, against a 38.6 % chance rate.**~~ +⚠️ **That test was too weak** — see *What `entry_a` really is* below. A trailing +data record has length 8 and so passes "nonzero, even length"; the 93.2 % counted +data as code. The `entry_b` result stands on a different footing: those targets +were matched against `isl.call_sites()`, an independent enumeration. And for Stage 02 the second entry of each record is the phase's force-end handler: @@ -72,3 +75,52 @@ own size earlier in this corpus. With both patched: exits **5 → 0**. Stage-02 records; what the first entry of each pair is has not been checked. * **6 of 88 values do not land on an instruction.** Not investigated — they may be absent phases, a different record variant, or a decode edge. + + +## 🔴 What `entry_a` really is — NOT an entry point + +Disassembling the three Stage-02 `entry_a` targets shows **opcodes 0x19 and +0x1A**, and the dispatcher's table has 25 entries (`cmplwi 0x18`). Those are not +instructions at all: + +``` +014848: 00000819 tag 19 00000019 int 25 +014850: 00000819 tag 19 00002B20 int +014858: 0000081A tag 1A 00000000 float 0.0 +014860: 00000819 tag 19 00000005 int 5 +014868: 00000819 tag 19 00002B88 int +014870: 0000081A tag 1A 3F000000 float 0.5 +``` + +Each phase region **ends with a trailing DATA table** of 8-byte typed records — +tag `0x19` = int, tag `0x1A` = IEEE float — and `entry_a` is where it starts. + +**Confirmed across the disc: in 44 of 44 phases, the first offset whose opcode +exceeds 0x18 is exactly that phase's `entry_a`. Zero exceptions.** Only two tags +ever appear: 1 394 × `0x19` and 675 × `0x1A`. + +So the record is `0x1883, base, size, 0, code_end, force_end_handler` — one +boundary and one entry. + +🟡 The table's contents are **not decoded**. Its int values do land on the +instruction stream more often than chance (46/51 vs 29.5 %), but **0 of them are +unreached run-starts** — so this is not what starts the unreachable code either. + +## ✅ And the decoder was reading that data as code + +`isl.linear_offsets` was decoding all **2 069** of those records as instructions, +1.23 % of the stream. Fixed by stopping each phase's walk at its boundary: + +| | before | after | +|---|---|---| +| decoded instructions | 168 251 | **166 182** = 168 251 − 2 069 | +| records with opcode > 0x18 | 2 069 | **0** | +| **call sites covered** | 25 705 / 25 705 | **25 705 / 25 705** | +| exits unreachable | 0 | 0 | +| conditions with unknown LHS | 400 | 400 | + +⚠️ **The first attempt at that fix destroyed 36 % of the stream** — 168 251 → +107 596, exits 0 → 74 — because `linear_offsets` is one global walk from the +first phase base, so stopping at phase 1's table lost every later phase. It has +to *skip* the region and resume at the next base. A count moving hard in the +wrong direction is the same signal as one that will not move. \ No newline at end of file diff --git a/tools/re-capture/isl.py b/tools/re-capture/isl.py index be8b0aac..75df8bc6 100755 --- a/tools/re-capture/isl.py +++ b/tools/re-capture/isl.py @@ -254,13 +254,36 @@ def linear_offsets(b, start=None): reaching a call site needs no control-flow reconstruction at all. """ end = struct.unpack_from('>I', b, 0x0C)[0] # symtab1 = end of code - if start is None: - start = phase_bases(b)[0] + # Walk EACH PHASE separately: a phase's code runs from its base up to that + # phase's trailing data table, and the next phase's code begins at its own + # base. A single global walk stops dead at phase 1's table and loses every + # later phase -- that mistake cost 36% of the instruction stream. + bases = phase_bases(b) + if start is None or start in bases: + out = [] + limits = list(bases[1:]) + [end] + for base, hi in zip(bases, limits): + out.extend(_walk_one(b, base, hi)) + return out + return _walk_one(b, start, end) + + +def _walk_one(b, start, end): out = [] off = start while off + 4 <= end: + w = struct.unpack_from('>I', b, off)[0] + # The dispatcher's table has 25 entries (`cmplwi 0x18`), so an opcode + # above 0x18 is NOT an instruction. Each phase region ends with a + # trailing DATA table of 8-byte typed records -- tag 0x19 = int, + # tag 0x1A = IEEE float -- and its start is the FIRST entry of that + # phase's mission-level `0x1883` record. Measured: in 44 of 44 phases + # across all 28 stages the first opcode > 0x18 is exactly that value. + # Decoding those 2069 records as instructions was 1.23% of the stream. + if (w & 0xFF) > 0x18: + break out.append(off) - ln = (struct.unpack_from('>I', b, off)[0] >> 8) & 0xFF + ln = (w >> 8) & 0xFF if ln == 0 or ln % 2: break off += ln