From d97e7df41f290d94b29a12ba29ed972916b9c285 Mon Sep 17 00:00:00 2001 From: ReaperOfVeriod Date: Wed, 14 Oct 2026 05:56:00 +0200 Subject: [PATCH] Second decode error in the same investigation; stopping rather than trusting this decoder Following e1482ab I disassembled the function supplying r2 and made two errors, both mine. First I read the jal target as 0x2ee178 when it is 0x2ee138 -- 0x0bb84e << 2 is 3,072,312. Second, at the correct address the bytes do not decode: d8a10000 is opcode 0x36, which is not a valid MIPS major opcode for user-space code. The coherent readings are that this is data, that the decomp's extent is mis-bounded, or that the jal target is still wrong. Stopping here deliberately. An un-masked branch target that reported a false negative, and a transposed address that produced plausible-looking garbage, are enough to make anything else from this decoder untrustworthy. The next step is not another immediate scan or another hand-decoded disassembly -- it is tools/overlay-anchors, which links capstone, verified against a known-good function first. The established chain, with nothing inferred beyond it: 0x3a3d70 jal 0x2ee138 target decoded, callee unidentified 0x3a3d84 jal 0x3a7c30 r2 = return value of the above 0x3a7c30 580 bytes, never writes r2 0x3a7d88 jal 0x3a8060 passes r2 through 0x3a8060 addiu r17, r18, 0xc0 with 0xd0 and 0xe0; 16-byte-stride walk What 0x2ee138 returns is unknown, and it is the single remaining link between the program and moby_classes.offset. 284 passing with the disc present, clippy clean. --- docs/plan/level-assets.md | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/docs/plan/level-assets.md b/docs/plan/level-assets.md index 8b45738..d9ed3f9 100644 --- a/docs/plan/level-assets.md +++ b/docs/plan/level-assets.md @@ -2314,3 +2314,45 @@ worth nothing until the decoder is checked against a case where the answer is already known. `jal 0x3a8060` decoded correctly under a different constant in the same probe and I did not notice, because one probe reporting a plausible number is as convincing as one reporting zero. + +### Second decode error, and why the hand-rolled decoder is now untrusted + +Following `e1482ab`, I disassembled the function that supplies `r2`. Two errors, +both mine: + +**First: transposed digits.** I read the `jal` target as `0x2ee178`. It is +`0x2ee138` -- `0x0bb84e << 2` is 3,072,312. I disassembled the wrong address and +got obviously nonsensical output, which is the only reason it was caught. + +**Second, and the one that matters: at the correct address the bytes do not +decode.** + + 0x2ee138 d8a10000 opcode 0x36 + 0x2ee13c d8c20000 opcode 0x36 + 0x2ee140 4bc2086c opcode 0x12 (COP2) + 0x2ee144 00000000 nop + 0x2ee148 03e00008 jr $ra + +`0x36` is not a valid MIPS major opcode for user-space code. The only coherent +readings are that this is data rather than code, that the function extent from the +decomp is mis-bounded, or that the `jal` target is still wrong. + +**I am stopping here rather than continuing.** Two decode bugs in the same +investigation -- an un-masked branch target that reported a false negative, and a +transposed hex address that produced plausible-looking garbage -- are enough to +make anything else produced by this same hand-rolled decoder untrustworthy. The +next step is not another immediate scan or another hand-decoded disassembly. It is +to use `tools/overlay-anchors`, which links capstone and has a proper MIPS +decoder, and to verify it against a known-correct function before trusting +anything it says. + +The chain as far as it is established, with nothing inferred beyond it: + + 0x3a3d70 jal 0x2ee138 target decoded, callee not yet identified + 0x3a3d84 jal 0x3a7c30 r2 = v0, the return value of the above + 0x3a7c30 580 bytes, never writes r2 + 0x3a7d88 jal 0x3a8060 passes r2 through + 0x3a8060 addiu r17, r18, 0xc0 with 0xd0 and 0xe0; 16-byte-stride walk + +Everything above that is verified; what `0x2ee138` returns is **unknown**, and it +is the single remaining link between the program and `moby_classes.offset`.