Skip to content

fork-instrument: narrow indirect fork reachability#715

Open
brandonpayton wants to merge 1 commit into
debugger/pr701-pure-scalar-materializationfrom
debugger/kd-ea0-slot-reachability
Open

fork-instrument: narrow indirect fork reachability#715
brandonpayton wants to merge 1 commit into
debugger/pr701-pure-scalar-materializationfrom
debugger/kd-ea0-slot-reachability

Conversation

@brandonpayton

Copy link
Copy Markdown
Member

Summary

This PR narrows wasm-fork-instrument's indirect fork-reachability closure when a call_indirect site is statically proven to index a table slot that cannot dispatch to the fork-path target.

It keeps correctness first:

  • direct reverse closure is unchanged and unbounded;
  • return_call_indirect follows the same rule as call_indirect;
  • literal i32.const and folded constant i32.add / i32.sub indexes can use active-element constant slots;
  • dynamic indexes, passive table.init, dynamic table writes, unknown element refs, and copied table state stay conservative.

This is stacked on PR #714 (debugger/pr701-pure-scalar-materialization) and is the separate reachability follow-up for kd-ea0.

Before / After Discovery

Compared origin/debugger/pr701-pure-scalar-materialization against this branch with wasm-fork-instrument --discover-only on the same inputs. Counts are total (local, import).

Input Old closure New closure Delta Notes
Synthetic safe-slot fixture 3 (2 local, 1 import) 2 (1 local, 1 import) -1 Excludes the caller whose literal index selects the safe slot.
d_07_fork_call_indirect.wasm 4 (3 local, 1 import) 4 (3 local, 1 import) 0 D indirect fork coverage remains included.
k_04_fork_in_qsort_comparator.wasm 15 (14 local, 1 import) 15 (14 local, 1 import) 0 qsort callback fork path remains included.
k_07_fork_from_atexit.wasm 28 (27 local, 1 import) 28 (27 local, 1 import) 0 atexit callback fork path remains included.
p_04_popen_pclose.wasm no kernel.kernel_fork import no kernel.kernel_fork import n/a No fork-path set reported by design.
p_09_posix_spawn_fork.wasm no kernel.kernel_fork import no kernel.kernel_fork import n/a No fork-path set reported by design.
bash.wasm 1446 (1445 local, 1 import) 1446 (1445 local, 1 import) 0 No package improvement claim.
dash.wasm 322 (321 local, 1 import) 322 (321 local, 1 import) 0 No package improvement claim.
ruby.wasm 5246 (5245 local, 1 import) 5246 (5245 local, 1 import) 0 Confirms large dynamic-index case still completes and stays conservative.

While preparing this report, the first implementation made the Ruby analysis exceed the 90s report timeout because unknown-index queries scanned all known slots repeatedly. The final commit keeps a table-level union cache for known slot functions, so ruby.wasm completes with the same closure count as the old analyzer.

Validation

Ran from /Users/brandon/src/kandelo-kd-ea0 unless noted.

  • cargo fmt -p fork-instrument: passed using host cargo fmt; scripts/dev-shell.sh cargo fmt -p fork-instrument failed because the dev shell currently lacks cargo fmt.
  • bash scripts/dev-shell.sh cargo test -p fork-instrument --target aarch64-apple-darwin --test call_graph constant_slot_pointing_to_safe_target_excludes_indirect_caller -- --nocapture: passed, 1 passed / 0 failed.
  • bash scripts/dev-shell.sh cargo test -p fork-instrument --target aarch64-apple-darwin --test call_graph -- --nocapture: passed, 23 passed / 0 failed.
  • bash scripts/dev-shell.sh cargo test -p fork-instrument --target aarch64-apple-darwin: passed, 177 passed / 0 failed; doctests 0.
  • cd host && bash ../scripts/dev-shell.sh npx vitest run test/fork-instrument-coverage.test.ts: passed, 41 passed / 0 failed / 8 skipped.
  • bash scripts/dev-shell.sh bash scripts/check-abi-version.sh: passed; ABI snapshot, libc header, and TS bindings are in sync.
  • bash scripts/dev-shell.sh cargo build -p fork-instrument --target aarch64-apple-darwin: passed for both the base analyzer and this branch's analyzer before running the before/after discovery report.

