summaryrefslogtreecommitdiffstats
path: root/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c
diff options
context:
space:
mode:
Diffstat (limited to 'fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c')
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c1123
1 files changed, 1123 insertions, 0 deletions
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c
new file mode 100644
index 000000000..55916deb4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c
@@ -0,0 +1,1123 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_common.h"
+#include "bh_log.h"
+#include "wasm_export.h"
+#include "../interpreter/wasm.h"
+
+#if defined(_WIN32) || defined(_WIN32_)
+#define strncasecmp _strnicmp
+#define strcasecmp _stricmp
+#endif
+
+void
+wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception);
+
+uint32
+wasm_runtime_module_realloc(wasm_module_inst_t module, uint32 ptr, uint32 size,
+ void **p_native_addr);
+
+/* clang-format off */
+#define get_module_inst(exec_env) \
+ wasm_runtime_get_module_inst(exec_env)
+
+#define validate_app_addr(offset, size) \
+ wasm_runtime_validate_app_addr(module_inst, offset, size)
+
+#define validate_app_str_addr(offset) \
+ wasm_runtime_validate_app_str_addr(module_inst, offset)
+
+#define validate_native_addr(addr, size) \
+ wasm_runtime_validate_native_addr(module_inst, addr, size)
+
+#define addr_app_to_native(offset) \
+ wasm_runtime_addr_app_to_native(module_inst, offset)
+
+#define addr_native_to_app(ptr) \
+ wasm_runtime_addr_native_to_app(module_inst, ptr)
+
+#define module_malloc(size, p_native_addr) \
+ wasm_runtime_module_malloc(module_inst, size, p_native_addr)
+
+#define module_free(offset) \
+ wasm_runtime_module_free(module_inst, offset)
+/* clang-format on */
+
+typedef int (*out_func_t)(int c, void *ctx);
+
+typedef char *_va_list;
+#define _INTSIZEOF(n) (((uint32)sizeof(n) + 3) & (uint32)~3)
+#define _va_arg(ap, t) (*(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
+
+#define CHECK_VA_ARG(ap, t) \
+ do { \
+ if ((uint8 *)ap + _INTSIZEOF(t) > native_end_addr) { \
+ if (fmt_buf != temp_fmt) { \
+ wasm_runtime_free(fmt_buf); \
+ } \
+ goto fail; \
+ } \
+ } while (0)
+
+/* clang-format off */
+#define PREPARE_TEMP_FORMAT() \
+ char temp_fmt[32], *s, *fmt_buf = temp_fmt; \
+ uint32 fmt_buf_len = (uint32)sizeof(temp_fmt); \
+ int32 n; \
+ \
+ /* additional 2 bytes: one is the format char, \
+ the other is `\0` */ \
+ if ((uint32)(fmt - fmt_start_addr + 2) >= fmt_buf_len) { \
+ bh_assert((uint32)(fmt - fmt_start_addr) <= \
+ UINT32_MAX - 2); \
+ fmt_buf_len = (uint32)(fmt - fmt_start_addr + 2); \
+ if (!(fmt_buf = wasm_runtime_malloc(fmt_buf_len))) { \
+ print_err(out, ctx); \
+ break; \
+ } \
+ } \
+ \
+ memset(fmt_buf, 0, fmt_buf_len); \
+ bh_memcpy_s(fmt_buf, fmt_buf_len, fmt_start_addr, \
+ (uint32)(fmt - fmt_start_addr + 1));
+/* clang-format on */
+
+#define OUTPUT_TEMP_FORMAT() \
+ do { \
+ if (n > 0) { \
+ s = buf; \
+ while (*s) \
+ out((int)(*s++), ctx); \
+ } \
+ \
+ if (fmt_buf != temp_fmt) { \
+ wasm_runtime_free(fmt_buf); \
+ } \
+ } while (0)
+
+static void
+print_err(out_func_t out, void *ctx)
+{
+ out('E', ctx);
+ out('R', ctx);
+ out('R', ctx);
+}
+
+static bool
+_vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap,
+ wasm_module_inst_t module_inst)
+{
+ int might_format = 0; /* 1 if encountered a '%' */
+ int long_ctr = 0;
+ uint8 *native_end_addr;
+ const char *fmt_start_addr = NULL;
+
+ if (!wasm_runtime_get_native_addr_range(module_inst, (uint8 *)ap, NULL,
+ &native_end_addr))
+ goto fail;
+
+ /* fmt has already been adjusted if needed */
+
+ while (*fmt) {
+ if (!might_format) {
+ if (*fmt != '%') {
+ out((int)*fmt, ctx);
+ }
+ else {
+ might_format = 1;
+ long_ctr = 0;
+ fmt_start_addr = fmt;
+ }
+ }
+ else {
+ switch (*fmt) {
+ case '.':
+ case '+':
+ case '-':
+ case ' ':
+ case '#':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ goto still_might_format;
+
+ case 't': /* ptrdiff_t */
+ case 'z': /* size_t (32bit on wasm) */
+ long_ctr = 1;
+ goto still_might_format;
+
+ case 'j':
+ /* intmax_t/uintmax_t */
+ long_ctr = 2;
+ goto still_might_format;
+
+ case 'l':
+ long_ctr++;
+ /* Fall through */
+ case 'h':
+ /* FIXME: do nothing for these modifiers */
+ goto still_might_format;
+
+ case 'o':
+ case 'd':
+ case 'i':
+ case 'u':
+ case 'p':
+ case 'x':
+ case 'X':
+ case 'c':
+ {
+ char buf[64];
+ PREPARE_TEMP_FORMAT();
+
+ if (long_ctr < 2) {
+ int32 d;
+
+ CHECK_VA_ARG(ap, uint32);
+ d = _va_arg(ap, int32);
+
+ if (long_ctr == 1) {
+ uint32 fmt_end_idx = (uint32)(fmt - fmt_start_addr);
+
+ if (fmt_buf[fmt_end_idx - 1] == 'l'
+ || fmt_buf[fmt_end_idx - 1] == 'z'
+ || fmt_buf[fmt_end_idx - 1] == 't') {
+ /* The %ld, %zd and %td should be treated as
+ * 32bit integer in wasm */
+ fmt_buf[fmt_end_idx - 1] = fmt_buf[fmt_end_idx];
+ fmt_buf[fmt_end_idx] = '\0';
+ }
+ }
+
+ n = snprintf(buf, sizeof(buf), fmt_buf, d);
+ }
+ else {
+ int64 lld;
+
+ /* Make 8-byte aligned */
+ ap = (_va_list)(((uintptr_t)ap + 7) & ~(uintptr_t)7);
+ CHECK_VA_ARG(ap, uint64);
+ lld = _va_arg(ap, int64);
+ n = snprintf(buf, sizeof(buf), fmt_buf, lld);
+ }
+
+ OUTPUT_TEMP_FORMAT();
+ break;
+ }
+
+ case 's':
+ {
+ char buf_tmp[128], *buf = buf_tmp;
+ char *start;
+ uint32 s_offset, str_len, buf_len;
+
+ PREPARE_TEMP_FORMAT();
+
+ CHECK_VA_ARG(ap, int32);
+ s_offset = _va_arg(ap, uint32);
+
+ if (!validate_app_str_addr(s_offset)) {
+ if (fmt_buf != temp_fmt) {
+ wasm_runtime_free(fmt_buf);
+ }
+ return false;
+ }
+
+ s = start = addr_app_to_native(s_offset);
+
+ str_len = (uint32)strlen(start);
+ if (str_len >= UINT32_MAX - 64) {
+ print_err(out, ctx);
+ if (fmt_buf != temp_fmt) {
+ wasm_runtime_free(fmt_buf);
+ }
+ break;
+ }
+
+ /* reserve 64 more bytes as there may be width description
+ * in the fmt */
+ buf_len = str_len + 64;
+
+ if (buf_len > (uint32)sizeof(buf_tmp)) {
+ if (!(buf = wasm_runtime_malloc(buf_len))) {
+ print_err(out, ctx);
+ if (fmt_buf != temp_fmt) {
+ wasm_runtime_free(fmt_buf);
+ }
+ break;
+ }
+ }
+
+ n = snprintf(buf, buf_len, fmt_buf,
+ (s_offset == 0 && str_len == 0) ? NULL
+ : start);
+
+ OUTPUT_TEMP_FORMAT();
+
+ if (buf != buf_tmp) {
+ wasm_runtime_free(buf);
+ }
+
+ break;
+ }
+
+ case '%':
+ {
+ out((int)'%', ctx);
+ break;
+ }
+
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ case 'f':
+ case 'F':
+ {
+ float64 f64;
+ char buf[64];
+ PREPARE_TEMP_FORMAT();
+
+ /* Make 8-byte aligned */
+ ap = (_va_list)(((uintptr_t)ap + 7) & ~(uintptr_t)7);
+ CHECK_VA_ARG(ap, float64);
+ f64 = _va_arg(ap, float64);
+ n = snprintf(buf, sizeof(buf), fmt_buf, f64);
+
+ OUTPUT_TEMP_FORMAT();
+ break;
+ }
+
+ case 'n':
+ /* print nothing */
+ break;
+
+ default:
+ out((int)'%', ctx);
+ out((int)*fmt, ctx);
+ break;
+ }
+
+ might_format = 0;
+ }
+
+ still_might_format:
+ ++fmt;
+ }
+ return true;
+
+fail:
+ wasm_runtime_set_exception(module_inst, "out of bounds memory access");
+ return false;
+}
+
+struct str_context {
+ char *str;
+ uint32 max;
+ uint32 count;
+};
+
+static int
+sprintf_out(int c, struct str_context *ctx)
+{
+ if (!ctx->str || ctx->count >= ctx->max) {
+ ctx->count++;
+ return c;
+ }
+
+ if (ctx->count == ctx->max - 1) {
+ ctx->str[ctx->count++] = '\0';
+ }
+ else {
+ ctx->str[ctx->count++] = (char)c;
+ }
+
+ return c;
+}
+
+#ifndef BUILTIN_LIBC_BUFFERED_PRINTF
+#define BUILTIN_LIBC_BUFFERED_PRINTF 0
+#endif
+
+#ifndef BUILTIN_LIBC_BUFFERED_PRINT_SIZE
+#define BUILTIN_LIBC_BUFFERED_PRINT_SIZE 128
+#endif
+#ifndef BUILTIN_LIBC_BUFFERED_PRINT_PREFIX
+#define BUILTIN_LIBC_BUFFERED_PRINT_PREFIX
+#endif
+
+#if BUILTIN_LIBC_BUFFERED_PRINTF != 0
+
+BUILTIN_LIBC_BUFFERED_PRINT_PREFIX
+static char print_buf[BUILTIN_LIBC_BUFFERED_PRINT_SIZE] = { 0 };
+
+BUILTIN_LIBC_BUFFERED_PRINT_PREFIX
+static int print_buf_size = 0;
+
+static int
+printf_out(int c, struct str_context *ctx)
+{
+ if (c == '\n') {
+ print_buf[print_buf_size] = '\0';
+ os_printf("%s\n", print_buf);
+ print_buf_size = 0;
+ }
+ else if (print_buf_size >= sizeof(print_buf) - 2) {
+ print_buf[print_buf_size++] = (char)c;
+ print_buf[print_buf_size] = '\0';
+ os_printf("%s\n", print_buf);
+ print_buf_size = 0;
+ }
+ else {
+ print_buf[print_buf_size++] = (char)c;
+ }
+ ctx->count++;
+ return c;
+}
+#else
+static int
+printf_out(int c, struct str_context *ctx)
+{
+ os_printf("%c", c);
+ ctx->count++;
+ return c;
+}
+#endif
+
+static int
+printf_wrapper(wasm_exec_env_t exec_env, const char *format, _va_list va_args)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ struct str_context ctx = { NULL, 0, 0 };
+
+ /* format has been checked by runtime */
+ if (!validate_native_addr(va_args, sizeof(int32)))
+ return 0;
+
+ if (!_vprintf_wa((out_func_t)printf_out, &ctx, format, va_args,
+ module_inst))
+ return 0;
+
+ return (int)ctx.count;
+}
+
+static int
+sprintf_wrapper(wasm_exec_env_t exec_env, char *str, const char *format,
+ _va_list va_args)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint8 *native_end_offset;
+ struct str_context ctx;
+
+ /* str and format have been checked by runtime */
+ if (!validate_native_addr(va_args, sizeof(uint32)))
+ return 0;
+
+ if (!wasm_runtime_get_native_addr_range(module_inst, (uint8 *)str, NULL,
+ &native_end_offset)) {
+ wasm_runtime_set_exception(module_inst, "out of bounds memory access");
+ return false;
+ }
+
+ ctx.str = str;
+ ctx.max = (uint32)(native_end_offset - (uint8 *)str);
+ ctx.count = 0;
+
+ if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args,
+ module_inst))
+ return 0;
+
+ if (ctx.count < ctx.max) {
+ str[ctx.count] = '\0';
+ }
+
+ return (int)ctx.count;
+}
+
+static int
+snprintf_wrapper(wasm_exec_env_t exec_env, char *str, uint32 size,
+ const char *format, _va_list va_args)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ struct str_context ctx;
+
+ /* str and format have been checked by runtime */
+ if (!validate_native_addr(va_args, sizeof(uint32)))
+ return 0;
+
+ ctx.str = str;
+ ctx.max = size;
+ ctx.count = 0;
+
+ if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args,
+ module_inst))
+ return 0;
+
+ if (ctx.count < ctx.max) {
+ str[ctx.count] = '\0';
+ }
+
+ return (int)ctx.count;
+}
+
+static int
+puts_wrapper(wasm_exec_env_t exec_env, const char *str)
+{
+ return os_printf("%s\n", str);
+}
+
+static int
+putchar_wrapper(wasm_exec_env_t exec_env, int c)
+{
+ os_printf("%c", c);
+ return 1;
+}
+
+static uint32
+strdup_wrapper(wasm_exec_env_t exec_env, const char *str)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ char *str_ret;
+ uint32 len;
+ uint32 str_ret_offset = 0;
+
+ /* str has been checked by runtime */
+ if (str) {
+ len = (uint32)strlen(str) + 1;
+
+ str_ret_offset = module_malloc(len, (void **)&str_ret);
+ if (str_ret_offset) {
+ bh_memcpy_s(str_ret, len, str, len);
+ }
+ }
+
+ return str_ret_offset;
+}
+
+static uint32
+_strdup_wrapper(wasm_exec_env_t exec_env, const char *str)
+{
+ return strdup_wrapper(exec_env, str);
+}
+
+static int32
+memcmp_wrapper(wasm_exec_env_t exec_env, const void *s1, const void *s2,
+ uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ /* s2 has been checked by runtime */
+ if (!validate_native_addr((void *)s1, size))
+ return 0;
+
+ return memcmp(s1, s2, size);
+}
+
+static uint32
+memcpy_wrapper(wasm_exec_env_t exec_env, void *dst, const void *src,
+ uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 dst_offset = addr_native_to_app(dst);
+
+ if (size == 0)
+ return dst_offset;
+
+ /* src has been checked by runtime */
+ if (!validate_native_addr(dst, size))
+ return dst_offset;
+
+ bh_memcpy_s(dst, size, src, size);
+ return dst_offset;
+}
+
+static uint32
+memmove_wrapper(wasm_exec_env_t exec_env, void *dst, void *src, uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 dst_offset = addr_native_to_app(dst);
+
+ if (size == 0)
+ return dst_offset;
+
+ /* src has been checked by runtime */
+ if (!validate_native_addr(dst, size))
+ return dst_offset;
+
+ memmove(dst, src, size);
+ return dst_offset;
+}
+
+static uint32
+memset_wrapper(wasm_exec_env_t exec_env, void *s, int32 c, uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 s_offset = addr_native_to_app(s);
+
+ if (!validate_native_addr(s, size))
+ return s_offset;
+
+ memset(s, c, size);
+ return s_offset;
+}
+
+static uint32
+strchr_wrapper(wasm_exec_env_t exec_env, const char *s, int32 c)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ char *ret;
+
+ /* s has been checked by runtime */
+ ret = strchr(s, c);
+ return ret ? addr_native_to_app(ret) : 0;
+}
+
+static int32
+strcmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2)
+{
+ /* s1 and s2 have been checked by runtime */
+ return strcmp(s1, s2);
+}
+
+static int32
+strncmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2,
+ uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ /* s2 has been checked by runtime */
+ if (!validate_native_addr((void *)s1, size))
+ return 0;
+
+ return strncmp(s1, s2, size);
+}
+
+static uint32
+strcpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 len = (uint32)strlen(src) + 1;
+
+ /* src has been checked by runtime */
+ if (!validate_native_addr(dst, len))
+ return 0;
+
+#ifndef BH_PLATFORM_WINDOWS
+ strncpy(dst, src, len);
+#else
+ strncpy_s(dst, len, src, len);
+#endif
+ return addr_native_to_app(dst);
+}
+
+static uint32
+strncpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src,
+ uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ /* src has been checked by runtime */
+ if (!validate_native_addr(dst, size))
+ return 0;
+
+#ifndef BH_PLATFORM_WINDOWS
+ strncpy(dst, src, size);
+#else
+ strncpy_s(dst, size, src, size);
+#endif
+ return addr_native_to_app(dst);
+}
+
+static uint32
+strlen_wrapper(wasm_exec_env_t exec_env, const char *s)
+{
+ /* s has been checked by runtime */
+ return (uint32)strlen(s);
+}
+
+static uint32
+malloc_wrapper(wasm_exec_env_t exec_env, uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ return module_malloc(size, NULL);
+}
+
+static uint32
+calloc_wrapper(wasm_exec_env_t exec_env, uint32 nmemb, uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint64 total_size = (uint64)nmemb * (uint64)size;
+ uint32 ret_offset = 0;
+ uint8 *ret_ptr;
+
+ if (total_size >= UINT32_MAX)
+ return 0;
+
+ ret_offset = module_malloc((uint32)total_size, (void **)&ret_ptr);
+ if (ret_offset) {
+ memset(ret_ptr, 0, (uint32)total_size);
+ }
+
+ return ret_offset;
+}
+
+static uint32
+realloc_wrapper(wasm_exec_env_t exec_env, uint32 ptr, uint32 new_size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ return wasm_runtime_module_realloc(module_inst, ptr, new_size, NULL);
+}
+
+static void
+free_wrapper(wasm_exec_env_t exec_env, void *ptr)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ if (!validate_native_addr(ptr, sizeof(uint32)))
+ return;
+
+ module_free(addr_native_to_app(ptr));
+}
+
+static int32
+atoi_wrapper(wasm_exec_env_t exec_env, const char *s)
+{
+ /* s has been checked by runtime */
+ return atoi(s);
+}
+
+static void
+exit_wrapper(wasm_exec_env_t exec_env, int32 status)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ char buf[32];
+ snprintf(buf, sizeof(buf), "env.exit(%" PRId32 ")", status);
+ wasm_runtime_set_exception(module_inst, buf);
+}
+
+static int32
+strtol_wrapper(wasm_exec_env_t exec_env, const char *nptr, char **endptr,
+ int32 base)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ int32 num = 0;
+
+ /* nptr has been checked by runtime */
+ if (!validate_native_addr(endptr, sizeof(uint32)))
+ return 0;
+
+ num = (int32)strtol(nptr, endptr, base);
+ *(uint32 *)endptr = addr_native_to_app(*endptr);
+
+ return num;
+}
+
+static uint32
+strtoul_wrapper(wasm_exec_env_t exec_env, const char *nptr, char **endptr,
+ int32 base)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 num = 0;
+
+ /* nptr has been checked by runtime */
+ if (!validate_native_addr(endptr, sizeof(uint32)))
+ return 0;
+
+ num = (uint32)strtoul(nptr, endptr, base);
+ *(uint32 *)endptr = addr_native_to_app(*endptr);
+
+ return num;
+}
+
+static uint32
+memchr_wrapper(wasm_exec_env_t exec_env, const void *s, int32 c, uint32 n)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ void *res;
+
+ if (!validate_native_addr((void *)s, n))
+ return 0;
+
+ res = memchr(s, c, n);
+ return addr_native_to_app(res);
+}
+
+static int32
+strncasecmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2,
+ uint32 n)
+{
+ /* s1 and s2 have been checked by runtime */
+ return strncasecmp(s1, s2, n);
+}
+
+static uint32
+strspn_wrapper(wasm_exec_env_t exec_env, const char *s, const char *accept)
+{
+ /* s and accept have been checked by runtime */
+ return (uint32)strspn(s, accept);
+}
+
+static uint32
+strcspn_wrapper(wasm_exec_env_t exec_env, const char *s, const char *reject)
+{
+ /* s and reject have been checked by runtime */
+ return (uint32)strcspn(s, reject);
+}
+
+static uint32
+strstr_wrapper(wasm_exec_env_t exec_env, const char *s, const char *find)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ /* s and find have been checked by runtime */
+ char *res = strstr(s, find);
+ return addr_native_to_app(res);
+}
+
+static int32
+isupper_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isupper(c);
+}
+
+static int32
+isalpha_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isalpha(c);
+}
+
+static int32
+isspace_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isspace(c);
+}
+
+static int32
+isgraph_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isgraph(c);
+}
+
+static int32
+isprint_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isprint(c);
+}
+
+static int32
+isdigit_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isdigit(c);
+}
+
+static int32
+isxdigit_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isxdigit(c);
+}
+
+static int32
+tolower_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return tolower(c);
+}
+
+static int32
+toupper_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return toupper(c);
+}
+
+static int32
+isalnum_wrapper(wasm_exec_env_t exec_env, int32 c)
+{
+ return isalnum(c);
+}
+
+static uint32
+emscripten_memcpy_big_wrapper(wasm_exec_env_t exec_env, void *dst,
+ const void *src, uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 dst_offset = addr_native_to_app(dst);
+
+ /* src has been checked by runtime */
+ if (!validate_native_addr(dst, size))
+ return dst_offset;
+
+ bh_memcpy_s(dst, size, src, size);
+ return dst_offset;
+}
+
+static void
+abort_wrapper(wasm_exec_env_t exec_env, int32 code)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ char buf[32];
+ snprintf(buf, sizeof(buf), "env.abort(%" PRId32 ")", code);
+ wasm_runtime_set_exception(module_inst, buf);
+}
+
+static void
+abortStackOverflow_wrapper(wasm_exec_env_t exec_env, int32 code)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ char buf[32];
+ snprintf(buf, sizeof(buf), "env.abortStackOverflow(%" PRId32 ")", code);
+ wasm_runtime_set_exception(module_inst, buf);
+}
+
+static void
+nullFunc_X_wrapper(wasm_exec_env_t exec_env, int32 code)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ char buf[32];
+ snprintf(buf, sizeof(buf), "env.nullFunc_X(%" PRId32 ")", code);
+ wasm_runtime_set_exception(module_inst, buf);
+}
+
+static uint32
+__cxa_allocate_exception_wrapper(wasm_exec_env_t exec_env, uint32 thrown_size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 exception = module_malloc(thrown_size, NULL);
+ if (!exception)
+ return 0;
+
+ return exception;
+}
+
+static void
+__cxa_begin_catch_wrapper(wasm_exec_env_t exec_env, void *exception_object)
+{}
+
+static void
+__cxa_throw_wrapper(wasm_exec_env_t exec_env, void *thrown_exception,
+ void *tinfo, uint32 table_elem_idx)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ char buf[32];
+
+ snprintf(buf, sizeof(buf), "%s", "exception thrown by stdc++");
+ wasm_runtime_set_exception(module_inst, buf);
+}
+
+struct timespec_app {
+ int64 tv_sec;
+ int32 tv_nsec;
+};
+
+static uint32
+clock_gettime_wrapper(wasm_exec_env_t exec_env, uint32 clk_id,
+ struct timespec_app *ts_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint64 time;
+
+ if (!validate_native_addr(ts_app, sizeof(struct timespec_app)))
+ return (uint32)-1;
+
+ time = os_time_get_boot_microsecond();
+ ts_app->tv_sec = time / 1000000;
+ ts_app->tv_nsec = (time % 1000000) * 1000;
+
+ return (uint32)0;
+}
+
+static uint64
+clock_wrapper(wasm_exec_env_t exec_env)
+{
+ /* Convert to nano seconds as CLOCKS_PER_SEC in wasi-sdk */
+
+ return os_time_get_boot_microsecond() * 1000;
+}
+
+#if WASM_ENABLE_SPEC_TEST != 0
+static void
+print_wrapper(wasm_exec_env_t exec_env)
+{
+ os_printf("in specttest.print()\n");
+}
+
+static void
+print_i32_wrapper(wasm_exec_env_t exec_env, int32 i32)
+{
+ os_printf("in specttest.print_i32(%" PRId32 ")\n", i32);
+}
+
+static void
+print_i32_f32_wrapper(wasm_exec_env_t exec_env, int32 i32, float f32)
+{
+ os_printf("in specttest.print_i32_f32(%" PRId32 ", %f)\n", i32, f32);
+}
+
+static void
+print_f64_f64_wrapper(wasm_exec_env_t exec_env, double f64_1, double f64_2)
+{
+ os_printf("in specttest.print_f64_f64(%f, %f)\n", f64_1, f64_2);
+}
+
+static void
+print_f32_wrapper(wasm_exec_env_t exec_env, float f32)
+{
+ os_printf("in specttest.print_f32(%f)\n", f32);
+}
+
+static void
+print_f64_wrapper(wasm_exec_env_t exec_env, double f64)
+{
+ os_printf("in specttest.print_f64(%f)\n", f64);
+}
+#endif /* WASM_ENABLE_SPEC_TEST */
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, func_name##_wrapper, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_libc_builtin[] = {
+ REG_NATIVE_FUNC(printf, "($*)i"),
+ REG_NATIVE_FUNC(sprintf, "($$*)i"),
+ REG_NATIVE_FUNC(snprintf, "(*~$*)i"),
+ { "vprintf", printf_wrapper, "($*)i", NULL },
+ { "vsprintf", sprintf_wrapper, "($$*)i", NULL },
+ { "vsnprintf", snprintf_wrapper, "(*~$*)i", NULL },
+ REG_NATIVE_FUNC(puts, "($)i"),
+ REG_NATIVE_FUNC(putchar, "(i)i"),
+ REG_NATIVE_FUNC(memcmp, "(**~)i"),
+ REG_NATIVE_FUNC(memcpy, "(**~)i"),
+ REG_NATIVE_FUNC(memmove, "(**~)i"),
+ REG_NATIVE_FUNC(memset, "(*ii)i"),
+ REG_NATIVE_FUNC(strchr, "($i)i"),
+ REG_NATIVE_FUNC(strcmp, "($$)i"),
+ REG_NATIVE_FUNC(strcpy, "(*$)i"),
+ REG_NATIVE_FUNC(strlen, "($)i"),
+ REG_NATIVE_FUNC(strncmp, "(**~)i"),
+ REG_NATIVE_FUNC(strncpy, "(**~)i"),
+ REG_NATIVE_FUNC(malloc, "(i)i"),
+ REG_NATIVE_FUNC(realloc, "(ii)i"),
+ REG_NATIVE_FUNC(calloc, "(ii)i"),
+ REG_NATIVE_FUNC(strdup, "($)i"),
+ /* clang may introduce __strdup */
+ REG_NATIVE_FUNC(_strdup, "($)i"),
+ REG_NATIVE_FUNC(free, "(*)"),
+ REG_NATIVE_FUNC(atoi, "($)i"),
+ REG_NATIVE_FUNC(exit, "(i)"),
+ REG_NATIVE_FUNC(strtol, "($*i)i"),
+ REG_NATIVE_FUNC(strtoul, "($*i)i"),
+ REG_NATIVE_FUNC(memchr, "(*ii)i"),
+ REG_NATIVE_FUNC(strncasecmp, "($$i)i"),
+ REG_NATIVE_FUNC(strspn, "($$)i"),
+ REG_NATIVE_FUNC(strcspn, "($$)i"),
+ REG_NATIVE_FUNC(strstr, "($$)i"),
+ REG_NATIVE_FUNC(isupper, "(i)i"),
+ REG_NATIVE_FUNC(isalpha, "(i)i"),
+ REG_NATIVE_FUNC(isspace, "(i)i"),
+ REG_NATIVE_FUNC(isgraph, "(i)i"),
+ REG_NATIVE_FUNC(isprint, "(i)i"),
+ REG_NATIVE_FUNC(isdigit, "(i)i"),
+ REG_NATIVE_FUNC(isxdigit, "(i)i"),
+ REG_NATIVE_FUNC(tolower, "(i)i"),
+ REG_NATIVE_FUNC(toupper, "(i)i"),
+ REG_NATIVE_FUNC(isalnum, "(i)i"),
+ REG_NATIVE_FUNC(emscripten_memcpy_big, "(**~)i"),
+ REG_NATIVE_FUNC(abort, "(i)"),
+ REG_NATIVE_FUNC(abortStackOverflow, "(i)"),
+ REG_NATIVE_FUNC(nullFunc_X, "(i)"),
+ REG_NATIVE_FUNC(__cxa_allocate_exception, "(i)i"),
+ REG_NATIVE_FUNC(__cxa_begin_catch, "(*)"),
+ REG_NATIVE_FUNC(__cxa_throw, "(**i)"),
+ REG_NATIVE_FUNC(clock_gettime, "(i*)i"),
+ REG_NATIVE_FUNC(clock, "()I"),
+};
+
+#if WASM_ENABLE_SPEC_TEST != 0
+static NativeSymbol native_symbols_spectest[] = {
+ REG_NATIVE_FUNC(print, "()"),
+ REG_NATIVE_FUNC(print_i32, "(i)"),
+ REG_NATIVE_FUNC(print_i32_f32, "(if)"),
+ REG_NATIVE_FUNC(print_f64_f64, "(FF)"),
+ REG_NATIVE_FUNC(print_f32, "(f)"),
+ REG_NATIVE_FUNC(print_f64, "(F)")
+};
+#endif
+
+uint32
+get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis)
+{
+ *p_libc_builtin_apis = native_symbols_libc_builtin;
+ return sizeof(native_symbols_libc_builtin) / sizeof(NativeSymbol);
+}
+
+#if WASM_ENABLE_SPEC_TEST != 0
+uint32
+get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis)
+{
+ *p_libc_builtin_apis = native_symbols_spectest;
+ return sizeof(native_symbols_spectest) / sizeof(NativeSymbol);
+}
+#endif
+
+/*************************************
+ * Global Variables *
+ *************************************/
+
+typedef struct WASMNativeGlobalDef {
+ const char *module_name;
+ const char *global_name;
+ uint8 type;
+ bool is_mutable;
+ WASMValue value;
+} WASMNativeGlobalDef;
+
+static WASMNativeGlobalDef native_global_defs[] = {
+#if WASM_ENABLE_SPEC_TEST != 0
+ { "spectest", "global_i32", VALUE_TYPE_I32, false, .value.i32 = 666 },
+ { "spectest", "global_i64", VALUE_TYPE_I64, false, .value.i64 = 666 },
+ { "spectest", "global_f32", VALUE_TYPE_F32, false, .value.f32 = 666.6 },
+ { "spectest", "global_f64", VALUE_TYPE_F64, false, .value.f64 = 666.6 },
+ { "test", "global-i32", VALUE_TYPE_I32, false, .value.i32 = 0 },
+ { "test", "global-f32", VALUE_TYPE_F32, false, .value.f32 = 0 },
+ { "test", "global-mut-i32", VALUE_TYPE_I32, true, .value.i32 = 0 },
+ { "test", "global-mut-i64", VALUE_TYPE_I64, true, .value.i64 = 0 },
+#endif
+ { "global", "NaN", VALUE_TYPE_F64, .value.u64 = 0x7FF8000000000000LL },
+ { "global", "Infinity", VALUE_TYPE_F64, .value.u64 = 0x7FF0000000000000LL }
+};
+
+bool
+wasm_native_lookup_libc_builtin_global(const char *module_name,
+ const char *global_name,
+ WASMGlobalImport *global)
+{
+ uint32 size = sizeof(native_global_defs) / sizeof(WASMNativeGlobalDef);
+ WASMNativeGlobalDef *global_def = native_global_defs;
+ WASMNativeGlobalDef *global_def_end = global_def + size;
+
+ if (!module_name || !global_name || !global)
+ return false;
+
+ /* Lookup constant globals which can be defined by table */
+ while (global_def < global_def_end) {
+ if (!strcmp(global_def->module_name, module_name)
+ && !strcmp(global_def->global_name, global_name)) {
+ global->type = global_def->type;
+ global->is_mutable = global_def->is_mutable;
+ global->global_data_linked = global_def->value;
+ return true;
+ }
+ global_def++;
+ }
+
+ return false;
+}