Files
BFM-decomp/cookbook/C0403.md
T

1.6 KiB

§362 — TWO TRAPS WHEN A CARVE MOVES A STUB INTO THE -O0 TU (P31 S68; byte-proven, 6 fns / 2,547 ins across ov_MAIN_012 / ov_SC02_037 / ov_SC03_107)

Banking an -O0 function that sits inside an -O2 object needs o0_subsplit to cut it into its own region (§116: opt level is per FILE). Two things then bite, both measured:

Trap A — rollout_o0.py goes BLIND to exactly the stubs you just carved. Its stub_file_of() skips any file whose basename contains _o0, because its design assumes stub-in--O2-TU plus def-appended-to--O0-TU. A carve that moves the stub INTO the -O0 TU makes both the same file, so the driver reports no-stub / already banked? and banks nothing. Edit <ov>_o0d.c directly.

Trap B — do not keep the generated §8b carried decl layer. The carve emits #include "../shared/engine_core.h" plus ~1,100 carried decls, which conflict with the shared -O0 header on 7 symbols (func_80015978 void*/s32, func_800CF854 void/s32, func_801336E8, D_801274C8/CC/D0). Replace the TU wholesale with the minimal fleet-standard form — legitimate precisely when the carved region holds only the functions the shared header defines (here 0xD44 = 0xC08 + 0x13C, exact).

Both carve and bank are byte-gated: the carve must be byte-NEUTRAL (sha1 == check.<ov>.sha, interleave_check ALIGNED, config/overlays.mk unchanged), and only then does the bank get gated. Derive AND carve under .run/auto/gate.<ov>.lock — a plan derived outside the lock can describe a tree state that never existed (the c03cd6f3a rule; a concurrent recovery lane was observed editing the very TU this carve splits, mid-analysis).