Title: riscv64: SIGILL in JS->wasm wrapper — lazy compilation enters unpopulated code pages (unofficial-builds v24.20.0 & v26.0.0) · Issue #65724 · nodejs/node · GitHub
Open Graph Title: riscv64: SIGILL in JS->wasm wrapper — lazy compilation enters unpopulated code pages (unofficial-builds v24.20.0 & v26.0.0) · Issue #65724 · nodejs/node
X Title: riscv64: SIGILL in JS->wasm wrapper — lazy compilation enters unpopulated code pages (unofficial-builds v24.20.0 & v26.0.0) · Issue #65724 · nodejs/node
Description: Version v26.0.0 (node -v), unofficial-builds linux-riscv64.tar.xz, V8 14.6.202.33-node.19, pointer compression off (also reproduces on v24.20.0 of the same line; both are currently-supported releases) Platform Linux lpi3a 6.1.15 #1.0.15....
Open Graph Description: Version v26.0.0 (node -v), unofficial-builds linux-riscv64.tar.xz, V8 14.6.202.33-node.19, pointer compression off (also reproduces on v24.20.0 of the same line; both are currently-supported releas...
X Description: Version v26.0.0 (node -v), unofficial-builds linux-riscv64.tar.xz, V8 14.6.202.33-node.19, pointer compression off (also reproduces on v24.20.0 of the same line; both are currently-supported releas...
Opengraph URL: https://github.com/nodejs/node/issues/65724
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"riscv64: SIGILL in JS->wasm wrapper — lazy compilation enters unpopulated code pages (unofficial-builds v24.20.0 & v26.0.0)","articleBody":"### Version\n\nv26.0.0 (`node -v`), unofficial-builds `linux-riscv64.tar.xz`, V8 14.6.202.33-node.19, pointer compression off\n(also reproduces on v24.20.0 of the same line; both are currently-supported releases)\n\n### Platform\n\n```\nLinux lpi3a 6.1.15 #1.0.15.1 SMP PREEMPT Sat Sep 7 07:20:18 UTC 2024 riscv64 riscv64 riscv64 GNU/Linux\n```\n\nHardware: Sipeed Lichee Pi 3A — SpacemiT K1, 8× T-Heng X60, 16 GB RAM.\nOS: Bianbu 1.0.15 \"Mantic Minotaur\" (Ubuntu mantic base), glibc 2.38.\nCPU ISA (per `/proc/cpuinfo`): `rv64imafdcv_sscofpmf_sstc_svpbmt_zicbom_zicboz_zicbop_zihintpause` — **no Zba/Zbb/Zcb/Zfa**; MMU sv39; RVV 1.0 works (verified with userspace vector benchmarks).\nKernel 6.1.15 has **no `riscv_hwprobe` syscall**, so V8 must fall back to `AT_HWCAP` for feature detection.\nThe `node` binary itself runs general workloads fine on this machine (npm install trees, 500k-call JS/wasm loops, NAPI addons incl. sharp/clipboard prebuilds — none crash).\n\n### Subsystem\n\nwebassembly (V8 wasm runtime on riscv64; JS→wasm wrapper / lazy compilation entry)\n\n### What steps will reproduce the bug?\n\nWe could not reduce the trigger below a large Rust→wasm module (see notes under “Additional information” about synthetic attempts), so the shortest reliable repro uses one publicly-published npm app that ships the wasm fallback of SWC inside `next`:\n\n```bash\n# on the riscv64 machine (Node >= 22.19 from https://unofficial-builds.nodejs.org/download/release/ )\nnpm i -g @agegr/pi-web@0.8.11\npi-web --port 30141\n```\n\nOutput observed (no client traffic involved):\n\n```\n▲ Next.js 16.3.1\n- Local: http://127.0.0.1:30141\n✓ Ready in 1632ms\n⚠ next-swc does not have native bindings support for target triple [object Object]. ...\n[pi-web] Next.js exited unexpectedly (signal SIGILL)\n```\n\nControl (only difference = one V8 flag):\n\n```bash\nnode --no-wasm-lazy-compilation \"$(npm root -g)/@agegr/pi-web/bin/pi-web.js\" --port 30141\n# → stays alive indefinitely; serving real pages (verified 90+ s, HTTP 200s at 15/45/75 s, zero SIGILL)\n```\n\nThe crashing wasm module is `node_modules/next/wasm/@next/swc-wasm-nodejs/wasm_bg.wasm` (Next.js 16.3.1), which Next.js loads automatically on platforms without a native SWC binding.\n\n### How often does it reproduce? Is there a required condition?\n\nDeterministic, ~100% on this machine. Required conditions:\n\n* riscv64 `node` from unofficial-builds, default V8 flags (both the standard **and** the pointer-compression flavors reproduce — see controls below);\n* a large wasm module whose functions are called lazily in a long-running process;\n* crash fires **5–8 s after the app becomes ready with zero requests** — it is self-triggered, not traffic-triggered.\n\nAll of the following were tested and **do not change the outcome** (still SIGILL at the same code-page offset): `--no-wasm-code-gc`, `--no-wasm-tier-up`, `--no-liftoff`, `--no-flush-baseline-code --no-flush-liftoff-code --no-flush-bytecode --no-flush-code-based-on-time`, `OPENSSL_riscvcap=` (empty), `NEXT_TELEMETRY_DISABLED=1`, `--no-riscv-b-extension` (already default-off on this build), and Node v24.20.0 vs v26.0.0.\n\n### What is the expected behavior? Why is that the expected behavior?\n\nExpected: WebAssembly functions compile lazily on first call (or eagerly if lazy is disabled) and execute correctly, as on all other supported architectures.\n\nWhy we believe this is an engine bug and not userland / not “unsupported hardware”:\n\n* The crash PC is inside an **anonymous executable mapping owned by V8's code space**, filled with `0x00000000` (RISC-V zero word = illegal instruction) — i.e. execution entered a code page that was never populated.\n* The return address at the crash is inside **Node's own V8 builtin `Builtins_JSToWasmWrapperAsm`** — the JS→wasm call trampoline itself. Nothing userland controls that jump target.\n* The crashing instruction offset is **byte-identical across runs** (page offset `0xa28`, constant register values) — a deterministic codegen/stub-patching defect, not corruption.\n* Pure V8 flag (`--no-wasm-lazy-compilation`) makes it disappear; every non-wasm path on this binary is healthy.\n* The CPU fully supports the base ISA V8 uses here (rv64gc); no Zb*/Zfa instructions are involved (V8's B-extension use is default-off, and the same flag matrix shows the fault follows wasm lazy compilation, not ISA extensions).\n\n### What do you see instead?\n\nKernel log (repeats identically for every run):\n\n```\nnext-server (v1[4259]: unhandled signal 4 code 0x1 at 0x00000011d183fa28\nCPU: 2 PID: 4259 Comm: next-server (v1 Not tainted 6.1.15 #1.0.15.1\nHardware name: SiPEED LPi3A Board (DT)\n...\nstatus: 8000000200006020 badaddr: 0000000000000000 cause: 0000000000000002\n```\n\n(`cause 2` = RISC-V \"illegal instruction\"; the low page offset is always `0xa28`; `t0` is always `0x6bae`.)\n\nUnder gdb:\n\n```\nThread 1 \"next-server (v1\" received signal SIGILL, Illegal instruction.\n0x0000003fa86cba28 in ?? ()\n(gdb) x/8i $pc\n=> 0x3fa86cba28: unimp (eight consecutive `unimp`)\n(gdb) x/8xw $pc-16\n0x3fa86cba18: 0x00000000 0x00000000 0x00000000 0x00000000\n0x3fa86cba28: 0x00000000 0x00000000 0x00000000 0x00000000\n(gdb) p/x $ra\n$1 = 0x2aabf96458\n(gdb) info symbol $ra\nBuiltins_JSToWasmWrapperAsm + 184 in section .text of .../bin/node\n```\n\n### Additional information\n\n**Relationship to #64538 (important).** We are aware of the concurrent riscv64 wasm SIGILL thread (#64538, RVV/SIMD on SpacemiT chips) and believe our non-pc-flavor report is a *distinct* mechanism, not the same root cause:\n\n* On the exact crashing binary (non-pointer-compression v26.0.0), V8 **refuses to compile SIMD-containing modules** — we verified directly: a SIMD wasm (`llhttp.wasm` shipped with Next.js) dies with `CompileError: Wasm SIMD unsupported` instead of executing, so none of the `VU::SetSimd128*` RVV lowering paths can be reached by the crashing app;\n* the failing function itself is plain non-SIMD Rust→wasm (Next.js `swc-wasm-nodejs`), and the fault is a **jump into zero-filled, never-written code** (`badaddr 0x0`; in #64538 the kernel's badaddr carries a real RVV encoding such as `vmv.s.x 0x4209ec57`);\n* the fixer is orthogonal to SIMD: `--no-wasm-lazy-compilation` (SIMD support untouched) eliminates our crash 100%.\n\nCaveat for honesty: the pointer-compression flavor also SIGILLs on this board, but we have not yet captured its kernel `badaddr` signature — if it turns out to be a real RVV instruction word, that flavor's crash belongs to #64538 and only the non-pc zero-page crash is new. We will capture it when our board is next reachable and post an update here.\n\n**Build-flavor control.** The `linux-riscv64-pointer-compression` variant of the same v26.0.0 release **also crashes**, at the same page offset `0xa28` with the same register signature — so the bug is riscv64-wide, not tied to the non-pointer-compression flavor.\n\n**Synthetic-reduction attempts (negative results).** A 45-byte `add` module called 500k times, and generated modules with thousands of trivial exported functions called in sequence, all run fine — so a minimal pure-builtins snippet does not (yet) reproduce. The trigger appears tied to how large Rust→wasm modules are consumed (we suspect re-entrant import→export calls and/or wide first-call coverage across many functions). We can share our stress-generator scripts, and — more usefully — **test candidate patches/flags on this exact board via ssh** (8-core X60, always reachable); we can also try to continue bisecting with `--trace-wasm-*` on request.\n\n**Why userland is exonerated** (per the guideline about userland modules): the only userland code involved is Next.js choosing its documented wasm-SWC fallback on an unmapped platform; the fault itself is in Node's V8 trampoline→code-space boundary as shown above. The identical app works on x86_64/aarch64. A prior riscv64 field report of the same fallback crashing is documented here: https://dev.to/gounthar/the-one-line-patch-that-unlocked-nextjs-on-risc-v-a-detective-story-71h\n\n**Related platform facts** (context, independent of this crash):\n\n* **QEMU control (negative — very likely the key localization clue):** the same node binary and app under `qemu-system-riscv64 -cpu max` (all extensions enabled) + our mainline 7.2.0-rc7 kernel (**with** `riscv_hwprobe`, so V8 detects Zba/Zbb/Zfa/…) **does not crash** — ran 900 s with traffic every 30 s, `GET /` consistently OK (wasm-SWC config compile took 4.1 min under TCG and completed). The board differs in two coupled ways: no hwprobe on kernel 6.1.15 → V8 falls back to AT_HWCAP → reduced feature set → **no-B fallback code path**. Suspect the bug lives in V8's riscv64 code path taken when B-class extensions are *not* detected. (We could not test `-cpu` with B off using this guest image — its userspace is RVA23 and fails to boot without Zb\\*; would need an rv64gc userspace rootfs, e.g. Debian riscv64. Happy to run that test for you — the board is not required if a suitable rootfs is specified.)\n* Because kernel 6.1.15 lacks `riscv_hwprobe`, V8 additionally reports “Wasm SIMD unsupported” and cleanly refuses SIMD-containing modules (e.g. `llhttp.wasm` → CompileError). This SIGILL is on non-SIMD modules.\n* We have filed a downstream tracker so users can work around this immediately: pi-web issue **agegr/pi-web#685** (https://github.com/agegr/pi-web/issues/685) — asking the app to pass `--no-wasm-lazy-compilation` on riscv64.\n\n**Artifacts**: `node -v` v26.0.0; tarball sha256 `071bb81d19de45393b91412ec4f01ae85bfde2b7e78bb62c5fabfa72347b8ff8`; app `@agegr/pi-web@0.8.11`; `next@16.3.1`; V8 `14.6.202.33-node.19`; uv 1.52.1; openssl 3.5.5.\n\n— Acidmoon, KUBUDS Tech","author":{"url":"https://github.com/Acidmoon","@type":"Person","name":"Acidmoon"},"datePublished":"2026-09-01T18:49:23Z","url":"https://github.com/nodejs/node/issues/65724"}
| react-profiling | 0 |
| react-import-map | react,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@d5750093facf |
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:a04e4c52-3ae2-3982-969f-2c332919181c |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | CC48:DF107:70D6FF:98D3E7:6AED29D9 |
| html-safe-nonce | 9d7cee7b513cd01d5e67ea8ce44f057707b61cf2e37e1b51b800f020d4fba6a8 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJDQzQ4OkRGMTA3OjcwRDZGRjo5OEQzRTc6NkFFRDI5RDkiLCJ2aXNpdG9yX2lkIjoiNDkxODU3Mzc4MTU1MTQ5MTU0NSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 6818ed34c1318dfc15876e053c57a32d2062f3a46f630bd209adf7da6104562c |
| hovercard-subject-tag | issue:5315563977 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/nodejs/node/65724/issue_layout |
| twitter:image | https://opengraph.githubassets.com/572945271245153a8eb1a0671b1c0390bee0465ce0fe0a1c39e0c70c272f544f/nodejs/node/issues/65724 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/572945271245153a8eb1a0671b1c0390bee0465ce0fe0a1c39e0c70c272f544f/nodejs/node/issues/65724 |
| og:image:alt | Version v26.0.0 (node -v), unofficial-builds linux-riscv64.tar.xz, V8 14.6.202.33-node.19, pointer compression off (also reproduces on v24.20.0 of the same line; both are currently-supported releas... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | Acidmoon |
| hostname | github.com |
| expected-hostname | github.com |
| None | 9d95365dda0576efe9b71f45807595e396bd0ca9286fba5367a05048e6ddf8f2 |
| turbo-cache-control | no-preview |
| go-import | github.com/nodejs/node git https://github.com/nodejs/node.git |
| octolytics-dimension-user_id | 9950313 |
| octolytics-dimension-user_login | nodejs |
| octolytics-dimension-repository_id | 27193779 |
| octolytics-dimension-repository_nwo | nodejs/node |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 27193779 |
| octolytics-dimension-repository_network_root_nwo | nodejs/node |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 98b41fa4b5635ceb45a4c54320fced73817ff290 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
| react-app-name | issues |
Links:
Viewport: width=device-width