diff --git a/.github/workflows/icicle-spike.yml b/.github/workflows/icicle-spike.yml new file mode 100644 index 0000000..89483a4 --- /dev/null +++ b/.github/workflows/icicle-spike.yml @@ -0,0 +1,43 @@ +name: Icicle feasibility spike + +on: + workflow_dispatch: + push: + paths: + - ".github/workflows/icicle-spike.yml" + - "experiments/icicle/**" + - "rust-toolchain.toml" + pull_request: + paths: + - ".github/workflows/icicle-spike.yml" + - "experiments/icicle/**" + - "rust-toolchain.toml" + +permissions: + contents: read + +jobs: + native-aarch64-probe: + runs-on: ubuntu-latest + timeout-minutes: 20 + defaults: + run: + working-directory: experiments/icicle + steps: + - name: Check out repository + uses: actions/checkout@v6 + + - name: Install pinned Rust toolchain + run: rustup show + + - name: Fetch pinned AArch64 SLEIGH sources + run: ./fetch-supported-ghidra.sh "$RUNNER_TEMP/ghidra" + + - name: Check formatting + run: cargo fmt -- --check + + - name: Lint native probe + run: cargo clippy --locked --all-targets -- -D warnings + + - name: Decode and interpret AArch64 instructions + run: cargo run --locked -- "$RUNNER_TEMP/ghidra/Ghidra/Processors" diff --git a/Cargo.toml b/Cargo.toml index 341be94..ac7af58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "crates/runtime-core", "crates/wasm-probe", ] +exclude = ["experiments/icicle"] resolver = "3" [workspace.package] diff --git a/README.md b/README.md index f822d8d..d40b0e6 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,8 @@ The project is in the Phase 0 feasibility stage described in [PLAN.md](PLAN.md). - `crates/runtime-core`: host-independent process types, traps, and resource limits. - `crates/wasm-probe`: generation of the Memory64 WebAssembly module used by browser tests. - `web`: a Worker-based Chrome feature report and Playwright smoke test. -- `docs/decisions`: architecture decision records, including the pending Icicle evaluation. +- `experiments/icicle`: the pinned, isolated AArch64 decode/interpreter feasibility probe. +- `docs/decisions`: architecture decision records, including the selective Icicle adoption decision. ## Prerequisites diff --git a/docs/architecture.md b/docs/architecture.md index 69d8a4c..e8343dd 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -44,4 +44,4 @@ Owns generated WebAssembly feature fixtures. Keeping the bytes generated by `was ## Planned next boundaries -The next crate should be an isolated Icicle experiment, not a dependency of `runtime-core`. Its ADR will decide whether decoder, P-code, memory, and Linux components are adopted selectively or rejected. ELF loading and guest memory should be added only after that feasibility result clarifies their interfaces. +The Icicle feasibility spike is isolated under `experiments/icicle`; it is not a dependency of `runtime-core`. [ADR-0001](decisions/0001-adopt-selected-icicle-components.md) selects Icicle's SLEIGH/P-code/CPU interpreter components behind project-owned IR and memory adapters while excluding its native JIT and host-coupled runtime boundary. diff --git a/docs/decisions/0001-adopt-selected-icicle-components.md b/docs/decisions/0001-adopt-selected-icicle-components.md new file mode 100644 index 0000000..9986993 --- /dev/null +++ b/docs/decisions/0001-adopt-selected-icicle-components.md @@ -0,0 +1,74 @@ +# ADR-0001: Adopt selected Icicle components behind project-owned boundaries + +- Status: accepted +- Date: 2026-07-24 +- Owners: project maintainers + +## Context + +The project needs a trustworthy AArch64 decoder, instruction semantics, P-code interpreter, and guest memory model before it can load static Linux binaries. Icicle already implements these pieces, but its top-level VM was designed for native fuzzing and includes native JIT, filesystem, networking, and Linux-host assumptions. + +The Phase 0 feasibility gate asked whether useful Icicle components can run in browser Wasm without making the whole product depend on a brittle fork. + +## Decision drivers + +- Correct AArch64 semantics and existing differential instruction tests +- A browser-portable interpreter that remains usable as the semantic oracle +- Permissive licensing with no accidental GPL core dependency +- A narrow, maintainable patch surface +- Project ownership of the Linux/browser service boundary and future Wasm translator IR +- Ability to replace the CPU foundation without replacing the whole runtime + +## Considered options + +1. Adopt `icicle-vm`, `icicle-linux`, memory, and native JIT as the complete runtime. +2. Adopt the SLEIGH/P-code/CPU interpreter components selectively behind project adapters. +3. Reject Icicle and immediately implement a decoder, IR, and interpreter from scratch. + +## Decision + +Adopt option 2. + +Pin the investigated Icicle revision while integration begins. Use `pcode`, `sleigh-runtime`, selected `sleigh-compile` entry points, and the `icicle-cpu` lifter/interpreter as the initial semantic foundation. Use `icicle-mem` for the first interpreter spike behind a project-owned memory interface. + +Do not use `icicle-vm` as binarrow's public or browser runtime boundary. Do not port `icicle-jit`; the project will lower normalized IR to WebAssembly instead. Do not adopt Icicle's host filesystem and sleep behavior as the Linux/browser service layer. + +Icicle P-code is an input to a project-owned normalized IR, not a permanent public contract. This keeps the translator smaller and contains changes if Icicle's internal representation evolves. + +Submit the two narrow wasm fixes upstream where practical. Until they are accepted, carry a small pinned fork or patch set with explicit provenance. Avoid a broad long-lived fork of `icicle-vm`. + +## Consequences + +### Positive + +- A real AArch64 `mov`/`add` sequence already decodes and executes correctly through the interpreter. +- The useful leaf and middle-layer crates compile for wasm after two small, understood fixes. +- Existing AArch64 semantic tests can seed binarrow's differential suite. +- The native Cranelift JIT and executable-memory dependencies stay out of browser builds. +- Linux services remain shaped around explicit browser/native host interfaces. + +### Negative + +- The project must maintain an adapter from Icicle P-code to normalized IR. +- A narrow fork or upstream coordination is initially required. +- `icicle-cpu` currently owns a concrete `icicle-mem::Mmu`; replacing memory later will require an adapter or focused refactor. +- Ghidra AArch64 language data must be compiled from bundled source text or preprocessed during the build/install flow, with license and NOTICE tracking. +- Icicle Linux code can be reused only selectively; broad syscall and VFS work remains project-owned. + +## Memory design + +For the native interpreter and first browser proof, wrap `icicle-mem` and configure explicit page/resource limits. Its software mappings, permissions, dirty/executable tracking, and copy-on-write support are useful immediately. + +Do not expose `icicle-mem` types across the product API. The browser adapter must own address validation and code invalidation. If profiling shows its paged guest-to-host translation is incompatible with the desired Memory64 layout or Wasm backend, replace it behind that interface without changing ELF, Linux, or browser-host contracts. + +## Linux and host-call design + +Keep the project-defined filesystem, clock, terminal, randomness, and suspension traits. Feed guest bytes to loaders rather than host paths. Reuse or port Icicle's AArch64 syscall ABI extraction, constants, structures, and semantic tests where they fit; route actual operations through binarrow's Linux runtime and host traits. + +Native filesystem access, `std::thread::sleep`, UDP diagnostics, native signals, and executable host memory must never be reachable requirements of the browser core. + +## Validation + +The full commands, crate-by-crate results, dependency path to the native JIT blocker, runtime assumptions, and licensing review are recorded in [the Icicle dependency report](../research/icicle-dependency-report.md). + +The pinned experiment in `experiments/icicle` compiles the supported Ghidra AArch64 SLEIGH source, interprets two instructions with JIT disabled, and validates the resulting register and program-counter state. diff --git a/docs/decisions/README.md b/docs/decisions/README.md index d1150ae..2b241d7 100644 --- a/docs/decisions/README.md +++ b/docs/decisions/README.md @@ -4,4 +4,4 @@ Architecture decision records (ADRs) document decisions that are costly to rever Copy `0000-template.md`, assign the next number, and replace every placeholder. Keep superseded records; link the record that replaces them. -`0001` is reserved for the Icicle adoption decision required by Phase 0. +- [ADR-0001](0001-adopt-selected-icicle-components.md): adopt selected Icicle components behind project-owned boundaries. diff --git a/docs/licensing.md b/docs/licensing.md index 86d22f5..e7f3218 100644 --- a/docs/licensing.md +++ b/docs/licensing.md @@ -24,6 +24,8 @@ Before adopting a foundational emulator, decoder, ABI source, runtime, or toolch | `wasmparser` | Validate generated WebAssembly in tests | Apache-2.0 WITH LLVM-exception | Rust dev dependency | | `wasm-feature-detect` | Canonical browser feature probes | Apache-2.0 | JavaScript dependency | | Vite, TypeScript, Playwright | Build, type-check, and test the probe | MIT / Apache-2.0 | Development dependencies | +| Selected Icicle components | AArch64 SLEIGH/P-code lifter and interpreter feasibility | MIT OR Apache-2.0 | Pinned Git experiment; product integration pending | +| Ghidra AArch64 language data | AArch64 decode and semantics specification | Apache-2.0 | Fetched pinned source data; not yet distributed | Refresh this table whenever production or foundational dependencies change. Toolchain and guest-runtime distribution manifests will be tracked separately once binary assets are introduced. diff --git a/docs/research/icicle-dependency-report.md b/docs/research/icicle-dependency-report.md new file mode 100644 index 0000000..8a2ee2b --- /dev/null +++ b/docs/research/icicle-dependency-report.md @@ -0,0 +1,83 @@ +# Icicle dependency and browser-portability report + +- Investigated: 2026-07-24 +- Icicle revision: `6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3` +- Icicle commit date: 2026-06-29 +- Supported Ghidra revision: `50230050fa58bd40d5a96cab9c167fc55bc92a76` +- Rust target: `wasm32-unknown-unknown` +- Rust toolchain: 1.93.0 + +This report supports [ADR-0001](../decisions/0001-adopt-selected-icicle-components.md). The reproducible native probe lives in `experiments/icicle`. + +## Native result + +The selected Icicle revision builds natively on macOS for `pcode`, `sleigh-runtime`, `sleigh-compile`, `icicle-mem`, `icicle-cpu`, `icicle-linux`, and `icicle-vm`. + +Using Icicle's supported AArch64 Ghidra specification, the probe decoded and interpreted `mov x0, #42` followed by `add x0, x0, #1`. It observed `x0 = 43` and `pc = 0x1008`. JIT, JIT memory, shadow stack, and recompilation were disabled, so this result exercises the SLEIGH-to-P-code interpreter path. + +## Crate assessment + +| Component | Native | Upstream wasm32 | wasm32 after two narrow patches | Decision | +|---|---:|---:|---:|---| +| `pcode` | Pass | Pass | Pass | Adopt as an input format behind a project adapter | +| `sleigh-parse` | Pass | Pass | Pass | Adopt transitively | +| `sleigh-runtime` | Pass | Blocked by `ahash` RNG | Pass | Adopt | +| `sleigh-compile` | Pass | Blocked transitively | Pass | Use during build/installation; avoid browser filesystem paths | +| `icicle-mem` | Pass | Blocked by `ahash` RNG | Pass | Use initially behind a project memory adapter | +| `icicle-cpu` | Pass | Also has a 48-bit `usize` sentinel | Pass | Adopt lifter and interpreter selectively | +| `icicle-linux` | Pass | Blocked transitively | Pass | Mine ABI/architecture behavior; replace host-coupled services | +| `icicle-jit` | Pass | Fails in native executable-memory crates | Not pursued | Reject for browser builds | +| `icicle-vm` | Pass | Pulls `icicle-jit` unconditionally | Not pursued | Do not expose as the browser runtime boundary | + +“Pass” means `cargo check` completed for the selected target. It does not prove browser runtime behavior. + +## Exact wasm blockers + +The unmodified selective build was attempted with: + +```sh +cargo +1.93.0 check --locked \ + --target wasm32-unknown-unknown \ + -p pcode -p sleigh-runtime -p sleigh-compile \ + -p icicle-mem -p icicle-cpu -p icicle-linux +``` + +It first fails because workspace-default `ahash` enables runtime entropy through `getrandom`, whose bare-wasm backend must be selected explicitly. After configuring `getrandom`'s `wasm_js` feature/backend, `icicle-cpu` fails because `UNKNOWN_BLOCK` uses the 48-bit literal `0xbadbadbadbad` as a `usize`; wasm32 has a 32-bit `usize`. + +The temporary evidence patch was limited to: + +1. Enable `getrandom`'s `wasm_js` feature for the browser target and compile with `--cfg getrandom_backend="wasm_js"`. +2. Replace the diagnostic-only `UNKNOWN_BLOCK` value with `usize::MAX`. + +The exact diff is retained in `experiments/icicle/patches/0001-wasm-portability.patch`. The successful selective build additionally set: + +```sh +RUSTFLAGS='--cfg getrandom_backend="wasm_js"' +``` + +After those changes, all seven selective crates in the command above compile for wasm32. + +Building `icicle-vm` still fails in `region`, reached through its unconditional `icicle-vm → icicle-jit → cranelift-jit → region` dependency. `region` expects native virtual-memory allocation/protection functions that do not exist for `wasm32-unknown-unknown`. Setting `Config::enable_jit = false` is only a runtime switch and does not remove the dependency or the `JIT` field from `Vm`. + +## Browser-runtime assumptions not caught by `cargo check` + +- `sleigh-compile`'s language builder reads `.ldefs`, `.pspec`, and `.slaspec` files through `std::fs`. The lower-level `from_data` entry point accepts in-memory source text and is the browser-compatible integration seam. +- `icicle-linux` contains direct host filesystem reads and `std::thread::sleep`. These compile for wasm but cannot be the browser host boundary. +- `icicle-cpu::utils::UdpWriter` directly uses `std::net::UdpSocket`; diagnostic networking must remain unused or be gated. +- `icicle-mem` uses a software page map, copy-on-write pages, per-byte permissions, raw-pointer TLB entries, and a separate guest-to-host translation. It is suitable for an interpreter spike but is not direct Memory64 guest addressing. +- `icicle-vm` reads executables/specifications from paths in several helpers. Browser loading must pass bytes and project-owned services explicitly. + +## Licenses + +Icicle is `MIT OR Apache-2.0`. The investigated AArch64 Ghidra processor files are marked `GHIDRA` in that module's certification manifest; the Ghidra repository describes those files under Apache-2.0. The selected native dependency graph contains permissive dependencies; no GPL crate is required by the core path. + +The Ghidra source bundle must retain its Apache license and NOTICE if redistributed. It should be versioned as an explicit source/data input rather than copied without provenance. + +## Recommended integration shape + +1. Pin Icicle and the AArch64 specification as explicit, reviewable inputs. +2. Carry or upstream the two narrow wasm portability fixes. +3. Build a project-owned adapter from Icicle P-code into a normalized IR; do not make Icicle's `Vm` the public runtime API. +4. Start the interpreter with `icicle-mem` behind a project interface, then measure whether direct Memory64 storage warrants replacement. +5. Implement Linux and browser host services in project crates. Port only clearly useful Icicle ABI tables, AArch64 register/syscall context logic, and tests. +6. Replace the native Cranelift JIT with the planned project IR-to-Wasm backend. diff --git a/experiments/icicle/.gitignore b/experiments/icicle/.gitignore new file mode 100644 index 0000000..d72160d --- /dev/null +++ b/experiments/icicle/.gitignore @@ -0,0 +1,2 @@ +/.cache/ +/target/ diff --git a/experiments/icicle/Cargo.lock b/experiments/icicle/Cargo.lock new file mode 100644 index 0000000..8b6ed0e --- /dev/null +++ b/experiments/icicle/Cargo.lock @@ -0,0 +1,1122 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59317f77929f0e679d39364702289274de2f0f0b22cbf50b2b8cff2169a0b27a" +dependencies = [ + "cpp_demangle", + "fallible-iterator", + "gimli", + "memmap2", + "object 0.39.1", + "rustc-demangle", + "smallvec", + "typed-arena", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "anyhow" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "binarrow-icicle-spike" +version = "0.0.0" +dependencies = [ + "icicle-cpu", + "icicle-vm", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +dependencies = [ + "serde_core", +] + +[[package]] +name = "bstr" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f7dc094d718f2e1c1559ad110e27eeaae14a5465d3d56dd6dbd793079fbd530" +dependencies = [ + "memchr", + "serde_core", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +dependencies = [ + "allocator-api2", +] + +[[package]] +name = "bytemuck" +version = "1.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" + +[[package]] +name = "cc" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89588d05638b5b4594a3348a2d6c20277e43a7f5c5202b05cc56888475a47b8" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cpp_demangle" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0667304c32ea56cb4cd6d2d7c0cfe9a2f8041229db8c033af7f8d69492429def" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cranelift" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bdf52c60935374adffd78561409189eef357c77033f44b1be472d835fcc8201" +dependencies = [ + "cranelift-codegen", + "cranelift-frontend", + "cranelift-module", +] + +[[package]] +name = "cranelift-assembler-x64" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b242b4c3675139f52f0b55624fb92571551a344305c5998f55ad20fa527bc55" +dependencies = [ + "cranelift-assembler-x64-meta", +] + +[[package]] +name = "cranelift-assembler-x64-meta" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "499715f19799219f32641b14f2a162f91e50bc1b61c2d2184c2be971716f5c56" +dependencies = [ + "cranelift-srcgen", +] + +[[package]] +name = "cranelift-bforest" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebca2ea7c62c56feb88a5b23ec380460fe6d7c18134520f6ddf4bfa35cbea68" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-bitset" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe11f154b62d7421d909503a746e89995393b1b71926e6f12b08a2076396d7fb" +dependencies = [ + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-codegen" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f2d0da3d51979dc0183fac3076a535477eab794716b063143ecb16632408664" +dependencies = [ + "bumpalo", + "cranelift-assembler-x64", + "cranelift-bforest", + "cranelift-bitset", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-control", + "cranelift-entity", + "cranelift-isle", + "gimli", + "hashbrown 0.15.5", + "libm", + "log", + "regalloc2", + "rustc-hash", + "serde", + "smallvec", + "target-lexicon", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "483b2c94a1b7f6fba0714387ba34ca56d114b2214a80be018acbb2ed40e09a1e" +dependencies = [ + "cranelift-assembler-x64-meta", + "cranelift-codegen-shared", + "cranelift-srcgen", + "heck", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4aae718c336a52d90d4ebe9a2d8c3cf0906a4bee78f0e6867e777eebbe554fe" + +[[package]] +name = "cranelift-control" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18e94519070dc56cddb71906a08cea6a28a1d7c58ed501b88f273fa6b45fa07" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "cranelift-entity" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ab4e0eff1045ff2f5ddd8195bf3c97d7b5ef9b780cb044e0cce76e4d352057" +dependencies = [ + "cranelift-bitset", + "wasmtime-internal-core", +] + +[[package]] +name = "cranelift-frontend" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7645a236e1ec49e660f09ec9fa979a1c5d0b612c419db7610573d4d58a03b7c" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57e0b4a1a0ea01cc19084ff01aaeb640dfe22905d47d83037a419b81ba587ed0" + +[[package]] +name = "cranelift-jit" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68c397bbf844f50828b66c315844331404d89e93592515d56837cb9b2b97cf3" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity", + "cranelift-module", + "cranelift-native", + "libc", + "log", + "region", + "target-lexicon", + "wasmtime-internal-jit-icache-coherence", + "windows-sys 0.61.2", +] + +[[package]] +name = "cranelift-module" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a58a82190e7ecd36b8d55880eadff59f045d20a491dacfaecc11aac24453092" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-control", +] + +[[package]] +name = "cranelift-native" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bdec40b396eb630ecfb0e7a81766d7287f464a7631b9eb5862f7711f1020012" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "cranelift-srcgen" +version = "0.129.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1a001a9dc4557d9e2be324bc932621c0aa9bf33b74dfefa2338f0bf8913329" + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "gimli" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7f043f89559805f8c7cacc432749b2fa0d0a0a9ee46ce47164ed5ba7f126c" +dependencies = [ + "fnv", + "hashbrown 0.16.1", + "indexmap", + "stable_deref_trait", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "foldhash 0.2.0", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "icicle-cpu" +version = "0.1.0" +source = "git+https://github.com/icicle-emu/icicle-emu?rev=6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3#6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3" +dependencies = [ + "addr2line", + "ahash", + "anyhow", + "bitflags 2.13.1", + "bytemuck", + "gimli", + "half", + "icicle-mem", + "object 0.38.1", + "pcode", + "sleigh-runtime", + "target-lexicon", + "tracing", +] + +[[package]] +name = "icicle-jit" +version = "0.2.0" +source = "git+https://github.com/icicle-emu/icicle-emu?rev=6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3#6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3" +dependencies = [ + "cranelift", + "cranelift-codegen", + "cranelift-jit", + "cranelift-module", + "cranelift-native", + "icicle-cpu", + "memoffset", + "pcode", + "target-lexicon", + "tracing", + "wasmtime-jit-debug", +] + +[[package]] +name = "icicle-linux" +version = "0.1.0" +source = "git+https://github.com/icicle-emu/icicle-emu?rev=6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3#6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3" +dependencies = [ + "bitflags 2.13.1", + "bstr", + "bytemuck", + "icicle-cpu", + "object 0.38.1", + "pcode", + "sleigh-runtime", + "target-lexicon", + "tracing", +] + +[[package]] +name = "icicle-mem" +version = "0.3.0" +source = "git+https://github.com/icicle-emu/icicle-emu?rev=6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3#6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3" +dependencies = [ + "ahash", + "tracing", +] + +[[package]] +name = "icicle-vm" +version = "0.2.0" +source = "git+https://github.com/icicle-emu/icicle-emu?rev=6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3#6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3" +dependencies = [ + "anyhow", + "icicle-cpu", + "icicle-jit", + "icicle-linux", + "ihex", + "object 0.38.1", + "pcode", + "ron", + "serde", + "serde-xml-rs", + "sleigh-compile", + "sleigh-runtime", + "target-lexicon", + "tracing", +] + +[[package]] +name = "ihex" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "365a784774bb381e8c19edb91190a90d7f2625e057b55de2bc0f6b57bc779ff2" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", +] + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "mach2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "memmap2" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "object" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271638cd5fa9cca89c4c304675ca658efc4e64a66c716b7cfe1afb4b9611dbbc" +dependencies = [ + "crc32fast", + "hashbrown 0.16.1", + "indexmap", + "memchr", +] + +[[package]] +name = "object" +version = "0.39.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b" +dependencies = [ + "flate2", + "memchr", + "ruzstd", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "pcode" +version = "0.2.0" +source = "git+https://github.com/icicle-emu/icicle-emu?rev=6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3#6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "regalloc2" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08effbc1fa53aaebff69521a5c05640523fab037b34a4a2c109506bc938246fa" +dependencies = [ + "allocator-api2", + "bumpalo", + "hashbrown 0.15.5", + "log", + "rustc-hash", + "smallvec", +] + +[[package]] +name = "region" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" +dependencies = [ + "bitflags 1.3.2", + "libc", + "mach2", + "windows-sys 0.52.0", +] + +[[package]] +name = "ron" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db09040cc89e461f1a265139777a2bde7f8d8c67c4936f700c63ce3e2904d468" +dependencies = [ + "base64", + "bitflags 2.13.1", + "serde", + "serde_derive", + "unicode-ident", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" + +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags 2.13.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "ruzstd" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c1c839d570d835527c9a5e4db7cb2198683a988cb9d7293fc8674e6bd58fc8" +dependencies = [ + "twox-hash", +] + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-xml-rs" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2215ce3e6a77550b80a1c37251b7d294febaf42e36e21b7b411e0bf54d540d" +dependencies = [ + "log", + "serde", + "thiserror", + "xml", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" + +[[package]] +name = "sleigh-compile" +version = "0.3.0" +source = "git+https://github.com/icicle-emu/icicle-emu?rev=6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3#6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3" +dependencies = [ + "pcode", + "serde", + "serde-xml-rs", + "serde_derive", + "sleigh-parse", + "sleigh-runtime", +] + +[[package]] +name = "sleigh-parse" +version = "0.3.0" +source = "git+https://github.com/icicle-emu/icicle-emu?rev=6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3#6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3" + +[[package]] +name = "sleigh-runtime" +version = "0.1.0" +source = "git+https://github.com/icicle-emu/icicle-emu?rev=6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3#6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3" +dependencies = [ + "ahash", + "pcode", + "sleigh-parse", +] + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" + +[[package]] +name = "thiserror" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" + +[[package]] +name = "twox-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8464ec13c3691491391d9fce00f6416c9a48e46972f72d7865688be2080192c9" + +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasmtime-internal-core" +version = "42.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be7c68311d6220c20cefdf334e0c8021e16a050383c67edc5be42e5661ddf265" +dependencies = [ + "libm", +] + +[[package]] +name = "wasmtime-internal-jit-icache-coherence" +version = "42.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52c0779e711777b915d017b3f54049e658057a77df99e0e7958406b3c5d7d07" +dependencies = [ + "cfg-if", + "libc", + "wasmtime-internal-core", + "windows-sys 0.61.2", +] + +[[package]] +name = "wasmtime-jit-debug" +version = "34.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f935b198c58d3f85b6f8d2fedcbaf71e6f41dee3a8278d60cbe9326b82ac91aa" +dependencies = [ + "cc", + "object 0.36.7", + "rustix", + "wasmtime-versioned-export-macros", +] + +[[package]] +name = "wasmtime-versioned-export-macros" +version = "34.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ca100ed168ffc9b37aefc07a5be440645eab612a2ff6e2ff884e8cc3740e666" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "xml" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "636f85e5ca6488e96401b61eb7de54f4e44755c988af0f52cf90230c312a1a89" + +[[package]] +name = "zerocopy" +version = "0.8.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] diff --git a/experiments/icicle/Cargo.toml b/experiments/icicle/Cargo.toml new file mode 100644 index 0000000..af1fa3b --- /dev/null +++ b/experiments/icicle/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "binarrow-icicle-spike" +version = "0.0.0" +edition = "2024" +publish = false +license = "MIT OR Apache-2.0" + +[workspace] +resolver = "2" + +[dependencies] +icicle-cpu = { git = "https://github.com/icicle-emu/icicle-emu", rev = "6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3" } +icicle-vm = { git = "https://github.com/icicle-emu/icicle-emu", rev = "6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3" } + +[lints.rust] +unsafe_code = "forbid" + +[lints.clippy] +all = { level = "warn", priority = -1 } +pedantic = { level = "warn", priority = -1 } diff --git a/experiments/icicle/README.md b/experiments/icicle/README.md new file mode 100644 index 0000000..a3037ce --- /dev/null +++ b/experiments/icicle/README.md @@ -0,0 +1,34 @@ +# Icicle feasibility spike + +This isolated workspace reproduces the native AArch64 decode-and-interpret result used by ADR-0001. It is deliberately excluded from the product workspace: the pinned upstream `icicle-vm` still depends unconditionally on a native Cranelift JIT and cannot compile for `wasm32-unknown-unknown`. + +## Pinned inputs + +- Icicle: `6f53b6016e63ddcff80a105b8e5ad37caf7a6ed3` +- Icicle-supported Ghidra: `50230050fa58bd40d5a96cab9c167fc55bc92a76` + +The Ghidra checkout is not committed. Its AArch64 language sources are about 2.5 MiB and are fetched sparsely by the included script. + +## Reproduce the native probe + +From this directory: + +```sh +./fetch-supported-ghidra.sh .cache/ghidra +cargo run --locked -- .cache/ghidra/Ghidra/Processors +``` + +The probe compiles the AArch64 SLEIGH specification, decodes and interprets: + +```text +mov x0, #42 +add x0, x0, #1 +``` + +It succeeds only if `x0 == 43` and `pc == 0x1008` after two interpreted instructions. + +## Browser portability result + +The exact commands and temporary patch set used for the browser build experiment are recorded in [the dependency report](../../docs/research/icicle-dependency-report.md). Those patches are evidence only and are not silently applied here. + +The exact zero-context diff is preserved as `patches/0001-wasm-portability.patch`. Apply it with `git apply --unidiff-zero` only to a clean checkout of the pinned Icicle revision; it intentionally does not attempt to make `icicle-vm` or `icicle-jit` browser-portable. diff --git a/experiments/icicle/fetch-supported-ghidra.sh b/experiments/icicle/fetch-supported-ghidra.sh new file mode 100755 index 0000000..eb29abc --- /dev/null +++ b/experiments/icicle/fetch-supported-ghidra.sh @@ -0,0 +1,21 @@ +#!/bin/sh +set -eu + +if [ "$#" -ne 1 ]; then + echo "usage: $0 " >&2 + exit 2 +fi + +destination=$1 +revision=50230050fa58bd40d5a96cab9c167fc55bc92a76 + +if [ -e "$destination" ]; then + echo "refusing to overwrite existing path: $destination" >&2 + exit 1 +fi + +git init "$destination" +git -C "$destination" remote add origin https://github.com/icicle-emu/ghidra.git +git -C "$destination" sparse-checkout set Ghidra/Processors/AARCH64 +git -C "$destination" fetch --depth 1 --filter=blob:none origin "$revision" +git -C "$destination" checkout --detach FETCH_HEAD diff --git a/experiments/icicle/patches/0001-wasm-portability.patch b/experiments/icicle/patches/0001-wasm-portability.patch new file mode 100644 index 0000000..45ccac2 --- /dev/null +++ b/experiments/icicle/patches/0001-wasm-portability.patch @@ -0,0 +1,13 @@ +diff --git a/icicle-cpu/src/lifter/mod.rs b/icicle-cpu/src/lifter/mod.rs +index d38fbe4..ecd5606 100644 +--- a/icicle-cpu/src/lifter/mod.rs ++++ b/icicle-cpu/src/lifter/mod.rs +@@ -293 +293 @@ +-const UNKNOWN_BLOCK: usize = 0xbadbadbadbad; ++const UNKNOWN_BLOCK: usize = usize::MAX; +diff --git a/sleigh/sleigh-runtime/Cargo.toml b/sleigh/sleigh-runtime/Cargo.toml +index 741de36..edc6ffc 100644 +--- a/sleigh/sleigh-runtime/Cargo.toml ++++ b/sleigh/sleigh-runtime/Cargo.toml +@@ -9,0 +10 @@ ++getrandom = { version = "0.3.3", features = ["wasm_js"] } diff --git a/experiments/icicle/src/main.rs b/experiments/icicle/src/main.rs new file mode 100644 index 0000000..421e9e7 --- /dev/null +++ b/experiments/icicle/src/main.rs @@ -0,0 +1,83 @@ +use std::{env, path::Path, process::ExitCode}; + +use icicle_cpu::{ + Config, VmExit, + mem::{Mapping, perm}, +}; + +const CODE_ADDRESS: u64 = 0x1000; +const CODE: &[u8] = &[ + 0x40, 0x05, 0x80, 0xd2, // mov x0, #42 + 0x00, 0x04, 0x00, 0x91, // add x0, x0, #1 +]; + +fn main() -> ExitCode { + match run() { + Ok(()) => ExitCode::SUCCESS, + Err(message) => { + eprintln!("Icicle feasibility probe failed: {message}"); + ExitCode::FAILURE + } + } +} + +fn run() -> Result<(), String> { + let processors = env::args_os() + .nth(1) + .ok_or_else(|| "usage: binarrow-icicle-spike ".to_owned())?; + + let config = Config { + triple: "aarch64-none" + .parse() + .map_err(|error| format!("Icicle rejected the aarch64-none target: {error:?}"))?, + enable_jit: false, + enable_jit_mem: false, + enable_shadow_stack: false, + enable_recompilation: false, + ..Config::default() + }; + + let mut vm = icicle_vm::build_with_path(&config, Path::new(&processors)) + .map_err(|error| format!("could not build AArch64 VM: {error}"))?; + + let mapped = vm.cpu.mem.map_memory_len( + CODE_ADDRESS, + 0x100, + Mapping { + perm: perm::READ | perm::EXEC, + value: 0, + }, + ); + if !mapped { + return Err("could not map probe code".to_owned()); + } + + vm.cpu + .mem + .write_bytes(CODE_ADDRESS, CODE, perm::NONE) + .map_err(|error| format!("could not write probe code: {error:?}"))?; + vm.cpu.write_pc(CODE_ADDRESS); + + let exit = vm.step(2); + if exit != VmExit::InstructionLimit { + return Err(format!( + "unexpected VM exit after two instructions: {exit:?}" + )); + } + + let x0 = vm + .cpu + .arch + .sleigh + .get_varnode("x0") + .ok_or_else(|| "AArch64 SLEIGH data did not define x0".to_owned())?; + let x0_value = vm.cpu.read_reg(x0); + let pc = vm.cpu.read_pc(); + + if x0_value != 43 || pc != CODE_ADDRESS + CODE.len() as u64 { + return Err(format!("unexpected state: x0={x0_value}, pc={pc:#x}")); + } + + println!("decoded and interpreted AArch64 mov/add; x0={x0_value}, pc={pc:#x}"); + Ok(()) +}