wasix-org/wasix-libc

setjmp/longjmp example `jump.c` gives "failed to save stack: not exported __stack_pointer global"

Opened this issue · 2 comments

I found this example:

https://wasix.org/docs/language-guide/c/tutorials/longjmp

I have the WASI-SDK v20 installed, and picked up the wasix-sysroot from the build artifacts in the CI.

When I try to compile jump.c with plain wasi-sysroot, I get an error ('setjmp.h' file not found). But with wasix-sysroot, it compiles:

$ ~/wasi-sdk-20.0/bin/clang --sysroot=~/wasi/wasix-sysroot --target="wasm32-wasi" -c jump.c

If I try to link jump.o against plain wasi-sysroot, that also gets errors (undefined symbols: setjmp, longjmp). But with wasix-sysroot, it links.

$ ~/wasi-sdk-20.0/bin/clang --sysroot=~/wasi/wasix-sysroot --target="wasm32-wasi" jump.o -o jump.wasm

So that all seems to be as expected--and that makes it seem I'm getting the intended Wasix implementations.

But when I run jump.wasm in Wasmer 4.2.2 (on 64-bit Ubuntu, or on Windows), I don't get the expected output. It prints (A1) and terminates.

Here is the verbose (-v) output:

2023-10-17T08:17:56.706519Z INFO ThreadId(01) execute_wasm: wasmer_cli::commands::run: enter
2023-10-17T08:17:56.706634Z INFO ThreadId(01) execute_wasm:execute_wasi_module: wasmer_cli::commands::run: enter
(A1)
2023-10-17T08:17:56.708369Z WARN ThreadId(88) wasmer_wasix::syscalls: unable to get the memory stack - failed to save stack: not exported __stack_pointer global
2023-10-17T08:17:56.708827Z INFO ThreadId(01) execute_wasm:execute_wasi_module: wasmer_cli::commands::run: close time.busy=2.19ms time.idle=1.35µs
2023-10-17T08:17:56.708923Z INFO ThreadId(01) execute_wasm: wasmer_cli::commands::run: close time.busy=2.41ms time.idle=2.67µs

I tried --enable-all, but that did not help. I also tried an older Wasmer (4.1.1) since that was the version mentioned in the tutorial page, but get the same behavior.

The error about not getting the memory stack comes from the wasmer get_memory_stack_pointer() function:

https://github.com/wasmerio/wasmer/blob/15e5e44b5718fd229df40f65a1056fa27f1441e4/lib/wasix/src/syscalls/mod.rs#L810-L819

Any ideas on why this would be happening? Thanks...

I did some digging and found that __stack_pointer is something that is put in the code by LLVM, but it seems that since nothing was referencing it in jump.c it wasn't included in the Wasm file.

So I added -Wl,--export="__stack_pointer" to ask the linker to export the variable. This got a little further, to where it raises a problem about missing asyncify_start_rewind:

2023-10-17T10:17:15.229762Z INFO ThreadId(01) execute_wasm: wasmer_cli::commands::run: enter
2023-10-17T10:17:15.229916Z INFO ThreadId(01) execute_wasm:execute_wasi_module: wasmer_cli::commands::run: enter
(A1)
2023-10-17T10:17:15.231962Z WARN ThreadId(04) wasmer_wasix::syscalls: failed to unwind the stack because the asyncify_start_rewind export is missing
2023-10-17T10:17:15.232675Z INFO ThreadId(01) execute_wasm:execute_wasi_module: wasmer_cli::commands::run: close time.busy=2.76ms time.idle=1.38µs
2023-10-17T10:17:15.232777Z INFO ThreadId(01) execute_wasm: wasmer_cli::commands::run: close time.busy=3.02ms time.idle=2.55µs

But it seems that asyncify isn't part of Wasmer or Wasix, and requires an additional build step using the wasm-opt tool from binaryen:

$ wasm-opt --asyncify jump.wasm -o jump.wasm

Once I do that, I get the expected results from Wasmer:

(A1)
(B1)
(A2) r=10001
(B2) r=20001
(A3) r=10002
(B3) r=20002
(A4) r=10003

I notice that while the top of the webpage for jump.c says you need "wasi-sdk and wasi-libc" (and to specify your sysroot), the actual line which does the compilation in the example invokes something from a wasix-sdk folder:

# compilation command from the example page
$ /path/to/wasix-sdk/clang jump.c --target="wasm32-wasi" -o jump.wasm

So it may be that whoever wrote the example was using a clang which had been patched to set the sysroot, do the export, and run the asyncify steps automatically? :-/

@dynamite-bud can you take a look here?