How to call WASI functions directly in C using wasi-sdk (import module problem)

1k views Asked by At

I'm trying to call a WASI function (fd_write) directly in a C program using wasi-sdk. This is the the library (lib.c):

#include <stdint.h>

struct Ciovec
{
    uint8_t *buf;
    uint32_t buf_len;
};

uint16_t fd_write(uint32_t fd, struct Ciovec *iovs_ptr, uint32_t iovs_len, uint32_t *nwritten);

static char *str = "just testing\n";

void c_main()
{
    struct Ciovec vec = { .buf = (uint8_t*)str, .buf_len = 13 };
    uint32_t nwritten = 0;
    fd_write(1, &vec, 1, &nwritten);
}

Now if I build this to a statically-linkable library using wasi-sdk

~/wasi-sdk-11.0/bin/clang --sysroot ~/wasi-sdk-11.0/share/wasi-sysroot/ lib.c -c -o lib.o -fpic

I get this wat: (wasm2wat --enable-all output)

(module
  (type (;0;) (func))
  (type (;1;) (func (param i32 i32 i32 i32) (result i32)))
  (import "env" "__linear_memory" (memory (;0;) 1))
  (import "env" "__indirect_function_table" (table (;0;) 0 funcref))
  (import "env" "__stack_pointer" (global (;0;) (mut i32)))
  (import "env" "fd_write" (func (;0;) (type 1)))
  ...)

Now this import line for fd_write is not correct. As far as I understand WASI functions need to be imported from wasi_snapshot_preview1 or wasi_unstable (I don't have a source for the first one, I just saw it in an open-source code, for the second see the example here, but I'm not sure how to do then in C. Any ideas?

2

There are 2 answers

1
sinan On BEST ANSWER

Found the answer in wasi-libc source code:

uint16_t fd_write(uint32_t fd, struct Ciovec *iovs_ptr, uint32_t iovs_len, uint32_t *nwritten)
    __attribute__((
                __import_module__("wasi_snapshot_preview1"),
                __import_name__("fd_write"),
                ));

Generated Wasm:

  (import "wasi_snapshot_preview1" "fd_write" (func $fd_write (type 1)))

This still doesn't work though, I get undefined symbol: fd_write errors, but at least I know how to specify the import path now.

0
user2770034 On

So I made this to work:

#include <stdint.h>
#include <stdio.h>

extern uint16_t my_func()
__attribute__((
    __import_module__("my_module"),
    __import_name__("my_func"),
));

int main(){
    my_func();
    return 0;
}

Compile with -Wl,--allow-undefined

Generates

(module
  (type (;0;) (func (param i32 i32 i32) (result i32)))
  (type (;1;) (func (param i32 i64 i32) (result i64)))
  (type (;2;) (func (param i32 i32) (result i32)))
  (type (;3;) (func (result i32)))
  (type (;4;) (func (param i32)))
  (type (;5;) (func (param i32) (result i32)))
  (type (;6;) (func (param i32 i32 i32 i32) (result i32)))
  (type (;7;) (func (param i32 i64 i32 i32) (result i32)))
  (type (;8;) (func))
  (import "wasi_unstable" "fd_prestat_get" (func $__wasi_fd_prestat_get (type 2)))
  (import "wasi_unstable" "fd_prestat_dir_name" (func $__wasi_fd_prestat_dir_name (type 0)))
  (import "my_module" "my_func" (func $my_func__ (type 3)))
  (import "wasi_unstable" "proc_exit" (func $__wasi_proc_exit (type 4)))
  (import "wasi_unstable" "fd_fdstat_get" (func $__wasi_fd_fdstat_get (type 2)))
  (import "wasi_unstable" "fd_close" (func $__wasi_fd_close (type 5)))
  (import "wasi_unstable" "fd_write" (func $__wasi_fd_write (type 6)))
  (import "wasi_unstable" "fd_seek" (func $__wasi_fd_seek (type 7)))
  (func $__wasm_call_ctors (type 8))
  (func $undefined:__wasilibc_populate_environ (type 3) (result i32)