|
|
|
@ -14,32 +14,29 @@
|
|
|
|
|
|
|
|
|
|
#if defined(d_m3HasWASI)
|
|
|
|
|
|
|
|
|
|
typedef uint32_t __wasi_size_t;
|
|
|
|
|
#include "extra/wasi_core.h"
|
|
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <sys/uio.h>
|
|
|
|
|
#include <sys/random.h>
|
|
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
|
|
# if defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__)
|
|
|
|
|
# include <unistd.h>
|
|
|
|
|
# elif defined(_WIN32)
|
|
|
|
|
/* See http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */
|
|
|
|
|
# define SystemFunction036 NTAPI SystemFunction036
|
|
|
|
|
# include <NTSecAPI.h>
|
|
|
|
|
# undef SystemFunction036
|
|
|
|
|
# endif
|
|
|
|
|
|
|
|
|
|
//TODO
|
|
|
|
|
#define PREOPEN_CNT 5
|
|
|
|
|
#define NANOS_PER_SEC 1000000000
|
|
|
|
|
|
|
|
|
|
typedef uint32_t __wasi_size_t;
|
|
|
|
|
#if defined(__wasi__) || defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__)
|
|
|
|
|
# include <unistd.h>
|
|
|
|
|
# include <sys/uio.h>
|
|
|
|
|
# include <sys/random.h>
|
|
|
|
|
# include <fcntl.h>
|
|
|
|
|
# define HAS_IOVEC
|
|
|
|
|
#elif defined(_WIN32)
|
|
|
|
|
# include <Windows.h>
|
|
|
|
|
// See http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx
|
|
|
|
|
# define SystemFunction036 NTAPI SystemFunction036
|
|
|
|
|
# include <NTSecAPI.h>
|
|
|
|
|
# undef SystemFunction036
|
|
|
|
|
# define ssize_t SSIZE_T
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
struct wasi_iovec
|
|
|
|
|
{
|
|
|
|
@ -47,6 +44,18 @@ struct wasi_iovec
|
|
|
|
|
__wasi_size_t iov_len;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static inline
|
|
|
|
|
uint32_t addr2offset(IM3Runtime m, void *addr) {
|
|
|
|
|
return (u8*)addr - m->memory.wasmPages;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline
|
|
|
|
|
void *offset2addr(IM3Runtime m, uint32_t offset) {
|
|
|
|
|
return m->memory.wasmPages + offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define PREOPEN_CNT 5
|
|
|
|
|
|
|
|
|
|
typedef struct Preopen {
|
|
|
|
|
int fd;
|
|
|
|
|
char* path;
|
|
|
|
@ -96,20 +105,58 @@ __wasi_errno_t errno_to_wasi(int errnum) {
|
|
|
|
|
case EPIPE: return __WASI_EPIPE; break;
|
|
|
|
|
case EDOM: return __WASI_EDOM; break;
|
|
|
|
|
case ERANGE: return __WASI_ERANGE; break;
|
|
|
|
|
default: return errno;
|
|
|
|
|
default: return __WASI_EINVAL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
|
|
|
|
|
|
static inline
|
|
|
|
|
uint32_t addr2offset(IM3Runtime m, void *addr) {
|
|
|
|
|
return (u8*)addr - m->memory.wasmPages;
|
|
|
|
|
int clock_gettime(int clk_id, struct timespec *spec)
|
|
|
|
|
{
|
|
|
|
|
__int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime);
|
|
|
|
|
wintime -= 116444736000000000i64; //1jan1601 to 1jan1970
|
|
|
|
|
spec->tv_sec = wintime / 10000000i64; //seconds
|
|
|
|
|
spec->tv_nsec = wintime % 10000000i64 *100; //nano-seconds
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline
|
|
|
|
|
void *offset2addr(IM3Runtime m, uint32_t offset) {
|
|
|
|
|
return m->memory.wasmPages + offset;
|
|
|
|
|
int clock_getres(int clk_id, struct timespec *spec) {
|
|
|
|
|
return -1; // Defaults to 1000000
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline
|
|
|
|
|
int convert_clockid(__wasi_clockid_t in) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else // _WIN32
|
|
|
|
|
|
|
|
|
|
static inline
|
|
|
|
|
int convert_clockid(__wasi_clockid_t in) {
|
|
|
|
|
switch (in) {
|
|
|
|
|
case __WASI_CLOCK_MONOTONIC: return CLOCK_MONOTONIC;
|
|
|
|
|
case __WASI_CLOCK_PROCESS_CPUTIME_ID: return CLOCK_PROCESS_CPUTIME_ID;
|
|
|
|
|
case __WASI_CLOCK_REALTIME: return CLOCK_REALTIME;
|
|
|
|
|
case __WASI_CLOCK_THREAD_CPUTIME_ID: return CLOCK_THREAD_CPUTIME_ID;
|
|
|
|
|
default: return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // _WIN32
|
|
|
|
|
|
|
|
|
|
static inline
|
|
|
|
|
__wasi_timestamp_t convert_timespec(const struct timespec *ts) {
|
|
|
|
|
if (ts->tv_sec < 0)
|
|
|
|
|
return 0;
|
|
|
|
|
if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / 1000000000)
|
|
|
|
|
return UINT64_MAX;
|
|
|
|
|
return (__wasi_timestamp_t)ts->tv_sec * 1000000000 + ts->tv_nsec;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(HAS_IOVEC)
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
|
void copy_iov_to_host(struct iovec* host_iov, IM3Runtime runtime, uint32_t iov_offset, int32_t iovs_len)
|
|
|
|
|
{
|
|
|
|
@ -121,6 +168,7 @@ void copy_iov_to_host(struct iovec* host_iov, IM3Runtime runtime, uint32_t iov_o
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* WASI API implementation
|
|
|
|
@ -223,6 +271,13 @@ m3ApiRawFunction(m3_wasi_unstable_fd_fdstat_get)
|
|
|
|
|
|
|
|
|
|
if (runtime == NULL || fdstat == NULL) { m3ApiReturn(__WASI_EINVAL); }
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
fdstat->fs_filetype = 0;
|
|
|
|
|
fdstat->fs_flags = 0;
|
|
|
|
|
fdstat->fs_rights_base = (uint64_t)-1; // all rights
|
|
|
|
|
fdstat->fs_rights_inheriting = (uint64_t)-1; // all rights
|
|
|
|
|
m3ApiReturn(__WASI_ESUCCESS);
|
|
|
|
|
#else
|
|
|
|
|
struct stat fd_stat;
|
|
|
|
|
int fl = fcntl(fd, F_GETFL);
|
|
|
|
|
if (fl < 0) { m3ApiReturn(errno_to_wasi(errno)); }
|
|
|
|
@ -242,6 +297,7 @@ m3ApiRawFunction(m3_wasi_unstable_fd_fdstat_get)
|
|
|
|
|
fdstat->fs_rights_base = (uint64_t)-1; // all rights
|
|
|
|
|
fdstat->fs_rights_inheriting = (uint64_t)-1; // all rights
|
|
|
|
|
m3ApiReturn(__WASI_ESUCCESS);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m3ApiRawFunction(m3_wasi_unstable_fd_seek)
|
|
|
|
@ -286,6 +342,9 @@ m3ApiRawFunction(m3_wasi_unstable_path_open)
|
|
|
|
|
m3ApiReturn(__WASI_EINVAL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
// TODO
|
|
|
|
|
#else
|
|
|
|
|
// copy path so we can ensure it is NULL terminated
|
|
|
|
|
char host_path [path_len+1];
|
|
|
|
|
|
|
|
|
@ -322,7 +381,7 @@ m3ApiRawFunction(m3_wasi_unstable_path_open)
|
|
|
|
|
* fd = host_fd;
|
|
|
|
|
m3ApiReturn(__WASI_ESUCCESS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m3ApiRawFunction(m3_wasi_unstable_fd_read)
|
|
|
|
@ -335,6 +394,7 @@ m3ApiRawFunction(m3_wasi_unstable_fd_read)
|
|
|
|
|
|
|
|
|
|
if (runtime == NULL || nread == NULL) { m3ApiReturn(__WASI_EINVAL); }
|
|
|
|
|
|
|
|
|
|
#if defined(HAS_IOVEC)
|
|
|
|
|
struct iovec iovs[iovs_len];
|
|
|
|
|
copy_iov_to_host(iovs, runtime, iovs_offset, iovs_len);
|
|
|
|
|
|
|
|
|
@ -342,6 +402,24 @@ m3ApiRawFunction(m3_wasi_unstable_fd_read)
|
|
|
|
|
if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); }
|
|
|
|
|
*nread = ret;
|
|
|
|
|
m3ApiReturn(__WASI_ESUCCESS);
|
|
|
|
|
#else
|
|
|
|
|
ssize_t res = 0;
|
|
|
|
|
struct wasi_iovec *wasi_iov = offset2addr(runtime, iovs_offset);
|
|
|
|
|
for (int i = 0; i < iovs_len; i++) {
|
|
|
|
|
void* addr = offset2addr(runtime, wasi_iov[i].iov_base);
|
|
|
|
|
size_t len = wasi_iov[i].iov_len;
|
|
|
|
|
if (len == 0) continue;
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "R %d %d\n", i, len);
|
|
|
|
|
|
|
|
|
|
int ret = _read (fd, addr, len);
|
|
|
|
|
if (ret < 0) m3ApiReturn(errno_to_wasi(errno));
|
|
|
|
|
res += ret;
|
|
|
|
|
if (ret < len) break;
|
|
|
|
|
}
|
|
|
|
|
*nread = res;
|
|
|
|
|
m3ApiReturn(__WASI_ESUCCESS);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m3ApiRawFunction(m3_wasi_unstable_fd_write)
|
|
|
|
@ -354,6 +432,7 @@ m3ApiRawFunction(m3_wasi_unstable_fd_write)
|
|
|
|
|
|
|
|
|
|
if (runtime == NULL || nwritten == NULL) { m3ApiReturn(__WASI_EINVAL); }
|
|
|
|
|
|
|
|
|
|
#if defined(HAS_IOVEC)
|
|
|
|
|
struct iovec iovs[iovs_len];
|
|
|
|
|
copy_iov_to_host(iovs, runtime, iovs_offset, iovs_len);
|
|
|
|
|
|
|
|
|
@ -361,6 +440,24 @@ m3ApiRawFunction(m3_wasi_unstable_fd_write)
|
|
|
|
|
if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); }
|
|
|
|
|
*nwritten = ret;
|
|
|
|
|
m3ApiReturn(__WASI_ESUCCESS);
|
|
|
|
|
#else
|
|
|
|
|
ssize_t res = 0;
|
|
|
|
|
struct wasi_iovec *wasi_iov = offset2addr(runtime, iovs_offset);
|
|
|
|
|
for (int i = 0; i < iovs_len; i++) {
|
|
|
|
|
void* addr = offset2addr(runtime, wasi_iov[i].iov_base);
|
|
|
|
|
size_t len = wasi_iov[i].iov_len;
|
|
|
|
|
if (len == 0) continue;
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "W %d %d\n", i, len);
|
|
|
|
|
|
|
|
|
|
int ret = _write (fd, addr, len);
|
|
|
|
|
if (ret < 0) m3ApiReturn(errno_to_wasi(errno));
|
|
|
|
|
res += ret;
|
|
|
|
|
if (ret < len) break;
|
|
|
|
|
}
|
|
|
|
|
*nwritten = res;
|
|
|
|
|
m3ApiReturn(__WASI_ESUCCESS);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m3ApiRawFunction(m3_wasi_unstable_fd_close)
|
|
|
|
@ -377,39 +474,31 @@ m3ApiRawFunction(m3_wasi_unstable_fd_datasync)
|
|
|
|
|
m3ApiReturnType (uint32_t)
|
|
|
|
|
m3ApiGetArg (__wasi_fd_t, fd)
|
|
|
|
|
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
|
int ret = fflush(fd);
|
|
|
|
|
m3ApiReturn(ret == 0 ? __WASI_ESUCCESS : ret);
|
|
|
|
|
#else
|
|
|
|
|
int ret = fdatasync(fd);
|
|
|
|
|
m3ApiReturn(ret == 0 ? __WASI_ESUCCESS : ret);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m3ApiRawFunction(m3_wasi_unstable_random_get)
|
|
|
|
|
{
|
|
|
|
|
m3ApiReturnType (uint32_t)
|
|
|
|
|
m3ApiGetArgMem (void* , buf)
|
|
|
|
|
m3ApiGetArgMem (uint8_t* , buf)
|
|
|
|
|
m3ApiGetArg (__wasi_size_t , buflen)
|
|
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
ssize_t retlen = 0;
|
|
|
|
|
|
|
|
|
|
#if defined(__wasi__)
|
|
|
|
|
retlen = getentropy(buf, buflen);
|
|
|
|
|
if (retlen == 0) {
|
|
|
|
|
retlen = buflen;
|
|
|
|
|
}
|
|
|
|
|
#elif defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__)
|
|
|
|
|
size_t pos = 0;
|
|
|
|
|
for (; pos + 256 < buflen; pos += 256) {
|
|
|
|
|
if (getentropy((char *)buf + pos, 256)) {
|
|
|
|
|
m3ApiReturn(errno_to_wasi(errno));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (getentropy((char *)buf + pos, buflen - pos)) {
|
|
|
|
|
m3ApiReturn(errno_to_wasi(errno));
|
|
|
|
|
#if defined(__wasi__) || defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__)
|
|
|
|
|
size_t reqlen = min(buflen, 256);
|
|
|
|
|
if (getentropy(buf, reqlen) < 0) {
|
|
|
|
|
retlen = -1;
|
|
|
|
|
} else {
|
|
|
|
|
retlen = reqlen;
|
|
|
|
|
}
|
|
|
|
|
m3ApiReturn(__WASI_ESUCCESS);
|
|
|
|
|
|
|
|
|
|
#elif defined(__NetBSD__)
|
|
|
|
|
// TODO
|
|
|
|
|
// sysctl(buf, buflen)
|
|
|
|
|
#elif defined(__FreeBSD__) || defined(__linux__)
|
|
|
|
|
retlen = getrandom(buf, buflen, 0);
|
|
|
|
|
#elif defined(_WIN32)
|
|
|
|
@ -417,50 +506,60 @@ m3ApiRawFunction(m3_wasi_unstable_random_get)
|
|
|
|
|
m3ApiReturn(__WASI_ESUCCESS);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
// use syscall ?
|
|
|
|
|
abort (); // unsupport
|
|
|
|
|
retlen = -1;
|
|
|
|
|
m3ApiReturn(__WASI_ENOSYS);
|
|
|
|
|
#endif
|
|
|
|
|
if (retlen < 0) {
|
|
|
|
|
if (errno == EINTR) { continue; }
|
|
|
|
|
if (errno == EINTR || errno == EAGAIN) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
m3ApiReturn(errno_to_wasi(errno));
|
|
|
|
|
} else if (retlen == buflen) {
|
|
|
|
|
m3ApiReturn(__WASI_ESUCCESS);
|
|
|
|
|
} else {
|
|
|
|
|
buf += retlen;
|
|
|
|
|
buflen -= retlen;
|
|
|
|
|
}
|
|
|
|
|
if (retlen == buflen) { m3ApiReturn(__WASI_ESUCCESS); }
|
|
|
|
|
buf = (void *)((uint8_t *)buf + retlen);
|
|
|
|
|
buflen -= retlen;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m3ApiRawFunction(m3_wasi_unstable_clock_res_get)
|
|
|
|
|
{
|
|
|
|
|
m3ApiReturnType (uint32_t)
|
|
|
|
|
m3ApiGetArg (__wasi_clockid_t , clock_id)
|
|
|
|
|
m3ApiGetArg (__wasi_clockid_t , wasi_clk_id)
|
|
|
|
|
m3ApiGetArgMem (__wasi_timestamp_t* , resolution)
|
|
|
|
|
|
|
|
|
|
if (runtime == NULL || resolution == NULL) { m3ApiReturn(__WASI_EINVAL); }
|
|
|
|
|
|
|
|
|
|
int clk = convert_clockid(wasi_clk_id);
|
|
|
|
|
if (clk < 0) m3ApiReturn(__WASI_EINVAL);
|
|
|
|
|
|
|
|
|
|
struct timespec tp;
|
|
|
|
|
if (clock_getres(clock_id, &tp) != 0)
|
|
|
|
|
if (clock_getres(clk, &tp) != 0)
|
|
|
|
|
*resolution = 1000000;
|
|
|
|
|
else
|
|
|
|
|
*resolution = (tp.tv_sec * NANOS_PER_SEC) + tp.tv_nsec;
|
|
|
|
|
*resolution = convert_timespec(&tp);
|
|
|
|
|
|
|
|
|
|
m3ApiReturn(__WASI_ESUCCESS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m3ApiRawFunction(m3_wasi_unstable_clock_time_get)
|
|
|
|
|
{
|
|
|
|
|
m3ApiReturnType (uint32_t)
|
|
|
|
|
m3ApiGetArg (__wasi_clockid_t , clock_id)
|
|
|
|
|
m3ApiGetArg (__wasi_clockid_t , wasi_clk_id)
|
|
|
|
|
m3ApiGetArg (__wasi_timestamp_t , precision)
|
|
|
|
|
m3ApiGetArgMem (__wasi_timestamp_t* , time)
|
|
|
|
|
|
|
|
|
|
if (runtime == NULL || time == NULL) { m3ApiReturn(__WASI_EINVAL); }
|
|
|
|
|
|
|
|
|
|
int clk = convert_clockid(wasi_clk_id);
|
|
|
|
|
if (clk < 0) m3ApiReturn(__WASI_EINVAL);
|
|
|
|
|
|
|
|
|
|
struct timespec tp;
|
|
|
|
|
if (clock_gettime(clock_id, &tp) != 0) { m3ApiReturn(errno_to_wasi(errno)); }
|
|
|
|
|
if (clock_gettime(clk, &tp) != 0) {
|
|
|
|
|
m3ApiReturn(errno_to_wasi(errno));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//printf("=== time: %lu.%09u\n", tp.tv_sec, tp.tv_nsec);
|
|
|
|
|
*time = (uint64_t)tp.tv_sec * NANOS_PER_SEC + tp.tv_nsec;
|
|
|
|
|
*time = convert_timespec(&tp);
|
|
|
|
|
m3ApiReturn(__WASI_ESUCCESS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -493,11 +592,14 @@ M3Result m3_LinkWASI (IM3Module module)
|
|
|
|
|
|
|
|
|
|
const char* namespace = "wasi_unstable";
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
// TODO
|
|
|
|
|
#else
|
|
|
|
|
// Preopen dirs
|
|
|
|
|
for (int i = 3; i < PREOPEN_CNT; i++) {
|
|
|
|
|
preopen[i].fd = open(preopen[i].path, O_RDONLY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "args_sizes_get", &m3_wasi_unstable_args_sizes_get)));
|
|
|
|
|
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "environ_sizes_get", &m3_wasi_unstable_environ_sizes_get)));
|
|
|
|
|
_ (SuppressLookupFailure (m3_LinkRawFunction (module, namespace, "args_get", &m3_wasi_unstable_args_get)));
|
|
|
|
|