Not Run

  • Full cd host && npx vitest run: not run. The focused fork-instrument coverage suite exercises the host-visible fork paths relevant to this static analysis change.
  • cargo test -p kandelo --target aarch64-apple-darwin --lib, scripts/run-libc-tests.sh, and scripts/run-posix-tests.sh: not run. This PR changes fork-instrument static analysis and docs only; it does not change kernel, syscall, libc, VFS, fd, signal, process, memory, or host-runtime semantics.
  • Browser verification: not run. This PR does not claim browser stack recovery or browser behavior changes.

ABI / Artifacts

No ABI version change, no wpk_fork_* export change, no save-buffer layout change, and no package artifacts or package revisions are changed. Future rebuilt package bytes may change if their modules contain statically provable safe-slot false positives.

Model active element segments by constant table slot and infer literal or folded constant call_indirect indexes before adding indirect fork callers. Dynamic indexes, passive table.init, dynamic table writes, and table.copy remain conservative so possible fork paths are still instrumented.

Add WAT fixtures for proven safe-slot exclusion, fork-slot inclusion, folded constants, unknown indexes, dynamic writes, and return_call_indirect. Document the slot-sensitive rule and the remaining conservative boundaries for porters.
@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown

Phase B-1 matrix build status — pr-715-staging

ABI v15. 52 built, 0 failed, 52 total.

Package Arch Status Sha
bc wasm32 built a94d05b7
bzip2 wasm32 built 88684fcc
coreutils wasm32 built 22e8c2c9
curl wasm32 built 37455698
dash wasm32 built acccb4e4
diffutils wasm32 built f3961259
dinit wasm32 built a2486cf5
fbdoom wasm32 built 53a09277
file wasm32 built 4c45d90f
findutils wasm32 built 644fdf41
gawk wasm32 built 8140a749
git wasm32 built f008297f
grep wasm32 built 525f1019
gzip wasm32 built 38fa7618
kandelo-sdk wasm32 built 7b7ce355
kernel wasm32 built b69163ce
less wasm32 built 119b7aa1
lsof wasm32 built 6f055952
m4 wasm32 built bd47eb9b
make wasm32 built 303e83a3
mariadb wasm32 built 86896849
mariadb wasm64 built 8e38d51d
modeset wasm32 built eae6de87
msmtpd wasm32 built be861058
nano wasm32 built 6dcb6d34
ncurses wasm32 built 0c8219c1
netcat wasm32 built afe19f60
nginx wasm32 built b79d498c
php wasm32 built d179375f
posix-utils-lite wasm32 built 5a899556
sed wasm32 built ed13e28a
tar wasm32 built c0f03a87
tcl wasm32 built f6e01a08
unzip wasm32 built c483136b
userspace wasm32 built 14ea7145
vim wasm32 built 7cb87d3d
wget wasm32 built 3d44ee5c
xz wasm32 built 8c17fb6b
zip wasm32 built 54c0cbfd
zstd wasm32 built 817e623a
bash wasm32 built 258821c4
mariadb-test wasm32 built a4c67878
mariadb-vfs wasm32 built 524b6f23
mariadb-vfs wasm64 built d29226bc
nethack wasm32 built 1e53e846
vim-browser-bundle wasm32 built b0a9ac6a
nethack-browser-bundle wasm32 built 7edd72aa
rootfs wasm32 built 15626ca8
shell wasm32 built 48cac374
lamp wasm32 built 34eb3b9f
node-vfs wasm32 built 69deaade
wordpress wasm32 built de1706bd

Auto-generated; replaced on each push. Raw data in the publish-status workflow artifact.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant