1.6 KiB
§235 — THE PHANTOM SYMBOL: A MASKED MATCH CAN CARRY A RELOCATION THAT DOES NOT EXIST (P31 S58b)
match_one masks HI16/LO16/jal identity (Law 1c). Therefore a draft can score a clean MATCH
while naming a symbol that is not in the binary at all, and the failure surfaces only at link time
in the whole-binary gate, with no per-instruction diff to steer you.
THE CARD. func_801800D0 (ov_SC03_029, banked twice, waves ar/bc). The Ghidra seed invented
DAT_801d9752. No such label exists: asm/ov_SC03_029/data/tail18.data.s defines only
D_801D9750/54/58/5C. The target reaches the middle halfword through the REAL label —
BYTE-VERIFIED in func_801800D0.s:
lui $at, %hi(D_801D9750 + 0x2)
sh $v0, %lo(D_801D9750 + 0x2)($at)
THE C SPELLING THAT FOLDS A CONSTANT INDEX INTO symbol + offset INSIDE %hi/%lo IS ARRAY
INDEXING ON AN INCOMPLETE-ARRAY EXTERN: extern u16 D_801D9750[]; … D_801D9750[1] = v;
A scalar extern u16 D_801D9752 emits bare %hi(D_801D9752) — right address, wrong relocation
TEXT, and an undefined symbol at link.
GENERALISATION. Whenever the target's own relocation lines show %hi(SYM + K), the source used one
object and indexed into it. Whenever they show two distinct %hi(SYM_A) / %hi(SYM_B) pairs for
adjacent addresses, the source used two distinct objects (§216, and see func_8018BB44 in §250).
Read the relocation TEXT, not the effective address.
BOUNDARY. This is not the extern-type conflict class (§12/§14c) — the symbol simply does not exist. Symptom is a link/gate failure with a green oracle and a clean type audit.