Skip to content

__main_argc_argv is not retained in main module linked with libc.so #367

@kateinoigakukun

Description

@kateinoigakukun

I'm trying to add shared-everything support in WebAssembly port of CRuby, and found an issue.

Dependencies

Repro

$ curl -LO https://github.com/bytecodealliance/wasmtime/releases/download/v15.0.0/wasi_snapshot_preview1.command.wasm
$ cat main.c
int main(int argc, char **argv) {
    return 0;
}

$ $WASI_SDK_PATH/bin/clang main.c -fPIC -Xlinker -pie -Xlinker --import-memory -Xlinker --experimental-pic -o a.out
$ wasm-tools component link a.out $WASI_SDK_PATH/share/wasi-sysroot/lib/wasm32-wasi/libc.so --adapt wasi_snapshot_preview1.command.wasm -o a.out.wasm
$ wasmtime run --wasm component-model a.out.wasm
Error: failed to run main module `a.out.wasm`

Caused by:
    0: failed to invoke `run` function
    1: error while executing at wasm backtrace:
           0: 0x1417c - wit-component:stubs!<wasm function 0>
           1: 0x1f43a - libc.so!__main_void
           2: 0xae76c - a.out!_start
           3: 0xb05df - wit-component:shim!adapt-a.out-_start
           4: 0x5220 - wit-component:adapter:wasi_snapshot_preview1!wasi:cli/run@0.2.0-rc-2023-11-10#run
       note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information
    2: wasm trap: wasm `unreachable` instruction executed

The main problem here is:

  1. __main_argc_argv is defined with hidden visibility
$ wasm-objdump -x main.o | grep "F <__main_argc_argv>"
 - 0: F <__main_argc_argv> func=1 [ binding=global vis=hidden ]
  1. __main_argc_argv is referenced from libc.so's __main_void (which is referenced from crt1-command.o's _start)
    but the use of __main_argc_argv in libc.so doesn't mark it live.
    With static-link, libc.a, crt1-command.o, and main.o are linked together into a single image, so symbols are fully resolved.

Options

There are several ways to resolve the issue. I prefer option 3 as an ideal solution, but I'd like to hear @dicej opinion before tackling it.

Option 1. Adding -Xlinker -export-if-defined=__main_argc_argv to clang command.

This is a tentative workaround without toolchain modification.

Option 2. Set __main_argc_argv's visibility as default in clang

  • Need to update other compilers that use wasi-libc like Swift
  • The symbol will be leaked to other images

Option 3. Move __main_void to crt1-command.o

  • Linking __main_void into the main module cleanly solves the liveness issue.
  • According to the comment, something wrong happens with --no-gc-sections.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions