# Exact-matching methodology This document records recurring January 2002/XDK 3911 matching failures and the source-level changes that have actually moved them. It is an operational checklist, not permission to accept approximate code. Exact status still requires padded bytes, normalized bytes, relocation count/type/address/target/ addend, ABI, build, and regression evidence. ## Triage decision tree 1. Establish the untouched baseline: padded size, meaningful size, normalized hash, relocation table, first differing instruction, and sibling status. 2. If relocation targets or addresses differ, recover source structure before tuning registers: statement order, branch fall-through, linkage, field ownership, and eager versus lazy evaluation. 3. If the target uses 16-bit arithmetic, map every promotion and truncation boundary. Treat this separately from register allocation. 4. If instruction structure is identical modulo registers, locate a hardware-forced anchor before changing declarations: - `rep movs`/`rep stos` force ESI, EDI, and ECX; - variable shifts force CL/ECX; - multiply and divide force EAX/EDX; - ABI/API boundaries may force ECX/EDX or preserve callee-saved registers. 5. For private same-translation-unit helpers, make callers exact first. Start from the hardware-forced caller and propagate the convention toward the helper; do not tune the helper in isolation. 6. Stop after five evidence-based source shapes if only an interchangeable register or dependency-free instruction ordering remains. Record and park the case instead of perturbing unrelated exact code. 7. Run the strict semantic ledger before assigning work. A function already listed in `build/semantic_report.json` must not be reimplemented merely because objdiff displays a fuzzy percentage. 8. When a target macro or expression is known from an exact donor, preserve its **lvalue topology** as well as its arithmetic. VC7 can emit different code for mathematically equivalent forms such as transforming a temporary and transforming the destination member in place. Prefer the donor's assignment destination, member access, and read-back pattern before permuting commutative terms or adding artificial temporaries. ## Blocker classes ### A. Recoverable source-shape mismatch The emitted differences indicate that the reconstructed C is not yet shaped like the original source. Productive levers include statement order, branch polarity, local lifetime, explicit versus inlined expressions, linkage, and structure ownership. ### B. Integer promotion/truncation mismatch The target contains operand-size prefixes, partial-register operations, or `movsx`/`movzx` boundaries that ordinary C promotions erase. Recover the width of the accumulator and place signed/unsigned casts only at disassembly-proven boundaries. Do not file this as a register mirror. ### C. Private-ABI/register fixed point The instruction graph, sizes, and relocations agree, but a translation-unit cluster assigns interchangeable registers differently. Find a forced-register caller and solve outward. If the complete cluster remains a pure permutation after the checklist, park it as a compiler allocation tie. ### D. Scheduler/lifetime tie Two dependency-free instructions are transposed, or local lifetimes alter spills without changing semantics. Try only source changes justified by the surrounding target ordering. Do not add undefined behavior, inline assembly, compiler pragmas, or flag changes to force the result. ### E. Comparator/reporting mismatch The machine code is exact but COFF producers encode internal labels or relocation placeholders differently. Credit only through the hardened semantic comparator and the reviewed `config/semantic_matches.json` allowlist; each entry is reverified against current objects during `ninja progress`. ## Case catalog | Case | Class | Evidence and source lever | Outcome / next action | |---|---|---|---| | `lra_new` (`f0e5a48`) | A | Reordering field initialization to the target's emitted store order aligned the failure block and lifecycle setup. | Exact; make store-order recovery a standard first pass. | | `object_new` (`claude/object-new-16`, then the isolated XDK scheduler-control lane) | A then D | Writing the cleanup as failure-first eliminated 10 relocation differences and two divergence regions. Only `fmuls` versus deferred `add esp, 0x18` ordering remained. A production-context reproducer then tested 20 one-factor legal-C controls; all forms that moved `fmuls` first also changed x87 dataflow or other bytes. | Preserve failure-first shape; park the dependency-free scheduler tie unless new source provenance identifies a distinct original expression. | | `hashtable_remove` (`f2d30b9`) | A | Source-oriented comparison order, reload points, and the shared deletion path aligned 496 padded bytes and 20 relocations. | Exact; use comparison polarity and reload timing before register tuning. | | `csstrcasecmp` (`e5852f8`, `claude/csstrcasecmp-15`) | A then C | `if (c1 != c2)` reproduces the target operand order; `if (c2 != c1)` does not. The remainder is an ESI/EDI parameter/local permutation. | Land only evidence-backed logic changes; handle the remaining mirror through a forced-register caller or park. | | terminal tab stops (`a917110`) | A | Identical six-byte data still failed because `static` produced storage class 3 while the target symbol was external, class 2. | Exact after external linkage/name recovery; audit symbol class, not just bytes. | | `generate_private_key` (`public_key_crypt.obj`) | A | Applying the exact `SWAP4` donor arithmetic to a local temporary selected the wrong accumulator form across hundreds of equivalent expression trees. Assigning the helper result to `private_key->dwords[i]` and applying `SWAP4` directly to that same member preserved frontend lvalue provenance and reproduced January exactly. | Exact without assembly, volatility, undefined behavior, or flag changes; preserve donor lvalue topology before classifying a commutative residual as a register tie. | | `objects.obj` BSS ownership | A/E | Explicit zero initialization plus declaration order recovered the linked 13-byte layout (`object_name_list@0`, `object_memory_pool@4`, `object_globals@8`, debug byte `@12`) without changing any exact function. January PDB/public-symbol and cross-TU-reference evidence proves the first three globals are source-private; csplit had defaulted their manually split labels to external because `symbols.json` omitted `"static": true`. | Keep the globals source-static and mark exactly those three csplit symbols static. Regenerate the split target and require exact size, offsets, storage classes, and whole-TU regression; do not paper over the difference with a semantic allowlist. | | `tif_packbits.obj` (`7c9c092`) | A | Target linkage, RCSID ownership, `_csmemcpy`, and disassembly-proven TIFF field offsets were required. Repository header layout differed from the target object. | Five functions and data exact; raw offsets are acceptable only with explicit target-layout evidence. | | random-math globals (`aef5a7c`) | A | Replacing an anonymous address placeholder with the real externally linked 20-byte globals structure fixed BSS ownership and relocation addends. | Exact functions retained; model globals explicitly before function tuning. | | `default_hash_function` (`f2d30b9`) | B | Target uses 16-bit product/partial-register code while natural C promotes the polynomial and key byte to 32 bits (80 target versus 64 candidate bytes). | Reopen only with a promotion/truncation lattice derived instruction by instruction. | | LRA verify/free/lock cluster (`f0e5a48`) | C | Seven functions share cache-in-EBX versus cache-in-EDI and private helper conventions. Isolated helper shaping did not move the joint allocation. | Anchor on callers with forced registers, then propagate; otherwise park the whole permutation together. | | hashtable probe helper `code_0010b270` (`073e794`) | C | Size, relocations, control flow, and operations agree; two return blocks mirror ECX and EDX. | Try return-materialization/single-exit shape once under the checklist, then park if unchanged. | | `reference_list_copy` lane | C | Target and candidate reduce to the same operations with a callee-saved register mirror after source-shape attempts. | Revisit only from its caller cluster and a hardware-forced anchor. | | `object_get_marker_by_name` lane | A | Recovering the direct object-header block access removed the artificial wrapper lifetime and reproduced the original call/dataflow structure. | Exact: 272 padded bytes, 11 relocations, and normalized SHA-256 `302db0f36677f304c6d076e0f16f3bb4e9603519b34d650a4311c296bd21c8cf`. | | `object_compute_node_matrices` (`claude/object-compute-node-matrices` plus the E2 closeout) | D | The corrected C now has the exact 6,560-byte padded size, `0xA44` frame, and 318 relocation identities. The first address drift is relocation 245: January homes `tag_get_name`'s EAX result to `[ebp-8]`, while VC7 keeps EAX live. Independent source, PDB, tail-diff, and legal-C shape audits found no controllable semantic or structural difference. | Park as an EAX-liveness/register-allocation tie. Reopen only if new local-variable provenance or a demonstrated legal-C compiler control appears. | | `data_decode_array` (`d0a735d`) | E | Padded bytes and 31 semantic relocations are exact; objdiff reports 85.19% because one target symbol plus addends corresponds to several rebuilt local labels. | Credited through the dynamic semantic ledger; no source work required. | | 37-function switch/local-label set (`24c998a`) | E | Full dual sweep found 37 real functions and 21,051 meaningful bytes exact under conservative COFF normalization but fuzzy under objdiff. | The allowlist is reverified on every progress run; uncertain or changed entries fail closed. | ## Complexity gate For large aggregate objects such as `objects.obj`, queue a remaining function only when all of the following hold: - padded size is below approximately `0x60`; - local state is small and unambiguous; - relocation count is low; - no large inlined helper or private-ABI cluster dominates the function. Larger functions require a specific leverage reason (new structure proof, forced-register anchor, or reusable subsystem insight) before consuming an implementation lane. ## External type-information gate HCEX, Halo PC, October 2001, and community sources are hypothesis generators. Every imported field or enum value must carry a January-Xbox disassembly proof. Unproven spans remain named `reserved`/`unknown` and documented as such. No CEA offset enters a trusted header merely because it compiles or looks plausible. ## Original-bug policy Exact builds preserve confirmed original behavior. Mark only defects supported by binary and layout evidence: ```c /* BUG (preserved for exact matching): . * A corrected build should . */ ``` Keep the safe fix disabled in the exact build. Do not label suspicious code as a bug without target-machine and structure-layout proof.