Root cause: the per-section indexing used throughout this investigation was wrong
The verificationf2d7e7easked for. Reference case: the tool disassembles 0x2ee138 as 0x4bc00083; reading the flat overlay at 0x2ee138 - LIT_BASE gives 83 00 c0 4b, little-endian 0x4bc00083. Match. Correct mapping is off = ram - LIT_BASE indexed into the whole overlay.bin. What I used in every probe: off = addr - secs[6].dest indexed into secs[6].data, and OverlaySection::data includes the 16-byte section header. Every read was displaced. Invalidated: - cee17c9's addiu r17, r18, 0xc0 disassembly, the 16-byte-stride walk, and the 'address not float' conclusion. Built on wrong bytes. - the immediate-frequency and neighbour-enrichment numbers in3ea5ab7anda2f8c92. Scanned per-function windows, so uniformly displaced: ratios are probably robust, exact counts are not measured on the bytes they claim. -e1482ab,d97e7df,f2d7e7e: the jal decoding was verified correct, so branch targets stand; what lives at them was read wrongly. Survives intact: every chunk-offset measurement in the tie and overlay work, which read core_data and the overlay flat and never went through the section index. Fix: never index secs[n].data by addr - secs[n].dest. Either use overlay[addr - LIT_BASE], or add a helper that accounts for the 16-byte header so call sites cannot forget it -- and verify it against a word the decomp pins, as above. This was available from the first probe and skipped sixteen times. 284 passing with the disc present, clippy clean.
This commit is contained in:
@@ -2400,3 +2400,53 @@ independently known, and only then re-read `0x2ee138`. Until that mapping is
|
|||||||
verified, **no address in this investigation that I computed by hand is
|
verified, **no address in this investigation that I computed by hand is
|
||||||
trustworthy** -- including the `0x3a8060` walk, which happened to decode but may
|
trustworthy** -- including the `0x3a8060` walk, which happened to decode but may
|
||||||
have been read from the wrong bytes.
|
have been read from the wrong bytes.
|
||||||
|
|
||||||
|
### Root cause verified: the per-section indexing used throughout was wrong
|
||||||
|
|
||||||
|
The check `f2d7e7e` asked for, finally performed.
|
||||||
|
|
||||||
|
**Reference case:** `tools/overlay-anchors` disassembles `0x2ee138` as
|
||||||
|
`0x4bc00083`. Reading the flat overlay at `0x2ee138 - LIT_BASE` gives the bytes
|
||||||
|
`83 00 c0 4b`, which is little-endian `0x4bc00083`. **Match.** The correct mapping
|
||||||
|
is
|
||||||
|
|
||||||
|
off = ram_address - LIT_BASE, indexed into the whole overlay.bin
|
||||||
|
|
||||||
|
with `LIT_BASE = 0x1A7C80`.
|
||||||
|
|
||||||
|
**What I used instead**, in every probe in this investigation:
|
||||||
|
|
||||||
|
off = addr - secs[6].dest, indexed into secs[6].data
|
||||||
|
|
||||||
|
and `OverlaySection::data` **includes the 16-byte section header** ("the 16-byte
|
||||||
|
header included, since it is the first `size` bytes of the section in the table",
|
||||||
|
`overlay_reloc.rs`). So every read was displaced, and the addresses I printed
|
||||||
|
against the bytes they actually came from were wrong.
|
||||||
|
|
||||||
|
**Scope of the invalidation, stated as precisely as I can:**
|
||||||
|
|
||||||
|
- `cee17c9` -- the `addiu r17, r18, 0xc0` disassembly, the 16-byte-stride walk,
|
||||||
|
the "it is an address not a float" conclusion. **Built on wrong bytes.**
|
||||||
|
- `3ea5ab7`, `a2f8c92` -- the immediate-frequency and neighbour-enrichment
|
||||||
|
numbers. These scanned `[off, off+size)` per function, so each window was
|
||||||
|
displaced by a constant. A uniform displacement preserves most of a function's
|
||||||
|
body and loses the first few instructions, so the counts are *approximately*
|
||||||
|
right and the ratios are probably robust -- but they are not measured on the
|
||||||
|
bytes they claim to measure, and cannot be quoted as exact.
|
||||||
|
- `e1482ab`, `d97e7df`, `f2d7e7e` -- the `jal` decoding itself was verified
|
||||||
|
correct, so the branch *targets* stand; it is what lives at them that was read
|
||||||
|
wrongly.
|
||||||
|
|
||||||
|
**The one result that survives intact** is the one that never went through the
|
||||||
|
section index at all: the chunk-offset measurements in the tie and overlay work,
|
||||||
|
which read `core_data` and the overlay flat.
|
||||||
|
|
||||||
|
**The fix, for whoever continues:** never index `secs[n].data` by
|
||||||
|
`addr - secs[n].dest`. Either use `overlay[addr - LIT_BASE]`, or add a helper that
|
||||||
|
subtracts the 16-byte header from `data` and states that it does. The second is
|
||||||
|
better -- it puts the header in one place instead of making every call site
|
||||||
|
remember.
|
||||||
|
|
||||||
|
And then: **verify it**, the way the check above verifies, against a word the
|
||||||
|
decomp already pins. I had that verification available from the first probe and
|
||||||
|
skipped it sixteen times.
|
||||||
|
|||||||
Reference in New Issue
Block a user