Summary
A coroutinized __syscall_ret faults with a WebAssembly "memory access out of bounds" the FIRST time a
syscall returns an error. Its .resume clone's error branch (musl errno = -r; return -1) makes an OOB
access. The success path is fine — only the error branch faults. First hit while running a self-hosted
clang-22.wasm's C++ static ctors, but it should reproduce with any coroutinized program.
How to reproduce (minimal)
Compile a tiny program through the normal coroutinize flow (so __syscall_ret gets its .resume clone)
that makes ONE syscall which returns an error, then run it in the browser kernel:
int main(void) { open("/no/such/file", 0); return 0; } // open -> -1 => __syscall_ret error path
Expected: trap "memory access out of bounds" inside __syscall_ret.resume on the errno write.
(Any failing syscall works: mmap(len=0)->EINVAL, etc. If a bare main() doesn't trigger it but a global
ctor does, that itself is a useful signal — the first hit was from a static ctor.)
Evidence from the actual run (self-hosted clang.wasm as /init, --version)
During __wasm_call_ctors -> _GLOBAL__sub_I_WebAssemblyMCInstLower.cpp, 5 syscalls succeed then the 6th errors, and it traps on that first error return:
brk(0)->0 ; brk(0x2000)->0 ; mmap(len=0x2000)->0xF10000 ; mprotect(prot=3)->0 ; mmap(len=0, prot=3)->-22 (EINVAL) ; then TRAP
clang.__syscall_ret.resume (wasm-function[57356]) <- hwjs_resume <- hwjs_drive_loop <- __hwjs_drive <- __hwjs_ctor_drive._GLOBAL__sub_I_WebAssemblyMCInstLower.cpp <- __wasm_call_ctors RuntimeError: memory access out of bounds
Ruled out (so it's the error-branch itself, not the environment)
- NOT memory size: identical fault at user_memory 64 MB and 768 MB, same 6th syscall.
- NOT the stack: __stack_pointer init = 1 MiB.
- NOT the mmap region: the returned address (15.79 MB) is inside backed memory.
Analysis / suggested direction
__syscall_ret(-22) is the first trip down the ERROR branch: errno = -r; return -1 is the first errno
write of the run, and THAT access is OOB — so the bad access is in the coroutinized .resume clone of the
error path (TLS/errno pointer or the coroutine frame it reads). __syscall_ret is a tiny non-suspending
leaf — it likely should not be coroutinized at all; excluding it (and similar leaf libc helpers) from the
pass, or fixing the error-branch lowering of the .resume clone, should unblock. First time a program of
clang's scale has run under the drive, so this branch had not been exercised.