1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
//! Very basic WASI implementation for interpreter: sufficient to let stdout work.

use crate::interp::{read_u32, write_u32, ConstVal, InterpMemory, InterpResult};
use smallvec::smallvec;

pub fn call_wasi(mem: &mut InterpMemory, name: &str, args: &[ConstVal]) -> Option<InterpResult> {
    match name {
        "fd_prestat_get" => {
            Some(InterpResult::Ok(smallvec![ConstVal::I32(8)])) // BADF
        }
        "args_sizes_get" => {
            let p_argc = args[0].as_u32().unwrap();
            let p_argv_size = args[1].as_u32().unwrap();
            write_u32(mem, p_argc, 0);
            write_u32(mem, p_argv_size, 0);
            Some(InterpResult::Ok(smallvec![ConstVal::I32(0)]))
        }
        "environ_sizes_get" => {
            let p_environ_count = args[0].as_u32().unwrap();
            let p_environ_buf_size = args[0].as_u32().unwrap();
            write_u32(mem, p_environ_count, 0);
            write_u32(mem, p_environ_buf_size, 0);
            Some(InterpResult::Ok(smallvec![ConstVal::I32(0)]))
        }
        "args_get" => Some(InterpResult::Ok(smallvec![ConstVal::I32(0)])),
        "fd_fdstat_get" => {
            let fd = args[0].as_u32().unwrap();
            let p_fdstat_t = args[1].as_u32().unwrap();
            if fd == 1 {
                write_u32(mem, p_fdstat_t + 0, 2); // filetype = CHAR
                write_u32(mem, p_fdstat_t + 4, 0); // flags = 0
                write_u32(mem, p_fdstat_t + 8, 0x40); // rights_base = WRITE
                write_u32(mem, p_fdstat_t + 12, 0); // rights_inheriting = 0
                Some(InterpResult::Ok(smallvec![ConstVal::I32(0)]))
            } else {
                None
            }
        }
        "fd_write" => {
            let fd = args[0].as_u32().unwrap();
            let p_iovs = args[1].as_u32().unwrap();
            let iovs_len = args[2].as_u32().unwrap();
            let p_nwritten = args[3].as_u32().unwrap();
            if fd == 1 {
                let mut written = 0;
                for i in 0..iovs_len {
                    let iov_entry = p_iovs + 8 * i;
                    let base = read_u32(mem, iov_entry) as usize;
                    let len = read_u32(mem, iov_entry + 4) as usize;
                    let data = &mem.data[base..(base + len)];
                    print!("{}", std::str::from_utf8(data).unwrap());
                    written += len;
                }
                write_u32(mem, p_nwritten, written as u32);
                Some(InterpResult::Ok(smallvec![ConstVal::I32(0)]))
            } else {
                None
            }
        }
        "proc_exit" => {
            eprintln!("WASI exit: {:?}", args[0]);
            Some(InterpResult::Exit)
        }
        "clock_time_get" => {
            let p_time = args[2].as_u32().unwrap();
            write_u32(mem, p_time, 0);
            Some(InterpResult::Ok(smallvec![ConstVal::I32(0)]))
        }
        "clock_res_get" => {
            let p_res = args[1].as_u32().unwrap();
            write_u32(mem, p_res, 1);
            Some(InterpResult::Ok(smallvec![ConstVal::I32(0)]))
        }
        _ => None,
    }
}