aboutsummaryrefslogtreecommitdiffstats
path: root/psp_out/PHASE2-PORT-RESULTS.md
blob: fd51f625f3681232e0ecbc1612bcd85798661b02 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# Phase 2 results — symbol porting with measured confidence

Tooling: `phase2_port_symbols.py` -> `phase2_port.json`.
Tiers: **EXACT** (identical bytes) · **CREATED** (identical bytes occurring
*uniquely*, function created because IDA had not recognised it) · **MNEM**
(identical mnemonic sequence, operands differ) · **FUZZY** (mnemonic similarity
>= 0.90) · **UNMATCHED** (deliberately left unnamed — never guessed).

## The validation gate: self-port must reach ~100%

Porting the reference symbols onto the reference's *own* build:

| family | self-port | verdict |
|---|---|---|
| HDCP 23.0.0.82 | **100.0%** (EXACT 101, CREATED 8, UNMATCHED 0) | PASS |
| SYS_DRV 0.49.0.54 | **100.0%** (EXACT 1139, CREATED 2, UNMATCHED 0) | PASS |
| ASD 33.0.1.21 | **100.0%** (EXACT 1548, CREATED 14, UNMATCHED 0) | PASS |
| sOS 0.49.0.54 | 98.5% (UNMATCHED 8) | PASS, explained below |

### The first run FAILED this gate and was fixed, not accepted
HDCP self-port initially scored **92.7%** — 8 reference functions unmatched in
their own binary. Cause: auto-analysis recognises 102 functions where the
reference has 109 (the gap flagged at the end of Phase 1). Rather than accept it,
an **EXACT-CREATED** pass was added: if a reference function's bytes occur
*uniquely* in the image, create the function there. That is a sound placement,
not a guess, and it took the self-port to 100%.

### Why sOS stops at 98.5% — and why that is correct behaviour
34 sOS reference functions have **byte sequences that are not unique within their
own image**. They are interchangeable micro-stubs:

    sos_nop_retarg / sos_nop_svc9A / sos_nop_hook1..3 / sos_nop_svcAE   2 bytes each
    exc_irq_hang / hang_0 / hang_1                                      4 bytes
    sos_stub_ret8_a/b/c, svc_8B_8F_7F_stub9, svc_94_95_84_stub9         4 bytes

There is no content-based way to tell `sos_nop_retarg` from `sos_nop_svcAE` —
they are identical bytes. The porter **refuses to place them** rather than
assigning a name by position. That is the anti-corner-cutting rule working as
intended, and these stubs are semantically irrelevant to diffing.

## Coverage achieved per family (named % of reference symbols)

| family | oldest build | newest build |
|---|---|---|
| sOS | 92.0% (0.49.0.37) | 98.5% (0.49.0.54) |
| SYS_DRV | 93.2% (0.49.0.37) | 100% (0.49.0.54) |
| HDCP | 59.6% (23.0.0.49) | 100% (23.0.0.82) |
| ASD | 47.5% (33.0.0.154) | 100% (33.0.1.21) |

Compare with the **4.4-12.9%** coverage of the previous diffing effort
(`PLAN-COMPLETE-VERSION-DIFF.md`). Even the worst build here (ASD 33.0.0.154 at
47.5%) is ~10x the old ASD coverage, and every modern build is above 85%.

## Honest reading of UNMATCHED
`UNMATCHED` does **not** mean the tool failed. It means the function diverged far
enough from the reference that no identity can be asserted at >=0.90 similarity.
For diffing purposes that is itself a signal — those functions are *structurally
changed*, and Phase 4 must report them as a separate class rather than silently
dropping them from a name-keyed comparison.

The ASD gradient is the clearest example: 820 unmatched at 33.0.0.154 falling
monotonically to 0 at 33.0.1.21, with the module growing 176 KB -> 208 KB over
that span. That is real churn, not matcher weakness.

## Note on the FUZZY tier
FUZZY fires rarely (0-22 per build). The 0.90 threshold plus the +-25% size
prefilter is strict by design; loosening it would trade correctness for coverage,
which is the wrong trade for a diffing baseline. Leaving these in UNMATCHED is
the safer outcome.

## Carry-forward into Phase 4
1. Diff only functions named at **EXACT / CREATED / MNEM** confidence in *both*
   builds being compared.
2. Report FUZZY-named functions separately (lower trust).
3. Report UNMATCHED as "structurally diverged" — a result, not a gap.
4. State per-pair how many functions were actually comparable.

================================================================================
# Phase 4 — gate result

**The pipeline was required to re-discover the known fixes before any new result
could be trusted. It did, and it refined them.**

| target | found | where |
|---|---|---|
| `sos_check_va_window_request` | YES | ADDED in `sos 0.49.0.51 -> 0.49.0.53` |
| `sysdrv_tee_map_shared_mem` | YES | ADDED in `sys_drv 0.49.0.51 -> 0.49.0.53` |
| `range_overlap_check` | YES | same pair |
| `ranges_must_not_overlap` | YES | same pair |

## And it corrected the existing documentation
Both findings are titled "FIXED-IN-54". They actually landed in **0.49.0.53**:

* the guard functions are absent from `.51`, present in `.53`;
* **`.53` text is byte-identical to `.54`** for all four functions;
* a **name-independent constant census** shows the sOS guard's window values
  (`0x3900000`/`0x3A00000`/`0x3800000`/`0x3700000`) occur **nowhere in the entire
  `.51` image**, but do in `.53` and `.54`;
* `0.49.0.53` is a genuine distinct build (sha256 differs from both neighbours in
  both families).

The original work compared `.51` against `.54` because **`.53` was not in the
archive then** — it is still missing from `versions/*.bin`, present only as an
ELF. Both FINDING docs have been annotated in place.

## Adjacent-pair change volumes (the new search surface)
    sOS      4, 12, 1, 1, 3, 5, 11, 3 changed per adjacent pair
    SYS_DRV  7, 38, 3, 16, 9, 7, 2, 12 changed per adjacent pair

These are the semantic deltas now available for triage — computed over 483-1142
comparable functions per pair, against the previous effort's 4.4-12.9% coverage.