summaryrefslogtreecommitdiffstats
path: root/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries
diff options
context:
space:
mode:
Diffstat (limited to 'fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries')
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.c1433
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.cmake12
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.h253
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.c330
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.h70
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.c876
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.h70
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.c91
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.h17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.c47
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.h23
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/SConscript20
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread.cmake17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c1331
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats.cmake43
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_common.h40
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.c115
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.h48
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h999
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake9
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c1009
-rwxr-xr-xfluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/build.sh25
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/nslookup.c49
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/tcp_udp.c193
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads.cmake12
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c184
-rwxr-xr-xfluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/build.sh35
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/common.h126
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c128
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c70
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c83
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/linear_memory_size_update.c94
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.c16
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/spawn_multiple_times.c72
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/sync_primitives.h91
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c44
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json3
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c97
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c80
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h36
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/SConscript24
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin.cmake13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c1123
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/SConscript19
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc.cmake12
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c554
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_LIBUV66
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_UVWASI21
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake44
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c1150
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/SConscript34
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi.cmake13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c2329
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h55
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE7
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE121
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h1508
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE24
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md14
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h14
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h265
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c4072
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h89
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h98
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c98
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h21
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h139
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h100
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h143
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c47
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h22
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/SConscript19
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.c1351
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.h218
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_mgr.cmake13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/README.md96
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake41
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/logger.h69
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c163
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h51
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn.c306
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h31
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp417
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp45
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/CMakeLists.txt173
-rwxr-xr-xfluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/build.sh21
-rwxr-xr-xfluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/average.py16
-rwxr-xr-xfluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/max.py17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_dimension.py15
-rwxr-xr-xfluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_outputs.py33
-rwxr-xr-xfluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/sum.py17
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/utils.py13
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/requirements.txt1
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/test_tensorflow.c146
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.c162
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.h52
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.cmake22
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.h89
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn_types.h106
122 files changed, 24445 insertions, 0 deletions
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.c
new file mode 100644
index 000000000..1b3db1d49
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.c
@@ -0,0 +1,1433 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "debug_engine.h"
+#include "gdbserver.h"
+#include "handler.h"
+#include "bh_platform.h"
+#include "wasm_interp.h"
+#include "wasm_opcode.h"
+#include "wasm_runtime.h"
+
+static const uint8 break_instr[] = { DEBUG_OP_BREAK };
+
+typedef struct WASMDebugEngine {
+ struct WASMDebugEngine *next;
+ WASMDebugControlThread *control_thread;
+ char ip_addr[128];
+ int32 process_base_port;
+ bh_list debug_instance_list;
+ korp_mutex instance_list_lock;
+} WASMDebugEngine;
+
+void
+on_thread_stop_event(WASMDebugInstance *debug_inst, WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&debug_inst->wait_lock);
+ debug_inst->stopped_thread = exec_env;
+
+ if (debug_inst->current_state == DBG_LAUNCHING) {
+ /* In launching phase, send a signal so that handle_threadstop_request
+ * can be woken up */
+ os_cond_signal(&debug_inst->wait_cond);
+ }
+ os_mutex_unlock(&debug_inst->wait_lock);
+}
+
+void
+on_thread_exit_event(WASMDebugInstance *debug_inst, WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&debug_inst->wait_lock);
+
+ /* DBG_LAUNCHING: exit when debugger detached,
+ * DBG_ERROR: exit when debugger error */
+ if (debug_inst->current_state != DBG_LAUNCHING
+ && debug_inst->current_state != DBG_ERROR) {
+ /* only when exit normally the debugger thread will participate in
+ * teardown phase */
+ debug_inst->stopped_thread = exec_env;
+ }
+
+ os_mutex_unlock(&debug_inst->wait_lock);
+}
+
+static WASMDebugEngine *g_debug_engine;
+
+static uint32 current_instance_id = 1;
+
+static uint32
+allocate_instance_id()
+{
+ uint32 id;
+
+ bh_assert(g_debug_engine);
+
+ os_mutex_lock(&g_debug_engine->instance_list_lock);
+ id = current_instance_id++;
+ os_mutex_unlock(&g_debug_engine->instance_list_lock);
+
+ return id;
+}
+
+static bool
+is_thread_running(WASMDebugControlThread *control_thread)
+{
+ return control_thread->status == RUNNING;
+}
+
+static bool
+is_thread_stopped(WASMDebugControlThread *control_thread)
+{
+ return control_thread->status == STOPPED;
+}
+
+static bool
+is_thread_detached(WASMDebugControlThread *control_thread)
+{
+ return control_thread->status == DETACHED;
+}
+
+static void *
+control_thread_routine(void *arg)
+{
+ WASMDebugInstance *debug_inst = (WASMDebugInstance *)arg;
+ WASMDebugControlThread *control_thread = NULL;
+
+ control_thread = debug_inst->control_thread;
+ bh_assert(control_thread);
+
+ os_mutex_lock(&debug_inst->wait_lock);
+
+ control_thread->status = RUNNING;
+
+ debug_inst->id = allocate_instance_id();
+
+ control_thread->debug_engine = g_debug_engine;
+ control_thread->debug_instance = debug_inst;
+ bh_strcpy_s(control_thread->ip_addr, sizeof(control_thread->ip_addr),
+ g_debug_engine->ip_addr);
+ if (control_thread->port == -1) {
+ control_thread->port =
+ (g_debug_engine->process_base_port == 0)
+ ? 0
+ : g_debug_engine->process_base_port + debug_inst->id - 1;
+ }
+
+ LOG_WARNING("control thread of debug object %p start\n", debug_inst);
+
+ control_thread->server =
+ wasm_create_gdbserver(control_thread->ip_addr, &control_thread->port);
+
+ if (!control_thread->server) {
+ LOG_ERROR("Failed to create debug server\n");
+ control_thread->port = 0;
+ os_cond_signal(&debug_inst->wait_cond);
+ os_mutex_unlock(&debug_inst->wait_lock);
+ return NULL;
+ }
+
+ control_thread->server->thread = control_thread;
+
+ /*
+ * wasm gdbserver created, the execution thread
+ * doesn't need to wait for the debugger connection,
+ * so we wake up the execution thread before listen
+ */
+ os_cond_signal(&debug_inst->wait_cond);
+ os_mutex_unlock(&debug_inst->wait_lock);
+
+ if (!wasm_gdbserver_listen(control_thread->server)) {
+ LOG_ERROR("Failed while listening for debugger\n");
+ goto fail;
+ }
+
+ /* outer infinite loop: try to connect with the debugger */
+ while (true) {
+ /* wait lldb client to connect */
+ if (!wasm_gdbserver_accept(control_thread->server)) {
+ LOG_ERROR("Failed while accepting debugger connection\n");
+ goto fail;
+ }
+
+ control_thread->status = RUNNING;
+ /* when reattached, send signal */
+ wasm_cluster_send_signal_all(debug_inst->cluster, WAMR_SIG_SINGSTEP);
+
+ /* inner infinite loop: keep serving until detach */
+ while (true) {
+ os_mutex_lock(&control_thread->wait_lock);
+ if (is_thread_running(control_thread)) {
+ /* send thread stop reply */
+ if (debug_inst->stopped_thread
+ && debug_inst->current_state == APP_RUNNING) {
+ uint32 status;
+ korp_tid tid;
+
+ status = (uint32)debug_inst->stopped_thread->current_status
+ ->signal_flag;
+ tid = debug_inst->stopped_thread->handle;
+
+ if (debug_inst->stopped_thread->current_status
+ ->running_status
+ == STATUS_EXIT) {
+ /* If the thread exits, report "W00" if it's the last
+ * thread in the cluster, otherwise ignore this event */
+ status = 0;
+
+ /* By design, all the other threads should have been
+ * stopped at this moment, so it is safe to access the
+ * exec_env_list.len without lock */
+ if (debug_inst->cluster->exec_env_list.len != 1) {
+ debug_inst->stopped_thread = NULL;
+ /* The exiting thread may wait for the signal */
+ os_cond_signal(&debug_inst->wait_cond);
+ os_mutex_unlock(&control_thread->wait_lock);
+ continue;
+ }
+ }
+
+ wasm_debug_instance_set_cur_thread(
+ debug_inst, debug_inst->stopped_thread->handle);
+
+ send_thread_stop_status(control_thread->server, status,
+ tid);
+
+ debug_inst->current_state = APP_STOPPED;
+ debug_inst->stopped_thread = NULL;
+
+ if (status == 0) {
+ /* The exiting thread may wait for the signal */
+ os_cond_signal(&debug_inst->wait_cond);
+ }
+ }
+
+ /* Processing incoming requests */
+ if (!wasm_gdbserver_handle_packet(control_thread->server)) {
+ control_thread->status = STOPPED;
+ LOG_ERROR("An error occurs when handling a packet\n");
+ os_mutex_unlock(&control_thread->wait_lock);
+ goto fail;
+ }
+ }
+ else if (is_thread_detached(control_thread)) {
+ os_mutex_unlock(&control_thread->wait_lock);
+ break;
+ }
+ else if (is_thread_stopped(control_thread)) {
+ os_mutex_unlock(&control_thread->wait_lock);
+ return NULL;
+ }
+ os_mutex_unlock(&control_thread->wait_lock);
+ }
+ }
+fail:
+ wasm_debug_instance_on_failure(debug_inst);
+ LOG_VERBOSE("control thread of debug object [%p] stopped with failure\n",
+ debug_inst);
+ return NULL;
+}
+
+static WASMDebugControlThread *
+wasm_debug_control_thread_create(WASMDebugInstance *debug_instance, int32 port)
+{
+ WASMDebugControlThread *control_thread;
+
+ if (!(control_thread =
+ wasm_runtime_malloc(sizeof(WASMDebugControlThread)))) {
+ LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
+ return NULL;
+ }
+ memset(control_thread, 0, sizeof(WASMDebugControlThread));
+ control_thread->port = port;
+
+ if (os_mutex_init(&control_thread->wait_lock) != 0)
+ goto fail;
+
+ debug_instance->control_thread = control_thread;
+
+ os_mutex_lock(&debug_instance->wait_lock);
+
+ if (0
+ != os_thread_create(&control_thread->tid, control_thread_routine,
+ debug_instance, APP_THREAD_STACK_SIZE_DEFAULT)) {
+ os_mutex_unlock(&debug_instance->wait_lock);
+ goto fail1;
+ }
+
+ /* wait until the debug control thread ready */
+ os_cond_wait(&debug_instance->wait_cond, &debug_instance->wait_lock);
+ os_mutex_unlock(&debug_instance->wait_lock);
+ if (!control_thread->server) {
+ os_thread_join(control_thread->tid, NULL);
+ goto fail1;
+ }
+
+ os_mutex_lock(&g_debug_engine->instance_list_lock);
+ /* create control thread success, append debug instance to debug engine */
+ bh_list_insert(&g_debug_engine->debug_instance_list, debug_instance);
+ os_mutex_unlock(&g_debug_engine->instance_list_lock);
+
+ /* If we set WAMR_SIG_STOP here, the VSCode debugger adaptor will raise an
+ * exception in the UI. We use WAMR_SIG_SINGSTEP to avoid this exception for
+ * better user experience */
+ wasm_cluster_send_signal_all(debug_instance->cluster, WAMR_SIG_SINGSTEP);
+
+ return control_thread;
+
+fail1:
+ os_mutex_destroy(&control_thread->wait_lock);
+fail:
+ wasm_runtime_free(control_thread);
+ return NULL;
+}
+
+static void
+wasm_debug_control_thread_destroy(WASMDebugInstance *debug_instance)
+{
+ WASMDebugControlThread *control_thread = debug_instance->control_thread;
+
+ LOG_VERBOSE("stopping control thread of debug object [%p]\n",
+ debug_instance);
+ control_thread->status = STOPPED;
+ os_mutex_lock(&control_thread->wait_lock);
+ wasm_close_gdbserver(control_thread->server);
+ os_mutex_unlock(&control_thread->wait_lock);
+ os_thread_join(control_thread->tid, NULL);
+ wasm_runtime_free(control_thread->server);
+
+ os_mutex_destroy(&control_thread->wait_lock);
+ wasm_runtime_free(control_thread);
+}
+
+static WASMDebugEngine *
+wasm_debug_engine_create()
+{
+ WASMDebugEngine *engine;
+
+ if (!(engine = wasm_runtime_malloc(sizeof(WASMDebugEngine)))) {
+ LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
+ return NULL;
+ }
+ memset(engine, 0, sizeof(WASMDebugEngine));
+
+ if (os_mutex_init(&engine->instance_list_lock) != 0) {
+ wasm_runtime_free(engine);
+ LOG_ERROR("WASM Debug Engine error: failed to init mutex");
+ return NULL;
+ }
+
+ /* reset current instance id */
+ current_instance_id = 1;
+
+ bh_list_init(&engine->debug_instance_list);
+ return engine;
+}
+
+void
+wasm_debug_engine_destroy()
+{
+ if (g_debug_engine) {
+ wasm_debug_handler_deinit();
+ os_mutex_destroy(&g_debug_engine->instance_list_lock);
+ wasm_runtime_free(g_debug_engine);
+ g_debug_engine = NULL;
+ }
+}
+
+bool
+wasm_debug_engine_init(char *ip_addr, int32 process_port)
+{
+ if (wasm_debug_handler_init() != 0) {
+ return false;
+ }
+
+ if (g_debug_engine == NULL) {
+ g_debug_engine = wasm_debug_engine_create();
+ }
+
+ if (g_debug_engine) {
+ g_debug_engine->process_base_port =
+ (process_port > 0) ? process_port : 0;
+ if (ip_addr)
+ snprintf(g_debug_engine->ip_addr, sizeof(g_debug_engine->ip_addr),
+ "%s", ip_addr);
+ else
+ snprintf(g_debug_engine->ip_addr, sizeof(g_debug_engine->ip_addr),
+ "%s", "127.0.0.1");
+ }
+ else {
+ wasm_debug_handler_deinit();
+ }
+
+ return g_debug_engine != NULL ? true : false;
+}
+
+/* A debug Instance is a debug "process" in gdb remote protocol
+ and bound to a runtime cluster */
+WASMDebugInstance *
+wasm_debug_instance_create(WASMCluster *cluster, int32 port)
+{
+ WASMDebugInstance *instance;
+ WASMExecEnv *exec_env = NULL;
+ wasm_module_inst_t module_inst = NULL;
+
+ if (!g_debug_engine) {
+ return NULL;
+ }
+
+ if (!(instance = wasm_runtime_malloc(sizeof(WASMDebugInstance)))) {
+ LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
+ return NULL;
+ }
+ memset(instance, 0, sizeof(WASMDebugInstance));
+
+ if (os_mutex_init(&instance->wait_lock) != 0) {
+ goto fail1;
+ }
+
+ if (os_cond_init(&instance->wait_cond) != 0) {
+ goto fail2;
+ }
+
+ bh_list_init(&instance->break_point_list);
+ bh_list_init(&instance->watch_point_list_read);
+ bh_list_init(&instance->watch_point_list_write);
+
+ instance->cluster = cluster;
+ exec_env = bh_list_first_elem(&cluster->exec_env_list);
+ bh_assert(exec_env);
+
+ instance->current_tid = exec_env->handle;
+
+ module_inst = wasm_runtime_get_module_inst(exec_env);
+ bh_assert(module_inst);
+
+ /* Allocate linear memory for evaluating expressions during debugging. If
+ * the allocation failed, the debugger will not be able to evaluate
+ * expressions */
+ instance->exec_mem_info.size = DEBUG_EXECUTION_MEMORY_SIZE;
+ instance->exec_mem_info.start_offset = wasm_runtime_module_malloc(
+ module_inst, instance->exec_mem_info.size, NULL);
+ if (instance->exec_mem_info.start_offset == 0) {
+ LOG_WARNING(
+ "WASM Debug Engine warning: failed to allocate linear memory for "
+ "execution. \n"
+ "Will not be able to evaluate expressions during "
+ "debugging");
+ }
+ instance->exec_mem_info.current_pos = instance->exec_mem_info.start_offset;
+
+ if (!wasm_debug_control_thread_create(instance, port)) {
+ LOG_ERROR("WASM Debug Engine error: failed to create control thread");
+ goto fail3;
+ }
+
+ wasm_cluster_set_debug_inst(cluster, instance);
+
+ return instance;
+
+fail3:
+ os_cond_destroy(&instance->wait_cond);
+fail2:
+ os_mutex_destroy(&instance->wait_lock);
+fail1:
+ wasm_runtime_free(instance);
+
+ return NULL;
+}
+
+static void
+wasm_debug_instance_destroy_breakpoints(WASMDebugInstance *instance)
+{
+ WASMDebugBreakPoint *breakpoint, *next_bp;
+
+ breakpoint = bh_list_first_elem(&instance->break_point_list);
+ while (breakpoint) {
+ next_bp = bh_list_elem_next(breakpoint);
+
+ bh_list_remove(&instance->break_point_list, breakpoint);
+ wasm_runtime_free(breakpoint);
+
+ breakpoint = next_bp;
+ }
+}
+
+static void
+wasm_debug_instance_destroy_watchpoints(WASMDebugInstance *instance,
+ bh_list *watchpoints)
+{
+ WASMDebugWatchPoint *watchpoint, *next;
+
+ watchpoint = bh_list_first_elem(watchpoints);
+ while (watchpoint) {
+ next = bh_list_elem_next(watchpoint);
+
+ bh_list_remove(watchpoints, watchpoint);
+ wasm_runtime_free(watchpoint);
+
+ watchpoint = next;
+ }
+}
+
+void
+wasm_debug_instance_destroy(WASMCluster *cluster)
+{
+ WASMDebugInstance *instance = NULL;
+
+ if (!g_debug_engine) {
+ return;
+ }
+
+ instance = cluster->debug_inst;
+ if (instance) {
+ /* destroy control thread */
+ wasm_debug_control_thread_destroy(instance);
+
+ os_mutex_lock(&g_debug_engine->instance_list_lock);
+ bh_list_remove(&g_debug_engine->debug_instance_list, instance);
+ os_mutex_unlock(&g_debug_engine->instance_list_lock);
+
+ /* destroy all breakpoints */
+ wasm_debug_instance_destroy_breakpoints(instance);
+ wasm_debug_instance_destroy_watchpoints(
+ instance, &instance->watch_point_list_read);
+ wasm_debug_instance_destroy_watchpoints(
+ instance, &instance->watch_point_list_write);
+
+ os_mutex_destroy(&instance->wait_lock);
+ os_cond_destroy(&instance->wait_cond);
+
+ wasm_runtime_free(instance);
+ cluster->debug_inst = NULL;
+ }
+}
+
+WASMExecEnv *
+wasm_debug_instance_get_current_env(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env = NULL;
+
+ if (instance) {
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ while (exec_env) {
+ if (exec_env->handle == instance->current_tid)
+ break;
+ exec_env = bh_list_elem_next(exec_env);
+ }
+ }
+ return exec_env;
+}
+
+#if WASM_ENABLE_LIBC_WASI != 0
+bool
+wasm_debug_instance_get_current_object_name(WASMDebugInstance *instance,
+ char name_buffer[], uint32 len)
+{
+ WASMExecEnv *exec_env;
+ WASIArguments *wasi_args;
+ WASMModuleInstance *module_inst;
+
+ if (!instance)
+ return false;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+ wasi_args = &module_inst->module->wasi_args;
+ if (wasi_args && wasi_args->argc > 0) {
+ char *argv_name = wasi_args->argv[0];
+ uint32 name_len = (uint32)strlen(argv_name);
+
+ printf("the module name is %s\n", argv_name);
+ if (len - 1 >= name_len)
+ bh_strcpy_s(name_buffer, len, argv_name);
+ else
+ bh_strcpy_s(name_buffer, len, argv_name + (name_len + 1 - len));
+ return true;
+ }
+ return false;
+}
+#endif
+
+uint64
+wasm_debug_instance_get_pid(WASMDebugInstance *instance)
+{
+ if (instance != NULL) {
+ return (uint64)instance->id;
+ }
+ return (uint64)0;
+}
+
+korp_tid
+wasm_debug_instance_get_tid(WASMDebugInstance *instance)
+{
+ if (instance != NULL) {
+ return instance->current_tid;
+ }
+ return (korp_tid)(uintptr_t)0;
+}
+
+uint32
+wasm_debug_instance_get_tids(WASMDebugInstance *instance, korp_tid tids[],
+ uint32 len)
+{
+ WASMExecEnv *exec_env;
+ uint32 i = 0, threads_num = 0;
+
+ if (!instance)
+ return 0;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ while (exec_env && i < len) {
+ /* Some threads may not be ready */
+ if (exec_env->handle != 0) {
+ tids[i++] = exec_env->handle;
+ threads_num++;
+ }
+ exec_env = bh_list_elem_next(exec_env);
+ }
+ LOG_VERBOSE("find %d tids\n", threads_num);
+ return threads_num;
+}
+
+uint32
+wasm_debug_instance_get_thread_status(WASMDebugInstance *instance, korp_tid tid)
+{
+ WASMExecEnv *exec_env = NULL;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ while (exec_env) {
+ if (exec_env->handle == tid) {
+ return (uint32)exec_env->current_status->signal_flag;
+ }
+ exec_env = bh_list_elem_next(exec_env);
+ }
+
+ return 0;
+}
+
+void
+wasm_debug_instance_set_cur_thread(WASMDebugInstance *instance, korp_tid tid)
+{
+ instance->current_tid = tid;
+}
+
+uint64
+wasm_debug_instance_get_pc(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return 0;
+
+ exec_env = wasm_debug_instance_get_current_env(instance);
+ if ((exec_env != NULL) && (exec_env->cur_frame != NULL)
+ && (exec_env->cur_frame->ip != NULL)) {
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)exec_env->module_inst;
+ return WASM_ADDR(
+ WasmObj, instance->id,
+ (exec_env->cur_frame->ip - module_inst->module->load_addr));
+ }
+ return 0;
+}
+
+uint64
+wasm_debug_instance_get_load_addr(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return WASM_ADDR(WasmInvalid, 0, 0);
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (exec_env) {
+ return WASM_ADDR(WasmObj, instance->id, 0);
+ }
+
+ return WASM_ADDR(WasmInvalid, 0, 0);
+}
+
+WASMDebugMemoryInfo *
+wasm_debug_instance_get_memregion(WASMDebugInstance *instance, uint64 addr)
+{
+ WASMDebugMemoryInfo *mem_info;
+ WASMExecEnv *exec_env;
+ WASMModuleInstance *module_inst;
+ WASMMemoryInstance *memory;
+ uint32 num_bytes_per_page;
+ uint32 linear_mem_size = 0;
+
+ if (!instance)
+ return NULL;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return NULL;
+
+ if (!(mem_info = wasm_runtime_malloc(sizeof(WASMDebugMemoryInfo)))) {
+ LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
+ return NULL;
+ }
+ memset(mem_info, 0, sizeof(WASMDebugMemoryInfo));
+ mem_info->start = WASM_ADDR(WasmInvalid, 0, 0);
+ mem_info->size = 0;
+ mem_info->name[0] = '\0';
+ mem_info->permisson[0] = '\0';
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+
+ switch (WASM_ADDR_TYPE(addr)) {
+ case WasmObj:
+ if (WASM_ADDR_OFFSET(addr) < module_inst->module->load_size) {
+ mem_info->start = WASM_ADDR(WasmObj, instance->id, 0);
+ mem_info->size = module_inst->module->load_size;
+ snprintf(mem_info->name, sizeof(mem_info->name), "%s",
+ "module");
+ snprintf(mem_info->permisson, sizeof(mem_info->permisson), "%s",
+ "rx");
+ }
+ break;
+ case WasmMemory:
+ {
+ memory = wasm_get_default_memory(module_inst);
+
+ if (memory) {
+ num_bytes_per_page = memory->num_bytes_per_page;
+ linear_mem_size = num_bytes_per_page * memory->cur_page_count;
+ }
+ if (WASM_ADDR_OFFSET(addr) < linear_mem_size) {
+ mem_info->start = WASM_ADDR(WasmMemory, instance->id, 0);
+ mem_info->size = linear_mem_size;
+ snprintf(mem_info->name, sizeof(mem_info->name), "%s",
+ "memory");
+ snprintf(mem_info->permisson, sizeof(mem_info->permisson), "%s",
+ "rw");
+ }
+ break;
+ }
+ default:
+ mem_info->start = WASM_ADDR(WasmInvalid, 0, 0);
+ mem_info->size = 0;
+ }
+ return mem_info;
+}
+
+void
+wasm_debug_instance_destroy_memregion(WASMDebugInstance *instance,
+ WASMDebugMemoryInfo *mem_info)
+{
+ wasm_runtime_free(mem_info);
+}
+
+bool
+wasm_debug_instance_get_obj_mem(WASMDebugInstance *instance, uint64 offset,
+ char *buf, uint64 *size)
+{
+ WASMExecEnv *exec_env;
+ WASMModuleInstance *module_inst;
+ WASMDebugBreakPoint *breakpoint;
+ WASMFastOPCodeNode *fast_opcode;
+
+ if (!instance)
+ return false;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+
+ if (offset + *size > module_inst->module->load_size) {
+ LOG_VERBOSE("wasm_debug_instance_get_data_mem size over flow!\n");
+ *size = module_inst->module->load_size >= offset
+ ? module_inst->module->load_size - offset
+ : 0;
+ }
+
+ bh_memcpy_s(buf, (uint32)*size, module_inst->module->load_addr + offset,
+ (uint32)*size);
+
+ breakpoint = bh_list_first_elem(&instance->break_point_list);
+ while (breakpoint) {
+ if (offset <= breakpoint->addr && breakpoint->addr < offset + *size) {
+ bh_memcpy_s(buf + (breakpoint->addr - offset), sizeof(break_instr),
+ &breakpoint->orignal_data, sizeof(break_instr));
+ }
+ breakpoint = bh_list_elem_next(breakpoint);
+ }
+
+ fast_opcode = bh_list_first_elem(&module_inst->module->fast_opcode_list);
+ while (fast_opcode) {
+ if (offset <= fast_opcode->offset
+ && fast_opcode->offset < offset + *size) {
+ *(uint8 *)(buf + (fast_opcode->offset - offset)) =
+ fast_opcode->orig_op;
+ }
+ fast_opcode = bh_list_elem_next(fast_opcode);
+ }
+
+ return true;
+}
+
+bool
+wasm_debug_instance_get_linear_mem(WASMDebugInstance *instance, uint64 offset,
+ char *buf, uint64 *size)
+{
+ WASMExecEnv *exec_env;
+ WASMModuleInstance *module_inst;
+ WASMMemoryInstance *memory;
+ uint32 num_bytes_per_page;
+ uint32 linear_mem_size;
+
+ if (!instance)
+ return false;
+
+ exec_env = wasm_debug_instance_get_current_env(instance);
+ if (!exec_env)
+ return false;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+ memory = wasm_get_default_memory(module_inst);
+ if (memory) {
+ num_bytes_per_page = memory->num_bytes_per_page;
+ linear_mem_size = num_bytes_per_page * memory->cur_page_count;
+ if (offset + *size > linear_mem_size) {
+ LOG_VERBOSE("wasm_debug_instance_get_linear_mem size over flow!\n");
+ *size = linear_mem_size >= offset ? linear_mem_size - offset : 0;
+ }
+ bh_memcpy_s(buf, (uint32)*size, memory->memory_data + offset,
+ (uint32)*size);
+ return true;
+ }
+ return false;
+}
+
+bool
+wasm_debug_instance_set_linear_mem(WASMDebugInstance *instance, uint64 offset,
+ char *buf, uint64 *size)
+{
+ WASMExecEnv *exec_env;
+ WASMModuleInstance *module_inst;
+ WASMMemoryInstance *memory;
+ uint32 num_bytes_per_page;
+ uint32 linear_mem_size;
+
+ if (!instance)
+ return false;
+
+ exec_env = wasm_debug_instance_get_current_env(instance);
+ if (!exec_env)
+ return false;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+ memory = wasm_get_default_memory(module_inst);
+ if (memory) {
+ num_bytes_per_page = memory->num_bytes_per_page;
+ linear_mem_size = num_bytes_per_page * memory->cur_page_count;
+ if (offset + *size > linear_mem_size) {
+ LOG_VERBOSE("wasm_debug_instance_get_linear_mem size over flow!\n");
+ *size = linear_mem_size >= offset ? linear_mem_size - offset : 0;
+ }
+ bh_memcpy_s(memory->memory_data + offset, (uint32)*size, buf,
+ (uint32)*size);
+ return true;
+ }
+ return false;
+}
+
+bool
+wasm_debug_instance_get_mem(WASMDebugInstance *instance, uint64 addr, char *buf,
+ uint64 *size)
+{
+ switch (WASM_ADDR_TYPE(addr)) {
+ case WasmMemory:
+ return wasm_debug_instance_get_linear_mem(
+ instance, WASM_ADDR_OFFSET(addr), buf, size);
+ break;
+ case WasmObj:
+ return wasm_debug_instance_get_obj_mem(
+ instance, WASM_ADDR_OFFSET(addr), buf, size);
+ break;
+ default:
+ return false;
+ }
+}
+
+bool
+wasm_debug_instance_set_mem(WASMDebugInstance *instance, uint64 addr, char *buf,
+ uint64 *size)
+{
+ switch (WASM_ADDR_TYPE(addr)) {
+ case WasmMemory:
+ return wasm_debug_instance_set_linear_mem(
+ instance, WASM_ADDR_OFFSET(addr), buf, size);
+ break;
+ case WasmObj:
+ default:
+ return false;
+ }
+}
+
+WASMDebugInstance *
+wasm_exec_env_get_instance(WASMExecEnv *exec_env)
+{
+ WASMDebugInstance *instance = NULL;
+
+ if (!g_debug_engine) {
+ return NULL;
+ }
+
+ os_mutex_lock(&g_debug_engine->instance_list_lock);
+ instance = bh_list_first_elem(&g_debug_engine->debug_instance_list);
+ while (instance) {
+ if (instance->cluster == exec_env->cluster)
+ break;
+ instance = bh_list_elem_next(instance);
+ }
+
+ os_mutex_unlock(&g_debug_engine->instance_list_lock);
+ return instance;
+}
+
+uint32
+wasm_debug_instance_get_call_stack_pcs(WASMDebugInstance *instance,
+ korp_tid tid, uint64 buf[], uint64 size)
+{
+ WASMExecEnv *exec_env;
+ struct WASMInterpFrame *frame;
+ uint32 i = 0;
+
+ if (!instance)
+ return 0;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ while (exec_env) {
+ if (exec_env->handle == tid) {
+ WASMModuleInstance *module_inst =
+ (WASMModuleInstance *)exec_env->module_inst;
+ frame = exec_env->cur_frame;
+ while (frame && i < size) {
+ if (frame->ip != NULL) {
+ buf[i++] =
+ WASM_ADDR(WasmObj, instance->id,
+ (frame->ip - module_inst->module->load_addr));
+ }
+ frame = frame->prev_frame;
+ }
+ return i;
+ }
+ exec_env = bh_list_elem_next(exec_env);
+ }
+ return 0;
+}
+
+bool
+wasm_debug_instance_add_breakpoint(WASMDebugInstance *instance, uint64 addr,
+ uint64 length)
+{
+ WASMExecEnv *exec_env;
+ WASMModuleInstance *module_inst;
+ uint64 offset;
+
+ if (!instance)
+ return false;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+ if (WASM_ADDR_TYPE(addr) != WasmObj)
+ return false;
+
+ offset = WASM_ADDR_OFFSET(addr);
+
+ if (length >= sizeof(break_instr)) {
+ if (offset + sizeof(break_instr) <= module_inst->module->load_size) {
+ WASMDebugBreakPoint *breakpoint;
+ if (!(breakpoint =
+ wasm_runtime_malloc(sizeof(WASMDebugBreakPoint)))) {
+ LOG_ERROR("WASM Debug Engine error: failed to allocate memory");
+ return false;
+ }
+ memset(breakpoint, 0, sizeof(WASMDebugBreakPoint));
+ breakpoint->addr = offset;
+ /* TODO: how to if more than one breakpoints are set
+ at the same addr? */
+ bh_memcpy_s(&breakpoint->orignal_data, (uint32)sizeof(break_instr),
+ module_inst->module->load_addr + offset,
+ (uint32)sizeof(break_instr));
+
+ bh_memcpy_s(module_inst->module->load_addr + offset,
+ (uint32)sizeof(break_instr), break_instr,
+ (uint32)sizeof(break_instr));
+
+ bh_list_insert(&instance->break_point_list, breakpoint);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+wasm_debug_instance_remove_breakpoint(WASMDebugInstance *instance, uint64 addr,
+ uint64 length)
+{
+ WASMExecEnv *exec_env;
+ WASMModuleInstance *module_inst;
+ uint64 offset;
+
+ if (!instance)
+ return false;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+
+ if (WASM_ADDR_TYPE(addr) != WasmObj)
+ return false;
+ offset = WASM_ADDR_OFFSET(addr);
+
+ if (length >= sizeof(break_instr)) {
+ if (offset + sizeof(break_instr) <= module_inst->module->load_size) {
+ WASMDebugBreakPoint *breakpoint =
+ bh_list_first_elem(&instance->break_point_list);
+ while (breakpoint) {
+ WASMDebugBreakPoint *next_break = bh_list_elem_next(breakpoint);
+ if (breakpoint->addr == offset) {
+ /* TODO: how to if more than one breakpoints are set
+ at the same addr? */
+ bh_memcpy_s(module_inst->module->load_addr + offset,
+ (uint32)sizeof(break_instr),
+ &breakpoint->orignal_data,
+ (uint32)sizeof(break_instr));
+ bh_list_remove(&instance->break_point_list, breakpoint);
+ wasm_runtime_free(breakpoint);
+ }
+ breakpoint = next_break;
+ }
+ }
+ }
+ return true;
+}
+
+static bool
+add_watchpoint(bh_list *list, uint64 addr, uint64 length)
+{
+ WASMDebugWatchPoint *watchpoint;
+ if (!(watchpoint = wasm_runtime_malloc(sizeof(WASMDebugWatchPoint)))) {
+ LOG_ERROR("WASM Debug Engine error: failed to allocate memory for "
+ "watchpoint");
+ return false;
+ }
+ memset(watchpoint, 0, sizeof(WASMDebugWatchPoint));
+ watchpoint->addr = addr;
+ watchpoint->length = length;
+ bh_list_insert(list, watchpoint);
+ return true;
+}
+
+static bool
+remove_watchpoint(bh_list *list, uint64 addr, uint64 length)
+{
+ WASMDebugWatchPoint *watchpoint = bh_list_first_elem(list);
+ while (watchpoint) {
+ WASMDebugWatchPoint *next = bh_list_elem_next(watchpoint);
+ if (watchpoint->addr == addr && watchpoint->length == length) {
+ bh_list_remove(list, watchpoint);
+ wasm_runtime_free(watchpoint);
+ }
+ watchpoint = next;
+ }
+ return true;
+}
+
+bool
+wasm_debug_instance_watchpoint_write_add(WASMDebugInstance *instance,
+ uint64 addr, uint64 length)
+{
+ return add_watchpoint(&instance->watch_point_list_write, addr, length);
+}
+
+bool
+wasm_debug_instance_watchpoint_write_remove(WASMDebugInstance *instance,
+ uint64 addr, uint64 length)
+{
+ return remove_watchpoint(&instance->watch_point_list_write, addr, length);
+}
+
+bool
+wasm_debug_instance_watchpoint_read_add(WASMDebugInstance *instance,
+ uint64 addr, uint64 length)
+{
+ return add_watchpoint(&instance->watch_point_list_read, addr, length);
+}
+
+bool
+wasm_debug_instance_watchpoint_read_remove(WASMDebugInstance *instance,
+ uint64 addr, uint64 length)
+{
+ return remove_watchpoint(&instance->watch_point_list_read, addr, length);
+}
+
+bool
+wasm_debug_instance_on_failure(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return false;
+
+ os_mutex_lock(&instance->wait_lock);
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env) {
+ os_mutex_unlock(&instance->wait_lock);
+ return false;
+ }
+
+ if (instance->stopped_thread == NULL
+ && instance->current_state == DBG_LAUNCHING) {
+ /* if fail in start stage: may need wait for main thread to notify it */
+ os_cond_wait(&instance->wait_cond, &instance->wait_lock);
+ }
+ instance->current_state = DBG_ERROR;
+ instance->stopped_thread = NULL;
+
+ /* terminate the wasm execution thread */
+ while (exec_env) {
+ /* Resume all threads so they can receive the TERM signal */
+ os_mutex_lock(&exec_env->wait_lock);
+ wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM);
+ exec_env->current_status->running_status = STATUS_RUNNING;
+ os_cond_signal(&exec_env->wait_cond);
+ os_mutex_unlock(&exec_env->wait_lock);
+ exec_env = bh_list_elem_next(exec_env);
+ }
+ os_mutex_unlock(&instance->wait_lock);
+
+ return true;
+}
+
+bool
+wasm_debug_instance_continue(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return false;
+
+ if (instance->current_state == APP_RUNNING) {
+ LOG_VERBOSE("Already in running state, ignore continue request");
+ return false;
+ }
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ while (exec_env) {
+ wasm_cluster_thread_continue(exec_env);
+ exec_env = bh_list_elem_next(exec_env);
+ }
+
+ instance->current_state = APP_RUNNING;
+
+ return true;
+}
+
+bool
+wasm_debug_instance_interrupt_all_threads(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return false;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ while (exec_env) {
+ wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TRAP);
+ exec_env = bh_list_elem_next(exec_env);
+ }
+ return true;
+}
+
+bool
+wasm_debug_instance_detach(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return false;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ wasm_gdbserver_detach(instance->control_thread->server);
+
+ while (exec_env) {
+ if (instance->current_state == APP_STOPPED) {
+ /* Resume all threads since remote debugger detached*/
+ wasm_cluster_thread_continue(exec_env);
+ }
+ exec_env = bh_list_elem_next(exec_env);
+ }
+
+ /* relaunch, accept new debug connection */
+ instance->current_state = DBG_LAUNCHING;
+ instance->control_thread->status = DETACHED;
+ instance->stopped_thread = NULL;
+
+ return true;
+}
+
+bool
+wasm_debug_instance_kill(WASMDebugInstance *instance)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return false;
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ while (exec_env) {
+ wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM);
+ if (instance->current_state == APP_STOPPED) {
+ /* Resume all threads so they can receive the TERM signal */
+ os_mutex_lock(&exec_env->wait_lock);
+ exec_env->current_status->running_status = STATUS_RUNNING;
+ os_cond_signal(&exec_env->wait_cond);
+ os_mutex_unlock(&exec_env->wait_lock);
+ }
+ exec_env = bh_list_elem_next(exec_env);
+ }
+
+ instance->current_state = APP_RUNNING;
+ return true;
+}
+
+bool
+wasm_debug_instance_singlestep(WASMDebugInstance *instance, korp_tid tid)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return false;
+
+ if (instance->current_state == APP_RUNNING) {
+ LOG_VERBOSE("Already in running state, ignore step request");
+ return false;
+ }
+
+ exec_env = bh_list_first_elem(&instance->cluster->exec_env_list);
+ if (!exec_env)
+ return false;
+
+ while (exec_env) {
+ if (exec_env->handle == tid || tid == (korp_tid)(uintptr_t)~0LL) {
+ wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_SINGSTEP);
+ wasm_cluster_thread_step(exec_env);
+ }
+ exec_env = bh_list_elem_next(exec_env);
+ }
+
+ instance->current_state = APP_RUNNING;
+
+ return true;
+}
+
+bool
+wasm_debug_instance_get_local(WASMDebugInstance *instance, int32 frame_index,
+ int32 local_index, char buf[], int32 *size)
+{
+ WASMExecEnv *exec_env;
+ struct WASMInterpFrame *frame;
+ WASMFunctionInstance *cur_func;
+ uint8 local_type = 0xFF;
+ uint32 local_offset;
+ int32 param_count;
+ int32 fi = 0;
+
+ if (!instance)
+ return false;
+
+ exec_env = wasm_debug_instance_get_current_env(instance);
+ if (!exec_env)
+ return false;
+
+ frame = exec_env->cur_frame;
+ while (frame && fi++ != frame_index) {
+ frame = frame->prev_frame;
+ }
+
+ if (!frame)
+ return false;
+ cur_func = frame->function;
+ if (!cur_func)
+ return false;
+
+ param_count = cur_func->param_count;
+
+ if (local_index >= param_count + cur_func->local_count)
+ return false;
+
+ local_offset = cur_func->local_offsets[local_index];
+ if (local_index < param_count)
+ local_type = cur_func->param_types[local_index];
+ else if (local_index < cur_func->local_count + param_count)
+ local_type = cur_func->local_types[local_index - param_count];
+
+ switch (local_type) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_F32:
+ *size = 4;
+ bh_memcpy_s(buf, 4, (char *)(frame->lp + local_offset), 4);
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ *size = 8;
+ bh_memcpy_s(buf, 8, (char *)(frame->lp + local_offset), 8);
+ break;
+ default:
+ *size = 0;
+ break;
+ }
+ return true;
+}
+
+bool
+wasm_debug_instance_get_global(WASMDebugInstance *instance, int32 frame_index,
+ int32 global_index, char buf[], int32 *size)
+{
+ WASMExecEnv *exec_env;
+ struct WASMInterpFrame *frame;
+ WASMModuleInstance *module_inst;
+ WASMGlobalInstance *globals, *global;
+ uint8 *global_addr;
+ uint8 global_type = 0xFF;
+ uint8 *global_data;
+ int32 fi = 0;
+
+ if (!instance)
+ return false;
+
+ exec_env = wasm_debug_instance_get_current_env(instance);
+ if (!exec_env)
+ return false;
+
+ frame = exec_env->cur_frame;
+ while (frame && fi++ != frame_index) {
+ frame = frame->prev_frame;
+ }
+
+ if (!frame)
+ return false;
+
+ module_inst = (WASMModuleInstance *)exec_env->module_inst;
+ global_data = module_inst->global_data;
+ globals = module_inst->e->globals;
+
+ if ((global_index < 0)
+ || ((uint32)global_index >= module_inst->e->global_count)) {
+ return false;
+ }
+ global = globals + global_index;
+
+#if WASM_ENABLE_MULTI_MODULE == 0
+ global_addr = global_data + global->data_offset;
+#else
+ global_addr = global->import_global_inst
+ ? global->import_module_inst->global_data
+ + global->import_global_inst->data_offset
+ : global_data + global->data_offset;
+#endif
+ global_type = global->type;
+
+ switch (global_type) {
+ case VALUE_TYPE_I32:
+ case VALUE_TYPE_F32:
+ *size = 4;
+ bh_memcpy_s(buf, 4, (char *)(global_addr), 4);
+ break;
+ case VALUE_TYPE_I64:
+ case VALUE_TYPE_F64:
+ *size = 8;
+ bh_memcpy_s(buf, 8, (char *)(global_addr), 8);
+ break;
+ default:
+ *size = 0;
+ break;
+ }
+ return true;
+}
+
+uint64
+wasm_debug_instance_mmap(WASMDebugInstance *instance, uint32 size,
+ int32 map_prot)
+{
+ WASMExecEnv *exec_env;
+ uint32 offset = 0;
+ (void)map_prot;
+
+ if (!instance)
+ return 0;
+
+ exec_env = wasm_debug_instance_get_current_env(instance);
+ if (!exec_env)
+ return 0;
+
+ if (instance->exec_mem_info.start_offset == 0) {
+ return 0;
+ }
+
+ if ((uint64)instance->exec_mem_info.current_pos
+ - instance->exec_mem_info.start_offset + size
+ <= (uint64)instance->exec_mem_info.size) {
+ offset = instance->exec_mem_info.current_pos;
+ instance->exec_mem_info.current_pos += size;
+ }
+
+ if (offset == 0) {
+ LOG_WARNING("the memory may be not enough for debug, try use larger "
+ "--heap-size");
+ return 0;
+ }
+
+ return WASM_ADDR(WasmMemory, 0, offset);
+}
+
+bool
+wasm_debug_instance_ummap(WASMDebugInstance *instance, uint64 addr)
+{
+ WASMExecEnv *exec_env;
+
+ if (!instance)
+ return false;
+
+ exec_env = wasm_debug_instance_get_current_env(instance);
+ if (!exec_env)
+ return false;
+
+ if (instance->exec_mem_info.start_offset == 0) {
+ return false;
+ }
+
+ (void)addr;
+
+ /* Currently we don't support to free the execution memory, simply return
+ * true here */
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.cmake
new file mode 100644
index 000000000..914ddd639
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.cmake
@@ -0,0 +1,12 @@
+# Copyright (C) 2021 Ant Group. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (DEBUG_ENGINE_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions (-DWASM_ENABLE_DEBUG_INTERP=1)
+
+include_directories(${DEBUG_ENGINE_DIR})
+
+file (GLOB source_all ${DEBUG_ENGINE_DIR}/*.c)
+
+set (DEBUG_ENGINE_SOURCE ${source_all})
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.h
new file mode 100644
index 000000000..e12f827bd
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/debug_engine.h
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _DEBUG_ENGINE_H
+#define _DEBUG_ENGINE_H
+
+#include "bh_list.h"
+#include "gdbserver.h"
+#include "thread_manager.h"
+
+typedef enum WASMDebugControlThreadStatus {
+ RUNNING,
+ DETACHED,
+ STOPPED,
+} WASMDebugControlThreadStatus;
+
+struct WASMDebugEngine;
+struct WASMDebugInstance;
+
+typedef struct WASMDebugControlThread {
+ WASMGDBServer *server;
+ korp_tid tid;
+ korp_mutex wait_lock;
+ char ip_addr[128];
+ int port;
+ WASMDebugControlThreadStatus status;
+ struct WASMDebugEngine *debug_engine;
+ struct WASMDebugInstance *debug_instance;
+} WASMDebugControlThread;
+
+typedef struct WASMDebugBreakPoint {
+ struct WASMDebugBreakPoint *next;
+ uint64 addr;
+ uint64 orignal_data;
+} WASMDebugBreakPoint;
+
+typedef struct WASMDebugWatchPoint {
+ bh_list_link next;
+ uint64 addr;
+ uint64 length;
+} WASMDebugWatchPoint;
+
+typedef enum debug_state_t {
+ /* Debugger state conversion sequence:
+ * DBG_LAUNCHING ---> APP_STOPPED <---> APP_RUNNING
+ */
+ DBG_LAUNCHING,
+ APP_RUNNING,
+ APP_STOPPED,
+ DBG_ERROR
+} debug_state_t;
+
+typedef struct WASMDebugExecutionMemory {
+ uint32 start_offset;
+ uint32 size;
+ uint32 current_pos;
+} WASMDebugExecutionMemory;
+
+struct WASMDebugInstance {
+ struct WASMDebugInstance *next;
+ WASMDebugControlThread *control_thread;
+ bh_list break_point_list;
+ bh_list watch_point_list_read;
+ bh_list watch_point_list_write;
+ WASMCluster *cluster;
+ uint32 id;
+ korp_tid current_tid;
+ korp_mutex wait_lock;
+ korp_cond wait_cond;
+ /* Last stopped thread, it should be set to NULL when sending
+ * out the thread stop reply */
+ WASMExecEnv *volatile stopped_thread;
+ /* Currently status of the debug instance, it will be set to
+ * RUNNING when receiving STEP/CONTINUE commands, and set to
+ * STOPPED when any thread stopped */
+ volatile debug_state_t current_state;
+ /* Execution memory info. During debugging, the debug client may request to
+ * malloc a memory space to evaluate user expressions. We preserve a buffer
+ * during creating debug instance, and use a simple bump pointer allocator
+ * to serve lldb's memory request */
+ WASMDebugExecutionMemory exec_mem_info;
+};
+
+typedef enum WASMDebugEventKind {
+ BREAK_POINT_ADD,
+ BREAK_POINT_REMOVE
+} WASMDebugEventKind;
+
+typedef struct WASMDebugEvent {
+ WASMDebugEventKind kind;
+ unsigned char metadata[0];
+} WASMDebugEvent;
+
+typedef struct WASMDebugMemoryInfo {
+ uint64 start;
+ uint64 size;
+ char name[128];
+ char permisson[4];
+} WASMDebugMemoryInfo;
+
+typedef enum WasmAddressType {
+ WasmMemory = 0x00,
+ WasmObj = 0x01,
+ WasmInvalid = 0x03
+} WasmAddressType;
+
+#define WASM_ADDR(type, id, offset) \
+ (((uint64)type << 62) | ((uint64)0 << 32) | ((uint64)offset << 0))
+
+#define WASM_ADDR_TYPE(addr) (((addr)&0xC000000000000000) >> 62)
+#define WASM_ADDR_OFFSET(addr) (((addr)&0x00000000FFFFFFFF))
+
+#define INVALIED_ADDR (0xFFFFFFFFFFFFFFFF)
+
+void
+on_thread_stop_event(WASMDebugInstance *debug_inst, WASMExecEnv *exec_env);
+
+void
+on_thread_exit_event(WASMDebugInstance *debug_inst, WASMExecEnv *exec_env);
+
+WASMDebugInstance *
+wasm_debug_instance_create(WASMCluster *cluster, int32 port);
+
+void
+wasm_debug_instance_destroy(WASMCluster *cluster);
+
+WASMDebugInstance *
+wasm_exec_env_get_instance(WASMExecEnv *exec_env);
+
+bool
+wasm_debug_engine_init(char *ip_addr, int32 process_port);
+
+void
+wasm_debug_engine_destroy();
+
+WASMExecEnv *
+wasm_debug_instance_get_current_env(WASMDebugInstance *instance);
+
+uint64
+wasm_debug_instance_get_pid(WASMDebugInstance *instance);
+
+korp_tid
+wasm_debug_instance_get_tid(WASMDebugInstance *instance);
+
+uint32
+wasm_debug_instance_get_tids(WASMDebugInstance *instance, korp_tid tids[],
+ uint32 len);
+
+void
+wasm_debug_instance_set_cur_thread(WASMDebugInstance *instance, korp_tid tid);
+
+uint64
+wasm_debug_instance_get_pc(WASMDebugInstance *instance);
+
+uint64
+wasm_debug_instance_get_load_addr(WASMDebugInstance *instance);
+
+WASMDebugMemoryInfo *
+wasm_debug_instance_get_memregion(WASMDebugInstance *instance, uint64 addr);
+
+void
+wasm_debug_instance_destroy_memregion(WASMDebugInstance *instance,
+ WASMDebugMemoryInfo *mem_info);
+
+bool
+wasm_debug_instance_get_obj_mem(WASMDebugInstance *instance, uint64 addr,
+ char *buf, uint64 *size);
+
+bool
+wasm_debug_instance_get_linear_mem(WASMDebugInstance *instance, uint64 addr,
+ char *buf, uint64 *size);
+
+bool
+wasm_debug_instance_get_mem(WASMDebugInstance *instance, uint64 addr, char *buf,
+ uint64 *size);
+
+bool
+wasm_debug_instance_set_mem(WASMDebugInstance *instance, uint64 addr, char *buf,
+ uint64 *size);
+
+uint32
+wasm_debug_instance_get_call_stack_pcs(WASMDebugInstance *instance,
+ korp_tid tid, uint64 buf[], uint64 size);
+
+bool
+wasm_debug_instance_add_breakpoint(WASMDebugInstance *instance, uint64 addr,
+ uint64 length);
+
+bool
+wasm_debug_instance_remove_breakpoint(WASMDebugInstance *instance, uint64 addr,
+ uint64 length);
+
+bool
+wasm_debug_instance_watchpoint_write_add(WASMDebugInstance *instance,
+ uint64 addr, uint64 length);
+
+bool
+wasm_debug_instance_watchpoint_write_remove(WASMDebugInstance *instance,
+ uint64 addr, uint64 length);
+
+bool
+wasm_debug_instance_watchpoint_read_add(WASMDebugInstance *instance,
+ uint64 addr, uint64 length);
+
+bool
+wasm_debug_instance_watchpoint_read_remove(WASMDebugInstance *instance,
+ uint64 addr, uint64 length);
+
+bool
+wasm_debug_instance_on_failure(WASMDebugInstance *instance);
+
+bool
+wasm_debug_instance_interrupt_all_threads(WASMDebugInstance *instance);
+
+bool
+wasm_debug_instance_continue(WASMDebugInstance *instance);
+
+bool
+wasm_debug_instance_detach(WASMDebugInstance *instance);
+
+bool
+wasm_debug_instance_kill(WASMDebugInstance *instance);
+
+uint32
+wasm_debug_instance_get_thread_status(WASMDebugInstance *instance,
+ korp_tid tid);
+
+bool
+wasm_debug_instance_singlestep(WASMDebugInstance *instance, korp_tid tid);
+
+bool
+wasm_debug_instance_get_local(WASMDebugInstance *instance, int32 frame_index,
+ int32 local_index, char buf[], int32 *size);
+
+bool
+wasm_debug_instance_get_global(WASMDebugInstance *instance, int32 frame_index,
+ int32 global_index, char buf[], int32 *size);
+
+#if WASM_ENABLE_LIBC_WASI != 0
+bool
+wasm_debug_instance_get_current_object_name(WASMDebugInstance *instance,
+ char name_buffer[], uint32 len);
+#endif
+
+uint64
+wasm_debug_instance_mmap(WASMDebugInstance *instance, uint32 size,
+ int32 map_prot);
+
+bool
+wasm_debug_instance_ummap(WASMDebugInstance *instance, uint64 addr);
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.c
new file mode 100644
index 000000000..fbd876ac3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_platform.h"
+#include "gdbserver.h"
+#include "handler.h"
+#include "packets.h"
+#include "utils.h"
+
+typedef void (*PacketHandler)(WASMGDBServer *server, char *payload);
+
+struct packet_handler_elem {
+ char request;
+ PacketHandler handler;
+};
+
+#define DEL_HANDLER(r, h) [r] = { .request = r, .handler = h }
+
+static const struct packet_handler_elem packet_handler_table[255] = {
+ DEL_HANDLER('Q', handle_general_set),
+ DEL_HANDLER('q', handle_general_query),
+ DEL_HANDLER('v', handle_v_packet),
+ DEL_HANDLER('?', handle_threadstop_request),
+ DEL_HANDLER('H', handle_set_current_thread),
+ DEL_HANDLER('p', handle_get_register),
+ DEL_HANDLER('j', handle_get_json_request),
+ DEL_HANDLER('m', handle_get_read_memory),
+ DEL_HANDLER('M', handle_get_write_memory),
+ DEL_HANDLER('x', handle_get_read_binary_memory),
+ DEL_HANDLER('Z', handle_add_break),
+ DEL_HANDLER('z', handle_remove_break),
+ DEL_HANDLER('c', handle_continue_request),
+ DEL_HANDLER('k', handle_kill_request),
+ DEL_HANDLER('_', handle____request),
+ DEL_HANDLER('D', handle_detach_request),
+};
+
+WASMGDBServer *
+wasm_create_gdbserver(const char *host, int32 *port)
+{
+ bh_socket_t listen_fd = (bh_socket_t)-1;
+ WASMGDBServer *server;
+
+ bh_assert(port);
+
+ if (!(server = wasm_runtime_malloc(sizeof(WASMGDBServer)))) {
+ LOG_ERROR("wasm gdb server error: failed to allocate memory");
+ return NULL;
+ }
+
+ memset(server, 0, sizeof(WASMGDBServer));
+
+ if (!(server->receive_ctx =
+ wasm_runtime_malloc(sizeof(rsp_recv_context_t)))) {
+ LOG_ERROR("wasm gdb server error: failed to allocate memory");
+ goto fail;
+ }
+
+ memset(server->receive_ctx, 0, sizeof(rsp_recv_context_t));
+
+ if (0 != os_socket_create(&listen_fd, true, true)) {
+ LOG_ERROR("wasm gdb server error: create socket failed");
+ goto fail;
+ }
+
+ if (0 != os_socket_bind(listen_fd, host, port)) {
+ LOG_ERROR("wasm gdb server error: socket bind failed");
+ goto fail;
+ }
+
+ LOG_WARNING("Debug server listening on %s:%" PRIu32 "\n", host, *port);
+ server->listen_fd = listen_fd;
+
+ return server;
+
+fail:
+ if (listen_fd >= 0) {
+ os_socket_shutdown(listen_fd);
+ os_socket_close(listen_fd);
+ }
+ if (server->receive_ctx)
+ wasm_runtime_free(server->receive_ctx);
+ if (server)
+ wasm_runtime_free(server);
+ return NULL;
+}
+
+bool
+wasm_gdbserver_listen(WASMGDBServer *server)
+{
+ int32 ret;
+
+ ret = os_socket_listen(server->listen_fd, 1);
+ if (ret != 0) {
+ LOG_ERROR("wasm gdb server error: socket listen failed");
+ goto fail;
+ }
+
+ LOG_VERBOSE("listen for gdb client");
+ return true;
+
+fail:
+ os_socket_shutdown(server->listen_fd);
+ os_socket_close(server->listen_fd);
+ return false;
+}
+
+bool
+wasm_gdbserver_accept(WASMGDBServer *server)
+{
+
+ bh_socket_t sockt_fd = (bh_socket_t)-1;
+
+ LOG_VERBOSE("waiting for gdb client to connect...");
+
+ os_socket_accept(server->listen_fd, &sockt_fd, NULL, NULL);
+ if (sockt_fd < 0) {
+ LOG_ERROR("wasm gdb server error: socket accept failed");
+ goto fail;
+ }
+
+ LOG_VERBOSE("accept gdb client");
+ server->socket_fd = sockt_fd;
+ server->noack = false;
+ return true;
+
+fail:
+ os_socket_shutdown(server->listen_fd);
+ os_socket_close(server->listen_fd);
+ return false;
+}
+
+void
+wasm_gdbserver_detach(WASMGDBServer *server)
+{
+ if (server->socket_fd > 0) {
+ os_socket_shutdown(server->socket_fd);
+ os_socket_close(server->socket_fd);
+ }
+}
+
+void
+wasm_close_gdbserver(WASMGDBServer *server)
+{
+ if (server->receive_ctx) {
+ wasm_runtime_free(server->receive_ctx);
+ }
+ if (server->socket_fd > 0) {
+ os_socket_shutdown(server->socket_fd);
+ os_socket_close(server->socket_fd);
+ }
+ if (server->listen_fd > 0) {
+ os_socket_shutdown(server->listen_fd);
+ os_socket_close(server->listen_fd);
+ }
+}
+
+static inline void
+handle_packet(WASMGDBServer *server, char request, char *payload)
+{
+ if (packet_handler_table[(int)request].handler != NULL)
+ packet_handler_table[(int)request].handler(server, payload);
+}
+
+static void
+process_packet(WASMGDBServer *server)
+{
+ uint8 *inbuf = (uint8 *)server->receive_ctx->receive_buffer;
+ char request;
+ char *payload = NULL;
+
+ request = inbuf[0];
+
+ if (request == '\0') {
+ LOG_VERBOSE("ignore empty request");
+ return;
+ }
+
+ payload = (char *)&inbuf[1];
+
+ LOG_VERBOSE("receive request:%c %s\n", request, payload);
+ handle_packet(server, request, payload);
+}
+
+static inline void
+push_byte(rsp_recv_context_t *ctx, unsigned char ch, bool checksum)
+{
+ if (ctx->receive_index >= sizeof(ctx->receive_buffer)) {
+ LOG_ERROR("RSP message buffer overflow");
+ bh_assert(false);
+ return;
+ }
+
+ ctx->receive_buffer[ctx->receive_index++] = ch;
+
+ if (checksum) {
+ ctx->check_sum += ch;
+ }
+}
+
+/**
+ * The packet layout is:
+ * 1. Normal packet:
+ * '$' + payload + '#' + checksum(2bytes)
+ * ^
+ * packetend
+ * 2. Interrupt:
+ * 0x03
+ */
+
+/* return:
+ * 0: incomplete message received
+ * 1: complete message received
+ * 2: interrupt message received
+ */
+static int
+on_rsp_byte_arrive(unsigned char ch, rsp_recv_context_t *ctx)
+{
+ if (ctx->phase == Phase_Idle) {
+ ctx->receive_index = 0;
+ ctx->check_sum = 0;
+
+ if (ch == 0x03) {
+ LOG_VERBOSE("Receive interrupt package");
+ return 2;
+ }
+ else if (ch == '$') {
+ ctx->phase = Phase_Payload;
+ }
+
+ return 0;
+ }
+ else if (ctx->phase == Phase_Payload) {
+ if (ch == '#') {
+ ctx->phase = Phase_Checksum;
+ push_byte(ctx, ch, false);
+ }
+ else {
+ push_byte(ctx, ch, true);
+ }
+
+ return 0;
+ }
+ else if (ctx->phase == Phase_Checksum) {
+ ctx->size_in_phase++;
+ push_byte(ctx, ch, false);
+
+ if (ctx->size_in_phase == 2) {
+ ctx->size_in_phase = 0;
+
+ bh_assert(ctx->receive_index >= 3);
+
+ if ((hex(ctx->receive_buffer[ctx->receive_index - 2]) << 4
+ | hex(ctx->receive_buffer[ctx->receive_index - 1]))
+ != ctx->check_sum) {
+ LOG_WARNING("RSP package checksum error, ignore it");
+ ctx->phase = Phase_Idle;
+ return 0;
+ }
+ else {
+ /* Change # to \0 */
+ ctx->receive_buffer[ctx->receive_index - 3] = '\0';
+ ctx->phase = Phase_Idle;
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ /* Should never reach here */
+ bh_assert(false);
+ return 0;
+}
+
+bool
+wasm_gdbserver_handle_packet(WASMGDBServer *server)
+{
+ int32 n;
+ char buf[1024];
+
+ if (os_socket_settimeout(server->socket_fd, 1000) != 0) {
+ LOG_ERROR("Set socket recv timeout failed");
+ return false;
+ }
+
+ n = os_socket_recv(server->socket_fd, buf, sizeof(buf));
+
+ if (n == 0) {
+ handle_detach_request(server, NULL);
+ LOG_VERBOSE("Debugger disconnected, waiting for debugger reconnection");
+ return true;
+ }
+ else if (n < 0) {
+#if defined(BH_PLATFORM_WINDOWS)
+ if (WSAGetLastError() == WSAETIMEDOUT)
+#else
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+#endif
+ {
+ /* No bytes arrived */
+ return true;
+ }
+ else {
+ LOG_ERROR("Socket receive error");
+ return false;
+ }
+ }
+ else {
+ int32 i, ret;
+
+ for (i = 0; i < n; i++) {
+ ret = on_rsp_byte_arrive(buf[i], server->receive_ctx);
+
+ if (ret == 1) {
+ if (!server->noack)
+ write_data_raw(server, (uint8 *)"+", 1);
+
+ process_packet(server);
+ }
+ else if (ret == 2) {
+ handle_interrupt(server);
+ }
+ }
+ }
+
+ return true;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.h
new file mode 100644
index 000000000..9e279a2e6
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/gdbserver.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _GDB_SERVER_H
+#define _GDB_SERVER_H
+
+#include "bh_platform.h"
+
+#define PACKET_BUF_SIZE 0x8000
+
+enum GDBStoppointType {
+ eStoppointInvalid = -1,
+ eBreakpointSoftware = 0,
+ eBreakpointHardware,
+ eWatchpointWrite,
+ eWatchpointRead,
+ eWatchpointReadWrite
+};
+
+typedef enum rsp_recv_phase_t {
+ Phase_Idle,
+ Phase_Payload,
+ Phase_Checksum
+} rsp_recv_phase_t;
+
+/* Remote Serial Protocol Receive Context */
+typedef struct rsp_recv_context_t {
+ rsp_recv_phase_t phase;
+ uint16 receive_index;
+ uint16 size_in_phase;
+ uint8 check_sum;
+ /* RSP packet should not be too long */
+ char receive_buffer[1024];
+} rsp_recv_context_t;
+
+typedef struct WasmDebugPacket {
+ unsigned char buf[PACKET_BUF_SIZE];
+ uint32 size;
+} WasmDebugPacket;
+
+struct WASMDebugControlThread;
+typedef struct WASMGDBServer {
+ bh_socket_t listen_fd;
+ bh_socket_t socket_fd;
+ WasmDebugPacket pkt;
+ bool noack;
+ struct WASMDebugControlThread *thread;
+ rsp_recv_context_t *receive_ctx;
+} WASMGDBServer;
+
+WASMGDBServer *
+wasm_create_gdbserver(const char *host, int32 *port);
+
+bool
+wasm_gdbserver_listen(WASMGDBServer *server);
+
+bool
+wasm_gdbserver_accept(WASMGDBServer *server);
+
+void
+wasm_gdbserver_detach(WASMGDBServer *server);
+
+void
+wasm_close_gdbserver(WASMGDBServer *server);
+
+bool
+wasm_gdbserver_handle_packet(WASMGDBServer *server);
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.c
new file mode 100644
index 000000000..8d451b1a3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.c
@@ -0,0 +1,876 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_platform.h"
+#include "handler.h"
+#include "debug_engine.h"
+#include "packets.h"
+#include "utils.h"
+#include "wasm_runtime.h"
+
+/*
+ * Note: A moderate MAX_PACKET_SIZE is ok because
+ * LLDB queries our buffer size (via qSupported PacketSize)
+ * and limits packet sizes accordingly.
+ */
+
+#if defined(DEBUG_MAX_PACKET_SIZE)
+#define MAX_PACKET_SIZE DEBUG_MAX_PACKET_SIZE
+#else
+#define MAX_PACKET_SIZE (4096)
+#endif
+
+/*
+ * Note: It's assumed that MAX_PACKET_SIZE is reasonably large.
+ * See GetWorkingDir, WasmCallStack, etc.
+ */
+#if MAX_PACKET_SIZE < PATH_MAX || MAX_PACKET_SIZE < (2048 + 1)
+#error MAX_PACKET_SIZE is too small
+#endif
+
+static char *tmpbuf;
+static korp_mutex tmpbuf_lock;
+
+int
+wasm_debug_handler_init()
+{
+ int ret;
+ tmpbuf = wasm_runtime_malloc(MAX_PACKET_SIZE);
+ if (tmpbuf == NULL) {
+ LOG_ERROR("debug-engine: Packet buffer allocation failure");
+ return BHT_ERROR;
+ }
+ ret = os_mutex_init(&tmpbuf_lock);
+ if (ret != BHT_OK) {
+ wasm_runtime_free(tmpbuf);
+ tmpbuf = NULL;
+ }
+ return ret;
+}
+
+void
+wasm_debug_handler_deinit()
+{
+ wasm_runtime_free(tmpbuf);
+ tmpbuf = NULL;
+ os_mutex_destroy(&tmpbuf_lock);
+}
+
+void
+handle_interrupt(WASMGDBServer *server)
+{
+ wasm_debug_instance_interrupt_all_threads(server->thread->debug_instance);
+}
+
+void
+handle_general_set(WASMGDBServer *server, char *payload)
+{
+ const char *name;
+ char *args;
+
+ args = strchr(payload, ':');
+ if (args)
+ *args++ = '\0';
+
+ name = payload;
+ LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
+
+ if (!strcmp(name, "StartNoAckMode")) {
+ server->noack = true;
+ write_packet(server, "OK");
+ }
+ if (!strcmp(name, "ThreadSuffixSupported")) {
+ write_packet(server, "");
+ }
+ if (!strcmp(name, "ListThreadsInStopReply")) {
+ write_packet(server, "");
+ }
+ if (!strcmp(name, "EnableErrorStrings")) {
+ write_packet(server, "OK");
+ }
+}
+
+static void
+process_xfer(WASMGDBServer *server, const char *name, char *args)
+{
+ const char *mode = args;
+
+ args = strchr(args, ':');
+ if (args)
+ *args++ = '\0';
+
+ if (!strcmp(name, "libraries") && !strcmp(mode, "read")) {
+ // TODO: how to get current wasm file name?
+ uint64 addr = wasm_debug_instance_get_load_addr(
+ (WASMDebugInstance *)server->thread->debug_instance);
+ os_mutex_lock(&tmpbuf_lock);
+#if WASM_ENABLE_LIBC_WASI != 0
+ char objname[128];
+ if (!wasm_debug_instance_get_current_object_name(
+ (WASMDebugInstance *)server->thread->debug_instance, objname,
+ 128)) {
+ objname[0] = 0; /* use an empty string */
+ }
+ snprintf(tmpbuf, MAX_PACKET_SIZE,
+ "l<library-list><library name=\"%s\"><section "
+ "address=\"0x%" PRIx64 "\"/></library></library-list>",
+ objname, addr);
+#else
+ snprintf(tmpbuf, MAX_PACKET_SIZE,
+ "l<library-list><library name=\"%s\"><section "
+ "address=\"0x%" PRIx64 "\"/></library></library-list>",
+ "nobody.wasm", addr);
+#endif
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+}
+
+void
+process_wasm_local(WASMGDBServer *server, char *args)
+{
+ int32 frame_index;
+ int32 local_index;
+ char buf[16];
+ int32 size = 16;
+ bool ret;
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "E01");
+ if (sscanf(args, "%" PRId32 ";%" PRId32, &frame_index, &local_index) == 2) {
+ ret = wasm_debug_instance_get_local(
+ (WASMDebugInstance *)server->thread->debug_instance, frame_index,
+ local_index, buf, &size);
+ if (ret && size > 0) {
+ mem2hex(buf, tmpbuf, size);
+ }
+ }
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+void
+process_wasm_global(WASMGDBServer *server, char *args)
+{
+ int32 frame_index;
+ int32 global_index;
+ char buf[16];
+ int32 size = 16;
+ bool ret;
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "E01");
+ if (sscanf(args, "%" PRId32 ";%" PRId32, &frame_index, &global_index)
+ == 2) {
+ ret = wasm_debug_instance_get_global(
+ (WASMDebugInstance *)server->thread->debug_instance, frame_index,
+ global_index, buf, &size);
+ if (ret && size > 0) {
+ mem2hex(buf, tmpbuf, size);
+ }
+ }
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+void
+handle_general_query(WASMGDBServer *server, char *payload)
+{
+ const char *name;
+ char *args;
+ char triple[256];
+
+ args = strchr(payload, ':');
+ if (args)
+ *args++ = '\0';
+ name = payload;
+ LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
+
+ if (!strcmp(name, "C")) {
+ uint64 pid, tid;
+ pid = wasm_debug_instance_get_pid(
+ (WASMDebugInstance *)server->thread->debug_instance);
+ tid = (uint64)(uintptr_t)wasm_debug_instance_get_tid(
+ (WASMDebugInstance *)server->thread->debug_instance);
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "QCp%" PRIx64 ".%" PRIx64 "", pid,
+ tid);
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+ if (!strcmp(name, "Supported")) {
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE,
+ "qXfer:libraries:read+;PacketSize=%" PRIx32 ";",
+ MAX_PACKET_SIZE);
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+
+ if (!strcmp(name, "Xfer")) {
+ name = args;
+
+ if (!args) {
+ LOG_ERROR("payload parse error during handle_general_query");
+ return;
+ }
+
+ args = strchr(args, ':');
+
+ if (args) {
+ *args++ = '\0';
+ process_xfer(server, name, args);
+ }
+ }
+
+ if (!strcmp(name, "HostInfo")) {
+ mem2hex("wasm32-wamr-wasi-wasm", triple,
+ strlen("wasm32-wamr-wasi-wasm"));
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE,
+ "vendor:wamr;ostype:wasi;arch:wasm32;"
+ "triple:%s;endian:little;ptrsize:4;",
+ triple);
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+ if (!strcmp(name, "ModuleInfo")) {
+ write_packet(server, "");
+ }
+ if (!strcmp(name, "GetWorkingDir")) {
+ os_mutex_lock(&tmpbuf_lock);
+ if (getcwd(tmpbuf, PATH_MAX))
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+ if (!strcmp(name, "QueryGDBServer")) {
+ write_packet(server, "");
+ }
+ if (!strcmp(name, "VAttachOrWaitSupported")) {
+ write_packet(server, "");
+ }
+ if (!strcmp(name, "ProcessInfo")) {
+ // Todo: process id parent-pid
+ uint64 pid;
+ pid = wasm_debug_instance_get_pid(
+ (WASMDebugInstance *)server->thread->debug_instance);
+ mem2hex("wasm32-wamr-wasi-wasm", triple,
+ strlen("wasm32-wamr-wasi-wasm"));
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE,
+ "pid:%" PRIx64 ";parent-pid:%" PRIx64
+ ";vendor:wamr;ostype:wasi;arch:wasm32;"
+ "triple:%s;endian:little;ptrsize:4;",
+ pid, pid, triple);
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+ if (!strcmp(name, "RegisterInfo0")) {
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(
+ tmpbuf, MAX_PACKET_SIZE,
+ "name:pc;alt-name:pc;bitsize:64;offset:0;encoding:uint;format:hex;"
+ "set:General Purpose Registers;gcc:16;dwarf:16;generic:pc;");
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+ else if (!strncmp(name, "RegisterInfo", strlen("RegisterInfo"))) {
+ write_packet(server, "E45");
+ }
+ if (!strcmp(name, "StructuredDataPlugins")) {
+ write_packet(server, "");
+ }
+
+ if (args && (!strcmp(name, "MemoryRegionInfo"))) {
+ uint64 addr = strtoll(args, NULL, 16);
+ WASMDebugMemoryInfo *mem_info = wasm_debug_instance_get_memregion(
+ (WASMDebugInstance *)server->thread->debug_instance, addr);
+ if (mem_info) {
+ char name_buf[256];
+ mem2hex(mem_info->name, name_buf, strlen(mem_info->name));
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE,
+ "start:%" PRIx64 ";size:%" PRIx64
+ ";permissions:%s;name:%s;",
+ (uint64)mem_info->start, mem_info->size,
+ mem_info->permisson, name_buf);
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+
+ wasm_debug_instance_destroy_memregion(
+ (WASMDebugInstance *)server->thread->debug_instance, mem_info);
+ }
+ }
+
+ if (!strcmp(name, "WasmData")) {
+ }
+
+ if (!strcmp(name, "WasmMem")) {
+ }
+
+ if (!strcmp(name, "Symbol")) {
+ write_packet(server, "");
+ }
+
+ if (args && (!strcmp(name, "WasmCallStack"))) {
+ uint64 tid = strtoll(args, NULL, 16);
+ uint64 buf[1024 / sizeof(uint64)];
+ uint32 count = wasm_debug_instance_get_call_stack_pcs(
+ (WASMDebugInstance *)server->thread->debug_instance,
+ (korp_tid)(uintptr_t)tid, buf, 1024 / sizeof(uint64));
+
+ if (count > 0) {
+ os_mutex_lock(&tmpbuf_lock);
+ mem2hex((char *)buf, tmpbuf, count * sizeof(uint64));
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+ else
+ write_packet(server, "");
+ }
+
+ if (args && (!strcmp(name, "WasmLocal"))) {
+ process_wasm_local(server, args);
+ }
+
+ if (args && (!strcmp(name, "WasmGlobal"))) {
+ process_wasm_global(server, args);
+ }
+
+ if (!strcmp(name, "Offsets")) {
+ write_packet(server, "");
+ }
+
+ if (!strncmp(name, "ThreadStopInfo", strlen("ThreadStopInfo"))) {
+ int32 prefix_len = strlen("ThreadStopInfo");
+ uint64 tid_number = strtoll(name + prefix_len, NULL, 16);
+ korp_tid tid = (korp_tid)(uintptr_t)tid_number;
+ uint32 status;
+
+ status = wasm_debug_instance_get_thread_status(
+ server->thread->debug_instance, tid);
+
+ send_thread_stop_status(server, status, tid);
+ }
+
+ if (!strcmp(name, "WatchpointSupportInfo")) {
+ os_mutex_lock(&tmpbuf_lock);
+ // Any uint32 is OK for the watchpoint support
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "num:32;");
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ }
+}
+
+void
+send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid)
+{
+ int32 len = 0;
+ uint64 pc;
+ korp_tid tids[20];
+ char pc_string[17];
+ uint32 tids_count, i = 0;
+ uint32 gdb_status = status;
+ WASMExecEnv *exec_env;
+ const char *exception;
+
+ if (status == 0) {
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "W%02x", status);
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+ return;
+ }
+ tids_count = wasm_debug_instance_get_tids(
+ (WASMDebugInstance *)server->thread->debug_instance, tids, 20);
+ pc = wasm_debug_instance_get_pc(
+ (WASMDebugInstance *)server->thread->debug_instance);
+
+ if (status == WAMR_SIG_SINGSTEP) {
+ gdb_status = WAMR_SIG_TRAP;
+ }
+
+ os_mutex_lock(&tmpbuf_lock);
+ // TODO: how name a wasm thread?
+ len += snprintf(tmpbuf, MAX_PACKET_SIZE, "T%02xthread:%" PRIx64 ";name:%s;",
+ gdb_status, (uint64)(uintptr_t)tid, "nobody");
+ if (tids_count > 0) {
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len, "threads:");
+ while (i < tids_count) {
+ if (i == tids_count - 1)
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len,
+ "%" PRIx64 ";", (uint64)(uintptr_t)tids[i]);
+ else
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len,
+ "%" PRIx64 ",", (uint64)(uintptr_t)tids[i]);
+ i++;
+ }
+ }
+ mem2hex((void *)&pc, pc_string, 8);
+ pc_string[8 * 2] = '\0';
+
+ exec_env = wasm_debug_instance_get_current_env(
+ (WASMDebugInstance *)server->thread->debug_instance);
+ bh_assert(exec_env);
+
+ exception =
+ wasm_runtime_get_exception(wasm_runtime_get_module_inst(exec_env));
+ if (exception) {
+ /* When exception occurs, use reason:exception so the description can be
+ * correctly processed by LLDB */
+ uint32 exception_len = strlen(exception);
+ len +=
+ snprintf(tmpbuf + len, MAX_PACKET_SIZE - len,
+ "thread-pcs:%" PRIx64 ";00:%s;reason:%s;description:", pc,
+ pc_string, "exception");
+ /* The description should be encoded as HEX */
+ for (i = 0; i < exception_len; i++) {
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len, "%02x",
+ exception[i]);
+ }
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len, ";");
+ }
+ else {
+ if (status == WAMR_SIG_TRAP) {
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len,
+ "thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc,
+ pc_string, "breakpoint");
+ }
+ else if (status == WAMR_SIG_SINGSTEP) {
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len,
+ "thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc,
+ pc_string, "trace");
+ }
+ else if (status > 0) {
+ len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len,
+ "thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc,
+ pc_string, "signal");
+ }
+ }
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+void
+handle_v_packet(WASMGDBServer *server, char *payload)
+{
+ const char *name;
+ char *args;
+
+ args = strchr(payload, ';');
+ if (args)
+ *args++ = '\0';
+ name = payload;
+ LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
+
+ if (!strcmp("Cont?", name))
+ write_packet(server, "vCont;c;C;s;S;");
+
+ if (!strcmp("Cont", name)) {
+ if (args) {
+ if (args[0] == 's' || args[0] == 'c') {
+ char *numstring = strchr(args, ':');
+ if (numstring) {
+ uint64 tid_number;
+ korp_tid tid;
+
+ *numstring++ = '\0';
+ tid_number = strtoll(numstring, NULL, 16);
+ tid = (korp_tid)(uintptr_t)tid_number;
+ wasm_debug_instance_set_cur_thread(
+ (WASMDebugInstance *)server->thread->debug_instance,
+ tid);
+
+ if (args[0] == 's') {
+ wasm_debug_instance_singlestep(
+ (WASMDebugInstance *)server->thread->debug_instance,
+ tid);
+ }
+ else {
+ wasm_debug_instance_continue(
+ (WASMDebugInstance *)
+ server->thread->debug_instance);
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+handle_threadstop_request(WASMGDBServer *server, char *payload)
+{
+ korp_tid tid;
+ uint32 status;
+ WASMDebugInstance *debug_inst =
+ (WASMDebugInstance *)server->thread->debug_instance;
+ bh_assert(debug_inst);
+
+ /* According to
+ https://sourceware.org/gdb/onlinedocs/gdb/Packets.html#Packets, the "?"
+ package should be sent when connection is first established to query the
+ reason the target halted */
+ bh_assert(debug_inst->current_state == DBG_LAUNCHING);
+
+ /* Waiting for the stop event */
+ os_mutex_lock(&debug_inst->wait_lock);
+ while (!debug_inst->stopped_thread) {
+ os_cond_wait(&debug_inst->wait_cond, &debug_inst->wait_lock);
+ }
+ os_mutex_unlock(&debug_inst->wait_lock);
+
+ tid = debug_inst->stopped_thread->handle;
+ status = (uint32)debug_inst->stopped_thread->current_status->signal_flag;
+
+ wasm_debug_instance_set_cur_thread(debug_inst, tid);
+
+ send_thread_stop_status(server, status, tid);
+
+ debug_inst->current_state = APP_STOPPED;
+ debug_inst->stopped_thread = NULL;
+}
+
+void
+handle_set_current_thread(WASMGDBServer *server, char *payload)
+{
+ LOG_VERBOSE("%s:%s\n", __FUNCTION__, payload);
+ if ('g' == *payload++) {
+ uint64 tid = strtoll(payload, NULL, 16);
+ if (tid > 0)
+ wasm_debug_instance_set_cur_thread(
+ (WASMDebugInstance *)server->thread->debug_instance,
+ (korp_tid)(uintptr_t)tid);
+ }
+ write_packet(server, "OK");
+}
+
+void
+handle_get_register(WASMGDBServer *server, char *payload)
+{
+ uint64 regdata;
+ int32 i = strtol(payload, NULL, 16);
+
+ if (i != 0) {
+ write_packet(server, "E01");
+ return;
+ }
+ regdata = wasm_debug_instance_get_pc(
+ (WASMDebugInstance *)server->thread->debug_instance);
+
+ os_mutex_lock(&tmpbuf_lock);
+ mem2hex((void *)&regdata, tmpbuf, 8);
+ tmpbuf[8 * 2] = '\0';
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+void
+handle_get_json_request(WASMGDBServer *server, char *payload)
+{
+ char *args;
+
+ args = strchr(payload, ':');
+ if (args)
+ *args++ = '\0';
+ write_packet(server, "");
+}
+
+void
+handle_get_read_binary_memory(WASMGDBServer *server, char *payload)
+{
+ write_packet(server, "");
+}
+
+void
+handle_get_read_memory(WASMGDBServer *server, char *payload)
+{
+ uint64 maddr, mlen;
+ bool ret;
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "%s", "");
+ if (sscanf(payload, "%" SCNx64 ",%" SCNx64, &maddr, &mlen) == 2) {
+ char *buff;
+
+ if (mlen * 2 > MAX_PACKET_SIZE) {
+ LOG_ERROR("Buffer overflow!");
+ mlen = MAX_PACKET_SIZE / 2;
+ }
+
+ buff = wasm_runtime_malloc(mlen);
+ if (buff) {
+ ret = wasm_debug_instance_get_mem(
+ (WASMDebugInstance *)server->thread->debug_instance, maddr,
+ buff, &mlen);
+ if (ret) {
+ mem2hex(buff, tmpbuf, mlen);
+ }
+ wasm_runtime_free(buff);
+ }
+ }
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+void
+handle_get_write_memory(WASMGDBServer *server, char *payload)
+{
+ size_t hex_len;
+ int32 offset, act_len;
+ uint64 maddr, mlen;
+ char *buff;
+ bool ret;
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "%s", "");
+ if (sscanf(payload, "%" SCNx64 ",%" SCNx64 ":%n", &maddr, &mlen, &offset)
+ == 2) {
+ payload += offset;
+ hex_len = strlen(payload);
+ act_len = hex_len / 2 < mlen ? hex_len / 2 : mlen;
+
+ buff = wasm_runtime_malloc(act_len);
+ if (buff) {
+ hex2mem(payload, buff, act_len);
+ ret = wasm_debug_instance_set_mem(
+ (WASMDebugInstance *)server->thread->debug_instance, maddr,
+ buff, &mlen);
+ if (ret) {
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "%s", "OK");
+ }
+ wasm_runtime_free(buff);
+ }
+ }
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+void
+handle_breakpoint_software_add(WASMGDBServer *server, uint64 addr,
+ size_t length)
+{
+ bool ret = wasm_debug_instance_add_breakpoint(
+ (WASMDebugInstance *)server->thread->debug_instance, addr, length);
+ write_packet(server, ret ? "OK" : "EO1");
+}
+
+void
+handle_breakpoint_software_remove(WASMGDBServer *server, uint64 addr,
+ size_t length)
+{
+ bool ret = wasm_debug_instance_remove_breakpoint(
+ (WASMDebugInstance *)server->thread->debug_instance, addr, length);
+ write_packet(server, ret ? "OK" : "EO1");
+}
+
+void
+handle_watchpoint_write_add(WASMGDBServer *server, uint64 addr, size_t length)
+{
+ bool ret = wasm_debug_instance_watchpoint_write_add(
+ (WASMDebugInstance *)server->thread->debug_instance, addr, length);
+ write_packet(server, ret ? "OK" : "EO1");
+}
+
+void
+handle_watchpoint_write_remove(WASMGDBServer *server, uint64 addr,
+ size_t length)
+{
+ bool ret = wasm_debug_instance_watchpoint_write_remove(
+ (WASMDebugInstance *)server->thread->debug_instance, addr, length);
+ write_packet(server, ret ? "OK" : "EO1");
+}
+
+void
+handle_watchpoint_read_add(WASMGDBServer *server, uint64 addr, size_t length)
+{
+ bool ret = wasm_debug_instance_watchpoint_read_add(
+ (WASMDebugInstance *)server->thread->debug_instance, addr, length);
+ write_packet(server, ret ? "OK" : "EO1");
+}
+
+void
+handle_watchpoint_read_remove(WASMGDBServer *server, uint64 addr, size_t length)
+{
+ bool ret = wasm_debug_instance_watchpoint_read_remove(
+ (WASMDebugInstance *)server->thread->debug_instance, addr, length);
+ write_packet(server, ret ? "OK" : "EO1");
+}
+
+void
+handle_add_break(WASMGDBServer *server, char *payload)
+{
+ int arg_c;
+ size_t type, length;
+ uint64 addr;
+
+ if ((arg_c = sscanf(payload, "%zx,%" SCNx64 ",%zx", &type, &addr, &length))
+ != 3) {
+ LOG_ERROR("Unsupported number of add break arguments %d", arg_c);
+ write_packet(server, "");
+ return;
+ }
+
+ switch (type) {
+ case eBreakpointSoftware:
+ handle_breakpoint_software_add(server, addr, length);
+ break;
+ case eWatchpointWrite:
+ handle_watchpoint_write_add(server, addr, length);
+ break;
+ case eWatchpointRead:
+ handle_watchpoint_read_add(server, addr, length);
+ break;
+ case eWatchpointReadWrite:
+ handle_watchpoint_write_add(server, addr, length);
+ handle_watchpoint_read_add(server, addr, length);
+ break;
+ default:
+ LOG_ERROR("Unsupported breakpoint type %zu", type);
+ write_packet(server, "");
+ break;
+ }
+}
+
+void
+handle_remove_break(WASMGDBServer *server, char *payload)
+{
+ int arg_c;
+ size_t type, length;
+ uint64 addr;
+
+ if ((arg_c = sscanf(payload, "%zx,%" SCNx64 ",%zx", &type, &addr, &length))
+ != 3) {
+ LOG_ERROR("Unsupported number of remove break arguments %d", arg_c);
+ write_packet(server, "");
+ return;
+ }
+
+ switch (type) {
+ case eBreakpointSoftware:
+ handle_breakpoint_software_remove(server, addr, length);
+ break;
+ case eWatchpointWrite:
+ handle_watchpoint_write_remove(server, addr, length);
+ break;
+ case eWatchpointRead:
+ handle_watchpoint_read_remove(server, addr, length);
+ break;
+ case eWatchpointReadWrite:
+ handle_watchpoint_write_remove(server, addr, length);
+ handle_watchpoint_read_remove(server, addr, length);
+ break;
+ default:
+ LOG_ERROR("Unsupported breakpoint type %zu", type);
+ write_packet(server, "");
+ break;
+ }
+}
+
+void
+handle_continue_request(WASMGDBServer *server, char *payload)
+{
+ wasm_debug_instance_continue(
+ (WASMDebugInstance *)server->thread->debug_instance);
+}
+
+void
+handle_kill_request(WASMGDBServer *server, char *payload)
+{
+ wasm_debug_instance_kill(
+ (WASMDebugInstance *)server->thread->debug_instance);
+}
+
+static void
+handle_malloc(WASMGDBServer *server, char *payload)
+{
+ char *args;
+ uint64 addr, size;
+ int32 map_prot = MMAP_PROT_NONE;
+
+ args = strstr(payload, ",");
+ if (args) {
+ *args++ = '\0';
+ }
+ else {
+ LOG_ERROR("Payload parse error during handle malloc");
+ return;
+ }
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "%s", "E03");
+
+ size = strtoll(payload, NULL, 16);
+ if (size > 0) {
+ while (*args) {
+ if (*args == 'r') {
+ map_prot |= MMAP_PROT_READ;
+ }
+ if (*args == 'w') {
+ map_prot |= MMAP_PROT_WRITE;
+ }
+ if (*args == 'x') {
+ map_prot |= MMAP_PROT_EXEC;
+ }
+ args++;
+ }
+ addr = wasm_debug_instance_mmap(
+ (WASMDebugInstance *)server->thread->debug_instance, size,
+ map_prot);
+ if (addr) {
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "%" PRIx64, addr);
+ }
+ }
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+static void
+handle_free(WASMGDBServer *server, char *payload)
+{
+ uint64 addr;
+ bool ret;
+
+ os_mutex_lock(&tmpbuf_lock);
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "%s", "E03");
+ addr = strtoll(payload, NULL, 16);
+
+ ret = wasm_debug_instance_ummap(
+ (WASMDebugInstance *)server->thread->debug_instance, addr);
+ if (ret) {
+ snprintf(tmpbuf, MAX_PACKET_SIZE, "%s", "OK");
+ }
+
+ write_packet(server, tmpbuf);
+ os_mutex_unlock(&tmpbuf_lock);
+}
+
+void
+handle____request(WASMGDBServer *server, char *payload)
+{
+ char *args;
+
+ if (payload[0] == 'M') {
+ args = payload + 1;
+ handle_malloc(server, args);
+ }
+ if (payload[0] == 'm') {
+ args = payload + 1;
+ handle_free(server, args);
+ }
+}
+
+void
+handle_detach_request(WASMGDBServer *server, char *payload)
+{
+ if (payload != NULL) {
+ write_packet(server, "OK");
+ }
+ wasm_debug_instance_detach(
+ (WASMDebugInstance *)server->thread->debug_instance);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.h
new file mode 100644
index 000000000..af2566da5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/handler.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef HANDLER_H
+#define HANDLER_H
+
+#include "gdbserver.h"
+
+int
+wasm_debug_handler_init();
+
+void
+wasm_debug_handler_deinit();
+
+void
+handle_interrupt(WASMGDBServer *server);
+
+void
+handle_general_set(WASMGDBServer *server, char *payload);
+
+void
+handle_general_query(WASMGDBServer *server, char *payload);
+
+void
+handle_v_packet(WASMGDBServer *server, char *payload);
+
+void
+handle_threadstop_request(WASMGDBServer *server, char *payload);
+
+void
+handle_set_current_thread(WASMGDBServer *server, char *payload);
+
+void
+handle_get_register(WASMGDBServer *server, char *payload);
+
+void
+handle_get_json_request(WASMGDBServer *server, char *payload);
+
+void
+handle_get_read_binary_memory(WASMGDBServer *server, char *payload);
+
+void
+handle_get_read_memory(WASMGDBServer *server, char *payload);
+
+void
+handle_get_write_memory(WASMGDBServer *server, char *payload);
+
+void
+handle_add_break(WASMGDBServer *server, char *payload);
+
+void
+handle_remove_break(WASMGDBServer *server, char *payload);
+
+void
+handle_continue_request(WASMGDBServer *server, char *payload);
+
+void
+handle_kill_request(WASMGDBServer *server, char *payload);
+
+void
+handle____request(WASMGDBServer *server, char *payload);
+
+void
+handle_detach_request(WASMGDBServer *server, char *payload);
+
+void
+send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid);
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.c
new file mode 100644
index 000000000..1bdb3d2ce
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_platform.h"
+#include "packets.h"
+#include "gdbserver.h"
+
+void
+write_data_raw(WASMGDBServer *gdbserver, const uint8 *data, ssize_t len)
+{
+ ssize_t nwritten;
+
+ nwritten = os_socket_send(gdbserver->socket_fd, data, len);
+ if (nwritten < 0) {
+ LOG_ERROR("Write error\n");
+ exit(-2);
+ }
+}
+
+void
+write_hex(WASMGDBServer *gdbserver, unsigned long hex)
+{
+ char buf[32];
+ size_t len;
+
+ len = snprintf(buf, sizeof(buf) - 1, "%02lx", hex);
+ write_data_raw(gdbserver, (uint8 *)buf, len);
+}
+
+void
+write_packet_bytes(WASMGDBServer *gdbserver, const uint8 *data,
+ size_t num_bytes)
+{
+ uint8 checksum;
+ size_t i;
+
+ write_data_raw(gdbserver, (uint8 *)"$", 1);
+ for (i = 0, checksum = 0; i < num_bytes; ++i)
+ checksum += data[i];
+ write_data_raw(gdbserver, (uint8 *)data, num_bytes);
+ write_data_raw(gdbserver, (uint8 *)"#", 1);
+ write_hex(gdbserver, checksum);
+}
+
+void
+write_packet(WASMGDBServer *gdbserver, const char *data)
+{
+ LOG_VERBOSE("send replay:%s", data);
+ write_packet_bytes(gdbserver, (const uint8 *)data, strlen(data));
+}
+
+void
+write_binary_packet(WASMGDBServer *gdbserver, const char *pfx,
+ const uint8 *data, ssize_t num_bytes)
+{
+ uint8 *buf;
+ ssize_t pfx_num_chars = strlen(pfx);
+ ssize_t buf_num_bytes = 0, total_size;
+ int32 i;
+
+ total_size = 2 * num_bytes + pfx_num_chars;
+ buf = wasm_runtime_malloc(total_size);
+ if (!buf) {
+ LOG_ERROR("Failed to allocate memory for binary packet");
+ return;
+ }
+
+ memset(buf, 0, total_size);
+ memcpy(buf, pfx, pfx_num_chars);
+ buf_num_bytes += pfx_num_chars;
+
+ for (i = 0; i < num_bytes; ++i) {
+ uint8 b = data[i];
+ switch (b) {
+ case '#':
+ case '$':
+ case '}':
+ case '*':
+ buf[buf_num_bytes++] = '}';
+ buf[buf_num_bytes++] = b ^ 0x20;
+ break;
+ default:
+ buf[buf_num_bytes++] = b;
+ break;
+ }
+ }
+ write_packet_bytes(gdbserver, buf, buf_num_bytes);
+ wasm_runtime_free(buf);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.h
new file mode 100644
index 000000000..b35889394
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/packets.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef PACKETS_H
+#define PACKETS_H
+
+#include "gdbserver.h"
+
+void
+write_data_raw(WASMGDBServer *gdbserver, const uint8 *data, ssize_t len);
+
+void
+write_packet(WASMGDBServer *gdbserver, const char *data);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.c
new file mode 100644
index 000000000..4d9299c1b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "utils.h"
+
+static const char hexchars[] = "0123456789abcdef";
+
+int32
+hex(char ch)
+{
+ if ((ch >= 'a') && (ch <= 'f'))
+ return (ch - 'a' + 10);
+ if ((ch >= '0') && (ch <= '9'))
+ return (ch - '0');
+ if ((ch >= 'A') && (ch <= 'F'))
+ return (ch - 'A' + 10);
+ return (-1);
+}
+
+char *
+mem2hex(char *mem, char *buf, int32 count)
+{
+ uint8 ch;
+
+ for (int i = 0; i < count; i++) {
+ ch = *(mem++);
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch % 16];
+ }
+ *buf = 0;
+ return (buf);
+}
+
+char *
+hex2mem(char *buf, char *mem, int32 count)
+{
+ uint8 ch;
+
+ for (int i = 0; i < count; i++) {
+ ch = hex(*buf++) << 4;
+ ch = ch + hex(*buf++);
+ *(mem++) = ch;
+ }
+ return (mem);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.h
new file mode 100644
index 000000000..1c7580859
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/debug-engine/utils.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2021 Ant Group. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+#include "bh_platform.h"
+
+int32
+hex(char ch);
+
+char *
+mem2hex(char *mem, char *buf, int32 count);
+
+char *
+hex2mem(char *buf, char *mem, int32 count);
+
+int32
+unescape(char *msg, int32 len);
+
+#endif /* UTILS_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/SConscript
new file mode 100644
index 000000000..d03936c2f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/SConscript
@@ -0,0 +1,20 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+
+cwd = GetCurrentDir()
+
+src = Split('''
+libc_pthread_wrapper.c
+''')
+
+CPPPATH = [cwd]
+
+
+group = DefineGroup('iwasm_libc_pthread', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread.cmake
new file mode 100644
index 000000000..134edf0e8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread.cmake
@@ -0,0 +1,17 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (LIB_PTHREAD_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions (-DWASM_ENABLE_LIB_PTHREAD=1)
+
+if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1)
+add_definitions (-DWASM_ENABLE_LIB_PTHREAD_SEMAPHORE=1)
+endif()
+
+include_directories(${LIB_PTHREAD_DIR})
+
+file (GLOB source_all ${LIB_PTHREAD_DIR}/*.c)
+
+set (LIB_PTHREAD_SOURCE ${source_all})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c
new file mode 100644
index 000000000..206479c2a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c
@@ -0,0 +1,1331 @@
+/*
+ * 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"
+#include "../common/wasm_runtime_common.h"
+#include "thread_manager.h"
+
+#if WASM_ENABLE_INTERP != 0
+#include "wasm_runtime.h"
+#endif
+
+#if WASM_ENABLE_AOT != 0
+#include "aot_runtime.h"
+#endif
+
+#define WAMR_PTHREAD_KEYS_MAX 32
+
+/* clang-format off */
+#define get_module(exec_env) \
+ wasm_exec_env_get_module(exec_env)
+
+#define get_module_inst(exec_env) \
+ wasm_runtime_get_module_inst(exec_env)
+
+#define get_thread_arg(exec_env) \
+ wasm_exec_env_get_thread_arg(exec_env)
+
+#define get_wasi_ctx(module_inst) \
+ wasm_runtime_get_wasi_ctx(module_inst)
+
+#define validate_app_addr(offset, size) \
+ wasm_runtime_validate_app_addr(module_inst, offset, size)
+
+#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)
+/* clang-format on */
+
+enum {
+ T_THREAD,
+ T_MUTEX,
+ T_COND,
+ T_SEM,
+};
+
+enum thread_status_t {
+ THREAD_INIT,
+ THREAD_RUNNING,
+ THREAD_CANCELLED,
+ THREAD_EXIT,
+};
+
+enum mutex_status_t {
+ MUTEX_CREATED,
+ MUTEX_DESTROYED,
+};
+
+enum cond_status_t {
+ COND_CREATED,
+ COND_DESTROYED,
+};
+
+enum sem_status_t {
+ SEM_CREATED,
+ SEM_CLOSED,
+ SEM_DESTROYED,
+};
+
+typedef struct ThreadKeyValueNode {
+ bh_list_link l;
+ wasm_exec_env_t exec_env;
+ int32 thread_key_values[WAMR_PTHREAD_KEYS_MAX];
+} ThreadKeyValueNode;
+
+typedef struct KeyData {
+ int32 destructor_func;
+ bool is_created;
+} KeyData;
+
+typedef struct ClusterInfoNode {
+ bh_list_link l;
+ WASMCluster *cluster;
+ HashMap *thread_info_map;
+ /* Key data list */
+ KeyData key_data_list[WAMR_PTHREAD_KEYS_MAX];
+ korp_mutex key_data_list_lock;
+ /* Every node contains the key value list for a thread */
+ bh_list thread_list_head;
+ bh_list *thread_list;
+} ClusterInfoNode;
+
+typedef struct ThreadInfoNode {
+ wasm_exec_env_t parent_exec_env;
+ wasm_exec_env_t exec_env;
+ /* the id returned to app */
+ uint32 handle;
+ /* type can be [THREAD | MUTEX | CONDITION] */
+ uint32 type;
+ /* Thread status, this variable should be volatile
+ as its value may be changed in different threads */
+ volatile uint32 status;
+ bool joinable;
+ union {
+ korp_tid thread;
+ korp_mutex *mutex;
+ korp_cond *cond;
+#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
+ korp_sem *sem;
+#endif
+ /* A copy of the thread return value */
+ void *ret;
+ } u;
+} ThreadInfoNode;
+
+typedef struct {
+ ThreadInfoNode *info_node;
+ /* table elem index of the app's entry function */
+ uint32 elem_index;
+ /* arg of the app's entry function */
+ uint32 arg;
+ wasm_module_inst_t module_inst;
+} ThreadRoutineArgs;
+
+typedef struct {
+ uint32 handle;
+ ThreadInfoNode *node;
+} SemCallbackArgs;
+
+static bh_list cluster_info_list;
+#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
+static HashMap *sem_info_map;
+#endif
+static korp_mutex thread_global_lock;
+static uint32 handle_id = 1;
+
+static void
+lib_pthread_destroy_callback(WASMCluster *cluster);
+
+static uint32
+thread_handle_hash(void *handle)
+{
+ return (uint32)(uintptr_t)handle;
+}
+
+static bool
+thread_handle_equal(void *h1, void *h2)
+{
+ return (uint32)(uintptr_t)h1 == (uint32)(uintptr_t)h2 ? true : false;
+}
+
+static void
+thread_info_destroy(void *node)
+{
+ ThreadInfoNode *info_node = (ThreadInfoNode *)node;
+
+ os_mutex_lock(&thread_global_lock);
+ if (info_node->type == T_MUTEX) {
+ if (info_node->status != MUTEX_DESTROYED)
+ os_mutex_destroy(info_node->u.mutex);
+ wasm_runtime_free(info_node->u.mutex);
+ }
+ else if (info_node->type == T_COND) {
+ if (info_node->status != COND_DESTROYED)
+ os_cond_destroy(info_node->u.cond);
+ wasm_runtime_free(info_node->u.cond);
+ }
+#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
+ else if (info_node->type == T_SEM) {
+ if (info_node->status != SEM_DESTROYED)
+ os_sem_close(info_node->u.sem);
+ }
+#endif
+ wasm_runtime_free(info_node);
+ os_mutex_unlock(&thread_global_lock);
+}
+
+bool
+lib_pthread_init()
+{
+ if (0 != os_mutex_init(&thread_global_lock))
+ return false;
+ bh_list_init(&cluster_info_list);
+ if (!wasm_cluster_register_destroy_callback(lib_pthread_destroy_callback)) {
+ os_mutex_destroy(&thread_global_lock);
+ return false;
+ }
+#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
+ if (!(sem_info_map = bh_hash_map_create(
+ 32, true, (HashFunc)wasm_string_hash,
+ (KeyEqualFunc)wasm_string_equal, NULL, thread_info_destroy))) {
+ os_mutex_destroy(&thread_global_lock);
+ return false;
+ }
+#endif
+ return true;
+}
+
+void
+lib_pthread_destroy()
+{
+#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
+ bh_hash_map_destroy(sem_info_map);
+#endif
+ os_mutex_destroy(&thread_global_lock);
+}
+
+static ClusterInfoNode *
+get_cluster_info(WASMCluster *cluster)
+{
+ ClusterInfoNode *node;
+
+ os_mutex_lock(&thread_global_lock);
+ node = bh_list_first_elem(&cluster_info_list);
+
+ while (node) {
+ if (cluster == node->cluster) {
+ os_mutex_unlock(&thread_global_lock);
+ return node;
+ }
+ node = bh_list_elem_next(node);
+ }
+ os_mutex_unlock(&thread_global_lock);
+
+ return NULL;
+}
+
+static KeyData *
+key_data_list_lookup(wasm_exec_env_t exec_env, int32 key)
+{
+ ClusterInfoNode *node;
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+
+ if ((node = get_cluster_info(cluster))) {
+ return (key >= 0 && key < WAMR_PTHREAD_KEYS_MAX
+ && node->key_data_list[key].is_created)
+ ? &(node->key_data_list[key])
+ : NULL;
+ }
+
+ return NULL;
+}
+
+/**
+ * Lookup the thread key value node for a thread, create a new one if failed
+ * This design will reduce the memory usage. If the thread doesn't use the
+ * local storage, it will not occupy memory space.
+ */
+static int32 *
+key_value_list_lookup_or_create(wasm_exec_env_t exec_env, ClusterInfoNode *info,
+ int32 key)
+{
+ KeyData *key_node;
+ ThreadKeyValueNode *data;
+
+ /* Check if the key is valid */
+ key_node = key_data_list_lookup(exec_env, key);
+ if (!key_node) {
+ return NULL;
+ }
+
+ /* Find key values node */
+ data = bh_list_first_elem(info->thread_list);
+ while (data) {
+ if (data->exec_env == exec_env)
+ return data->thread_key_values;
+ data = bh_list_elem_next(data);
+ }
+
+ /* If not found, create a new node for this thread */
+ if (!(data = wasm_runtime_malloc(sizeof(ThreadKeyValueNode))))
+ return NULL;
+ memset(data, 0, sizeof(ThreadKeyValueNode));
+ data->exec_env = exec_env;
+
+ if (bh_list_insert(info->thread_list, data) != 0) {
+ wasm_runtime_free(data);
+ return NULL;
+ }
+
+ return data->thread_key_values;
+}
+
+static void
+call_key_destructor(wasm_exec_env_t exec_env)
+{
+ int32 i;
+ uint32 destructor_index;
+ KeyData *key_node;
+ ThreadKeyValueNode *value_node;
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ ClusterInfoNode *info = get_cluster_info(cluster);
+
+ if (!info) {
+ return;
+ }
+
+ value_node = bh_list_first_elem(info->thread_list);
+ while (value_node) {
+ if (value_node->exec_env == exec_env)
+ break;
+ value_node = bh_list_elem_next(value_node);
+ }
+
+ /* This thread hasn't created key value node */
+ if (!value_node)
+ return;
+
+ /* Destroy key values */
+ for (i = 0; i < WAMR_PTHREAD_KEYS_MAX; i++) {
+ if (value_node->thread_key_values[i] != 0) {
+ int32 value = value_node->thread_key_values[i];
+ os_mutex_lock(&info->key_data_list_lock);
+
+ if ((key_node = key_data_list_lookup(exec_env, i)))
+ destructor_index = key_node->destructor_func;
+ else
+ destructor_index = 0;
+ os_mutex_unlock(&info->key_data_list_lock);
+
+ /* reset key value */
+ value_node->thread_key_values[i] = 0;
+
+ /* Call the destructor func provided by app */
+ if (destructor_index) {
+ uint32 argv[1];
+
+ argv[0] = value;
+ wasm_runtime_call_indirect(exec_env, destructor_index, 1, argv);
+ }
+ }
+ }
+
+ bh_list_remove(info->thread_list, value_node);
+ wasm_runtime_free(value_node);
+}
+
+static void
+destroy_thread_key_value_list(bh_list *list)
+{
+ ThreadKeyValueNode *node, *next;
+
+ /* There should be only one node for main thread */
+ bh_assert(list->len <= 1);
+
+ if (list->len) {
+ node = bh_list_first_elem(list);
+ while (node) {
+ next = bh_list_elem_next(node);
+ call_key_destructor(node->exec_env);
+ node = next;
+ }
+ }
+}
+
+static ClusterInfoNode *
+create_cluster_info(WASMCluster *cluster)
+{
+ ClusterInfoNode *node;
+ bh_list_status ret;
+
+ if (!(node = wasm_runtime_malloc(sizeof(ClusterInfoNode)))) {
+ return NULL;
+ }
+ memset(node, 0, sizeof(ClusterInfoNode));
+
+ node->thread_list = &node->thread_list_head;
+ ret = bh_list_init(node->thread_list);
+ bh_assert(ret == BH_LIST_SUCCESS);
+
+ if (os_mutex_init(&node->key_data_list_lock) != 0) {
+ wasm_runtime_free(node);
+ return NULL;
+ }
+
+ node->cluster = cluster;
+ if (!(node->thread_info_map = bh_hash_map_create(
+ 32, true, (HashFunc)thread_handle_hash,
+ (KeyEqualFunc)thread_handle_equal, NULL, thread_info_destroy))) {
+ os_mutex_destroy(&node->key_data_list_lock);
+ wasm_runtime_free(node);
+ return NULL;
+ }
+ os_mutex_lock(&thread_global_lock);
+ ret = bh_list_insert(&cluster_info_list, node);
+ bh_assert(ret == BH_LIST_SUCCESS);
+ os_mutex_unlock(&thread_global_lock);
+
+ (void)ret;
+ return node;
+}
+
+static bool
+destroy_cluster_info(WASMCluster *cluster)
+{
+ ClusterInfoNode *node = get_cluster_info(cluster);
+ if (node) {
+ bh_hash_map_destroy(node->thread_info_map);
+ destroy_thread_key_value_list(node->thread_list);
+ os_mutex_destroy(&node->key_data_list_lock);
+
+ /* Remove from the cluster info list */
+ os_mutex_lock(&thread_global_lock);
+ bh_list_remove(&cluster_info_list, node);
+ wasm_runtime_free(node);
+ os_mutex_unlock(&thread_global_lock);
+ return true;
+ }
+ return false;
+}
+
+static void
+lib_pthread_destroy_callback(WASMCluster *cluster)
+{
+ destroy_cluster_info(cluster);
+}
+
+static void
+delete_thread_info_node(ThreadInfoNode *thread_info)
+{
+ ClusterInfoNode *node;
+ bool ret;
+ WASMCluster *cluster = wasm_exec_env_get_cluster(thread_info->exec_env);
+
+ if ((node = get_cluster_info(cluster))) {
+ ret = bh_hash_map_remove(node->thread_info_map,
+ (void *)(uintptr_t)thread_info->handle, NULL,
+ NULL);
+ (void)ret;
+ }
+
+ thread_info_destroy(thread_info);
+}
+
+static bool
+append_thread_info_node(ThreadInfoNode *thread_info)
+{
+ ClusterInfoNode *node;
+ WASMCluster *cluster = wasm_exec_env_get_cluster(thread_info->exec_env);
+
+ if (!(node = get_cluster_info(cluster))) {
+ if (!(node = create_cluster_info(cluster))) {
+ return false;
+ }
+ }
+
+ if (!bh_hash_map_insert(node->thread_info_map,
+ (void *)(uintptr_t)thread_info->handle,
+ thread_info)) {
+ return false;
+ }
+
+ return true;
+}
+
+static ThreadInfoNode *
+get_thread_info(wasm_exec_env_t exec_env, uint32 handle)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ ClusterInfoNode *info = get_cluster_info(cluster);
+
+ if (!info) {
+ return NULL;
+ }
+
+ return bh_hash_map_find(info->thread_info_map, (void *)(uintptr_t)handle);
+}
+
+static uint32
+allocate_handle()
+{
+ uint32 id;
+ os_mutex_lock(&thread_global_lock);
+ id = handle_id++;
+ os_mutex_unlock(&thread_global_lock);
+ return id;
+}
+
+static void *
+pthread_start_routine(void *arg)
+{
+ wasm_exec_env_t exec_env = (wasm_exec_env_t)arg;
+ wasm_exec_env_t parent_exec_env;
+ ThreadRoutineArgs *routine_args = exec_env->thread_arg;
+ ThreadInfoNode *info_node = routine_args->info_node;
+ uint32 argv[1];
+
+ parent_exec_env = info_node->parent_exec_env;
+ os_mutex_lock(&parent_exec_env->wait_lock);
+ info_node->exec_env = exec_env;
+ info_node->u.thread = exec_env->handle;
+ if (!append_thread_info_node(info_node)) {
+ delete_thread_info_node(info_node);
+ os_cond_signal(&parent_exec_env->wait_cond);
+ os_mutex_unlock(&parent_exec_env->wait_lock);
+ return NULL;
+ }
+
+ info_node->status = THREAD_RUNNING;
+ os_cond_signal(&parent_exec_env->wait_cond);
+ os_mutex_unlock(&parent_exec_env->wait_lock);
+
+ wasm_exec_env_set_thread_info(exec_env);
+ argv[0] = routine_args->arg;
+
+ if (!wasm_runtime_call_indirect(exec_env, routine_args->elem_index, 1,
+ argv)) {
+ /* Exception has already been spread during throwing */
+ }
+
+ /* destroy pthread key values */
+ call_key_destructor(exec_env);
+
+ wasm_runtime_free(routine_args);
+
+ /* if the thread is joinable, store the result in its info node,
+ if the other threads join this thread after exited, then we
+ can return the stored result */
+ if (!info_node->joinable) {
+ delete_thread_info_node(info_node);
+ }
+ else {
+ info_node->u.ret = (void *)(uintptr_t)argv[0];
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (exec_env->suspend_flags.flags & 0x08)
+ /* argv[0] isn't set after longjmp(1) to
+ invoke_native_with_hw_bound_check */
+ info_node->u.ret = exec_env->thread_ret_value;
+#endif
+ /* Update node status after ret value was set */
+ info_node->status = THREAD_EXIT;
+ }
+
+ return (void *)(uintptr_t)argv[0];
+}
+
+static int
+pthread_create_wrapper(wasm_exec_env_t exec_env,
+ uint32 *thread, /* thread_handle */
+ const void *attr, /* not supported */
+ uint32 elem_index, /* entry function */
+ uint32 arg) /* arguments buffer */
+{
+ wasm_module_t module = get_module(exec_env);
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasm_module_inst_t new_module_inst = NULL;
+ ThreadInfoNode *info_node = NULL;
+ ThreadRoutineArgs *routine_args = NULL;
+ uint32 thread_handle;
+ uint32 stack_size = 8192;
+ int32 ret = -1;
+#if WASM_ENABLE_LIBC_WASI != 0
+ WASIContext *wasi_ctx;
+#endif
+
+ bh_assert(module);
+ bh_assert(module_inst);
+
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ stack_size =
+ ((WASMModuleInstance *)module_inst)->default_wasm_stack_size;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ stack_size =
+ ((AOTModuleInstance *)module_inst)->default_wasm_stack_size;
+ }
+#endif
+
+ if (!(new_module_inst = wasm_runtime_instantiate_internal(
+ module, true, exec_env, stack_size, 0, NULL, 0)))
+ return -1;
+
+ /* Set custom_data to new module instance */
+ wasm_runtime_set_custom_data_internal(
+ new_module_inst, wasm_runtime_get_custom_data(module_inst));
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ wasi_ctx = get_wasi_ctx(module_inst);
+ if (wasi_ctx)
+ wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
+#endif
+
+ if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst)))
+ goto fail;
+
+ if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode))))
+ goto fail;
+
+ memset(info_node, 0, sizeof(ThreadInfoNode));
+ thread_handle = allocate_handle();
+ info_node->parent_exec_env = exec_env;
+ info_node->handle = thread_handle;
+ info_node->type = T_THREAD;
+ info_node->status = THREAD_INIT;
+ info_node->joinable = true;
+
+ if (!(routine_args = wasm_runtime_malloc(sizeof(ThreadRoutineArgs))))
+ goto fail;
+
+ routine_args->arg = arg;
+ routine_args->elem_index = elem_index;
+ routine_args->info_node = info_node;
+ routine_args->module_inst = new_module_inst;
+
+ os_mutex_lock(&exec_env->wait_lock);
+ ret =
+ wasm_cluster_create_thread(exec_env, new_module_inst, true,
+ pthread_start_routine, (void *)routine_args);
+ if (ret != 0) {
+ os_mutex_unlock(&exec_env->wait_lock);
+ goto fail;
+ }
+
+ /* Wait for the thread routine to assign the exec_env to
+ thread_info_node, otherwise the exec_env in the thread
+ info node may be NULL in the next pthread API call */
+ os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock);
+ os_mutex_unlock(&exec_env->wait_lock);
+
+ if (thread)
+ *thread = thread_handle;
+
+ return 0;
+
+fail:
+ if (new_module_inst)
+ wasm_runtime_deinstantiate_internal(new_module_inst, true);
+ if (info_node)
+ wasm_runtime_free(info_node);
+ if (routine_args)
+ wasm_runtime_free(routine_args);
+ return ret;
+}
+
+static int32
+pthread_join_wrapper(wasm_exec_env_t exec_env, uint32 thread,
+ int32 retval_offset) /* void **retval */
+{
+ uint32 *ret;
+ int32 join_ret;
+ void **retval;
+ ThreadInfoNode *node;
+ wasm_module_inst_t module_inst;
+ wasm_exec_env_t target_exec_env;
+
+ module_inst = get_module_inst(exec_env);
+
+ /* validate addr, we can use current thread's
+ module instance here as the memory is shared */
+ if (!validate_app_addr(retval_offset, sizeof(int32))) {
+ /* Join failed, but we don't want to terminate all threads,
+ do not spread exception here */
+ wasm_runtime_set_exception(module_inst, NULL);
+ return -1;
+ }
+
+ retval = (void **)addr_app_to_native(retval_offset);
+
+ node = get_thread_info(exec_env, thread);
+ if (!node) {
+ /* The thread has exited and not joinable, return 0 to app */
+ return 0;
+ }
+
+ target_exec_env = node->exec_env;
+ bh_assert(target_exec_env);
+
+ if (node->status != THREAD_EXIT) {
+ /* if the thread is still running, call the platforms join API */
+ join_ret = wasm_cluster_join_thread(target_exec_env, (void **)&ret);
+ }
+ else {
+ /* if the thread has exited, return stored results */
+
+ /* this thread must be joinable, otherwise the
+ info_node should be destroyed once exit */
+ bh_assert(node->joinable);
+ join_ret = 0;
+ ret = node->u.ret;
+ }
+
+ if (retval_offset != 0)
+ *(uint32 *)retval = (uint32)(uintptr_t)ret;
+
+ return join_ret;
+}
+
+static int32
+pthread_detach_wrapper(wasm_exec_env_t exec_env, uint32 thread)
+{
+ ThreadInfoNode *node;
+ wasm_exec_env_t target_exec_env;
+
+ node = get_thread_info(exec_env, thread);
+ if (!node)
+ return 0;
+
+ node->joinable = false;
+
+ target_exec_env = node->exec_env;
+ bh_assert(target_exec_env != NULL);
+
+ return wasm_cluster_detach_thread(target_exec_env);
+}
+
+static int32
+pthread_cancel_wrapper(wasm_exec_env_t exec_env, uint32 thread)
+{
+ ThreadInfoNode *node;
+ wasm_exec_env_t target_exec_env;
+
+ node = get_thread_info(exec_env, thread);
+ if (!node)
+ return 0;
+
+ node->status = THREAD_CANCELLED;
+ node->joinable = false;
+
+ target_exec_env = node->exec_env;
+ bh_assert(target_exec_env != NULL);
+
+ return wasm_cluster_cancel_thread(target_exec_env);
+}
+
+static int32
+pthread_self_wrapper(wasm_exec_env_t exec_env)
+{
+ ThreadRoutineArgs *args = get_thread_arg(exec_env);
+ /* If thread_arg is NULL, it's the exec_env of the main thread,
+ return id 0 to app */
+ if (!args)
+ return 0;
+
+ return args->info_node->handle;
+}
+
+/* emcc use __pthread_self rather than pthread_self */
+static int32
+__pthread_self_wrapper(wasm_exec_env_t exec_env)
+{
+ return pthread_self_wrapper(exec_env);
+}
+
+static void
+pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ ThreadRoutineArgs *args = get_thread_arg(exec_env);
+ /* Currently exit main thread is not allowed */
+ if (!args)
+ return;
+
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && !defined(BH_PLATFORM_WINDOWS)
+ /* If hardware bound check enabled, don't deinstantiate module inst
+ and thread info node here for AoT module, as they will be freed
+ in pthread_start_routine */
+ if (exec_env->jmpbuf_stack_top) {
+ wasm_cluster_exit_thread(exec_env, (void *)(uintptr_t)retval_offset);
+ }
+#endif
+
+ /* destroy pthread key values */
+ call_key_destructor(exec_env);
+
+ /* routine exit, destroy instance */
+ wasm_runtime_deinstantiate_internal(module_inst, true);
+
+ if (!args->info_node->joinable) {
+ delete_thread_info_node(args->info_node);
+ }
+ else {
+ args->info_node->u.ret = (void *)(uintptr_t)retval_offset;
+ /* Update node status after ret value was set */
+ args->info_node->status = THREAD_EXIT;
+ }
+
+ wasm_runtime_free(args);
+
+ wasm_cluster_exit_thread(exec_env, (void *)(uintptr_t)retval_offset);
+}
+
+static int32
+pthread_mutex_init_wrapper(wasm_exec_env_t exec_env, uint32 *mutex, void *attr)
+{
+ korp_mutex *pmutex;
+ ThreadInfoNode *info_node;
+
+ if (!(pmutex = wasm_runtime_malloc(sizeof(korp_mutex)))) {
+ return -1;
+ }
+
+ if (os_mutex_init(pmutex) != 0) {
+ goto fail1;
+ }
+
+ if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode))))
+ goto fail2;
+
+ memset(info_node, 0, sizeof(ThreadInfoNode));
+ info_node->exec_env = exec_env;
+ info_node->handle = allocate_handle();
+ info_node->type = T_MUTEX;
+ info_node->u.mutex = pmutex;
+ info_node->status = MUTEX_CREATED;
+
+ if (!append_thread_info_node(info_node))
+ goto fail3;
+
+ /* Return the mutex handle to app */
+ if (mutex)
+ *(uint32 *)mutex = info_node->handle;
+
+ return 0;
+
+fail3:
+ delete_thread_info_node(info_node);
+fail2:
+ os_mutex_destroy(pmutex);
+fail1:
+ wasm_runtime_free(pmutex);
+
+ return -1;
+}
+
+static int32
+pthread_mutex_lock_wrapper(wasm_exec_env_t exec_env, uint32 *mutex)
+{
+ ThreadInfoNode *info_node = get_thread_info(exec_env, *mutex);
+ if (!info_node || info_node->type != T_MUTEX)
+ return -1;
+
+ return os_mutex_lock(info_node->u.mutex);
+}
+
+static int32
+pthread_mutex_unlock_wrapper(wasm_exec_env_t exec_env, uint32 *mutex)
+{
+ ThreadInfoNode *info_node = get_thread_info(exec_env, *mutex);
+ if (!info_node || info_node->type != T_MUTEX)
+ return -1;
+
+ return os_mutex_unlock(info_node->u.mutex);
+}
+
+static int32
+pthread_mutex_destroy_wrapper(wasm_exec_env_t exec_env, uint32 *mutex)
+{
+ int32 ret_val;
+ ThreadInfoNode *info_node = get_thread_info(exec_env, *mutex);
+ if (!info_node || info_node->type != T_MUTEX)
+ return -1;
+
+ ret_val = os_mutex_destroy(info_node->u.mutex);
+
+ info_node->status = MUTEX_DESTROYED;
+ delete_thread_info_node(info_node);
+
+ return ret_val;
+}
+
+static int32
+pthread_cond_init_wrapper(wasm_exec_env_t exec_env, uint32 *cond, void *attr)
+{
+ korp_cond *pcond;
+ ThreadInfoNode *info_node;
+
+ if (!(pcond = wasm_runtime_malloc(sizeof(korp_cond)))) {
+ return -1;
+ }
+
+ if (os_cond_init(pcond) != 0) {
+ goto fail1;
+ }
+
+ if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode))))
+ goto fail2;
+
+ memset(info_node, 0, sizeof(ThreadInfoNode));
+ info_node->exec_env = exec_env;
+ info_node->handle = allocate_handle();
+ info_node->type = T_COND;
+ info_node->u.cond = pcond;
+ info_node->status = COND_CREATED;
+
+ if (!append_thread_info_node(info_node))
+ goto fail3;
+
+ /* Return the cond handle to app */
+ if (cond)
+ *(uint32 *)cond = info_node->handle;
+
+ return 0;
+
+fail3:
+ delete_thread_info_node(info_node);
+fail2:
+ os_cond_destroy(pcond);
+fail1:
+ wasm_runtime_free(pcond);
+
+ return -1;
+}
+
+static int32
+pthread_cond_wait_wrapper(wasm_exec_env_t exec_env, uint32 *cond, uint32 *mutex)
+{
+ ThreadInfoNode *cond_info_node, *mutex_info_node;
+
+ cond_info_node = get_thread_info(exec_env, *cond);
+ if (!cond_info_node || cond_info_node->type != T_COND)
+ return -1;
+
+ mutex_info_node = get_thread_info(exec_env, *mutex);
+ if (!mutex_info_node || mutex_info_node->type != T_MUTEX)
+ return -1;
+
+ return os_cond_wait(cond_info_node->u.cond, mutex_info_node->u.mutex);
+}
+
+/**
+ * Currently we don't support struct timespec in built-in libc,
+ * so the pthread_cond_timedwait use useconds instead
+ */
+static int32
+pthread_cond_timedwait_wrapper(wasm_exec_env_t exec_env, uint32 *cond,
+ uint32 *mutex, uint64 useconds)
+{
+ ThreadInfoNode *cond_info_node, *mutex_info_node;
+
+ cond_info_node = get_thread_info(exec_env, *cond);
+ if (!cond_info_node || cond_info_node->type != T_COND)
+ return -1;
+
+ mutex_info_node = get_thread_info(exec_env, *mutex);
+ if (!mutex_info_node || mutex_info_node->type != T_MUTEX)
+ return -1;
+
+ return os_cond_reltimedwait(cond_info_node->u.cond,
+ mutex_info_node->u.mutex, useconds);
+}
+
+static int32
+pthread_cond_signal_wrapper(wasm_exec_env_t exec_env, uint32 *cond)
+{
+ ThreadInfoNode *info_node = get_thread_info(exec_env, *cond);
+ if (!info_node || info_node->type != T_COND)
+ return -1;
+
+ return os_cond_signal(info_node->u.cond);
+}
+
+static int32
+pthread_cond_broadcast_wrapper(wasm_exec_env_t exec_env, uint32 *cond)
+{
+ ThreadInfoNode *info_node = get_thread_info(exec_env, *cond);
+ if (!info_node || info_node->type != T_COND)
+ return -1;
+
+ return os_cond_broadcast(info_node->u.cond);
+}
+
+static int32
+pthread_cond_destroy_wrapper(wasm_exec_env_t exec_env, uint32 *cond)
+{
+ int32 ret_val;
+ ThreadInfoNode *info_node = get_thread_info(exec_env, *cond);
+ if (!info_node || info_node->type != T_COND)
+ return -1;
+
+ ret_val = os_cond_destroy(info_node->u.cond);
+
+ info_node->status = COND_DESTROYED;
+ delete_thread_info_node(info_node);
+
+ return ret_val;
+}
+
+static int32
+pthread_key_create_wrapper(wasm_exec_env_t exec_env, int32 *key,
+ int32 destructor_elem_index)
+{
+ uint32 i;
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ ClusterInfoNode *info = get_cluster_info(cluster);
+
+ if (!info) {
+ /* The user may call pthread_key_create in main thread,
+ in this case the cluster info hasn't been created */
+ if (!(info = create_cluster_info(cluster))) {
+ return -1;
+ }
+ }
+
+ os_mutex_lock(&info->key_data_list_lock);
+ for (i = 0; i < WAMR_PTHREAD_KEYS_MAX; i++) {
+ if (!info->key_data_list[i].is_created) {
+ break;
+ }
+ }
+
+ if (i == WAMR_PTHREAD_KEYS_MAX) {
+ os_mutex_unlock(&info->key_data_list_lock);
+ return -1;
+ }
+
+ info->key_data_list[i].destructor_func = destructor_elem_index;
+ info->key_data_list[i].is_created = true;
+ *key = i;
+ os_mutex_unlock(&info->key_data_list_lock);
+
+ return 0;
+}
+
+static int32
+pthread_setspecific_wrapper(wasm_exec_env_t exec_env, int32 key,
+ int32 value_offset)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ ClusterInfoNode *info = get_cluster_info(cluster);
+ int32 *key_values;
+
+ if (!info)
+ return -1;
+
+ os_mutex_lock(&info->key_data_list_lock);
+
+ key_values = key_value_list_lookup_or_create(exec_env, info, key);
+ if (!key_values) {
+ os_mutex_unlock(&info->key_data_list_lock);
+ return -1;
+ }
+
+ key_values[key] = value_offset;
+ os_mutex_unlock(&info->key_data_list_lock);
+
+ return 0;
+}
+
+static int32
+pthread_getspecific_wrapper(wasm_exec_env_t exec_env, int32 key)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ ClusterInfoNode *info = get_cluster_info(cluster);
+ int32 ret, *key_values;
+
+ if (!info)
+ return 0;
+
+ os_mutex_lock(&info->key_data_list_lock);
+
+ key_values = key_value_list_lookup_or_create(exec_env, info, key);
+ if (!key_values) {
+ os_mutex_unlock(&info->key_data_list_lock);
+ return 0;
+ }
+
+ ret = key_values[key];
+ os_mutex_unlock(&info->key_data_list_lock);
+
+ return ret;
+}
+
+static int32
+pthread_key_delete_wrapper(wasm_exec_env_t exec_env, int32 key)
+{
+ KeyData *data;
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ ClusterInfoNode *info = get_cluster_info(cluster);
+
+ if (!info)
+ return -1;
+
+ os_mutex_lock(&info->key_data_list_lock);
+ data = key_data_list_lookup(exec_env, key);
+ if (!data) {
+ os_mutex_unlock(&info->key_data_list_lock);
+ return -1;
+ }
+
+ memset(data, 0, sizeof(KeyData));
+ os_mutex_unlock(&info->key_data_list_lock);
+
+ return 0;
+}
+
+/**
+ * Currently the memory allocator doesn't support alloc specific aligned
+ * space, we wrap posix_memalign to simply malloc memory
+ */
+static int32
+posix_memalign_wrapper(wasm_exec_env_t exec_env, void **memptr, int32 align,
+ int32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ void *p = NULL;
+
+ *((int32 *)memptr) = module_malloc(size, (void **)&p);
+ if (!p)
+ return -1;
+
+ return 0;
+}
+
+#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
+
+static int32
+sem_open_wrapper(wasm_exec_env_t exec_env, const char *name, int32 oflags,
+ int32 mode, int32 val)
+{
+ korp_sem *psem = NULL;
+ ThreadInfoNode *info_node = NULL;
+
+ /**
+ * For RTOS, global semaphore map is safe for share the same semaphore
+ * between task/pthread.
+ * For Unix like system, it's dedicated for multiple processes.
+ */
+
+ if ((info_node = bh_hash_map_find(sem_info_map, (void *)name))) {
+ return info_node->handle;
+ }
+
+ if (!(psem = os_sem_open(name, oflags, mode, val))) {
+ goto fail1;
+ }
+
+ if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode))))
+ goto fail2;
+
+ memset(info_node, 0, sizeof(ThreadInfoNode));
+ info_node->exec_env = exec_env;
+ info_node->handle = allocate_handle();
+ info_node->type = T_SEM;
+ info_node->u.sem = psem;
+ info_node->status = SEM_CREATED;
+
+ if (!bh_hash_map_insert(sem_info_map, (void *)name, info_node))
+ goto fail3;
+
+ return info_node->handle;
+
+fail3:
+ wasm_runtime_free(info_node);
+fail2:
+ os_sem_close(psem);
+fail1:
+ return -1;
+}
+
+void
+sem_fetch_cb(void *key, void *value, void *user_data)
+{
+ (void)key;
+ SemCallbackArgs *args = user_data;
+ ThreadInfoNode *info_node = value;
+ if (args->handle == info_node->handle && info_node->status == SEM_CREATED) {
+ args->node = info_node;
+ }
+}
+
+static int32
+sem_close_wrapper(wasm_exec_env_t exec_env, uint32 sem)
+{
+ (void)exec_env;
+ int ret = -1;
+ SemCallbackArgs args = { sem, NULL };
+
+ bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
+
+ if (args.node) {
+ ret = os_sem_close(args.node->u.sem);
+ if (ret == 0) {
+ args.node->status = SEM_CLOSED;
+ }
+ }
+
+ return ret;
+}
+
+static int32
+sem_wait_wrapper(wasm_exec_env_t exec_env, uint32 sem)
+{
+ (void)exec_env;
+ SemCallbackArgs args = { sem, NULL };
+
+ bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
+
+ if (args.node) {
+ return os_sem_wait(args.node->u.sem);
+ }
+
+ return -1;
+}
+
+static int32
+sem_trywait_wrapper(wasm_exec_env_t exec_env, uint32 sem)
+{
+ (void)exec_env;
+ SemCallbackArgs args = { sem, NULL };
+
+ bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
+
+ if (args.node) {
+ return os_sem_trywait(args.node->u.sem);
+ }
+
+ return -1;
+}
+
+static int32
+sem_post_wrapper(wasm_exec_env_t exec_env, uint32 sem)
+{
+ (void)exec_env;
+ SemCallbackArgs args = { sem, NULL };
+
+ bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
+
+ if (args.node) {
+ return os_sem_post(args.node->u.sem);
+ }
+
+ return -1;
+}
+
+static int32
+sem_getvalue_wrapper(wasm_exec_env_t exec_env, uint32 sem, int32 *sval)
+{
+ int32 ret = -1;
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ (void)exec_env;
+ SemCallbackArgs args = { sem, NULL };
+
+ if (validate_native_addr(sval, sizeof(int32))) {
+
+ bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
+
+ if (args.node) {
+ ret = os_sem_getvalue(args.node->u.sem, sval);
+ }
+ }
+ return ret;
+}
+
+static int32
+sem_unlink_wrapper(wasm_exec_env_t exec_env, const char *name)
+{
+ (void)exec_env;
+ int32 ret_val;
+
+ ThreadInfoNode *info_node = bh_hash_map_find(sem_info_map, (void *)name);
+ if (!info_node || info_node->type != T_SEM)
+ return -1;
+
+ if (info_node->status != SEM_CLOSED) {
+ ret_val = os_sem_close(info_node->u.sem);
+ if (ret_val != 0) {
+ return ret_val;
+ }
+ }
+
+ ret_val = os_sem_unlink(name);
+
+ if (ret_val == 0) {
+ bh_hash_map_remove(sem_info_map, (void *)name, NULL, NULL);
+ info_node->status = SEM_DESTROYED;
+ thread_info_destroy(info_node);
+ }
+ return ret_val;
+}
+
+#endif
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, func_name##_wrapper, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_lib_pthread[] = {
+ REG_NATIVE_FUNC(pthread_create, "(**ii)i"),
+ REG_NATIVE_FUNC(pthread_join, "(ii)i"),
+ REG_NATIVE_FUNC(pthread_detach, "(i)i"),
+ REG_NATIVE_FUNC(pthread_cancel, "(i)i"),
+ REG_NATIVE_FUNC(pthread_self, "()i"),
+ REG_NATIVE_FUNC(__pthread_self, "()i"),
+ REG_NATIVE_FUNC(pthread_exit, "(i)"),
+ REG_NATIVE_FUNC(pthread_mutex_init, "(**)i"),
+ REG_NATIVE_FUNC(pthread_mutex_lock, "(*)i"),
+ REG_NATIVE_FUNC(pthread_mutex_unlock, "(*)i"),
+ REG_NATIVE_FUNC(pthread_mutex_destroy, "(*)i"),
+ REG_NATIVE_FUNC(pthread_cond_init, "(**)i"),
+ REG_NATIVE_FUNC(pthread_cond_wait, "(**)i"),
+ REG_NATIVE_FUNC(pthread_cond_timedwait, "(**I)i"),
+ REG_NATIVE_FUNC(pthread_cond_signal, "(*)i"),
+ REG_NATIVE_FUNC(pthread_cond_broadcast, "(*)i"),
+ REG_NATIVE_FUNC(pthread_cond_destroy, "(*)i"),
+ REG_NATIVE_FUNC(pthread_key_create, "(*i)i"),
+ REG_NATIVE_FUNC(pthread_setspecific, "(ii)i"),
+ REG_NATIVE_FUNC(pthread_getspecific, "(i)i"),
+ REG_NATIVE_FUNC(pthread_key_delete, "(i)i"),
+ REG_NATIVE_FUNC(posix_memalign, "(*ii)i"),
+#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
+ REG_NATIVE_FUNC(sem_open, "($iii)i"),
+ REG_NATIVE_FUNC(sem_close, "(i)i"),
+ REG_NATIVE_FUNC(sem_wait, "(i)i"),
+ REG_NATIVE_FUNC(sem_trywait, "(i)i"),
+ REG_NATIVE_FUNC(sem_post, "(i)i"),
+ REG_NATIVE_FUNC(sem_getvalue, "(i*)i"),
+ REG_NATIVE_FUNC(sem_unlink, "($)i"),
+#endif
+};
+
+uint32
+get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis)
+{
+ *p_lib_pthread_apis = native_symbols_lib_pthread;
+ return sizeof(native_symbols_lib_pthread) / sizeof(NativeSymbol);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats.cmake
new file mode 100644
index 000000000..b773c837e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats.cmake
@@ -0,0 +1,43 @@
+# Copyright (c) 2022 Intel Corporation
+# Copyright (c) 2020-2021 Alibaba Cloud
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (LIB_RATS_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+if ("$ENV{SGX_SSL_DIR}" STREQUAL "")
+ set (SGX_SSL_DIR "/opt/intel/sgxssl")
+else()
+ set (SGX_SSL_DIR $ENV{SGX_SSL_DIR})
+endif()
+
+if (NOT EXISTS ${SGX_SSL_DIR})
+ message(FATAL_ERROR "Can not find SGX_SSL, please install it first")
+endif()
+
+add_definitions (-DWASM_ENABLE_LIB_RATS=1)
+
+include_directories(${LIB_RATS_DIR} ${SGX_SSL_DIR}/include)
+
+include(FetchContent)
+
+set(RATS_BUILD_MODE "sgx"
+ CACHE INTERNAL "Select build mode for librats(host|occlum|sgx|wasm)")
+set(RATS_INSTALL_PATH "${CMAKE_BINARY_DIR}/librats" CACHE INTERNAL "")
+
+FetchContent_Declare(
+ librats
+ GIT_REPOSITORY https://github.com/inclavare-containers/librats
+ GIT_TAG master
+)
+FetchContent_GetProperties(librats)
+if (NOT librats_POPULATED)
+ message("-- Fetching librats ..")
+ FetchContent_Populate(librats)
+ include_directories("${librats_SOURCE_DIR}/include")
+ add_subdirectory(${librats_SOURCE_DIR} ${librats_BINARY_DIR} EXCLUDE_FROM_ALL)
+
+endif()
+
+file (GLOB source_all ${LIB_RATS_DIR}/*.c)
+
+set (LIB_RATS_SOURCE ${source_all}) \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_common.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_common.h
new file mode 100644
index 000000000..929e105f0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_common.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022 Intel Corporation
+ * Copyright (c) 2020-2021 Alibaba Cloud
+ *
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _RATS_WAMR_COMMON_H
+#define _RATS_WAMR_COMMON_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SGX_QUOTE_MAX_SIZE 8192
+#define SGX_USER_DATA_SIZE 64
+#define SGX_MEASUREMENT_SIZE 32
+
+/* clang-format off */
+typedef struct rats_sgx_evidence {
+ uint8_t quote[SGX_QUOTE_MAX_SIZE]; /* The quote of the Enclave */
+ uint32_t quote_size; /* The size of the quote */
+ uint8_t user_data[SGX_USER_DATA_SIZE]; /* The custom data in the quote */
+ uint32_t product_id; /* Product ID of the Enclave */
+ uint8_t mr_enclave[SGX_MEASUREMENT_SIZE]; /* The MRENCLAVE of the Enclave */
+ uint32_t security_version; /* Security Version of the Enclave */
+ uint8_t mr_signer[SGX_MEASUREMENT_SIZE]; /* The MRSIGNER of the Enclave */
+ uint64_t att_flags; /* Flags of the Enclave in attributes */
+ uint64_t att_xfrm; /* XSAVE Feature Request Mask */
+} rats_sgx_evidence_t;
+/* clang-format on */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.c
new file mode 100644
index 000000000..59d61f4c8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2022 Intel Corporation
+ * Copyright (c) 2020-2021 Alibaba Cloud
+ *
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <librats/api.h>
+#include <string.h>
+#include <openssl/sha.h>
+
+#include "sgx_quote_3.h"
+#include "wasm_export.h"
+#include "bh_common.h"
+#include "lib_rats_common.h"
+
+static int
+librats_collect_wrapper(wasm_exec_env_t exec_env, char **evidence_json,
+ const char *buffer, uint32_t buffer_size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasm_module_t module = wasm_runtime_get_module(module_inst);
+ char *wasm_module_hash = wasm_runtime_get_module_hash(module);
+
+ char *json, *str_ret;
+ uint32_t str_ret_offset;
+ uint8_t final_hash[SHA256_DIGEST_LENGTH];
+
+ SHA256_CTX sha256;
+ SHA256_Init(&sha256);
+ SHA256_Update(&sha256, wasm_module_hash, SHA256_DIGEST_LENGTH);
+ if (buffer != NULL)
+ SHA256_Update(&sha256, buffer, buffer_size);
+ SHA256_Final(final_hash, &sha256);
+
+ int ret_code = librats_collect_evidence_to_json(final_hash, &json);
+ if (ret_code != 0) {
+ return ret_code;
+ }
+
+ uint32_t json_size = strlen(json) + 1;
+ str_ret_offset = module_malloc(json_size, (void **)&str_ret);
+ if (!str_ret_offset) {
+ free(json);
+ return (int)RATS_ATTESTER_ERR_NO_MEM;
+ }
+ bh_memcpy_s(str_ret, json_size, json, json_size);
+ *((int *)evidence_json) = str_ret_offset;
+ free(json);
+
+ return 0;
+}
+
+static int
+librats_verify_wrapper(wasm_exec_env_t exec_env, const char *evidence_json,
+ uint32_t evidence_size, const uint8_t *hash,
+ uint32_t hash_size)
+{
+ return librats_verify_evidence_from_json(evidence_json, hash);
+}
+
+static int
+librats_parse_evidence_wrapper(wasm_exec_env_t exec_env,
+ const char *evidence_json, uint32_t json_size,
+ rats_sgx_evidence_t *evidence,
+ uint32_t evidence_size)
+{
+ attestation_evidence_t att_ev;
+
+ if (get_evidence_from_json(evidence_json, &att_ev) != 0) {
+ return -1;
+ }
+
+ // Only supports parsing sgx evidence currently
+ if (strcmp(att_ev.type, "sgx_ecdsa") != 0) {
+ return -1;
+ }
+
+ sgx_quote3_t *quote_ptr = (sgx_quote3_t *)att_ev.ecdsa.quote;
+ bh_memcpy_s(evidence->quote, att_ev.ecdsa.quote_len, att_ev.ecdsa.quote,
+ att_ev.ecdsa.quote_len);
+ evidence->quote_size = att_ev.ecdsa.quote_len;
+ bh_memcpy_s(evidence->user_data, SGX_REPORT_DATA_SIZE,
+ quote_ptr->report_body.report_data.d, SGX_REPORT_DATA_SIZE);
+ bh_memcpy_s(evidence->mr_enclave, sizeof(sgx_measurement_t),
+ quote_ptr->report_body.mr_enclave.m, sizeof(sgx_measurement_t));
+ bh_memcpy_s(evidence->mr_signer, sizeof(sgx_measurement_t),
+ quote_ptr->report_body.mr_signer.m, sizeof(sgx_measurement_t));
+ evidence->product_id = quote_ptr->report_body.isv_prod_id;
+ evidence->security_version = quote_ptr->report_body.isv_svn;
+ evidence->att_flags = quote_ptr->report_body.attributes.flags;
+ evidence->att_xfrm = quote_ptr->report_body.attributes.flags;
+
+ return 0;
+}
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, func_name##_wrapper, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_lib_rats[] = {
+ REG_NATIVE_FUNC(librats_collect, "(**~)i"),
+ REG_NATIVE_FUNC(librats_verify, "(*~*~)i"),
+ REG_NATIVE_FUNC(librats_parse_evidence, "(*~*~)i")
+};
+
+uint32_t
+get_lib_rats_export_apis(NativeSymbol **p_lib_rats_apis)
+{
+ *p_lib_rats_apis = native_symbols_lib_rats;
+ return sizeof(native_symbols_lib_rats) / sizeof(NativeSymbol);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.h
new file mode 100644
index 000000000..e334983e9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-rats/lib_rats_wrapper.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2022 Intel Corporation
+ * Copyright (c) 2020-2021 Alibaba Cloud
+ *
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _RATS_WAMR_API_H
+#define _RATS_WAMR_API_H
+
+#include <stdint.h>
+#include <string.h>
+
+#include "lib_rats_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int
+librats_collect(char **evidence_json, const char *buffer, uint32_t buffer_size);
+
+int
+librats_verify(const char *evidence_json, uint32_t evidence_size,
+ const uint8_t *hash, uint32_t hash_size);
+
+int
+librats_parse_evidence(const char *evidence_json, uint32_t json_size,
+ rats_sgx_evidence_t *evidence, uint32_t evidence_size);
+
+#define librats_collect(evidence_json, buffer) \
+ librats_collect(evidence_json, buffer, buffer ? strlen(buffer) + 1 : 0)
+
+#define librats_verify(evidence_json, hash) \
+ librats_verify(evidence_json, \
+ evidence_json ? strlen(evidence_json) + 1 : 0, hash, \
+ hash ? strlen((const char *)hash) + 1 : 0)
+
+#define librats_parse_evidence(evidence_json, evidence) \
+ librats_parse_evidence(evidence_json, \
+ evidence_json ? strlen(evidence_json) + 1 : 0, \
+ evidence, sizeof(rats_sgx_evidence_t))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h
new file mode 100644
index 000000000..c9a07eb72
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/inc/wasi_socket_ext.h
@@ -0,0 +1,999 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _WASI_SOCKET_EXT_H_
+#define _WASI_SOCKET_EXT_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/*Be a part of <wasi/api.h>*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ SOCKET_DGRAM = 0,
+ SOCKET_STREAM,
+} __wasi_sock_type_t;
+
+typedef uint16_t __wasi_ip_port_t;
+
+typedef enum { IPv4 = 0, IPv6 } __wasi_addr_type_t;
+
+/*
+ n0.n1.n2.n3
+ Example:
+ IP Address: 127.0.0.1
+ Structure: {n0: 127, n1: 0, n2: 0, n3: 1}
+*/
+typedef struct __wasi_addr_ip4_t {
+ uint8_t n0;
+ uint8_t n1;
+ uint8_t n2;
+ uint8_t n3;
+} __wasi_addr_ip4_t;
+
+typedef struct __wasi_addr_ip4_port_t {
+ __wasi_addr_ip4_t addr;
+ __wasi_ip_port_t port; /* host byte order */
+} __wasi_addr_ip4_port_t;
+
+/*
+ n0:n1:n2:n3:h0:h1:h2:h3, each 16bit value uses host byte order
+ Example (little-endian system)
+ IP Address fe80::3ba2:893b:4be0:e3dd
+ Structure: {
+ n0: 0xfe80, n1:0x0, n2: 0x0, n3: 0x0,
+ h0: 0x3ba2, h1: 0x893b, h2: 0x4be0, h3: 0xe3dd
+ }
+*/
+typedef struct __wasi_addr_ip6_t {
+ uint16_t n0;
+ uint16_t n1;
+ uint16_t n2;
+ uint16_t n3;
+ uint16_t h0;
+ uint16_t h1;
+ uint16_t h2;
+ uint16_t h3;
+} __wasi_addr_ip6_t;
+
+typedef struct __wasi_addr_ip6_port_t {
+ __wasi_addr_ip6_t addr;
+ __wasi_ip_port_t port; /* host byte order */
+} __wasi_addr_ip6_port_t;
+
+typedef struct __wasi_addr_ip_t {
+ __wasi_addr_type_t kind;
+ union {
+ __wasi_addr_ip4_t ip4;
+ __wasi_addr_ip6_t ip6;
+ } addr;
+} __wasi_addr_ip_t;
+
+typedef struct __wasi_addr_t {
+ __wasi_addr_type_t kind;
+ union {
+ __wasi_addr_ip4_port_t ip4;
+ __wasi_addr_ip6_port_t ip6;
+ } addr;
+} __wasi_addr_t;
+
+typedef enum { INET4 = 0, INET6 } __wasi_address_family_t;
+
+typedef struct __wasi_addr_info_t {
+ __wasi_addr_t addr;
+ __wasi_sock_type_t type;
+} __wasi_addr_info_t;
+
+typedef struct __wasi_addr_info_hints_t {
+ __wasi_sock_type_t type;
+ __wasi_address_family_t family;
+ // this is to workaround lack of optional parameters
+ uint8_t hints_enabled;
+} __wasi_addr_info_hints_t;
+
+#ifdef __wasi__
+/**
+ * Reimplement below POSIX APIs with __wasi_sock_XXX functions.
+ *
+ * Keep sync with
+ * <sys/socket.h>
+ * <sys/types.h>
+ */
+#define SO_REUSEADDR 2
+#define SO_BROADCAST 6
+#define SO_SNDBUF 7
+#define SO_RCVBUF 8
+#define SO_KEEPALIVE 9
+#define SO_LINGER 13
+#define SO_REUSEPORT 15
+#define SO_RCVTIMEO 20
+#define SO_SNDTIMEO 21
+
+#define TCP_NODELAY 1
+#define TCP_KEEPIDLE 4
+#define TCP_KEEPINTVL 5
+#define TCP_QUICKACK 12
+#define TCP_FASTOPEN_CONNECT 30
+
+#define IP_TTL 2
+#define IP_MULTICAST_TTL 33
+#define IP_MULTICAST_LOOP 34
+#define IP_ADD_MEMBERSHIP 35
+#define IP_DROP_MEMBERSHIP 36
+
+#define IPV6_MULTICAST_LOOP 19
+#define IPV6_JOIN_GROUP 20
+#define IPV6_LEAVE_GROUP 21
+#define IPV6_V6ONLY 26
+
+struct addrinfo {
+ int ai_flags; /* Input flags. */
+ int ai_family; /* Protocol family for socket. */
+ int ai_socktype; /* Socket type. */
+ int ai_protocol; /* Protocol for socket. */
+ socklen_t ai_addrlen; /* Length of socket address. */
+ struct sockaddr *ai_addr; /* Socket address for socket. */
+ char *ai_canonname; /* Canonical name for service location. */
+ struct addrinfo *ai_next; /* Pointer to next in list. */
+};
+
+#ifndef __WASI_RIGHTS_SOCK_ACCEPT
+int
+accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+#endif
+
+int
+bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+
+int
+connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+
+int
+listen(int sockfd, int backlog);
+
+ssize_t
+recvmsg(int sockfd, struct msghdr *msg, int flags);
+
+ssize_t
+sendmsg(int sockfd, const struct msghdr *msg, int flags);
+
+ssize_t
+sendto(int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, socklen_t addrlen);
+
+ssize_t
+recvfrom(int sockfd, void *buf, size_t len, int flags,
+ struct sockaddr *src_addr, socklen_t *addrlen);
+
+int
+socket(int domain, int type, int protocol);
+
+int
+getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
+int
+getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
+int
+getsockopt(int sockfd, int level, int optname, void *__restrict optval,
+ socklen_t *__restrict optlen);
+
+int
+setsockopt(int sockfd, int level, int optname, const void *optval,
+ socklen_t optlen);
+
+int
+getaddrinfo(const char *node, const char *service, const struct addrinfo *hints,
+ struct addrinfo **res);
+
+void
+freeaddrinfo(struct addrinfo *res);
+#endif
+
+/**
+ * __wasi_sock_accept was introduced in wasi-sdk v15. To
+ * temporarily maintain backward compatibility with the old
+ * wasi-sdk, we explicitly add that implementation here so it works
+ * with older versions of the SDK.
+ */
+#ifndef __WASI_RIGHTS_SOCK_ACCEPT
+/**
+ * Accept a connection on a socket
+ * Note: This is similar to `accept`
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_accept(int32_t arg0, int32_t arg1,
+ int32_t arg2)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_accept")));
+
+static inline __wasi_errno_t
+__wasi_sock_accept(__wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_accept(
+ (int32_t)fd, (int32_t)flags, (int32_t)fd_new);
+}
+#endif
+
+/**
+ * Returns the local address to which the socket is bound.
+ *
+ * Note: This is similar to `getsockname` in POSIX
+ *
+ * When successful, the contents of the output buffer consist of an IP address,
+ * either IP4 or IP6.
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_addr_local(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_addr_local")));
+
+static inline __wasi_errno_t
+__wasi_sock_addr_local(__wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_local(
+ (int32_t)fd, (int32_t)addr);
+}
+
+/**
+ * Returns the remote address to which the socket is connected to.
+ *
+ * Note: This is similar to `getpeername` in POSIX
+ *
+ * When successful, the contents of the output buffer consist of an IP address,
+ * either IP4 or IP6.
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_addr_remote(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_addr_remote")));
+
+static inline __wasi_errno_t
+__wasi_sock_addr_remote(__wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_remote(
+ (int32_t)fd, (int32_t)addr);
+}
+
+/**
+ * Resolve a hostname and a service to one or more IP addresses. Service is
+ * optional and you can pass empty string in most cases, it is used as a hint
+ * for protocol.
+ *
+ * Note: This is similar to `getaddrinfo` in POSIX
+ *
+ * When successful, the contents of the output buffer consist of a sequence of
+ * IPv4 and/or IPv6 addresses. Each address entry consists of a wasi_addr_t
+ * object.
+ *
+ * This function fills the output buffer as much as possible, truncating the
+ * entries that didn't fit into the buffer. A number of available addresses
+ * will be returned through the last parameter.
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_addr_resolve(int32_t arg0, int32_t arg1,
+ int32_t arg2, int32_t arg3,
+ int32_t arg4, int32_t arg5)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_addr_resolve")));
+
+static inline __wasi_errno_t
+__wasi_sock_addr_resolve(const char *host, const char *service,
+ __wasi_addr_info_hints_t *hints,
+ __wasi_addr_info_t *addr_info,
+ __wasi_size_t addr_info_size,
+ __wasi_size_t *max_info_size)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_addr_resolve(
+ (int32_t)host, (int32_t)service, (int32_t)hints, (int32_t)addr_info,
+ (int32_t)addr_info_size, (int32_t)max_info_size);
+}
+
+/**
+ * Bind a socket
+ * Note: This is similar to `bind` in POSIX using PF_INET
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_bind(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_bind")));
+
+static inline __wasi_errno_t
+__wasi_sock_bind(__wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_bind(
+ (int32_t)fd, (int32_t)addr);
+}
+
+/**
+ * Send data to a specific target
+ * Note: This is similar to `sendto` in POSIX
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_send_to(int32_t arg0, int32_t arg1,
+ int32_t arg2, int32_t arg3,
+ int32_t arg4, int32_t arg5)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_send_to")));
+
+static inline __wasi_errno_t
+__wasi_sock_send_to(__wasi_fd_t fd, const __wasi_ciovec_t *si_data,
+ uint32_t si_data_len, __wasi_siflags_t si_flags,
+ const __wasi_addr_t *dest_addr, uint32_t *so_data_len)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_send_to(
+ (int32_t)fd, (int32_t)si_data, (int32_t)si_data_len, (int32_t)si_flags,
+ (uint32_t)dest_addr, (uint32_t)so_data_len);
+}
+
+/**
+ * Receives data from a socket
+ * Note: This is similar to `recvfrom` in POSIX
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_recv_from(int32_t arg0, int32_t arg1,
+ int32_t arg2, int32_t arg3,
+ int32_t arg4, int32_t arg5)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_recv_from")));
+
+static inline __wasi_errno_t
+__wasi_sock_recv_from(__wasi_fd_t fd, __wasi_ciovec_t *ri_data,
+ uint32_t ri_data_len, __wasi_riflags_t ri_flags,
+ __wasi_addr_t *src_addr, uint32_t *ro_data_len)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_recv_from(
+ (int32_t)fd, (int32_t)ri_data, (int32_t)ri_data_len, (int32_t)ri_flags,
+ (uint32_t)src_addr, (uint32_t)ro_data_len);
+}
+
+/**
+ * Close a socket (this is an alias for `fd_close`)
+ * Note: This is similar to `close` in POSIX.
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_close(int32_t arg0)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_close")));
+
+static inline __wasi_errno_t
+__wasi_sock_close(__wasi_fd_t fd)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_close(
+ (int32_t)fd);
+}
+
+/**
+ * Initiate a connection on a socket to the specified address
+ * Note: This is similar to `connect` in POSIX
+ */
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_connect(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_connect")));
+
+static inline __wasi_errno_t
+__wasi_sock_connect(__wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_connect(
+ (int32_t)fd, (int32_t)addr);
+}
+/**
+ * Retrieve the size of the receive buffer
+ * Note: This is similar to `getsockopt` in POSIX for SO_RCVBUF
+ */
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_recv_buf_size(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_recv_buf_size")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_recv_buf_size(__wasi_fd_t fd, __wasi_size_t *size)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_recv_buf_size((int32_t)fd,
+ (int32_t)size);
+}
+/**
+ * Retrieve status of address reuse on a socket
+ * Note: This is similar to `getsockopt` in POSIX for SO_REUSEADDR
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_reuse_addr(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_reuse_addr")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_reuse_addr(__wasi_fd_t fd, bool *reuse)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_reuse_addr((int32_t)fd,
+ (int32_t)reuse);
+}
+
+/**
+ * Retrieve status of port reuse on a socket
+ * Note: This is similar to `getsockopt` in POSIX for SO_REUSEPORT
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_reuse_port(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_reuse_port")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_reuse_port(__wasi_fd_t fd, bool *reuse)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_reuse_port((int32_t)fd,
+ (int32_t)reuse);
+}
+
+/**
+ * Retrieve the size of the send buffer
+ * Note: This is similar to `getsockopt` in POSIX for SO_SNDBUF
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_send_buf_size(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_send_buf_size")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_send_buf_size(__wasi_fd_t fd, __wasi_size_t *size)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_send_buf_size((int32_t)fd,
+ (int32_t)size);
+}
+
+/**
+ * Listen for connections on a socket
+ * Note: This is similar to `listen`
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_listen(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_listen")));
+
+static inline __wasi_errno_t
+__wasi_sock_listen(__wasi_fd_t fd, __wasi_size_t backlog)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_listen(
+ (int32_t)fd, (int32_t)backlog);
+}
+
+/**
+ * Open a socket
+
+ * The first argument to this function is a handle to an
+ * address pool. The address pool determines what actions can
+ * be performed and at which addresses they can be performed to.
+
+ * The address pool cannot be re-assigned. You will need to close
+ * the socket and open a new one to use a different address pool.
+
+ * Note: This is similar to `socket` in POSIX using PF_INET
+ */
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_open(int32_t arg0, int32_t arg1,
+ int32_t arg2, int32_t arg3)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_open")));
+
+static inline __wasi_errno_t
+__wasi_sock_open(__wasi_fd_t fd, __wasi_address_family_t af,
+ __wasi_sock_type_t socktype, __wasi_fd_t *sockfd)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_open(
+ (int32_t)fd, (int32_t)af, (int32_t)socktype, (int32_t)sockfd);
+}
+
+/**
+ * Set size of receive buffer
+ * Note: This is similar to `setsockopt` in POSIX for SO_RCVBUF
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_recv_buf_size(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_recv_buf_size")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_recv_buf_size(__wasi_fd_t fd, __wasi_size_t size)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_recv_buf_size((int32_t)fd,
+ (int32_t)size);
+}
+
+/**
+ * Enable/disable address reuse on a socket
+ * Note: This is similar to `setsockopt` in POSIX for SO_REUSEADDR
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_reuse_addr(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_reuse_addr")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_reuse_addr(__wasi_fd_t fd, bool reuse)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_reuse_addr((int32_t)fd,
+ (int32_t)reuse);
+}
+
+/**
+ * Enable port reuse on a socket
+ * Note: This is similar to `setsockopt` in POSIX for SO_REUSEPORT
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_reuse_port(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_reuse_port")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_reuse_port(__wasi_fd_t fd, bool reuse)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_reuse_port((int32_t)fd,
+ (int32_t)reuse);
+}
+
+/**
+ * Set size of send buffer
+ * Note: This is similar to `setsockopt` in POSIX for SO_SNDBUF
+ */
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_send_buf_size(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_send_buf_size")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_send_buf_size(__wasi_fd_t fd, __wasi_size_t buf_len)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_send_buf_size(
+ (int32_t)fd, (int32_t)buf_len);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_recv_timeout(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_recv_timeout")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_recv_timeout(__wasi_fd_t fd, uint64_t *timeout_us)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_recv_timeout(
+ (int32_t)fd, (int32_t)timeout_us);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_recv_timeout(int32_t arg0,
+ int64_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_recv_timeout")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_recv_timeout(__wasi_fd_t fd, uint64_t timeout_us)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_recv_timeout(
+ (int32_t)fd, (int64_t)timeout_us);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_send_timeout(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_send_timeout")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_send_timeout(__wasi_fd_t fd, uint64_t *timeout_us)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_send_timeout(
+ (int32_t)fd, (int32_t)timeout_us);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_send_timeout(int32_t arg0,
+ int64_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_send_timeout")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_send_timeout(__wasi_fd_t fd, uint64_t timeout_us)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_send_timeout(
+ (int32_t)fd, (int64_t)timeout_us);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_keep_alive(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_keep_alive")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_keep_alive(__wasi_fd_t fd, bool option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_keep_alive((int32_t)fd,
+ (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_keep_alive(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_keep_alive")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_keep_alive(__wasi_fd_t fd, bool *option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_keep_alive((int32_t)fd,
+ (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_linger(int32_t arg0, int32_t arg1,
+ int32_t arg2)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_linger")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_linger(__wasi_fd_t fd, bool is_enabled, int linger_s)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_linger(
+ (int32_t)fd, (int32_t)is_enabled, (int32_t)linger_s);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_linger(int32_t arg0, int32_t arg1,
+ int32_t arg2)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_linger")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_linger(__wasi_fd_t fd, bool *is_enabled, int *linger_s)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_linger(
+ (int32_t)fd, (int32_t)is_enabled, (int32_t)linger_s);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_tcp_keep_idle(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_tcp_keep_idle")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_tcp_keep_idle(__wasi_fd_t fd, uint32_t time_s)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_tcp_keep_idle(
+ (int32_t)fd, (int32_t)time_s);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_tcp_keep_idle(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_tcp_keep_idle")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_tcp_keep_idle(__wasi_fd_t fd, uint32_t *time_s)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_tcp_keep_idle(
+ (int32_t)fd, (int32_t)time_s);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_tcp_keep_intvl(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_tcp_keep_intvl")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_tcp_keep_intvl(__wasi_fd_t fd, uint32_t time_s)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_tcp_keep_intvl(
+ (int32_t)fd, (int32_t)time_s);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_tcp_keep_intvl(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_tcp_keep_intvl")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_tcp_keep_intvl(__wasi_fd_t fd, uint32_t *time_s)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_tcp_keep_intvl(
+ (int32_t)fd, (int32_t)time_s);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_tcp_fastopen_connect(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_tcp_fastopen_connect")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_tcp_fastopen_connect(__wasi_fd_t fd, bool option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_tcp_fastopen_connect(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_tcp_fastopen_connect(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_tcp_fastopen_connect")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_tcp_fastopen_connect(__wasi_fd_t fd, bool *option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_tcp_fastopen_connect(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_ip_multicast_loop(int32_t arg0,
+ int32_t arg1,
+ int32_t arg2)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_ip_multicast_loop")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_ip_multicast_loop(__wasi_fd_t fd, bool ipv6, bool option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_ip_multicast_loop(
+ (int32_t)fd, (int32_t)ipv6, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_ip_multicast_loop(int32_t arg0,
+ int32_t arg1,
+ int32_t arg2)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_ip_multicast_loop")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_ip_multicast_loop(__wasi_fd_t fd, bool ipv6, bool *option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_ip_multicast_loop(
+ (int32_t)fd, (int32_t)ipv6, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_ip_multicast_ttl(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_ip_multicast_ttl")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_ip_multicast_ttl(__wasi_fd_t fd, uint8_t option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_ip_multicast_ttl(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_ip_multicast_ttl(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_ip_multicast_ttl")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_ip_multicast_ttl(__wasi_fd_t fd, uint8_t *option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_ip_multicast_ttl(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_ip_add_membership(int32_t arg0,
+ int32_t arg1,
+ int32_t arg2)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_ip_add_membership")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_ip_add_membership(__wasi_fd_t fd,
+ __wasi_addr_ip_t *imr_multiaddr,
+ uint32_t imr_interface)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_ip_add_membership(
+ (int32_t)fd, (int32_t)imr_multiaddr, (int32_t)imr_interface);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_ip_drop_membership(int32_t arg0,
+ int32_t arg1,
+ int32_t arg2)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_ip_drop_membership")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_ip_drop_membership(__wasi_fd_t fd,
+ __wasi_addr_ip_t *imr_multiaddr,
+ uint32_t imr_interface)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_ip_drop_membership(
+ (int32_t)fd, (int32_t)imr_multiaddr, (int32_t)imr_interface);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_broadcast(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_broadcast")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_broadcast(__wasi_fd_t fd, bool option)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_broadcast(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_broadcast(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_broadcast")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_broadcast(__wasi_fd_t fd, bool *option)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_broadcast(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_tcp_no_delay(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_tcp_no_delay")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_tcp_no_delay(__wasi_fd_t fd, bool option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_tcp_no_delay(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_tcp_no_delay(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_tcp_no_delay")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_tcp_no_delay(__wasi_fd_t fd, bool *option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_tcp_no_delay(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_tcp_quick_ack(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_tcp_quick_ack")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_tcp_quick_ack(__wasi_fd_t fd, bool option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_set_tcp_quick_ack(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_tcp_quick_ack(int32_t arg0,
+ int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_tcp_quick_ack")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_tcp_quick_ack(__wasi_fd_t fd, bool *option)
+{
+ return (__wasi_errno_t)
+ __imported_wasi_snapshot_preview1_sock_get_tcp_quick_ack(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_ip_ttl(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_ip_ttl")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_ip_ttl(__wasi_fd_t fd, uint8_t option)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_ip_ttl(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_ip_ttl(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_ip_ttl")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_ip_ttl(__wasi_fd_t fd, uint8_t *option)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_ip_ttl(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_set_ipv6_only(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_set_ipv6_only")));
+
+static inline __wasi_errno_t
+__wasi_sock_set_ipv6_only(__wasi_fd_t fd, bool option)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_set_ipv6_only(
+ (int32_t)fd, (int32_t)option);
+}
+
+int32_t
+__imported_wasi_snapshot_preview1_sock_get_ipv6_only(int32_t arg0, int32_t arg1)
+ __attribute__((__import_module__("wasi_snapshot_preview1"),
+ __import_name__("sock_get_ipv6_only")));
+
+static inline __wasi_errno_t
+__wasi_sock_get_ipv6_only(__wasi_fd_t fd, bool *option)
+{
+ return (__wasi_errno_t)__imported_wasi_snapshot_preview1_sock_get_ipv6_only(
+ (int32_t)fd, (int32_t)option);
+}
+/**
+ * TODO: modify recv() and send()
+ * since don't want to re-compile the wasi-libc,
+ * we tend to keep original implentations of recv() and send().
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake
new file mode 100644
index 000000000..209b0c4c9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/lib_socket_wasi.cmake
@@ -0,0 +1,9 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required (VERSION 2.8...3.16)
+
+project(socket_wasi_ext)
+
+add_library(${PROJECT_NAME} STATIC ${CMAKE_CURRENT_LIST_DIR}/src/wasi/wasi_socket_ext.c)
+target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc/)
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c
new file mode 100644
index 000000000..defbc6efe
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/src/wasi/wasi_socket_ext.c
@@ -0,0 +1,1009 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <wasi/api.h>
+#include <wasi_socket_ext.h>
+
+#define HANDLE_ERROR(error) \
+ if (error != __WASI_ERRNO_SUCCESS) { \
+ errno = error; \
+ return -1; \
+ }
+
+static void
+ipv4_addr_to_wasi_ip4_addr(uint32_t addr_num, __wasi_addr_ip4_t *out)
+{
+ addr_num = ntohl(addr_num);
+ out->n0 = (addr_num & 0xFF000000) >> 24;
+ out->n1 = (addr_num & 0x00FF0000) >> 16;
+ out->n2 = (addr_num & 0x0000FF00) >> 8;
+ out->n3 = (addr_num & 0x000000FF);
+}
+
+/* addr_num and port are in network order */
+static void
+ipv4_addr_to_wasi_addr(uint32_t addr_num, uint16_t port, __wasi_addr_t *out)
+{
+ out->kind = IPv4;
+ out->addr.ip4.port = ntohs(port);
+ ipv4_addr_to_wasi_ip4_addr(addr_num, &(out->addr.ip4.addr));
+}
+
+static void
+ipv6_addr_to_wasi_ipv6_addr(uint16_t *addr, __wasi_addr_ip6_t *out)
+{
+ out->n0 = ntohs(addr[0]);
+ out->n1 = ntohs(addr[1]);
+ out->n2 = ntohs(addr[2]);
+ out->n3 = ntohs(addr[3]);
+ out->h0 = ntohs(addr[4]);
+ out->h1 = ntohs(addr[5]);
+ out->h2 = ntohs(addr[6]);
+ out->h3 = ntohs(addr[7]);
+}
+
+static void
+ipv6_addr_to_wasi_addr(uint16_t *addr, uint16_t port, __wasi_addr_t *out)
+{
+ out->kind = IPv6;
+ out->addr.ip6.port = ntohs(port);
+ ipv6_addr_to_wasi_ipv6_addr(addr, &(out->addr.ip6.addr));
+}
+
+static __wasi_errno_t
+sockaddr_to_wasi_addr(const struct sockaddr *sock_addr, socklen_t addrlen,
+ __wasi_addr_t *wasi_addr)
+{
+ __wasi_errno_t ret = __WASI_ERRNO_SUCCESS;
+ if (AF_INET == sock_addr->sa_family) {
+ assert(sizeof(struct sockaddr_in) <= addrlen);
+
+ ipv4_addr_to_wasi_addr(
+ ((struct sockaddr_in *)sock_addr)->sin_addr.s_addr,
+ ((struct sockaddr_in *)sock_addr)->sin_port, wasi_addr);
+ }
+ else if (AF_INET6 == sock_addr->sa_family) {
+ assert(sizeof(struct sockaddr_in6) <= addrlen);
+ ipv6_addr_to_wasi_addr(
+ (uint16_t *)((struct sockaddr_in6 *)sock_addr)->sin6_addr.s6_addr,
+ ((struct sockaddr_in6 *)sock_addr)->sin6_port, wasi_addr);
+ }
+ else {
+ ret = __WASI_ERRNO_AFNOSUPPORT;
+ }
+
+ return ret;
+}
+
+static __wasi_errno_t
+wasi_addr_to_sockaddr(const __wasi_addr_t *wasi_addr,
+ struct sockaddr *sock_addr, socklen_t *addrlen)
+{
+ switch (wasi_addr->kind) {
+ case IPv4:
+ {
+ struct sockaddr_in sock_addr_in;
+ uint32_t s_addr;
+
+ memset(&sock_addr_in, 0, sizeof(sock_addr_in));
+
+ s_addr = (wasi_addr->addr.ip4.addr.n0 << 24)
+ | (wasi_addr->addr.ip4.addr.n1 << 16)
+ | (wasi_addr->addr.ip4.addr.n2 << 8)
+ | wasi_addr->addr.ip4.addr.n3;
+
+ sock_addr_in.sin_family = AF_INET;
+ sock_addr_in.sin_addr.s_addr = htonl(s_addr);
+ sock_addr_in.sin_port = htons(wasi_addr->addr.ip4.port);
+ memcpy(sock_addr, &sock_addr_in, sizeof(sock_addr_in));
+
+ *addrlen = sizeof(sock_addr_in);
+ break;
+ }
+ case IPv6:
+ {
+ struct sockaddr_in6 sock_addr_in6;
+
+ memset(&sock_addr_in6, 0, sizeof(sock_addr_in6));
+
+ uint16_t *addr_buf = (uint16_t *)sock_addr_in6.sin6_addr.s6_addr;
+
+ addr_buf[0] = htons(wasi_addr->addr.ip6.addr.n0);
+ addr_buf[1] = htons(wasi_addr->addr.ip6.addr.n1);
+ addr_buf[2] = htons(wasi_addr->addr.ip6.addr.n2);
+ addr_buf[3] = htons(wasi_addr->addr.ip6.addr.n3);
+ addr_buf[4] = htons(wasi_addr->addr.ip6.addr.h0);
+ addr_buf[5] = htons(wasi_addr->addr.ip6.addr.h1);
+ addr_buf[6] = htons(wasi_addr->addr.ip6.addr.h2);
+ addr_buf[7] = htons(wasi_addr->addr.ip6.addr.h3);
+
+ sock_addr_in6.sin6_family = AF_INET6;
+ sock_addr_in6.sin6_port = htons(wasi_addr->addr.ip6.port);
+ memcpy(sock_addr, &sock_addr_in6, sizeof(sock_addr_in6));
+
+ *addrlen = sizeof(sock_addr_in6);
+ break;
+ }
+ default:
+ return __WASI_ERRNO_AFNOSUPPORT;
+ }
+ return __WASI_ERRNO_SUCCESS;
+}
+
+int
+accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+ __wasi_addr_t wasi_addr;
+ __wasi_fd_t new_sockfd;
+ __wasi_errno_t error;
+
+ memset(&wasi_addr, 0, sizeof(wasi_addr));
+
+ error = __wasi_sock_accept(sockfd, 0, &new_sockfd);
+ HANDLE_ERROR(error)
+
+ if (getpeername(new_sockfd, addr, addrlen) == -1) {
+ return -1;
+ }
+
+ return new_sockfd;
+}
+
+int
+bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+ __wasi_addr_t wasi_addr;
+ __wasi_errno_t error;
+
+ memset(&wasi_addr, 0, sizeof(wasi_addr));
+
+ error = sockaddr_to_wasi_addr(addr, addrlen, &wasi_addr);
+ HANDLE_ERROR(error)
+
+ error = __wasi_sock_bind(sockfd, &wasi_addr);
+ HANDLE_ERROR(error)
+
+ return __WASI_ERRNO_SUCCESS;
+}
+
+int
+connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+ __wasi_addr_t wasi_addr;
+ __wasi_errno_t error;
+
+ memset(&wasi_addr, 0, sizeof(wasi_addr));
+
+ if (NULL == addr) {
+ HANDLE_ERROR(__WASI_ERRNO_INVAL)
+ }
+
+ error = sockaddr_to_wasi_addr(addr, addrlen, &wasi_addr);
+ HANDLE_ERROR(error)
+
+ error = __wasi_sock_connect(sockfd, &wasi_addr);
+ HANDLE_ERROR(error)
+
+ return __WASI_ERRNO_SUCCESS;
+}
+
+int
+listen(int sockfd, int backlog)
+{
+ __wasi_errno_t error = __wasi_sock_listen(sockfd, backlog);
+ HANDLE_ERROR(error)
+ return __WASI_ERRNO_SUCCESS;
+}
+
+ssize_t
+recvmsg(int sockfd, struct msghdr *msg, int flags)
+{
+ // Prepare input parameters.
+ __wasi_iovec_t *ri_data = NULL;
+ size_t i = 0;
+ size_t ro_datalen = 0;
+ __wasi_roflags_t ro_flags = 0;
+
+ if (NULL == msg) {
+ HANDLE_ERROR(__WASI_ERRNO_INVAL)
+ }
+
+ // Validate flags.
+ if (flags != 0) {
+ HANDLE_ERROR(__WASI_ERRNO_NOPROTOOPT)
+ }
+
+ // __wasi_ciovec_t -> struct iovec
+ if (!(ri_data = (__wasi_iovec_t *)malloc(sizeof(__wasi_iovec_t)
+ * msg->msg_iovlen))) {
+ HANDLE_ERROR(__WASI_ERRNO_NOMEM)
+ }
+
+ for (i = 0; i < msg->msg_iovlen; i++) {
+ ri_data[i].buf = (uint8_t *)msg->msg_iov[i].iov_base;
+ ri_data[i].buf_len = msg->msg_iov[i].iov_len;
+ }
+
+ // Perform system call.
+ __wasi_errno_t error = __wasi_sock_recv(sockfd, ri_data, msg->msg_iovlen, 0,
+ &ro_datalen, &ro_flags);
+ free(ri_data);
+ HANDLE_ERROR(error)
+
+ return ro_datalen;
+}
+
+ssize_t
+sendmsg(int sockfd, const struct msghdr *msg, int flags)
+{
+ // Prepare input parameters.
+ __wasi_ciovec_t *si_data = NULL;
+ size_t so_datalen = 0;
+ size_t i = 0;
+
+ if (NULL == msg) {
+ HANDLE_ERROR(__WASI_ERRNO_INVAL)
+ }
+
+ // This implementation does not support any flags.
+ if (flags != 0) {
+ HANDLE_ERROR(__WASI_ERRNO_NOPROTOOPT)
+ }
+
+ // struct iovec -> __wasi_ciovec_t
+ if (!(si_data = (__wasi_ciovec_t *)malloc(sizeof(__wasi_ciovec_t)
+ * msg->msg_iovlen))) {
+ HANDLE_ERROR(__WASI_ERRNO_NOMEM)
+ }
+
+ for (i = 0; i < msg->msg_iovlen; i++) {
+ si_data[i].buf = (uint8_t *)msg->msg_iov[i].iov_base;
+ si_data[i].buf_len = msg->msg_iov[i].iov_len;
+ }
+
+ // Perform system call.
+ __wasi_errno_t error =
+ __wasi_sock_send(sockfd, si_data, msg->msg_iovlen, 0, &so_datalen);
+ free(si_data);
+ HANDLE_ERROR(error)
+
+ return so_datalen;
+}
+
+ssize_t
+sendto(int sockfd, const void *buf, size_t len, int flags,
+ const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+ // Prepare input parameters.
+ __wasi_ciovec_t iov = { .buf = (uint8_t *)buf, .buf_len = len };
+ uint32_t so_datalen = 0;
+ __wasi_addr_t wasi_addr;
+ __wasi_errno_t error;
+ size_t si_data_len = 1;
+ __wasi_siflags_t si_flags = 0;
+
+ // This implementation does not support any flags.
+ if (flags != 0) {
+ HANDLE_ERROR(__WASI_ERRNO_NOPROTOOPT)
+ }
+
+ error = sockaddr_to_wasi_addr(dest_addr, addrlen, &wasi_addr);
+ HANDLE_ERROR(error);
+
+ // Perform system call.
+ error = __wasi_sock_send_to(sockfd, &iov, si_data_len, si_flags, &wasi_addr,
+ &so_datalen);
+ HANDLE_ERROR(error)
+
+ return so_datalen;
+}
+
+ssize_t
+recvfrom(int sockfd, void *buf, size_t len, int flags,
+ struct sockaddr *src_addr, socklen_t *addrlen)
+{
+ // Prepare input parameters.
+ __wasi_ciovec_t iov = { .buf = (uint8_t *)buf, .buf_len = len };
+ uint32_t so_datalen = 0;
+ __wasi_addr_t wasi_addr;
+ __wasi_errno_t error;
+ size_t si_data_len = 1;
+ __wasi_siflags_t si_flags = 0;
+
+ // This implementation does not support any flags.
+ if (flags != 0) {
+ HANDLE_ERROR(__WASI_ERRNO_NOPROTOOPT)
+ }
+
+ if (!src_addr) {
+ return recv(sockfd, buf, len, flags);
+ }
+
+ // Perform system call.
+ error = __wasi_sock_recv_from(sockfd, &iov, si_data_len, si_flags,
+ &wasi_addr, &so_datalen);
+ HANDLE_ERROR(error);
+
+ error = wasi_addr_to_sockaddr(&wasi_addr, src_addr, addrlen);
+ HANDLE_ERROR(error);
+
+ return so_datalen;
+}
+
+int
+socket(int domain, int type, int protocol)
+{
+ // the stub of address pool fd
+ __wasi_fd_t poolfd = -1;
+ __wasi_fd_t sockfd;
+ __wasi_errno_t error;
+ __wasi_address_family_t af;
+ __wasi_sock_type_t socktype;
+
+ if (AF_INET == domain) {
+ af = INET4;
+ }
+ else if (AF_INET6 == domain) {
+ af = INET6;
+ }
+ else {
+ return __WASI_ERRNO_NOPROTOOPT;
+ }
+
+ if (SOCK_DGRAM == type) {
+ socktype = SOCKET_DGRAM;
+ }
+ else if (SOCK_STREAM == type) {
+ socktype = SOCKET_STREAM;
+ }
+ else {
+ return __WASI_ERRNO_NOPROTOOPT;
+ }
+
+ error = __wasi_sock_open(poolfd, af, socktype, &sockfd);
+ HANDLE_ERROR(error)
+
+ return sockfd;
+}
+
+int
+getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+ __wasi_addr_t wasi_addr;
+ __wasi_errno_t error;
+
+ memset(&wasi_addr, 0, sizeof(wasi_addr));
+
+ error = __wasi_sock_addr_local(sockfd, &wasi_addr);
+ HANDLE_ERROR(error)
+
+ error = wasi_addr_to_sockaddr(&wasi_addr, addr, addrlen);
+ HANDLE_ERROR(error)
+
+ return __WASI_ERRNO_SUCCESS;
+}
+
+int
+getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+ __wasi_addr_t wasi_addr;
+ __wasi_errno_t error;
+
+ memset(&wasi_addr, 0, sizeof(wasi_addr));
+
+ error = __wasi_sock_addr_remote(sockfd, &wasi_addr);
+ HANDLE_ERROR(error)
+
+ error = wasi_addr_to_sockaddr(&wasi_addr, addr, addrlen);
+ HANDLE_ERROR(error)
+
+ return __WASI_ERRNO_SUCCESS;
+}
+
+struct aibuf {
+ struct addrinfo ai;
+ union sa {
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ } sa;
+};
+
+static __wasi_errno_t
+addrinfo_hints_to_wasi_hints(const struct addrinfo *hints,
+ __wasi_addr_info_hints_t *wasi_hints)
+{
+ if (hints) {
+ wasi_hints->hints_enabled = 1;
+
+ switch (hints->ai_family) {
+ case AF_INET:
+ wasi_hints->family = INET4;
+ break;
+ case AF_INET6:
+ wasi_hints->family = INET6;
+ break;
+ default:
+ return __WASI_ERRNO_AFNOSUPPORT;
+ }
+ switch (hints->ai_socktype) {
+ case SOCK_STREAM:
+ wasi_hints->type = SOCKET_STREAM;
+ break;
+ case SOCK_DGRAM:
+ wasi_hints->type = SOCKET_DGRAM;
+ break;
+ default:
+ return __WASI_ERRNO_NOTSUP;
+ }
+
+ if (hints->ai_protocol != 0) {
+ return __WASI_ERRNO_NOTSUP;
+ }
+
+ if (hints->ai_flags != 0) {
+ return __WASI_ERRNO_NOTSUP;
+ }
+ }
+ else {
+ wasi_hints->hints_enabled = 0;
+ }
+
+ return __WASI_ERRNO_SUCCESS;
+}
+
+static __wasi_errno_t
+wasi_addr_info_to_addr_info(const __wasi_addr_info_t *addr_info,
+ struct addrinfo *ai)
+{
+ ai->ai_socktype =
+ addr_info->type == SOCKET_DGRAM ? SOCK_DGRAM : SOCK_STREAM;
+ ai->ai_protocol = 0;
+ ai->ai_canonname = NULL;
+
+ if (addr_info->addr.kind == IPv4) {
+ ai->ai_family = AF_INET;
+ ai->ai_addrlen = sizeof(struct sockaddr_in);
+ }
+ else {
+ ai->ai_family = AF_INET6;
+ ai->ai_addrlen = sizeof(struct sockaddr_in6);
+ }
+
+ return wasi_addr_to_sockaddr(&addr_info->addr, ai->ai_addr,
+ &ai->ai_addrlen); // TODO err handling
+}
+
+int
+getaddrinfo(const char *node, const char *service, const struct addrinfo *hints,
+ struct addrinfo **res)
+{
+ __wasi_addr_info_hints_t wasi_hints;
+ __wasi_addr_info_t *addr_info = NULL;
+ __wasi_size_t addr_info_size, i;
+ __wasi_size_t max_info_size = 16;
+ __wasi_errno_t error;
+ struct aibuf *aibuf_res;
+
+ error = addrinfo_hints_to_wasi_hints(hints, &wasi_hints);
+ HANDLE_ERROR(error)
+
+ do {
+ if (addr_info)
+ free(addr_info);
+
+ addr_info_size = max_info_size;
+ addr_info = (__wasi_addr_info_t *)malloc(addr_info_size
+ * sizeof(__wasi_addr_info_t));
+
+ if (!addr_info) {
+ HANDLE_ERROR(__WASI_ERRNO_NOMEM)
+ }
+
+ error = __wasi_sock_addr_resolve(node, service == NULL ? "" : service,
+ &wasi_hints, addr_info, addr_info_size,
+ &max_info_size);
+ if (error != __WASI_ERRNO_SUCCESS) {
+ free(addr_info);
+ HANDLE_ERROR(error);
+ }
+ } while (max_info_size > addr_info_size);
+
+ if (addr_info_size == 0) {
+ free(addr_info);
+ *res = NULL;
+ return __WASI_ERRNO_SUCCESS;
+ }
+
+ aibuf_res =
+ (struct aibuf *)calloc(1, addr_info_size * sizeof(struct aibuf));
+ if (!aibuf_res) {
+ free(addr_info);
+ HANDLE_ERROR(__WASI_ERRNO_NOMEM)
+ }
+
+ *res = &aibuf_res[0].ai;
+
+ if (addr_info_size) {
+ addr_info_size = max_info_size;
+ }
+
+ for (i = 0; i < addr_info_size; i++) {
+ struct addrinfo *ai = &aibuf_res[i].ai;
+ ai->ai_addr = (struct sockaddr *)&aibuf_res[i].sa;
+
+ error = wasi_addr_info_to_addr_info(&addr_info[i], ai);
+ if (error != __WASI_ERRNO_SUCCESS) {
+ free(addr_info);
+ free(aibuf_res);
+ HANDLE_ERROR(error)
+ }
+ ai->ai_next = i == addr_info_size - 1 ? NULL : &aibuf_res[i + 1].ai;
+ }
+
+ free(addr_info);
+
+ return __WASI_ERRNO_SUCCESS;
+}
+
+void
+freeaddrinfo(struct addrinfo *res)
+{
+ /* res is a pointer to a first field in the first element
+ * of aibuf array allocated in getaddrinfo, therefore this call
+ * frees the memory of the entire array. */
+ free(res);
+}
+
+static struct timeval
+time_us_to_timeval(uint64_t time_us)
+{
+ struct timeval tv;
+ tv.tv_sec = time_us / 1000000UL;
+ tv.tv_usec = time_us % 1000000UL;
+ return tv;
+}
+
+static uint64_t
+timeval_to_time_us(struct timeval tv)
+{
+ return (tv.tv_sec * 1000000UL) + tv.tv_usec;
+}
+
+static int
+get_sol_socket_option(int sockfd, int optname, void *__restrict optval,
+ socklen_t *__restrict optlen)
+{
+ __wasi_errno_t error;
+ uint64_t timeout_us;
+ bool is_linger_enabled;
+ int linger_s;
+
+ switch (optname) {
+ case SO_RCVTIMEO:
+ assert(*optlen == sizeof(struct timeval));
+ error = __wasi_sock_get_recv_timeout(sockfd, &timeout_us);
+ HANDLE_ERROR(error);
+ *(struct timeval *)optval = time_us_to_timeval(timeout_us);
+ return error;
+ case SO_SNDTIMEO:
+ assert(*optlen == sizeof(struct timeval));
+ error = __wasi_sock_get_send_timeout(sockfd, &timeout_us);
+ HANDLE_ERROR(error);
+ *(struct timeval *)optval = time_us_to_timeval(timeout_us);
+ return error;
+ case SO_SNDBUF:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_send_buf_size(sockfd, (size_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case SO_RCVBUF:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_recv_buf_size(sockfd, (size_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case SO_KEEPALIVE:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_keep_alive(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case SO_REUSEADDR:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_reuse_addr(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case SO_REUSEPORT:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_reuse_port(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case SO_LINGER:
+ assert(*optlen == sizeof(struct linger));
+ error =
+ __wasi_sock_get_linger(sockfd, &is_linger_enabled, &linger_s);
+ HANDLE_ERROR(error);
+ ((struct linger *)optval)->l_onoff = (int)is_linger_enabled;
+ ((struct linger *)optval)->l_linger = linger_s;
+ return error;
+ case SO_BROADCAST:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_broadcast(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+static int
+get_ipproto_tcp_option(int sockfd, int optname, void *__restrict optval,
+ socklen_t *__restrict optlen)
+{
+ __wasi_errno_t error;
+ switch (optname) {
+ case TCP_KEEPIDLE:
+ assert(*optlen == sizeof(uint32_t));
+ error = __wasi_sock_get_tcp_keep_idle(sockfd, (uint32_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_KEEPINTVL:
+ assert(*optlen == sizeof(uint32_t));
+ error = __wasi_sock_get_tcp_keep_intvl(sockfd, (uint32_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_FASTOPEN_CONNECT:
+ assert(*optlen == sizeof(int));
+ error =
+ __wasi_sock_get_tcp_fastopen_connect(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_NODELAY:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_tcp_no_delay(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_QUICKACK:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_tcp_quick_ack(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+static int
+get_ipproto_ip_option(int sockfd, int optname, void *__restrict optval,
+ socklen_t *__restrict optlen)
+{
+ __wasi_errno_t error;
+
+ switch (optname) {
+ case IP_MULTICAST_LOOP:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_ip_multicast_loop(sockfd, false,
+ (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case IP_TTL:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_ip_ttl(sockfd, (uint8_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case IP_MULTICAST_TTL:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_ip_multicast_ttl(sockfd, (uint8_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+static int
+get_ipproto_ipv6_option(int sockfd, int optname, void *__restrict optval,
+ socklen_t *__restrict optlen)
+{
+ __wasi_errno_t error;
+
+ switch (optname) {
+ case IPV6_V6ONLY:
+ assert(*optlen == sizeof(int));
+ error = __wasi_sock_get_ipv6_only(sockfd, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case IPV6_MULTICAST_LOOP:
+ assert(*optlen == sizeof(int));
+ error =
+ __wasi_sock_get_ip_multicast_loop(sockfd, true, (bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+int
+getsockopt(int sockfd, int level, int optname, void *__restrict optval,
+ socklen_t *__restrict optlen)
+{
+ __wasi_errno_t error;
+
+ switch (level) {
+ case SOL_SOCKET:
+ return get_sol_socket_option(sockfd, optname, optval, optlen);
+ case IPPROTO_TCP:
+ return get_ipproto_tcp_option(sockfd, optname, optval, optlen);
+ case IPPROTO_IP:
+ return get_ipproto_ip_option(sockfd, optname, optval, optlen);
+ case IPPROTO_IPV6:
+ return get_ipproto_ipv6_option(sockfd, optname, optval, optlen);
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+static int
+set_sol_socket_option(int sockfd, int optname, const void *optval,
+ socklen_t optlen)
+{
+ __wasi_errno_t error;
+ uint64_t timeout_us;
+
+ switch (optname) {
+ case SO_RCVTIMEO:
+ {
+ assert(optlen == sizeof(struct timeval));
+ timeout_us = timeval_to_time_us(*(struct timeval *)optval);
+ error = __wasi_sock_set_recv_timeout(sockfd, timeout_us);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_SNDTIMEO:
+ {
+ assert(optlen == sizeof(struct timeval));
+ timeout_us = timeval_to_time_us(*(struct timeval *)optval);
+ error = __wasi_sock_set_send_timeout(sockfd, timeout_us);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_SNDBUF:
+ {
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_send_buf_size(sockfd, *(size_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_RCVBUF:
+ {
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_recv_buf_size(sockfd, *(size_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_KEEPALIVE:
+ {
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_keep_alive(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_REUSEADDR:
+ {
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_reuse_addr(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_REUSEPORT:
+ {
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_reuse_port(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_LINGER:
+ {
+ assert(optlen == sizeof(struct linger));
+ struct linger *linger_opt = ((struct linger *)optval);
+ error = __wasi_sock_set_linger(sockfd, (bool)linger_opt->l_onoff,
+ linger_opt->l_linger);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ case SO_BROADCAST:
+ {
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_broadcast(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ }
+ default:
+ {
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+ }
+}
+
+static int
+set_ipproto_tcp_option(int sockfd, int optname, const void *optval,
+ socklen_t optlen)
+{
+ __wasi_errno_t error;
+
+ switch (optname) {
+ case TCP_NODELAY:
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_tcp_no_delay(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_KEEPIDLE:
+ assert(optlen == sizeof(uint32_t));
+ error = __wasi_sock_set_tcp_keep_idle(sockfd, *(uint32_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_KEEPINTVL:
+ assert(optlen == sizeof(uint32_t));
+ error = __wasi_sock_set_tcp_keep_intvl(sockfd, *(uint32_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_FASTOPEN_CONNECT:
+ assert(optlen == sizeof(int));
+ error =
+ __wasi_sock_set_tcp_fastopen_connect(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case TCP_QUICKACK:
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_tcp_quick_ack(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+static int
+set_ipproto_ip_option(int sockfd, int optname, const void *optval,
+ socklen_t optlen)
+{
+ __wasi_errno_t error;
+ __wasi_addr_ip_t imr_multiaddr;
+ struct ip_mreq *ip_mreq_opt;
+
+ switch (optname) {
+ case IP_MULTICAST_LOOP:
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_ip_multicast_loop(sockfd, false,
+ *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case IP_ADD_MEMBERSHIP:
+ assert(optlen == sizeof(struct ip_mreq));
+ ip_mreq_opt = (struct ip_mreq *)optval;
+ imr_multiaddr.kind = IPv4;
+ ipv4_addr_to_wasi_ip4_addr(ip_mreq_opt->imr_multiaddr.s_addr,
+ &imr_multiaddr.addr.ip4);
+ error = __wasi_sock_set_ip_add_membership(
+ sockfd, &imr_multiaddr, ip_mreq_opt->imr_interface.s_addr);
+ HANDLE_ERROR(error);
+ return error;
+ case IP_DROP_MEMBERSHIP:
+ assert(optlen == sizeof(struct ip_mreq));
+ ip_mreq_opt = (struct ip_mreq *)optval;
+ imr_multiaddr.kind = IPv4;
+ ipv4_addr_to_wasi_ip4_addr(ip_mreq_opt->imr_multiaddr.s_addr,
+ &imr_multiaddr.addr.ip4);
+ error = __wasi_sock_set_ip_drop_membership(
+ sockfd, &imr_multiaddr, ip_mreq_opt->imr_interface.s_addr);
+ HANDLE_ERROR(error);
+ return error;
+ case IP_TTL:
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_ip_ttl(sockfd, *(uint8_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case IP_MULTICAST_TTL:
+ assert(optlen == sizeof(int));
+ error =
+ __wasi_sock_set_ip_multicast_ttl(sockfd, *(uint8_t *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+static int
+set_ipproto_ipv6_option(int sockfd, int optname, const void *optval,
+ socklen_t optlen)
+{
+ __wasi_errno_t error;
+ struct ipv6_mreq *ipv6_mreq_opt;
+ __wasi_addr_ip_t imr_multiaddr;
+
+ switch (optname) {
+ case IPV6_V6ONLY:
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_ipv6_only(sockfd, *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case IPV6_MULTICAST_LOOP:
+ assert(optlen == sizeof(int));
+ error = __wasi_sock_set_ip_multicast_loop(sockfd, true,
+ *(bool *)optval);
+ HANDLE_ERROR(error);
+ return error;
+ case IPV6_JOIN_GROUP:
+ assert(optlen == sizeof(struct ipv6_mreq));
+ ipv6_mreq_opt = (struct ipv6_mreq *)optval;
+ imr_multiaddr.kind = IPv6;
+ ipv6_addr_to_wasi_ipv6_addr(
+ (uint16_t *)ipv6_mreq_opt->ipv6mr_multiaddr.s6_addr,
+ &imr_multiaddr.addr.ip6);
+ error = __wasi_sock_set_ip_add_membership(
+ sockfd, &imr_multiaddr, ipv6_mreq_opt->ipv6mr_interface);
+ HANDLE_ERROR(error);
+ return error;
+ case IPV6_LEAVE_GROUP:
+ assert(optlen == sizeof(struct ipv6_mreq));
+ ipv6_mreq_opt = (struct ipv6_mreq *)optval;
+ imr_multiaddr.kind = IPv6;
+ ipv6_addr_to_wasi_ipv6_addr(
+ (uint16_t *)ipv6_mreq_opt->ipv6mr_multiaddr.s6_addr,
+ &imr_multiaddr.addr.ip6);
+ error = __wasi_sock_set_ip_drop_membership(
+ sockfd, &imr_multiaddr, ipv6_mreq_opt->ipv6mr_interface);
+ HANDLE_ERROR(error);
+ return error;
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
+
+int
+setsockopt(int sockfd, int level, int optname, const void *optval,
+ socklen_t optlen)
+{
+ __wasi_errno_t error;
+
+ switch (level) {
+ case SOL_SOCKET:
+ return set_sol_socket_option(sockfd, optname, optval, optlen);
+ case IPPROTO_TCP:
+ return set_ipproto_tcp_option(sockfd, optname, optval, optlen);
+ case IPPROTO_IP:
+ return set_ipproto_ip_option(sockfd, optname, optval, optlen);
+ case IPPROTO_IPV6:
+ return set_ipproto_ipv6_option(sockfd, optname, optval, optlen);
+ default:
+ error = __WASI_ERRNO_NOTSUP;
+ HANDLE_ERROR(error);
+ return error;
+ }
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/build.sh b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/build.sh
new file mode 100755
index 000000000..24f5ee676
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/build.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set -eo pipefail
+CC="${CC:=/opt/wasi-sdk/bin/clang}"
+files=("tcp_udp.c" "nslookup.c")
+
+for file in "${files[@]}"
+do
+ echo $file
+ $CC \
+ --target=wasm32-wasi-threads \
+ -I../inc \
+ ../src/wasi/wasi_socket_ext.c -pthread -ftls-model=local-exec \
+ -Wl,--allow-undefined \
+ -Wl,--strip-all,--no-entry \
+ -Wl,--export=__heap_base \
+ -Wl,--export=__data_end \
+ -Wl,--shared-memory,--max-memory=10485760 \
+ -Wl,--export=malloc \
+ -Wl,--export=free \
+ -o "${file%.*}.wasm" "$file"
+done \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/nslookup.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/nslookup.c
new file mode 100644
index 000000000..37150f1eb
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/nslookup.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <assert.h>
+#include <string.h>
+#ifdef __wasi__
+#include <wasi/api.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <wasi_socket_ext.h>
+#else
+#include <netdb.h>
+#endif
+
+void
+test_nslookup(int af)
+{
+ struct addrinfo *res;
+ int count = 0;
+ struct addrinfo hints;
+ char *url = "google-public-dns-a.google.com";
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = af;
+ hints.ai_socktype = SOCK_STREAM;
+ int ret = getaddrinfo(url, 0, &hints, &res);
+ assert(ret == 0);
+ struct addrinfo *address = res;
+ while (address) {
+ assert(address->ai_family == af);
+ assert(address->ai_socktype == SOCK_STREAM);
+ count++;
+ address = address->ai_next;
+ }
+
+ assert(count > 0);
+ freeaddrinfo(res);
+}
+
+int
+main()
+{
+ test_nslookup(AF_INET); /* for ipv4 */
+ test_nslookup(AF_INET6); /* for ipv6 */
+
+ return 0;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/tcp_udp.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/tcp_udp.c
new file mode 100644
index 000000000..49231de89
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-socket/test/tcp_udp.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#ifdef __wasi__
+#include <wasi/api.h>
+#include <sys/socket.h>
+#include <wasi_socket_ext.h>
+#endif
+#include <arpa/inet.h>
+#include <pthread.h>
+#define SERVER_MSG "Message from server."
+#define PORT 8989
+pthread_mutex_t mut;
+pthread_cond_t cond;
+int server_init_complete = 0;
+char buffer[sizeof(SERVER_MSG) + 1];
+
+struct socket_info {
+ union {
+ struct sockaddr_in addr_ipv4;
+ struct sockaddr_in6 addr_ipv6;
+ } addr;
+ int sock;
+};
+
+struct thread_args {
+ int family;
+ int protocol;
+};
+
+struct socket_info
+init_socket_addr(int family, int protocol)
+{
+ int sock = socket(family, protocol, 0);
+ assert(sock != -1);
+
+ struct socket_info info;
+ if (family == AF_INET) {
+ struct sockaddr_in addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(PORT);
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ info.addr.addr_ipv4 = addr;
+ }
+ else if (family == AF_INET6) {
+ struct sockaddr_in6 addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ addr.sin6_port = htons(PORT);
+ addr.sin6_addr = in6addr_loopback;
+ info.addr.addr_ipv6 = addr;
+ }
+ info.sock = sock;
+ return info;
+}
+
+void
+assert_thread_args(struct thread_args *args)
+{
+ assert(args->family == AF_INET || args->family == AF_INET6);
+ assert(args->protocol == SOCK_STREAM || args->protocol == SOCK_DGRAM);
+}
+
+void *
+server(void *arg)
+{
+ server_init_complete = 0;
+ struct thread_args *args = (struct thread_args *)arg;
+ assert_thread_args(args);
+
+ struct socket_info init_server_sock =
+ init_socket_addr(args->family, args->protocol);
+
+ int server_sock = init_server_sock.sock;
+ socklen_t addr_size;
+ struct sockaddr_storage client_addr;
+ strcpy(buffer, SERVER_MSG);
+
+ struct sockaddr *server_addr = (struct sockaddr *)&init_server_sock.addr;
+ int ret = bind(server_sock, server_addr,
+ args->family == AF_INET ? sizeof(struct sockaddr_in)
+ : sizeof(struct sockaddr_in6));
+ assert(ret == 0);
+
+ (args->protocol == SOCK_STREAM) && listen(server_sock, 1);
+ pthread_mutex_lock(&mut);
+ server_init_complete = 1;
+ pthread_mutex_unlock(&mut);
+ pthread_cond_signal(&cond);
+
+ addr_size = sizeof(client_addr);
+ if (args->protocol == SOCK_STREAM) {
+ int client_sock =
+ accept(server_sock, (struct sockaddr *)&client_addr, &addr_size);
+ assert(client_sock >= 0);
+ sendto(client_sock, buffer, strlen(buffer), 0,
+ (struct sockaddr *)&client_addr, addr_size);
+
+ assert(close(client_sock) == 0);
+ }
+ else {
+ recvfrom(server_sock, buffer, sizeof(buffer), 0,
+ (struct sockaddr *)&client_addr, &addr_size);
+ sendto(server_sock, buffer, strlen(buffer), 0,
+ (struct sockaddr *)&client_addr, addr_size);
+
+ assert(close(server_sock) == 0);
+ }
+
+ return NULL;
+}
+
+void *
+client(void *arg)
+{
+ struct thread_args *args = (struct thread_args *)arg;
+ assert_thread_args(args);
+
+ pthread_mutex_lock(&mut);
+
+ while (server_init_complete == 0) {
+ pthread_cond_wait(&cond, &mut);
+ }
+
+ struct socket_info init_client_sock =
+ init_socket_addr(args->family, args->protocol);
+ int sock = init_client_sock.sock;
+ pthread_mutex_unlock(&mut);
+
+ if (args->family == AF_INET) {
+ struct sockaddr_in addr = init_client_sock.addr.addr_ipv4;
+ if (args->protocol == SOCK_STREAM) {
+ assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1);
+ }
+ else {
+ assert(sendto(sock, buffer, strlen(buffer), 0,
+ (struct sockaddr *)&addr, sizeof(addr))
+ != -1);
+ }
+ }
+ else {
+ struct sockaddr_in6 addr = init_client_sock.addr.addr_ipv6;
+ if (args->protocol == SOCK_STREAM) {
+ assert(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != -1);
+ }
+ else {
+ assert(sendto(sock, buffer, strlen(buffer), 0,
+ (struct sockaddr *)&addr, sizeof(addr))
+ != -1);
+ }
+ }
+
+ recv(sock, buffer, sizeof(buffer), 0);
+ assert(strcmp(buffer, SERVER_MSG) == 0);
+ assert(close(sock) == 0);
+ return NULL;
+}
+
+void
+test_protocol(int family, int protocol)
+{
+ pthread_t server_thread, client_thread;
+ assert(pthread_cond_init(&cond, NULL) == 0);
+ assert(pthread_mutex_init(&mut, NULL) == 0);
+
+ struct thread_args args = { family, protocol };
+ assert(pthread_create(&server_thread, NULL, server, (void *)&args) == 0);
+ assert(pthread_create(&client_thread, NULL, client, (void *)&args) == 0);
+ assert(pthread_join(server_thread, NULL) == 0);
+ assert(pthread_join(client_thread, NULL) == 0);
+
+ assert(pthread_mutex_destroy(&mut) == 0);
+ assert(pthread_cond_destroy(&cond) == 0);
+}
+
+int
+main(int argc, char **argv)
+{
+ /* test tcp with ipv4 and ipv6 */
+ test_protocol(AF_INET, SOCK_STREAM);
+ test_protocol(AF_INET6, SOCK_STREAM);
+
+ /* test udp with ipv4 and ipv6 */
+ test_protocol(AF_INET, SOCK_DGRAM);
+ test_protocol(AF_INET6, SOCK_DGRAM);
+
+ return 0;
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads.cmake
new file mode 100644
index 000000000..54d2ba902
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads.cmake
@@ -0,0 +1,12 @@
+# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (LIB_WASI_THREADS_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions (-DWASM_ENABLE_LIB_WASI_THREADS=1 -DWASM_ENABLE_HEAP_AUX_STACK_ALLOCATION=1)
+
+include_directories(${LIB_WASI_THREADS_DIR})
+
+set (LIB_WASI_THREADS_SOURCE
+ ${LIB_WASI_THREADS_DIR}/lib_wasi_threads_wrapper.c
+ ${LIB_WASI_THREADS_DIR}/tid_allocator.c) \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c
new file mode 100644
index 000000000..6b36c9073
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_log.h"
+#include "thread_manager.h"
+#include "tid_allocator.h"
+
+#if WASM_ENABLE_INTERP != 0
+#include "wasm_runtime.h"
+#endif
+
+#if WASM_ENABLE_AOT != 0
+#include "aot_runtime.h"
+#endif
+
+static const char *THREAD_START_FUNCTION = "wasi_thread_start";
+static korp_mutex thread_id_lock;
+static TidAllocator tid_allocator;
+
+typedef struct {
+ /* app's entry function */
+ wasm_function_inst_t start_func;
+ /* arg of the app's entry function */
+ uint32 arg;
+ /* thread id passed to the app */
+ int32 thread_id;
+} ThreadStartArg;
+
+static int32
+allocate_thread_id()
+{
+ os_mutex_lock(&thread_id_lock);
+ int32 id = tid_allocator_get_tid(&tid_allocator);
+ os_mutex_unlock(&thread_id_lock);
+
+ return id;
+}
+
+void
+deallocate_thread_id(int32 thread_id)
+{
+ os_mutex_lock(&thread_id_lock);
+ tid_allocator_release_tid(&tid_allocator, thread_id);
+ os_mutex_unlock(&thread_id_lock);
+}
+
+static void *
+thread_start(void *arg)
+{
+ wasm_exec_env_t exec_env = (wasm_exec_env_t)arg;
+ ThreadStartArg *thread_arg = exec_env->thread_arg;
+ uint32 argv[2];
+
+ wasm_exec_env_set_thread_info(exec_env);
+ argv[0] = thread_arg->thread_id;
+ argv[1] = thread_arg->arg;
+
+ if (!wasm_runtime_call_wasm(exec_env, thread_arg->start_func, 2, argv)) {
+ /* Exception has already been spread during throwing */
+ }
+
+ // Routine exit
+ deallocate_thread_id(thread_arg->thread_id);
+ wasm_runtime_free(thread_arg);
+ exec_env->thread_arg = NULL;
+
+ return NULL;
+}
+
+static int32
+thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
+{
+ wasm_module_t module = wasm_exec_env_get_module(exec_env);
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasm_module_inst_t new_module_inst = NULL;
+ ThreadStartArg *thread_start_arg = NULL;
+ wasm_function_inst_t start_func;
+ int32 thread_id;
+ uint32 stack_size = 8192;
+ int32 ret = -1;
+#if WASM_ENABLE_LIBC_WASI != 0
+ WASIContext *wasi_ctx;
+#endif
+
+ bh_assert(module);
+ bh_assert(module_inst);
+
+ stack_size = ((WASMModuleInstance *)module_inst)->default_wasm_stack_size;
+
+ if (!(new_module_inst = wasm_runtime_instantiate_internal(
+ module, true, exec_env, stack_size, 0, NULL, 0)))
+ return -1;
+
+ wasm_runtime_set_custom_data_internal(
+ new_module_inst, wasm_runtime_get_custom_data(module_inst));
+
+ if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst)))
+ goto thread_preparation_fail;
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
+ if (wasi_ctx)
+ wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
+#endif
+
+ start_func = wasm_runtime_lookup_function(new_module_inst,
+ THREAD_START_FUNCTION, NULL);
+ if (!start_func) {
+ LOG_ERROR("Failed to find thread start function %s",
+ THREAD_START_FUNCTION);
+ goto thread_preparation_fail;
+ }
+
+ if (!(thread_start_arg = wasm_runtime_malloc(sizeof(ThreadStartArg)))) {
+ LOG_ERROR("Runtime args allocation failed");
+ goto thread_preparation_fail;
+ }
+
+ thread_start_arg->thread_id = thread_id = allocate_thread_id();
+ if (thread_id < 0) {
+ LOG_ERROR("Failed to get thread identifier");
+ goto thread_preparation_fail;
+ }
+ thread_start_arg->arg = start_arg;
+ thread_start_arg->start_func = start_func;
+
+ ret = wasm_cluster_create_thread(exec_env, new_module_inst, false,
+ thread_start, thread_start_arg);
+ if (ret != 0) {
+ LOG_ERROR("Failed to spawn a new thread");
+ goto thread_spawn_fail;
+ }
+
+ return thread_id;
+
+thread_spawn_fail:
+ deallocate_thread_id(thread_id);
+
+thread_preparation_fail:
+ if (new_module_inst)
+ wasm_runtime_deinstantiate_internal(new_module_inst, true);
+ if (thread_start_arg)
+ wasm_runtime_free(thread_start_arg);
+
+ return -1;
+}
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(name, func_name, signature) \
+ { name, func_name##_wrapper, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_lib_wasi_threads[] = { REG_NATIVE_FUNC(
+ "thread-spawn", thread_spawn, "(i)i") };
+
+uint32
+get_lib_wasi_threads_export_apis(NativeSymbol **p_lib_wasi_threads_apis)
+{
+ *p_lib_wasi_threads_apis = native_symbols_lib_wasi_threads;
+ return sizeof(native_symbols_lib_wasi_threads) / sizeof(NativeSymbol);
+}
+
+bool
+lib_wasi_threads_init(void)
+{
+ if (0 != os_mutex_init(&thread_id_lock))
+ return false;
+
+ if (!tid_allocator_init(&tid_allocator)) {
+ os_mutex_destroy(&thread_id_lock);
+ return false;
+ }
+
+ return true;
+}
+
+void
+lib_wasi_threads_destroy(void)
+{
+ tid_allocator_deinit(&tid_allocator);
+ os_mutex_destroy(&thread_id_lock);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/build.sh b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/build.sh
new file mode 100755
index 000000000..32586c20c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/build.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+#
+# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+set -eo pipefail
+CC=${CC:=/opt/wasi-sdk/bin/clang}
+WAMR_DIR=../../../../..
+
+for test_c in *.c; do
+ test_wasm="$(basename $test_c .c).wasm"
+
+ if [ $test_wasm = "linear_memory_size_update.wasm" ]; then
+ thread_start_file=""
+ else
+ thread_start_file=$WAMR_DIR/samples/wasi-threads/wasm-apps/wasi_thread_start.S
+ fi
+
+ echo "Compiling $test_c to $test_wasm"
+ $CC \
+ -target wasm32-wasi-threads \
+ -pthread -ftls-model=local-exec \
+ -z stack-size=32768 \
+ -Wl,--export=__heap_base \
+ -Wl,--export=__data_end \
+ -Wl,--shared-memory,--max-memory=1966080 \
+ -Wl,--export=wasi_thread_start \
+ -Wl,--export=malloc \
+ -Wl,--export=free \
+ -I $WAMR_DIR/samples/wasi-threads/wasm-apps \
+ $thread_start_file \
+ $test_c -o $test_wasm
+done \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/common.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/common.h
new file mode 100644
index 000000000..01ca932c5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/common.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2022 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <limits.h>
+
+#if USE_CUSTOM_SYNC_PRIMITIVES != 0
+#include "sync_primitives.h"
+#else
+#include <pthread.h>
+#endif
+
+#include "wasi_thread_start.h"
+
+typedef enum {
+ BLOCKING_TASK_BUSY_WAIT,
+ BLOCKING_TASK_ATOMIC_WAIT,
+ BLOCKING_TASK_POLL_ONEOFF
+} blocking_task_type_t;
+
+/* Parameter to change test behavior */
+static bool termination_by_trap;
+static bool termination_in_main_thread;
+static blocking_task_type_t blocking_task_type;
+
+#define NUM_THREADS 3
+static pthread_barrier_t barrier;
+
+typedef struct {
+ start_args_t base;
+ bool throw_exception;
+} shared_t;
+
+void
+run_long_task()
+{
+ if (blocking_task_type == BLOCKING_TASK_BUSY_WAIT) {
+ for (;;) {
+ }
+ }
+ else if (blocking_task_type == BLOCKING_TASK_ATOMIC_WAIT) {
+ __builtin_wasm_memory_atomic_wait32(0, 0, -1);
+ }
+ else {
+ sleep(UINT_MAX);
+ }
+}
+
+void
+start_job()
+{
+ /* Wait for all threads (including the main thread) to be ready */
+ pthread_barrier_wait(&barrier);
+ run_long_task(); /* Task to be interrupted */
+ assert(false && "Thread termination test failed");
+}
+
+void
+terminate_process()
+{
+ /* Wait for all threads (including the main thread) to be ready */
+ pthread_barrier_wait(&barrier);
+
+ if (termination_by_trap)
+ __builtin_trap();
+ else
+ __wasi_proc_exit(33);
+}
+
+void
+__wasi_thread_start_C(int thread_id, int *start_arg)
+{
+ shared_t *data = (shared_t *)start_arg;
+
+ if (data->throw_exception) {
+ terminate_process();
+ }
+ else {
+ start_job();
+ }
+}
+
+void
+test_termination(bool trap, bool main, blocking_task_type_t task_type)
+{
+ termination_by_trap = trap;
+ termination_in_main_thread = main;
+ blocking_task_type = task_type;
+
+ int thread_id = -1, i;
+ shared_t data[NUM_THREADS] = { 0 };
+ assert(pthread_barrier_init(&barrier, NULL, NUM_THREADS + 1) == 0
+ && "Failed to init barrier");
+
+ for (i = 0; i < NUM_THREADS; i++) {
+ /* No graceful memory free to simplify the test */
+ assert(start_args_init(&data[i].base)
+ && "Failed to allocate thread's stack");
+ }
+
+ /* Create a thread that forces termination through trap or `proc_exit` */
+ data[0].throw_exception = !termination_in_main_thread;
+ thread_id = __wasi_thread_spawn(&data[0]);
+ assert(thread_id > 0 && "Failed to create thread");
+
+ /* Create two additional threads to test exception propagation */
+ data[1].throw_exception = false;
+ thread_id = __wasi_thread_spawn(&data[1]);
+ assert(thread_id > 0 && "Failed to create thread");
+ data[2].throw_exception = false;
+ thread_id = __wasi_thread_spawn(&data[2]);
+ assert(thread_id > 0 && "Failed to create thread");
+
+ if (termination_in_main_thread) {
+ terminate_process();
+ }
+ else {
+ start_job();
+ }
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c
new file mode 100644
index 000000000..23ba5f627
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/create_threads_until_limit.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdbool.h>
+
+#include "wasi_thread_start.h"
+
+enum CONSTANTS {
+ MAX_NUM_THREADS = 4, /* Should be the same as "--max-threads" */
+ NUM_RETRY = 5,
+ SECOND = 1000 * 1000 * 1000, /* 1 second */
+ TIMEOUT = 10LL * SECOND
+};
+
+int g_count = 0;
+
+typedef struct {
+ start_args_t base;
+ int th_ready;
+ int th_continue;
+ int th_done;
+ bool no_ops;
+} shared_t;
+
+void
+__wasi_thread_start_C(int thread_id, int *start_arg)
+{
+ shared_t *data = (shared_t *)start_arg;
+
+ if (data->no_ops) {
+ __builtin_wasm_memory_atomic_wait32(NULL, 0, 2 * SECOND);
+ return;
+ }
+
+ __atomic_store_n(&data->th_ready, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&data->th_ready, 1);
+
+ if (__builtin_wasm_memory_atomic_wait32(&data->th_continue, 0, TIMEOUT)
+ == 2) {
+ assert(false && "Wait should not time out");
+ }
+
+ __atomic_fetch_add(&g_count, 1, __ATOMIC_SEQ_CST);
+
+ __atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&data->th_done, 1);
+}
+
+int
+main(int argc, char **argv)
+{
+ shared_t data[MAX_NUM_THREADS] = { 0 };
+ int thread_ids[MAX_NUM_THREADS];
+
+ for (int i = 0; i < MAX_NUM_THREADS; i++) {
+ assert(start_args_init(&data[i].base));
+ thread_ids[i] = __wasi_thread_spawn(&data[i]);
+ printf("Thread created with id=%d\n", thread_ids[i]);
+ assert(thread_ids[i] > 0 && "Thread creation failed");
+
+ for (int j = 0; j < i; j++) {
+ assert(thread_ids[i] != thread_ids[j] && "Duplicated TIDs");
+ }
+
+ if (__builtin_wasm_memory_atomic_wait32(&data[i].th_ready, 0, TIMEOUT)
+ == 2) {
+ assert(false && "Wait should not time out");
+ }
+ }
+
+ printf("Attempt to create thread when not possible\n");
+ shared_t data_fail = { 0 };
+ assert(start_args_init(&data_fail.base));
+ int thread_id = __wasi_thread_spawn(&data_fail);
+ start_args_deinit(&data_fail.base);
+ assert(thread_id < 0 && "Thread creation should fail");
+
+ printf("Unlock created threads\n");
+ for (int i = 0; i < MAX_NUM_THREADS; i++) {
+ __atomic_store_n(&data[i].th_continue, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&data[i].th_continue, 1);
+ }
+
+ printf("Wait for threads to finish\n");
+ for (int i = 0; i < MAX_NUM_THREADS; i++) {
+ if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
+ == 2) {
+ assert(false && "Wait should not time out");
+ }
+
+ start_args_deinit(&data[i].base);
+ }
+
+ printf("Value of count after update: %d\n", g_count);
+ assert(g_count == (MAX_NUM_THREADS)
+ && "Global count not updated correctly");
+
+ /* --------------------------------------------------- */
+
+ printf("Create new threads without waiting from them to finish\n");
+ shared_t data_no_join[MAX_NUM_THREADS] = { 0 };
+ for (int i = 0; i < MAX_NUM_THREADS; i++) {
+ /* No graceful memory free to simplify the test */
+ assert(start_args_init(&data_no_join[i].base));
+ data_no_join[i].no_ops = true;
+
+ int thread_id = -1;
+ for (int j = 0; j < NUM_RETRY && thread_id < 0; j++) {
+ thread_id = __wasi_thread_spawn(&data_no_join[i]);
+ if (thread_id < 0)
+ __builtin_wasm_memory_atomic_wait32(NULL, 0, SECOND);
+ }
+
+ printf("Thread created with id=%d\n", thread_id);
+ assert(thread_id > 0 && "Thread creation should succeed");
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c
new file mode 100644
index 000000000..a38e75364
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_atomic.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdbool.h>
+
+#include "wasi_thread_start.h"
+
+enum CONSTANTS {
+ NUM_THREADS = 4,
+ NUM_ITER = 1000,
+ SECOND = 1000 * 1000 * 1000, /* 1 second */
+ TIMEOUT = 10LL * SECOND
+};
+
+int g_count = 0;
+
+typedef struct {
+ start_args_t base;
+ int th_done;
+} shared_t;
+
+void
+__wasi_thread_start_C(int thread_id, int *start_arg)
+{
+ shared_t *data = (shared_t *)start_arg;
+
+ for (int i = 0; i < NUM_ITER; i++)
+ __atomic_fetch_add(&g_count, 1, __ATOMIC_SEQ_CST);
+
+ __atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&data->th_done, 1);
+}
+
+int
+main(int argc, char **argv)
+{
+ shared_t data[NUM_THREADS] = { 0 };
+ int thread_ids[NUM_THREADS];
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ assert(start_args_init(&data[i].base));
+ thread_ids[i] = __wasi_thread_spawn(&data[i]);
+ assert(thread_ids[i] > 0 && "Thread creation failed");
+ }
+
+ printf("Wait for threads to finish\n");
+ for (int i = 0; i < NUM_THREADS; i++) {
+ if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
+ == 2) {
+ assert(false && "Wait should not time out");
+ }
+
+ start_args_deinit(&data[i].base);
+ }
+
+ printf("Value of count after update: %d\n", g_count);
+ assert(g_count == (NUM_THREADS * NUM_ITER)
+ && "Global count not updated correctly");
+
+ return EXIT_SUCCESS;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c
new file mode 100644
index 000000000..f81fca49b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/global_lock.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdbool.h>
+
+#if USE_CUSTOM_SYNC_PRIMITIVES != 0
+#include "sync_primitives.h"
+#else
+#include <pthread.h>
+#endif
+
+#include "wasi_thread_start.h"
+
+enum CONSTANTS {
+ NUM_THREADS = 4,
+ NUM_ITER = 200,
+ SECOND = 1000 * 1000 * 1000, /* 1 second */
+ TIMEOUT = 10LL * SECOND
+};
+
+pthread_mutex_t mutex;
+int g_count = 0;
+
+typedef struct {
+ start_args_t base;
+ int th_done;
+} shared_t;
+
+void
+__wasi_thread_start_C(int thread_id, int *start_arg)
+{
+ shared_t *data = (shared_t *)start_arg;
+
+ for (int i = 0; i < NUM_ITER; i++) {
+ pthread_mutex_lock(&mutex);
+ g_count++;
+ pthread_mutex_unlock(&mutex);
+ }
+
+ __atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&data->th_done, 1);
+}
+
+int
+main(int argc, char **argv)
+{
+ shared_t data[NUM_THREADS] = { 0 };
+ int thread_ids[NUM_THREADS];
+
+ assert(pthread_mutex_init(&mutex, NULL) == 0 && "Failed to init mutex");
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ assert(start_args_init(&data[i].base));
+ thread_ids[i] = __wasi_thread_spawn(&data[i]);
+ assert(thread_ids[i] > 0 && "Thread creation failed");
+ }
+
+ printf("Wait for threads to finish\n");
+ for (int i = 0; i < NUM_THREADS; i++) {
+ if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
+ == 2) {
+ assert(false && "Wait should not time out");
+ }
+
+ start_args_deinit(&data[i].base);
+ }
+
+ printf("Value of count after update: %d\n", g_count);
+ assert(g_count == (NUM_THREADS * NUM_ITER)
+ && "Global count not updated correctly");
+
+ assert(pthread_mutex_destroy(&mutex) == 0 && "Failed to destroy mutex");
+ return EXIT_SUCCESS;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/linear_memory_size_update.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/linear_memory_size_update.c
new file mode 100644
index 000000000..9dcb34a6c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/linear_memory_size_update.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+#include <stdlib.h>
+#include <pthread.h>
+
+typedef enum {
+ APP_STARTED,
+ THREAD_STARTED,
+ MEMORY_ALLOCATED,
+} app_state_t;
+typedef struct {
+
+ pthread_cond_t cond;
+ pthread_mutex_t mutex;
+ app_state_t state;
+ char *data;
+} context_t;
+
+void
+context_init(context_t *ctx)
+{
+ pthread_cond_init(&ctx->cond, NULL);
+ pthread_mutex_init(&ctx->mutex, NULL);
+ ctx->state = APP_STARTED;
+ ctx->data = NULL;
+}
+
+void
+context_destroy(context_t *ctx)
+{
+ pthread_cond_destroy(&ctx->cond);
+ pthread_mutex_destroy(&ctx->mutex);
+ if (ctx->data) {
+ free(ctx->data);
+ }
+}
+
+void
+context_set_state(context_t *ctx, app_state_t state)
+{
+ pthread_mutex_lock(&ctx->mutex);
+ ctx->state = state;
+ pthread_mutex_unlock(&ctx->mutex);
+ pthread_cond_signal(&ctx->cond);
+}
+
+void
+context_wait_for_state(context_t *ctx, app_state_t state)
+{
+ pthread_mutex_lock(&ctx->mutex);
+ while (ctx->state != state) {
+ pthread_cond_wait(&ctx->cond, &ctx->mutex);
+ }
+ pthread_mutex_unlock(&ctx->mutex);
+}
+
+void *
+fnc(void *p)
+{
+ context_t *ctx = (context_t *)p;
+ context_set_state(ctx, THREAD_STARTED);
+
+ context_wait_for_state(ctx, MEMORY_ALLOCATED);
+
+ // trigger memory.copy
+ __builtin_memcpy(ctx->data + 512 * 1024, ctx->data + 1024, 1024);
+
+ return NULL;
+}
+
+int
+main()
+{
+ context_t ctx;
+ context_init(&ctx);
+
+ pthread_t th;
+ pthread_create(&th, NULL, fnc, &ctx);
+
+ context_wait_for_state(&ctx, THREAD_STARTED);
+
+ // trigger memory.grow
+ ctx.data = calloc(1024 * 1024, 1);
+
+ context_set_state(&ctx, MEMORY_ALLOCATED);
+
+ pthread_join(th, NULL);
+
+ context_destroy(&ctx);
+
+ return 0;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.c
new file mode 100644
index 000000000..19d3ec256
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(false, true, BLOCKING_TASK_BUSY_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.json
new file mode 100644
index 000000000..5370f6670
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_busy.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 33
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.c
new file mode 100644
index 000000000..a667e9122
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(false, true, BLOCKING_TASK_POLL_ONEOFF);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.json
new file mode 100644
index 000000000..5370f6670
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_sleep.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 33
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.c
new file mode 100644
index 000000000..dc8615adb
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(false, true, BLOCKING_TASK_ATOMIC_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.json
new file mode 100644
index 000000000..5370f6670
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_proc_exit_wait.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 33
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.c
new file mode 100644
index 000000000..bb0ac8fa0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(true, true, BLOCKING_TASK_BUSY_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.json
new file mode 100644
index 000000000..07689a105
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_busy.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.c
new file mode 100644
index 000000000..a2c248882
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(true, true, BLOCKING_TASK_POLL_ONEOFF);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.json
new file mode 100644
index 000000000..07689a105
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_sleep.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.c
new file mode 100644
index 000000000..0904f34bb
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(true, true, BLOCKING_TASK_ATOMIC_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.json
new file mode 100644
index 000000000..07689a105
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/main_trap_wait.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.c
new file mode 100644
index 000000000..71fdcb817
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(false, false, BLOCKING_TASK_BUSY_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.json
new file mode 100644
index 000000000..5370f6670
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_busy.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 33
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.c
new file mode 100644
index 000000000..14352cf41
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(false, false, BLOCKING_TASK_POLL_ONEOFF);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.json
new file mode 100644
index 000000000..5370f6670
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_sleep.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 33
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.c
new file mode 100644
index 000000000..0963aa02f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(false, false, BLOCKING_TASK_ATOMIC_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.json
new file mode 100644
index 000000000..5370f6670
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_proc_exit_wait.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 33
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.c
new file mode 100644
index 000000000..b3e3af7dc
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(true, false, BLOCKING_TASK_BUSY_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.json
new file mode 100644
index 000000000..07689a105
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_busy.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.c
new file mode 100644
index 000000000..a68ae8be5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(true, false, BLOCKING_TASK_POLL_ONEOFF);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.json
new file mode 100644
index 000000000..07689a105
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_sleep.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.c
new file mode 100644
index 000000000..52c684a51
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include "common.h"
+
+int
+main(int argc, char **argv)
+{
+ test_termination(true, false, BLOCKING_TASK_ATOMIC_WAIT);
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.json
new file mode 100644
index 000000000..07689a105
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/nonmain_trap_wait.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/spawn_multiple_times.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/spawn_multiple_times.c
new file mode 100644
index 000000000..24664c470
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/spawn_multiple_times.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdbool.h>
+
+#include "wasi_thread_start.h"
+
+enum CONSTANTS {
+ NUM_ITER = 50,
+ NUM_RETRY = 5,
+ SECOND = 1000 * 1000 * 1000, /* 1 second */
+ TIMEOUT = 5LL * SECOND
+};
+
+typedef struct {
+ start_args_t base;
+ int th_done;
+} shared_t;
+
+int g_count = 0;
+
+void
+__wasi_thread_start_C(int thread_id, int *start_arg)
+{
+ shared_t *data = (shared_t *)start_arg;
+
+ g_count++;
+
+ __atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&data->th_done, 1);
+}
+
+int
+main(int argc, char **argv)
+{
+ shared_t data = { 0 };
+ assert(start_args_init(&data.base) && "Stack allocation for thread failed");
+
+ for (int i = 0; i < NUM_ITER; i++) {
+ data.th_done = 0;
+
+ printf("Creating thread\n");
+ int thread_id = -1;
+ for (int j = 0; j < NUM_RETRY && thread_id < 0; j++) {
+ thread_id = __wasi_thread_spawn(&data);
+ if (thread_id < 0)
+ __builtin_wasm_memory_atomic_wait32(NULL, 0, SECOND);
+ }
+ assert(thread_id > 0 && "Thread creation should succeed");
+
+ printf("Waiting for thread to finish\n");
+ if (__builtin_wasm_memory_atomic_wait32(&data.th_done, 0, TIMEOUT)
+ == 2) {
+ assert(false && "Wait should not time out");
+ }
+ printf("Thread has finished\n");
+ }
+
+ assert(g_count == NUM_ITER && "Count has not been updated correctly");
+
+ start_args_deinit(&data.base);
+ return EXIT_SUCCESS;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/sync_primitives.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/sync_primitives.h
new file mode 100644
index 000000000..4b7dac8ec
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/sync_primitives.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdbool.h>
+
+/* Mutex */
+
+typedef int pthread_mutex_t;
+
+int
+pthread_mutex_init(pthread_mutex_t *mutex, void *unused)
+{
+ *mutex = 0;
+ return 0;
+}
+
+int
+pthread_mutex_destroy(pthread_mutex_t *mutex)
+{
+ return 0;
+}
+
+static bool
+try_pthread_mutex_lock(pthread_mutex_t *mutex)
+{
+ int expected = 0;
+ return __atomic_compare_exchange_n(mutex, &expected, 1, false,
+ __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
+
+int
+pthread_mutex_lock(pthread_mutex_t *mutex)
+{
+ while (!try_pthread_mutex_lock(mutex))
+ __builtin_wasm_memory_atomic_wait32(mutex, 1, -1);
+ return 0;
+}
+
+int
+pthread_mutex_unlock(pthread_mutex_t *mutex)
+{
+ __atomic_store_n(mutex, 0, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(mutex, 1);
+ return 0;
+}
+
+/* Barrier */
+
+typedef struct {
+ int count;
+ int num_threads;
+ int mutex;
+ int ready;
+} pthread_barrier_t;
+
+int
+pthread_barrier_init(pthread_barrier_t *barrier, void *unused, int num_threads)
+{
+ barrier->count = 0;
+ barrier->num_threads = num_threads;
+ barrier->ready = 0;
+ pthread_mutex_init(&barrier->mutex, NULL);
+
+ return 0;
+}
+
+int
+pthread_barrier_wait(pthread_barrier_t *barrier)
+{
+ bool no_wait = false;
+ int count;
+
+ pthread_mutex_lock(&barrier->mutex);
+ count = barrier->count++;
+ if (barrier->count >= barrier->num_threads) {
+ no_wait = true;
+ barrier->count = 0;
+ }
+ pthread_mutex_unlock(&barrier->mutex);
+
+ if (no_wait) {
+ __atomic_store_n(&barrier->ready, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&barrier->ready, count);
+ return 0;
+ }
+
+ __builtin_wasm_memory_atomic_wait32(&barrier->ready, 0, -1);
+ return 0;
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c
new file mode 100644
index 000000000..69e125d40
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+#include "wasi_thread_start.h"
+
+enum CONSTANTS {
+ SECOND = 1000 * 1000 * 1000, /* 1 second */
+ TIMEOUT = 1LL * SECOND
+};
+
+typedef struct {
+ start_args_t base;
+} shared_t;
+
+void
+__wasi_thread_start_C(int thread_id, int *start_arg)
+{
+ /* Wait so that the exception is raised after the main thread has finished
+ * already */
+ __builtin_wasm_memory_atomic_wait32(NULL, 0, TIMEOUT);
+ __builtin_trap();
+}
+
+int
+main(int argc, char **argv)
+{
+ shared_t data = { 0 };
+
+ assert(start_args_init(&data.base));
+ int thread_id = __wasi_thread_spawn(&data);
+ assert(thread_id > 0 && "Thread creation failed");
+
+ return EXIT_SUCCESS;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json
new file mode 100644
index 000000000..9dc1e30d2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/trap_after_main_thread_finishes.json
@@ -0,0 +1,3 @@
+{
+ "exit_code": 1
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c
new file mode 100644
index 000000000..b7fb9afba
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/test/update_shared_data_and_alloc_heap.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 Amazon.com Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef __wasi__
+#error This example only compiles to WASM/WASI target
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <pthread.h>
+
+#include "wasi_thread_start.h"
+
+enum CONSTANTS {
+ NUM_THREADS = 4,
+ NUM_ITER = 30,
+ SECOND = 1000 * 1000 * 1000, /* 1 second */
+ TIMEOUT = 10LL * SECOND
+};
+
+typedef struct {
+ start_args_t base;
+ int th_done;
+ int *count;
+ int iteration;
+ int *pval;
+} shared_t;
+
+pthread_mutex_t mutex;
+int *vals[NUM_THREADS];
+
+void
+__wasi_thread_start_C(int thread_id, int *start_arg)
+{
+ shared_t *data = (shared_t *)start_arg;
+
+ for (int i = 0; i < NUM_ITER; i++)
+ __atomic_fetch_add(data->count, 1, __ATOMIC_SEQ_CST);
+
+ *vals[data->iteration] = data->iteration;
+
+ __atomic_store_n(&data->th_done, 1, __ATOMIC_SEQ_CST);
+ __builtin_wasm_memory_atomic_notify(&data->th_done, 1);
+}
+
+int
+main(int argc, char **argv)
+{
+ shared_t data[NUM_THREADS] = { 0 };
+ int thread_ids[NUM_THREADS];
+ int *count = calloc(1, sizeof(int));
+
+ assert(count != NULL && "Failed to call calloc");
+ assert(pthread_mutex_init(&mutex, NULL) == 0 && "Failed to init mutex");
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ vals[i] = malloc(sizeof(int));
+ assert(vals[i] != NULL && "Failed to call calloc");
+ }
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ assert(start_args_init(&data[i].base)
+ && "Stack allocation for thread failed");
+ __atomic_store_n(&data[i].count, count, __ATOMIC_SEQ_CST);
+ data[i].iteration = i;
+
+ thread_ids[i] = __wasi_thread_spawn(&data[i]);
+ assert(thread_ids[i] > 0 && "Thread creation failed");
+ }
+
+ printf("Wait for threads to finish\n");
+ for (int i = 0; i < NUM_THREADS; i++) {
+ if (__builtin_wasm_memory_atomic_wait32(&data[i].th_done, 0, TIMEOUT)
+ == 2) {
+ assert(false && "Wait should not time out");
+ }
+
+ start_args_deinit(&data[i].base);
+ }
+
+ assert(*count == (NUM_THREADS * NUM_ITER) && "Count not updated correctly");
+
+ for (int i = 0; i < NUM_THREADS; i++) {
+ printf("val=%d\n", *vals[i]);
+ assert(*vals[i] == i && "Value not updated correctly");
+ free(vals[i]);
+ }
+
+ free(count);
+ assert(pthread_mutex_destroy(&mutex) == 0 && "Failed to destroy mutex");
+
+ return EXIT_SUCCESS;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c
new file mode 100644
index 000000000..4d53da0c9
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "tid_allocator.h"
+#include "wasm_export.h"
+#include "bh_log.h"
+
+bh_static_assert(TID_MIN <= TID_MAX);
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+bool
+tid_allocator_init(TidAllocator *tid_allocator)
+{
+ tid_allocator->size = MIN(TID_ALLOCATOR_INIT_SIZE, TID_MAX - TID_MIN + 1);
+ tid_allocator->pos = tid_allocator->size;
+ tid_allocator->ids =
+ wasm_runtime_malloc(tid_allocator->size * sizeof(int32));
+ if (tid_allocator->ids == NULL)
+ return false;
+
+ for (int64 i = tid_allocator->pos - 1; i >= 0; i--)
+ tid_allocator->ids[i] = TID_MIN + (tid_allocator->pos - 1 - i);
+
+ return true;
+}
+
+void
+tid_allocator_deinit(TidAllocator *tid_allocator)
+{
+ wasm_runtime_free(tid_allocator->ids);
+}
+
+int32
+tid_allocator_get_tid(TidAllocator *tid_allocator)
+{
+ if (tid_allocator->pos == 0) { // Resize stack and push new thread ids
+ if (tid_allocator->size == TID_MAX - TID_MIN + 1) {
+ LOG_ERROR("Maximum thread identifier reached");
+ return -1;
+ }
+
+ uint32 old_size = tid_allocator->size;
+ uint32 new_size = MIN(tid_allocator->size * 2, TID_MAX - TID_MIN + 1);
+ if (new_size != TID_MAX - TID_MIN + 1
+ && new_size / 2 != tid_allocator->size) {
+ LOG_ERROR("Overflow detected during new size calculation");
+ return -1;
+ }
+
+ size_t realloc_size = new_size * sizeof(int32);
+ if (realloc_size / sizeof(int32) != new_size) {
+ LOG_ERROR("Overflow detected during realloc");
+ return -1;
+ }
+ int32 *tmp = wasm_runtime_realloc(tid_allocator->ids, realloc_size);
+ if (tmp == NULL) {
+ LOG_ERROR("Thread ID allocator realloc failed");
+ return -1;
+ }
+
+ tid_allocator->size = new_size;
+ tid_allocator->pos = new_size - old_size;
+ tid_allocator->ids = tmp;
+ for (int64 i = tid_allocator->pos - 1; i >= 0; i--)
+ tid_allocator->ids[i] = TID_MIN + (tid_allocator->size - 1 - i);
+ }
+
+ // Pop available thread identifier from the stack
+ return tid_allocator->ids[--tid_allocator->pos];
+}
+
+void
+tid_allocator_release_tid(TidAllocator *tid_allocator, int32 thread_id)
+{
+ // Release thread identifier by pushing it into the stack
+ bh_assert(tid_allocator->pos < tid_allocator->size);
+ tid_allocator->ids[tid_allocator->pos++] = thread_id;
+} \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h
new file mode 100644
index 000000000..53af1719f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/lib-wasi-threads/tid_allocator.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _TID_ALLOCATOR_H
+#define _TID_ALLOCATOR_H
+
+#include "platform_common.h"
+
+#define TID_ALLOCATOR_INIT_SIZE CLUSTER_MAX_THREAD_NUM
+enum {
+ TID_MIN = 1,
+ TID_MAX = 0x1FFFFFFF
+}; // Reserved TIDs (WASI specification)
+
+/* Stack data structure to track available thread identifiers */
+typedef struct {
+ int32 *ids; // Array used to store the stack
+ uint32 size; // Stack capacity
+ uint32 pos; // Index of the element after the stack top
+} TidAllocator;
+
+bool
+tid_allocator_init(TidAllocator *tid_allocator);
+
+void
+tid_allocator_deinit(TidAllocator *tid_allocator);
+
+int32
+tid_allocator_get_tid(TidAllocator *tid_allocator);
+
+void
+tid_allocator_release_tid(TidAllocator *tid_allocator, int32 thread_id);
+
+#endif /* _TID_ALLOCATOR_H */ \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/SConscript
new file mode 100644
index 000000000..8dd004382
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/SConscript
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+
+cwd = GetCurrentDir()
+
+#src = Split('''
+#libc_builtin_wrapper.c
+#''')
+
+src = Glob('*.c')
+
+CPPDEFINES = ['WASM_ENABLE_LIBC_BUILTIN=1']
+
+CPPPATH = [cwd]
+
+
+group = DefineGroup('iwasm_libc_builtin', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin.cmake
new file mode 100644
index 000000000..0838712b8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-builtin/libc_builtin.cmake
@@ -0,0 +1,13 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (LIBC_BUILTIN_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions (-DWASM_ENABLE_LIBC_BUILTIN=1)
+
+include_directories(${LIBC_BUILTIN_DIR})
+
+file (GLOB source_all ${LIBC_BUILTIN_DIR}/*.c)
+
+set (LIBC_BUILTIN_SOURCE ${source_all})
+
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;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/SConscript
new file mode 100644
index 000000000..432ed4a05
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/SConscript
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+
+cwd = GetCurrentDir()
+
+src = Split('''
+libc_emcc_wrapper.c
+''')
+
+CPPPATH = [cwd]
+
+group = DefineGroup('iwasm_libc_emcc', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc.cmake
new file mode 100644
index 000000000..d237a16ee
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc.cmake
@@ -0,0 +1,12 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (LIBC_EMCC_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions (-DWASM_ENABLE_LIBC_EMCC=1)
+
+include_directories(${LIBC_EMCC_DIR})
+
+file (GLOB source_all ${LIBC_EMCC_DIR}/*.c)
+
+set (LIBC_EMCC_SOURCE ${source_all}) \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c
new file mode 100644
index 000000000..23c02aad3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c
@@ -0,0 +1,554 @@
+/*
+ * Copyright (C) 2020 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(_DEFAULT_SOURCE) && !defined(BH_PLATFORM_LINUX_SGX)
+#include "sys/syscall.h"
+#endif
+
+/* 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 */
+
+static void
+invoke_viiii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0,
+ int arg1, int arg2, int arg3)
+{
+ uint32 argv[4];
+ bool ret;
+
+ argv[0] = arg0;
+ argv[1] = arg1;
+ argv[2] = arg2;
+ argv[3] = arg3;
+ ret = wasm_runtime_call_indirect(exec_env, elem_idx, 4, argv);
+ (void)ret;
+}
+
+static void
+invoke_viii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0,
+ int arg1, int arg2)
+{
+ uint32 argv[4];
+ bool ret;
+
+ argv[0] = arg0;
+ argv[1] = arg1;
+ argv[2] = arg2;
+ ret = wasm_runtime_call_indirect(exec_env, elem_idx, 3, argv);
+ (void)ret;
+}
+
+static void
+invoke_vii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0,
+ int arg1)
+{
+ uint32 argv[4];
+ bool ret;
+
+ argv[0] = arg0;
+ argv[1] = arg1;
+ ret = wasm_runtime_call_indirect(exec_env, elem_idx, 2, argv);
+ (void)ret;
+}
+
+static void
+invoke_vi_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0)
+{
+ uint32 argv[4];
+ bool ret;
+
+ argv[0] = arg0;
+ ret = wasm_runtime_call_indirect(exec_env, elem_idx, 1, argv);
+ (void)ret;
+}
+
+static int
+invoke_iii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0,
+ int arg1)
+{
+ uint32 argv[4];
+ bool ret;
+
+ argv[0] = arg0;
+ argv[1] = arg1;
+ ret = wasm_runtime_call_indirect(exec_env, elem_idx, 2, argv);
+ return ret ? argv[0] : 0;
+}
+
+static int
+invoke_ii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0)
+{
+ uint32 argv[4];
+ bool ret;
+
+ argv[0] = arg0;
+ ret = wasm_runtime_call_indirect(exec_env, elem_idx, 1, argv);
+ return ret ? argv[0] : 0;
+}
+
+struct timespec_emcc {
+ int tv_sec;
+ int tv_nsec;
+};
+
+struct stat_emcc {
+ unsigned st_dev;
+ int __st_dev_padding;
+ unsigned __st_ino_truncated;
+ unsigned st_mode;
+ unsigned st_nlink;
+ unsigned st_uid;
+ unsigned st_gid;
+ unsigned st_rdev;
+ int __st_rdev_padding;
+ int64 st_size;
+ int st_blksize;
+ int st_blocks;
+ struct timespec_emcc st_atim;
+ struct timespec_emcc st_mtim;
+ struct timespec_emcc st_ctim;
+ int64 st_ino;
+};
+
+static int
+open_wrapper(wasm_exec_env_t exec_env, const char *pathname, int flags,
+ int mode)
+{
+ if (pathname == NULL)
+ return -1;
+ return open(pathname, flags, mode);
+}
+
+static int
+__sys_read_wrapper(wasm_exec_env_t exec_env, int fd, void *buf, uint32 count)
+{
+ return read(fd, buf, count);
+}
+
+static void
+statbuf_native2app(const struct stat *statbuf_native,
+ struct stat_emcc *statbuf_app)
+{
+ statbuf_app->st_dev = (unsigned)statbuf_native->st_dev;
+ statbuf_app->__st_ino_truncated = (unsigned)statbuf_native->st_ino;
+ statbuf_app->st_mode = (unsigned)statbuf_native->st_mode;
+ statbuf_app->st_nlink = (unsigned)statbuf_native->st_nlink;
+ statbuf_app->st_uid = (unsigned)statbuf_native->st_uid;
+ statbuf_app->st_gid = (unsigned)statbuf_native->st_gid;
+ statbuf_app->st_rdev = (unsigned)statbuf_native->st_rdev;
+ statbuf_app->st_size = (int64)statbuf_native->st_size;
+ statbuf_app->st_blksize = (unsigned)statbuf_native->st_blksize;
+ statbuf_app->st_blocks = (unsigned)statbuf_native->st_blocks;
+ statbuf_app->st_ino = (int64)statbuf_native->st_ino;
+ statbuf_app->st_atim.tv_sec = (int)statbuf_native->st_atim.tv_sec;
+ statbuf_app->st_atim.tv_nsec = (int)statbuf_native->st_atim.tv_nsec;
+ statbuf_app->st_mtim.tv_sec = (int)statbuf_native->st_mtim.tv_sec;
+ statbuf_app->st_mtim.tv_nsec = (int)statbuf_native->st_mtim.tv_nsec;
+ statbuf_app->st_ctim.tv_sec = (int)statbuf_native->st_ctim.tv_sec;
+ statbuf_app->st_ctim.tv_nsec = (int)statbuf_native->st_ctim.tv_nsec;
+}
+
+static int
+__sys_stat64_wrapper(wasm_exec_env_t exec_env, const char *pathname,
+ struct stat_emcc *statbuf_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ int ret;
+ struct stat statbuf;
+
+ if (!validate_native_addr((void *)statbuf_app, sizeof(struct stat_emcc)))
+ return -1;
+
+ if (pathname == NULL)
+ return -1;
+
+ ret = stat(pathname, &statbuf);
+ if (ret == 0)
+ statbuf_native2app(&statbuf, statbuf_app);
+ return ret;
+}
+
+static int
+__sys_fstat64_wrapper(wasm_exec_env_t exec_env, int fd,
+ struct stat_emcc *statbuf_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ int ret;
+ struct stat statbuf;
+
+ if (!validate_native_addr((void *)statbuf_app, sizeof(struct stat_emcc)))
+ return -1;
+
+ if (fd <= 0)
+ return -1;
+
+ ret = fstat(fd, &statbuf);
+ if (ret == 0)
+ statbuf_native2app(&statbuf, statbuf_app);
+ return ret;
+}
+
+static int
+mmap_wrapper(wasm_exec_env_t exec_env, void *addr, int length, int prot,
+ int flags, int fd, int64 offset)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uint32 buf_offset;
+ char *buf;
+ int size_read;
+
+ buf_offset = module_malloc(length, (void **)&buf);
+ if (buf_offset == 0)
+ return -1;
+
+ if (fd <= 0)
+ return -1;
+
+ if (lseek(fd, offset, SEEK_SET) == -1)
+ return -1;
+
+ size_read = read(fd, buf, length);
+ (void)size_read;
+ return buf_offset;
+}
+
+static int
+munmap_wrapper(wasm_exec_env_t exec_env, uint32 buf_offset, int length)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ module_free(buf_offset);
+ return 0;
+}
+
+static int
+__munmap_wrapper(wasm_exec_env_t exec_env, uint32 buf_offset, int length)
+{
+ return munmap_wrapper(exec_env, buf_offset, length);
+}
+
+static int
+getentropy_wrapper(wasm_exec_env_t exec_env, void *buffer, uint32 length)
+{
+ if (buffer == NULL)
+ return -1;
+#if defined(_DEFAULT_SOURCE) || defined(BH_PLATFORM_LINUX_SGX)
+ return getentropy(buffer, length);
+#else
+ return syscall(SYS_getrandom, buffer, length, 0);
+#endif
+}
+
+static int
+setjmp_wrapper(wasm_exec_env_t exec_env, void *jmp_buf)
+{
+ os_printf("setjmp() called\n");
+ return 0;
+}
+
+static void
+longjmp_wrapper(wasm_exec_env_t exec_env, void *jmp_buf, int val)
+{
+ os_printf("longjmp() called\n");
+}
+
+#if !defined(BH_PLATFORM_LINUX_SGX)
+static FILE *file_list[32] = { 0 };
+
+static int
+get_free_file_slot()
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof(file_list) / sizeof(FILE *); i++) {
+ if (file_list[i] == NULL)
+ return (int)i;
+ }
+ return -1;
+}
+
+static int
+fopen_wrapper(wasm_exec_env_t exec_env, const char *pathname, const char *mode)
+{
+ FILE *file;
+ int file_id;
+
+ if (pathname == NULL || mode == NULL)
+ return 0;
+
+ if ((file_id = get_free_file_slot()) == -1)
+ return 0;
+
+ file = fopen(pathname, mode);
+ if (!file)
+ return 0;
+
+ file_list[file_id] = file;
+ return file_id + 1;
+}
+
+static uint32
+fread_wrapper(wasm_exec_env_t exec_env, void *ptr, uint32 size, uint32 nmemb,
+ int file_id)
+{
+ FILE *file;
+
+ file_id = file_id - 1;
+ if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *)) {
+ return 0;
+ }
+ if ((file = file_list[file_id]) == NULL) {
+ return 0;
+ }
+ return (uint32)fread(ptr, size, nmemb, file);
+}
+
+static int
+fseeko_wrapper(wasm_exec_env_t exec_env, int file_id, int64 offset, int whence)
+{
+ FILE *file;
+
+ file_id = file_id - 1;
+ if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *)) {
+ return -1;
+ }
+ if ((file = file_list[file_id]) == NULL) {
+ return -1;
+ }
+ return (uint32)fseek(file, offset, whence);
+}
+
+static uint32
+emcc_fwrite_wrapper(wasm_exec_env_t exec_env, const void *ptr, uint32 size,
+ uint32 nmemb, int file_id)
+{
+ FILE *file;
+
+ file_id = file_id - 1;
+ if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *)) {
+ return 0;
+ }
+ if ((file = file_list[file_id]) == NULL) {
+ return 0;
+ }
+ return (uint32)fwrite(ptr, size, nmemb, file);
+}
+
+static int
+feof_wrapper(wasm_exec_env_t exec_env, int file_id)
+{
+ FILE *file;
+
+ file_id = file_id - 1;
+ if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *))
+ return 1;
+ if ((file = file_list[file_id]) == NULL)
+ return 1;
+ return feof(file);
+}
+
+static int
+fclose_wrapper(wasm_exec_env_t exec_env, int file_id)
+{
+ FILE *file;
+
+ file_id = file_id - 1;
+ if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *))
+ return -1;
+ if ((file = file_list[file_id]) == NULL)
+ return -1;
+ file_list[file_id] = NULL;
+ return fclose(file);
+}
+
+static int
+__sys_mkdir_wrapper(wasm_exec_env_t exec_env, const char *pathname, int mode)
+{
+ if (!pathname)
+ return -1;
+ return mkdir(pathname, mode);
+}
+
+static int
+__sys_rmdir_wrapper(wasm_exec_env_t exec_env, const char *pathname)
+{
+ if (!pathname)
+ return -1;
+ return rmdir(pathname);
+}
+
+static int
+__sys_unlink_wrapper(wasm_exec_env_t exec_env, const char *pathname)
+{
+ if (!pathname)
+ return -1;
+ return unlink(pathname);
+}
+
+static uint32
+__sys_getcwd_wrapper(wasm_exec_env_t exec_env, char *buf, uint32 size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ char *ret;
+
+ if (!buf)
+ return -1;
+
+ ret = getcwd(buf, size);
+ return ret ? addr_native_to_app(ret) : 0;
+}
+
+#include <sys/utsname.h>
+
+struct utsname_app {
+ char sysname[64];
+ char nodename[64];
+ char release[64];
+ char version[64];
+ char machine[64];
+ char domainname[64];
+};
+
+static int
+__sys_uname_wrapper(wasm_exec_env_t exec_env, struct utsname_app *uname_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ struct utsname uname_native = { 0 };
+ uint32 length;
+
+ if (!validate_native_addr(uname_app, sizeof(struct utsname_app)))
+ return -1;
+
+ if (uname(&uname_native) != 0) {
+ return -1;
+ }
+
+ memset(uname_app, 0, sizeof(struct utsname_app));
+
+ length = strlen(uname_native.sysname);
+ if (length > sizeof(uname_app->sysname) - 1)
+ length = sizeof(uname_app->sysname) - 1;
+ bh_memcpy_s(uname_app->sysname, sizeof(uname_app->sysname),
+ uname_native.sysname, length);
+
+ length = strlen(uname_native.nodename);
+ if (length > sizeof(uname_app->nodename) - 1)
+ length = sizeof(uname_app->nodename) - 1;
+ bh_memcpy_s(uname_app->nodename, sizeof(uname_app->nodename),
+ uname_native.nodename, length);
+
+ length = strlen(uname_native.release);
+ if (length > sizeof(uname_app->release) - 1)
+ length = sizeof(uname_app->release) - 1;
+ bh_memcpy_s(uname_app->release, sizeof(uname_app->release),
+ uname_native.release, length);
+
+ length = strlen(uname_native.version);
+ if (length > sizeof(uname_app->version) - 1)
+ length = sizeof(uname_app->version) - 1;
+ bh_memcpy_s(uname_app->version, sizeof(uname_app->version),
+ uname_native.version, length);
+
+#ifdef _GNU_SOURCE
+ length = strlen(uname_native.domainname);
+ if (length > sizeof(uname_app->domainname) - 1)
+ length = sizeof(uname_app->domainname) - 1;
+ bh_memcpy_s(uname_app->domainname, sizeof(uname_app->domainname),
+ uname_native.domainname, length);
+#endif
+
+ return 0;
+}
+
+static void
+emscripten_notify_memory_growth_wrapper(wasm_exec_env_t exec_env, int i)
+{
+ (void)i;
+}
+
+static void
+emscripten_thread_sleep_wrapper(wasm_exec_env_t exec_env, double timeout_ms)
+{
+ uint64 ms = (uint64)timeout_ms;
+ uint64 sec = ms / 1000, us = (ms % 1000) * 1000;
+
+ if (sec > 0)
+ sleep(sec);
+ if (us > 0)
+ usleep(us);
+}
+
+#endif /* end of BH_PLATFORM_LINUX_SGX */
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, func_name##_wrapper, signature, NULL }
+/* clang-format off */
+
+static NativeSymbol native_symbols_libc_emcc[] = {
+ REG_NATIVE_FUNC(invoke_viiii, "(iiiii)"),
+ REG_NATIVE_FUNC(invoke_viii, "(iiii)"),
+ REG_NATIVE_FUNC(invoke_vii, "(iii)"),
+ REG_NATIVE_FUNC(invoke_vi, "(ii)"),
+ REG_NATIVE_FUNC(invoke_iii, "(iii)i"),
+ REG_NATIVE_FUNC(invoke_ii, "(ii)i"),
+ REG_NATIVE_FUNC(open, "($ii)i"),
+ REG_NATIVE_FUNC(__sys_read, "(i*~)i"),
+ REG_NATIVE_FUNC(__sys_stat64, "($*)i"),
+ REG_NATIVE_FUNC(__sys_fstat64, "(i*)i"),
+ REG_NATIVE_FUNC(mmap, "(*iiiiI)i"),
+ REG_NATIVE_FUNC(munmap, "(ii)i"),
+ REG_NATIVE_FUNC(__munmap, "(ii)i"),
+ REG_NATIVE_FUNC(getentropy, "(*~)i"),
+ REG_NATIVE_FUNC(setjmp, "(*)i"),
+ REG_NATIVE_FUNC(longjmp, "(*i)"),
+#if !defined(BH_PLATFORM_LINUX_SGX)
+ REG_NATIVE_FUNC(fopen, "($$)i"),
+ REG_NATIVE_FUNC(fread, "(*iii)i"),
+ REG_NATIVE_FUNC(fseeko, "(iIi)i"),
+ REG_NATIVE_FUNC(emcc_fwrite, "(*iii)i"),
+ REG_NATIVE_FUNC(feof, "(i)i"),
+ REG_NATIVE_FUNC(fclose, "(i)i"),
+ REG_NATIVE_FUNC(__sys_mkdir, "($i)i"),
+ REG_NATIVE_FUNC(__sys_rmdir, "($)i"),
+ REG_NATIVE_FUNC(__sys_unlink, "($)i"),
+ REG_NATIVE_FUNC(__sys_getcwd, "(*~)i"),
+ REG_NATIVE_FUNC(__sys_uname, "(*)i"),
+ REG_NATIVE_FUNC(emscripten_notify_memory_growth, "(i)"),
+ REG_NATIVE_FUNC(emscripten_thread_sleep, "(F)"),
+#endif /* end of BH_PLATFORM_LINUX_SGX */
+};
+
+uint32
+get_libc_emcc_export_apis(NativeSymbol **p_libc_emcc_apis)
+{
+ *p_libc_emcc_apis = native_symbols_libc_emcc;
+ return sizeof(native_symbols_libc_emcc) / sizeof(NativeSymbol);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_LIBUV b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_LIBUV
new file mode 100644
index 000000000..eb126dab3
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_LIBUV
@@ -0,0 +1,66 @@
+libuv is licensed for use as follows:
+
+====
+Copyright (c) 2015-present libuv project contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
+====
+
+This license applies to parts of libuv originating from the
+https://github.com/joyent/libuv repository:
+
+====
+
+Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
+
+====
+
+This license applies to all parts of libuv that are not externally
+maintained libraries.
+
+The externally maintained libraries used by libuv are:
+
+ - tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license.
+
+ - inet_pton and inet_ntop implementations, contained in src/inet.c, are
+ copyright the Internet Systems Consortium, Inc., and licensed under the ISC
+ license.
+
+ - stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three
+ clause BSD license.
+
+ - pthread-fixes.c, copyright Google Inc. and Sony Mobile Communications AB.
+ Three clause BSD license.
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_UVWASI b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_UVWASI
new file mode 100644
index 000000000..dfb8546af
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/LICENSE_UVWASI
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Colin Ihrig and Contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake
new file mode 100644
index 000000000..e0c8afa21
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi.cmake
@@ -0,0 +1,44 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (LIBC_WASI_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+set (LIBUV_VERSION v1.44.2)
+
+add_definitions (-DWASM_ENABLE_LIBC_WASI=1 -DWASM_ENABLE_UVWASI=1)
+
+include(FetchContent)
+
+## libuv
+FetchContent_Declare(
+ libuv
+ GIT_REPOSITORY https://github.com/libuv/libuv.git
+ GIT_TAG ${LIBUV_VERSION}
+)
+FetchContent_GetProperties(libuv)
+if (NOT libuv_POPULATED)
+ message("-- Fetching libuv ..")
+ FetchContent_Populate(libuv)
+ include_directories("${libuv_SOURCE_DIR}/include")
+ add_subdirectory(${libuv_SOURCE_DIR} ${libuv_BINARY_DIR} EXCLUDE_FROM_ALL)
+ set (UV_A_LIBS uv_a)
+ set_target_properties(uv_a PROPERTIES POSITION_INDEPENDENT_CODE 1)
+endif()
+
+## uvwasi
+FetchContent_Declare(
+ uvwasi
+ GIT_REPOSITORY https://github.com/nodejs/uvwasi.git
+ GIT_TAG main
+)
+FetchContent_GetProperties(uvwasi)
+if (NOT uvwasi_POPULATED)
+ message("-- Fetching uvwasi ..")
+ FetchContent_Populate(uvwasi)
+ include_directories("${uvwasi_SOURCE_DIR}/include")
+ add_subdirectory(${uvwasi_SOURCE_DIR} ${uvwasi_BINARY_DIR} EXCLUDE_FROM_ALL)
+endif()
+
+file (GLOB_RECURSE source_all ${LIBC_WASI_DIR}/*.c ${uvwasi_SOURCE_DIR}/src/*.c)
+
+set (LIBC_WASI_SOURCE ${source_all})
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c
new file mode 100644
index 000000000..504ff7f93
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-uvwasi/libc_uvwasi_wrapper.c
@@ -0,0 +1,1150 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "uvwasi.h"
+#include "bh_platform.h"
+#include "wasm_export.h"
+
+/* 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_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 */
+
+#define wasi_errno_t uvwasi_errno_t
+#define wasi_fd_t uvwasi_fd_t
+#define wasi_clockid_t uvwasi_clockid_t
+#define wasi_timestamp_t uvwasi_timestamp_t
+#define wasi_filesize_t uvwasi_filesize_t
+#define wasi_prestat_app_t uvwasi_prestat_app_t
+#define wasi_filedelta_t uvwasi_filedelta_t
+#define wasi_whence_t uvwasi_whence_t
+#define wasi_fdflags_t uvwasi_fdflags_t
+#define wasi_rights_t uvwasi_rights_t
+#define wasi_advice_t uvwasi_advice_t
+#define wasi_lookupflags_t uvwasi_lookupflags_t
+#define wasi_preopentype_t uvwasi_preopentype_t
+#define wasi_fdstat_t uvwasi_fdstat_t
+#define wasi_oflags_t uvwasi_oflags_t
+#define wasi_dircookie_t uvwasi_dircookie_t
+#define wasi_filestat_t uvwasi_filestat_t
+#define wasi_fstflags_t uvwasi_fstflags_t
+#define wasi_subscription_t uvwasi_subscription_t
+#define wasi_event_t uvwasi_event_t
+#define wasi_exitcode_t uvwasi_exitcode_t
+#define wasi_signal_t uvwasi_signal_t
+#define wasi_riflags_t uvwasi_riflags_t
+#define wasi_roflags_t uvwasi_roflags_t
+#define wasi_siflags_t uvwasi_siflags_t
+#define wasi_sdflags_t uvwasi_sdflags_t
+#define wasi_iovec_t uvwasi_iovec_t
+#define wasi_ciovec_t uvwasi_ciovec_t
+
+typedef struct wasi_prestat_app {
+ wasi_preopentype_t pr_type;
+ uint32 pr_name_len;
+} wasi_prestat_app_t;
+
+typedef struct iovec_app {
+ uint32 buf_offset;
+ uint32 buf_len;
+} iovec_app_t;
+
+typedef struct WASIContext {
+ uvwasi_t uvwasi;
+ uint32_t exit_code;
+} WASIContext;
+
+void *
+wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst);
+
+static uvwasi_t *
+get_wasi_ctx(wasm_module_inst_t module_inst)
+{
+ WASIContext *ctx = wasm_runtime_get_wasi_ctx(module_inst);
+ if (ctx == NULL) {
+ return NULL;
+ }
+ return &ctx->uvwasi;
+}
+
+static wasi_errno_t
+wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_size_t argc, argv_buf_size, i;
+ char **argv;
+ uint64 total_size;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_args_sizes_get(uvwasi, &argc, &argv_buf_size);
+ if (err)
+ return err;
+
+ total_size = sizeof(int32) * ((uint64)argc + 1);
+ if (total_size >= UINT32_MAX
+ || !validate_native_addr(argv_offsets, (uint32)total_size)
+ || argv_buf_size >= UINT32_MAX
+ || !validate_native_addr(argv_buf, (uint32)argv_buf_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(char *) * ((uint64)argc + 1);
+ if (total_size >= UINT32_MAX
+ || !(argv = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_args_get(uvwasi, argv, argv_buf);
+ if (err) {
+ wasm_runtime_free(argv);
+ return err;
+ }
+
+ for (i = 0; i < argc; i++)
+ argv_offsets[i] = addr_native_to_app(argv[i]);
+
+ wasm_runtime_free(argv);
+ return 0;
+}
+
+static wasi_errno_t
+wasi_args_sizes_get(wasm_exec_env_t exec_env, uint32 *argc_app,
+ uint32 *argv_buf_size_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_size_t argc, argv_buf_size;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(argc_app, sizeof(uint32))
+ || !validate_native_addr(argv_buf_size_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_args_sizes_get(uvwasi, &argc, &argv_buf_size);
+ if (err)
+ return err;
+
+ *argc_app = (uint32)argc;
+ *argv_buf_size_app = (uint32)argv_buf_size;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_clock_res_get(wasm_exec_env_t exec_env, wasi_clockid_t clock_id,
+ wasi_timestamp_t *resolution)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!validate_native_addr(resolution, sizeof(wasi_timestamp_t)))
+ return (wasi_errno_t)-1;
+
+ return uvwasi_clock_res_get(uvwasi, clock_id, resolution);
+}
+
+static wasi_errno_t
+wasi_clock_time_get(wasm_exec_env_t exec_env, wasi_clockid_t clock_id,
+ wasi_timestamp_t precision, wasi_timestamp_t *time)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!validate_native_addr(time, sizeof(wasi_timestamp_t)))
+ return (wasi_errno_t)-1;
+
+ return uvwasi_clock_time_get(uvwasi, clock_id, precision, time);
+}
+
+static wasi_errno_t
+wasi_environ_get(wasm_exec_env_t exec_env, uint32 *environ_offsets,
+ char *environ_buf)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_size_t environ_count, environ_buf_size, i;
+ uint64 total_size;
+ char **environs;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_environ_sizes_get(uvwasi, &environ_count, &environ_buf_size);
+ if (err)
+ return err;
+
+ if (environ_count == 0)
+ return 0;
+
+ total_size = sizeof(int32) * ((uint64)environ_count + 1);
+ if (total_size >= UINT32_MAX
+ || !validate_native_addr(environ_offsets, (uint32)total_size)
+ || environ_buf_size >= UINT32_MAX
+ || !validate_native_addr(environ_buf, (uint32)environ_buf_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(char *) * (((uint64)environ_count + 1));
+
+ if (total_size >= UINT32_MAX
+ || !(environs = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_environ_get(uvwasi, environs, environ_buf);
+ if (err) {
+ wasm_runtime_free(environs);
+ return err;
+ }
+
+ for (i = 0; i < environ_count; i++)
+ environ_offsets[i] = addr_native_to_app(environs[i]);
+
+ wasm_runtime_free(environs);
+ return 0;
+}
+
+static wasi_errno_t
+wasi_environ_sizes_get(wasm_exec_env_t exec_env, uint32 *environ_count_app,
+ uint32 *environ_buf_size_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_size_t environ_count, environ_buf_size;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(environ_count_app, sizeof(uint32))
+ || !validate_native_addr(environ_buf_size_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_environ_sizes_get(uvwasi, &environ_count, &environ_buf_size);
+ if (err)
+ return err;
+
+ *environ_count_app = (uint32)environ_count;
+ *environ_buf_size_app = (uint32)environ_buf_size;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_fd_prestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_prestat_app_t *prestat_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_prestat_t prestat;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(prestat_app, sizeof(wasi_prestat_app_t)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_fd_prestat_get(uvwasi, fd, &prestat);
+ if (err)
+ return err;
+
+ prestat_app->pr_type = prestat.pr_type;
+ prestat_app->pr_name_len = (uint32)prestat.u.dir.pr_name_len;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_fd_prestat_dir_name(wasm_exec_env_t exec_env, wasi_fd_t fd, char *path,
+ uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_prestat_dir_name(uvwasi, fd, path, path_len);
+}
+
+static wasi_errno_t
+wasi_fd_close(wasm_exec_env_t exec_env, wasi_fd_t fd)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_close(uvwasi, fd);
+}
+
+static wasi_errno_t
+wasi_fd_datasync(wasm_exec_env_t exec_env, wasi_fd_t fd)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_datasync(uvwasi, fd);
+}
+
+static wasi_errno_t
+wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app,
+ uint32 iovs_len, wasi_filesize_t offset, uint32 *nread_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_iovec_t *iovec, *iovec_begin;
+ uint64 total_size;
+ uvwasi_size_t nread;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nread_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr(iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ iovec = iovec_begin;
+ for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset);
+ iovec->buf_len = iovec_app->buf_len;
+ }
+
+ err = uvwasi_fd_pread(uvwasi, fd, iovec_begin, iovs_len, offset, &nread);
+ if (err)
+ goto fail;
+
+ *nread_app = (uint32)nread;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(iovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const iovec_app_t *iovec_app, uint32 iovs_len,
+ wasi_filesize_t offset, uint32 *nwritten_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_ciovec_t *ciovec, *ciovec_begin;
+ uint64 total_size;
+ uvwasi_size_t nwritten;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr((void *)iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ ciovec = ciovec_begin;
+ for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset);
+ ciovec->buf_len = iovec_app->buf_len;
+ }
+
+ err =
+ uvwasi_fd_pwrite(uvwasi, fd, ciovec_begin, iovs_len, offset, &nwritten);
+ if (err)
+ goto fail;
+
+ *nwritten_app = (uint32)nwritten;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(ciovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const iovec_app_t *iovec_app, uint32 iovs_len, uint32 *nread_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_iovec_t *iovec, *iovec_begin;
+ uint64 total_size;
+ uvwasi_size_t nread;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nread_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr((void *)iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ iovec = iovec_begin;
+ for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset);
+ iovec->buf_len = iovec_app->buf_len;
+ }
+
+ err = uvwasi_fd_read(uvwasi, fd, iovec_begin, iovs_len, &nread);
+ if (err)
+ goto fail;
+
+ *nread_app = (uint32)nread;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(iovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_renumber(wasm_exec_env_t exec_env, wasi_fd_t from, wasi_fd_t to)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_renumber(uvwasi, from, to);
+}
+
+static wasi_errno_t
+wasi_fd_seek(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filedelta_t offset,
+ wasi_whence_t whence, wasi_filesize_t *newoffset)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t)))
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_seek(uvwasi, fd, offset, whence, newoffset);
+}
+
+static wasi_errno_t
+wasi_fd_tell(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t *newoffset)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t)))
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_tell(uvwasi, fd, newoffset);
+}
+
+static wasi_errno_t
+wasi_fd_fdstat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_fdstat_t *fdstat_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_fdstat_t fdstat;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(fdstat_app, sizeof(wasi_fdstat_t)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_fd_fdstat_get(uvwasi, fd, &fdstat);
+ if (err)
+ return err;
+
+ memcpy(fdstat_app, &fdstat, sizeof(wasi_fdstat_t));
+ return 0;
+}
+
+static wasi_errno_t
+wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_fdflags_t flags)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_fdstat_set_flags(uvwasi, fd, flags);
+}
+
+static wasi_errno_t
+wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_rights_t fs_rights_base,
+ wasi_rights_t fs_rights_inheriting)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_fdstat_set_rights(uvwasi, fd, fs_rights_base,
+ fs_rights_inheriting);
+}
+
+static wasi_errno_t
+wasi_fd_sync(wasm_exec_env_t exec_env, wasi_fd_t fd)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_sync(uvwasi, fd);
+}
+
+static wasi_errno_t
+wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const iovec_app_t *iovec_app, uint32 iovs_len,
+ uint32 *nwritten_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_ciovec_t *ciovec, *ciovec_begin;
+ uint64 total_size;
+ uvwasi_size_t nwritten;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr((void *)iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ ciovec = ciovec_begin;
+ for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset);
+ ciovec->buf_len = iovec_app->buf_len;
+ }
+
+#ifndef BH_VPRINTF
+ err = uvwasi_fd_write(uvwasi, fd, ciovec_begin, iovs_len, &nwritten);
+#else
+ /* redirect stdout/stderr output to BH_VPRINTF function */
+ if (fd == 1 || fd == 2) {
+ int i;
+ const struct iovec *iov1 = (const struct iovec *)ciovec_begin;
+
+ nwritten = 0;
+ for (i = 0; i < (int)iovs_len; i++, iov1++) {
+ if (iov1->iov_len > 0 && iov1->iov_base) {
+ char format[16];
+
+ /* make up format string "%.ns" */
+ snprintf(format, sizeof(format), "%%.%ds", (int)iov1->iov_len);
+ nwritten += (uvwasi_size_t)os_printf(format, iov1->iov_base);
+ }
+ }
+ err = 0;
+ }
+ else {
+ err = uvwasi_fd_write(uvwasi, fd, ciovec_begin, iovs_len, &nwritten);
+ }
+#endif /* end of BH_VPRINTF */
+
+ if (err)
+ goto fail;
+
+ *nwritten_app = (uint32)nwritten;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(ciovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_advise(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset,
+ wasi_filesize_t len, wasi_advice_t advice)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_advise(uvwasi, fd, offset, len, advice);
+}
+
+static wasi_errno_t
+wasi_fd_allocate(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset,
+ wasi_filesize_t len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_allocate(uvwasi, fd, offset, len);
+}
+
+static wasi_errno_t
+wasi_path_create_directory(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const char *path, uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_create_directory(uvwasi, fd, path, path_len);
+}
+
+static wasi_errno_t
+wasi_path_link(wasm_exec_env_t exec_env, wasi_fd_t old_fd,
+ wasi_lookupflags_t old_flags, const char *old_path,
+ uint32 old_path_len, wasi_fd_t new_fd, const char *new_path,
+ uint32 new_path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_link(uvwasi, old_fd, old_flags, old_path, old_path_len,
+ new_fd, new_path, new_path_len);
+}
+
+static wasi_errno_t
+wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd,
+ wasi_lookupflags_t dirflags, const char *path, uint32 path_len,
+ wasi_oflags_t oflags, wasi_rights_t fs_rights_base,
+ wasi_rights_t fs_rights_inheriting, wasi_fdflags_t fs_flags,
+ wasi_fd_t *fd_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_fd_t fd = (wasi_fd_t)-1; /* set fd_app -1 if path open failed */
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(fd_app, sizeof(wasi_fd_t)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_path_open(uvwasi, dirfd, dirflags, path, path_len, oflags,
+ fs_rights_base, fs_rights_inheriting, fs_flags, &fd);
+
+ *fd_app = fd;
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, void *buf,
+ uint32 buf_len, wasi_dircookie_t cookie, uint32 *bufused_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_size_t bufused;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(bufused_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_fd_readdir(uvwasi, fd, buf, buf_len, cookie, &bufused);
+ if (err)
+ return err;
+
+ *bufused_app = (uint32)bufused;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path,
+ uint32 path_len, char *buf, uint32 buf_len,
+ uint32 *bufused_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_size_t bufused;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(bufused_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_path_readlink(uvwasi, fd, path, path_len, buf, buf_len,
+ &bufused);
+ if (err)
+ return err;
+
+ *bufused_app = (uint32)bufused;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_path_rename(wasm_exec_env_t exec_env, wasi_fd_t old_fd,
+ const char *old_path, uint32 old_path_len, wasi_fd_t new_fd,
+ const char *new_path, uint32 new_path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_rename(uvwasi, old_fd, old_path, old_path_len, new_fd,
+ new_path, new_path_len);
+}
+
+static wasi_errno_t
+wasi_fd_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_filestat_t *filestat)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(filestat, sizeof(wasi_filestat_t)))
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_filestat_get(uvwasi, fd, filestat);
+}
+
+static wasi_errno_t
+wasi_fd_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_timestamp_t st_atim, wasi_timestamp_t st_mtim,
+ wasi_fstflags_t fstflags)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_filestat_set_times(uvwasi, fd, st_atim, st_mtim, fstflags);
+}
+
+static wasi_errno_t
+wasi_fd_filestat_set_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_filesize_t st_size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_fd_filestat_set_size(uvwasi, fd, st_size);
+}
+
+static wasi_errno_t
+wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_lookupflags_t flags, const char *path,
+ uint32 path_len, wasi_filestat_t *filestat)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(filestat, sizeof(wasi_filestat_t)))
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_filestat_get(uvwasi, fd, flags, path, path_len,
+ filestat);
+}
+
+static wasi_errno_t
+wasi_path_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_lookupflags_t flags, const char *path,
+ uint32 path_len, wasi_timestamp_t st_atim,
+ wasi_timestamp_t st_mtim, wasi_fstflags_t fstflags)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_filestat_set_times(uvwasi, fd, flags, path, path_len,
+ st_atim, st_mtim, fstflags);
+}
+
+static wasi_errno_t
+wasi_path_symlink(wasm_exec_env_t exec_env, const char *old_path,
+ uint32 old_path_len, wasi_fd_t fd, const char *new_path,
+ uint32 new_path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_symlink(uvwasi, old_path, old_path_len, fd, new_path,
+ new_path_len);
+}
+
+static wasi_errno_t
+wasi_path_unlink_file(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path,
+ uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_unlink_file(uvwasi, fd, path, path_len);
+}
+
+static wasi_errno_t
+wasi_path_remove_directory(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const char *path, uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_path_remove_directory(uvwasi, fd, path, path_len);
+}
+
+static wasi_errno_t
+wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in,
+ wasi_event_t *out, uint32 nsubscriptions, uint32 *nevents_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ uvwasi_size_t nevents;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr((void *)in, sizeof(wasi_subscription_t))
+ || !validate_native_addr(out, sizeof(wasi_event_t))
+ || !validate_native_addr(nevents_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = uvwasi_poll_oneoff(uvwasi, in, out, nsubscriptions, &nevents);
+ if (err)
+ return err;
+
+ *nevents_app = (uint32)nevents;
+ return 0;
+}
+
+static void
+wasi_proc_exit(wasm_exec_env_t exec_env, wasi_exitcode_t rval)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ WASIContext *wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
+ /* Here throwing exception is just to let wasm app exit,
+ the upper layer should clear the exception and return
+ as normal */
+ wasm_runtime_set_exception(module_inst, "wasi proc exit");
+ wasi_ctx->exit_code = rval;
+}
+
+static wasi_errno_t
+wasi_proc_raise(wasm_exec_env_t exec_env, wasi_signal_t sig)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ char buf[32];
+
+ snprintf(buf, sizeof(buf), "%s%d", "wasi proc raise ", sig);
+ wasm_runtime_set_exception(module_inst, buf);
+ return 0;
+}
+
+static wasi_errno_t
+wasi_random_get(wasm_exec_env_t exec_env, void *buf, uint32 buf_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ return uvwasi_random_get(uvwasi, buf, buf_len);
+}
+
+static wasi_errno_t
+wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data,
+ uint32 ri_data_len, wasi_riflags_t ri_flags,
+ uint32 *ro_datalen_app, wasi_roflags_t *ro_flags)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_iovec_t *iovec, *iovec_begin;
+ uint64 total_size;
+ uvwasi_size_t ro_datalen;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)ri_data_len;
+ if (!validate_native_addr(ro_datalen_app, (uint32)sizeof(uint32))
+ || !validate_native_addr(ro_flags, (uint32)sizeof(wasi_roflags_t))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr(ri_data, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_iovec_t) * (uint64)ri_data_len;
+ if (total_size >= UINT32_MAX
+ || !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ iovec = iovec_begin;
+ for (i = 0; i < ri_data_len; i++, ri_data++, iovec++) {
+ if (!validate_app_addr(ri_data->buf_offset, ri_data->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ iovec->buf = (void *)addr_app_to_native(ri_data->buf_offset);
+ iovec->buf_len = ri_data->buf_len;
+ }
+
+ err = uvwasi_sock_recv(uvwasi, sock, iovec_begin, ri_data_len, ri_flags,
+ &ro_datalen, ro_flags);
+ if (err)
+ goto fail;
+
+ *(uint32 *)ro_datalen_app = (uint32)ro_datalen;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(iovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock,
+ const iovec_app_t *si_data, uint32 si_data_len,
+ wasi_siflags_t si_flags, uint32 *so_datalen_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+ wasi_ciovec_t *ciovec, *ciovec_begin;
+ uint64 total_size;
+ uvwasi_size_t so_datalen;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)si_data_len;
+ if (!validate_native_addr(so_datalen_app, sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr((void *)si_data, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_ciovec_t) * (uint64)si_data_len;
+ if (total_size >= UINT32_MAX
+ || !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ ciovec = ciovec_begin;
+ for (i = 0; i < si_data_len; i++, si_data++, ciovec++) {
+ if (!validate_app_addr(si_data->buf_offset, si_data->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ ciovec->buf = (char *)addr_app_to_native(si_data->buf_offset);
+ ciovec->buf_len = si_data->buf_len;
+ }
+
+ err = uvwasi_sock_send(uvwasi, sock, ciovec_begin, si_data_len, si_flags,
+ &so_datalen);
+ if (err)
+ goto fail;
+
+ *so_datalen_app = (uint32)so_datalen;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(ciovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ if (!uvwasi)
+ return (wasi_errno_t)-1;
+
+ return uvwasi_sock_shutdown(uvwasi, sock, how);
+}
+
+static wasi_errno_t
+wasi_sched_yield(wasm_exec_env_t exec_env)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ uvwasi_t *uvwasi = get_wasi_ctx(module_inst);
+
+ return uvwasi_sched_yield(uvwasi);
+}
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, wasi_##func_name, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_libc_wasi[] = {
+ REG_NATIVE_FUNC(args_get, "(**)i"),
+ REG_NATIVE_FUNC(args_sizes_get, "(**)i"),
+ REG_NATIVE_FUNC(clock_res_get, "(i*)i"),
+ REG_NATIVE_FUNC(clock_time_get, "(iI*)i"),
+ REG_NATIVE_FUNC(environ_get, "(**)i"),
+ REG_NATIVE_FUNC(environ_sizes_get, "(**)i"),
+ REG_NATIVE_FUNC(fd_prestat_get, "(i*)i"),
+ REG_NATIVE_FUNC(fd_prestat_dir_name, "(i*~)i"),
+ REG_NATIVE_FUNC(fd_close, "(i)i"),
+ REG_NATIVE_FUNC(fd_datasync, "(i)i"),
+ REG_NATIVE_FUNC(fd_pread, "(i*iI*)i"),
+ REG_NATIVE_FUNC(fd_pwrite, "(i*iI*)i"),
+ REG_NATIVE_FUNC(fd_read, "(i*i*)i"),
+ REG_NATIVE_FUNC(fd_renumber, "(ii)i"),
+ REG_NATIVE_FUNC(fd_seek, "(iIi*)i"),
+ REG_NATIVE_FUNC(fd_tell, "(i*)i"),
+ REG_NATIVE_FUNC(fd_fdstat_get, "(i*)i"),
+ REG_NATIVE_FUNC(fd_fdstat_set_flags, "(ii)i"),
+ REG_NATIVE_FUNC(fd_fdstat_set_rights, "(iII)i"),
+ REG_NATIVE_FUNC(fd_sync, "(i)i"),
+ REG_NATIVE_FUNC(fd_write, "(i*i*)i"),
+ REG_NATIVE_FUNC(fd_advise, "(iIIi)i"),
+ REG_NATIVE_FUNC(fd_allocate, "(iII)i"),
+ REG_NATIVE_FUNC(path_create_directory, "(i*~)i"),
+ REG_NATIVE_FUNC(path_link, "(ii*~i*~)i"),
+ REG_NATIVE_FUNC(path_open, "(ii*~iIIi*)i"),
+ REG_NATIVE_FUNC(fd_readdir, "(i*~I*)i"),
+ REG_NATIVE_FUNC(path_readlink, "(i*~*~*)i"),
+ REG_NATIVE_FUNC(path_rename, "(i*~i*~)i"),
+ REG_NATIVE_FUNC(fd_filestat_get, "(i*)i"),
+ REG_NATIVE_FUNC(fd_filestat_set_times, "(iIIi)i"),
+ REG_NATIVE_FUNC(fd_filestat_set_size, "(iI)i"),
+ REG_NATIVE_FUNC(path_filestat_get, "(ii*~*)i"),
+ REG_NATIVE_FUNC(path_filestat_set_times, "(ii*~IIi)i"),
+ REG_NATIVE_FUNC(path_symlink, "(*~i*~)i"),
+ REG_NATIVE_FUNC(path_unlink_file, "(i*~)i"),
+ REG_NATIVE_FUNC(path_remove_directory, "(i*~)i"),
+ REG_NATIVE_FUNC(poll_oneoff, "(**i*)i"),
+ REG_NATIVE_FUNC(proc_exit, "(i)"),
+ REG_NATIVE_FUNC(proc_raise, "(i)i"),
+ REG_NATIVE_FUNC(random_get, "(*~)i"),
+ REG_NATIVE_FUNC(sock_recv, "(i*ii**)i"),
+ REG_NATIVE_FUNC(sock_send, "(i*ii*)i"),
+ REG_NATIVE_FUNC(sock_shutdown, "(ii)i"),
+ REG_NATIVE_FUNC(sched_yield, "()i"),
+};
+
+uint32
+get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis)
+{
+ *p_libc_wasi_apis = native_symbols_libc_wasi;
+ return sizeof(native_symbols_libc_wasi) / sizeof(NativeSymbol);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/SConscript
new file mode 100644
index 000000000..6ed3799e0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/SConscript
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+import os
+
+cwd = GetCurrentDir()
+
+src = Split('''
+''')
+
+CPPPATH = [cwd,
+ cwd+'/sandboxed-system-primitives/include',
+ cwd+'/sandboxed-system-primitives/src']
+
+def addSrcFiles(arr, path):
+ for f in os.listdir(path):
+ fpath = os.path.join(path, f);
+ if os.path.isfile(fpath):
+ ext = os.path.splitext(fpath)[-1]
+ if ext == '.c' or ext == '.cpp':
+ arr += [fpath]
+ elif os.path.isdir(fpath):
+ addSrcFiles(arr, fpath)
+
+
+addSrcFiles(src, cwd)
+
+group = DefineGroup('iwasm_libc_wasi', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi.cmake
new file mode 100644
index 000000000..d72c42a06
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi.cmake
@@ -0,0 +1,13 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (LIBC_WASI_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions (-DWASM_ENABLE_LIBC_WASI=1)
+
+include_directories(${LIBC_WASI_DIR}/sandboxed-system-primitives/include
+ ${LIBC_WASI_DIR}/sandboxed-system-primitives/src)
+
+file (GLOB_RECURSE source_all ${LIBC_WASI_DIR}/*.c )
+
+set (LIBC_WASI_SOURCE ${source_all})
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c
new file mode 100644
index 000000000..afb11925a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c
@@ -0,0 +1,2329 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "libc_wasi_wrapper.h"
+#include "bh_platform.h"
+#include "wasm_export.h"
+#include "wasm_runtime_common.h"
+
+#if WASM_ENABLE_THREAD_MGR != 0
+#include "../../../thread-mgr/thread_manager.h"
+#endif
+
+void
+wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception);
+
+/* clang-format off */
+#define get_module_inst(exec_env) \
+ wasm_runtime_get_module_inst(exec_env)
+
+#define get_wasi_ctx(module_inst) \
+ wasm_runtime_get_wasi_ctx(module_inst)
+
+#define validate_app_addr(offset, size) \
+ wasm_runtime_validate_app_addr(module_inst, offset, size)
+
+#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 struct wasi_prestat_app {
+ wasi_preopentype_t pr_type;
+ uint32 pr_name_len;
+} wasi_prestat_app_t;
+
+typedef struct iovec_app {
+ uint32 buf_offset;
+ uint32 buf_len;
+} iovec_app_t;
+
+typedef struct WASIContext *wasi_ctx_t;
+
+wasi_ctx_t
+wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst);
+
+static inline uint64_t
+min_uint64(uint64_t a, uint64_t b)
+{
+ return a > b ? b : a;
+}
+
+static inline uint32_t
+min_uint32(uint32_t a, uint32_t b)
+{
+ return a > b ? b : a;
+}
+
+static inline struct fd_table *
+wasi_ctx_get_curfds(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
+{
+ if (!wasi_ctx)
+ return NULL;
+ return wasi_ctx->curfds;
+}
+
+static inline struct argv_environ_values *
+wasi_ctx_get_argv_environ(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
+{
+ if (!wasi_ctx)
+ return NULL;
+ return wasi_ctx->argv_environ;
+}
+
+static inline struct fd_prestats *
+wasi_ctx_get_prestats(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
+{
+ if (!wasi_ctx)
+ return NULL;
+ return wasi_ctx->prestats;
+}
+
+static inline struct addr_pool *
+wasi_ctx_get_addr_pool(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
+{
+ if (!wasi_ctx)
+ return NULL;
+ return wasi_ctx->addr_pool;
+}
+
+static inline char **
+wasi_ctx_get_ns_lookup_list(wasi_ctx_t wasi_ctx)
+{
+ if (!wasi_ctx)
+ return NULL;
+ return wasi_ctx->ns_lookup_list;
+}
+
+static wasi_errno_t
+wasi_args_get(wasm_exec_env_t exec_env, uint32 *argv_offsets, char *argv_buf)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct argv_environ_values *argv_environ =
+ wasi_ctx_get_argv_environ(module_inst, wasi_ctx);
+ size_t argc, argv_buf_size, i;
+ char **argv;
+ uint64 total_size;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_args_sizes_get(argv_environ, &argc, &argv_buf_size);
+ if (err)
+ return err;
+
+ total_size = sizeof(int32) * ((uint64)argc + 1);
+ if (total_size >= UINT32_MAX
+ || !validate_native_addr(argv_offsets, (uint32)total_size)
+ || argv_buf_size >= UINT32_MAX
+ || !validate_native_addr(argv_buf, (uint32)argv_buf_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(char *) * ((uint64)argc + 1);
+ if (total_size >= UINT32_MAX
+ || !(argv = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_args_get(argv_environ, argv, argv_buf);
+ if (err) {
+ wasm_runtime_free(argv);
+ return err;
+ }
+
+ for (i = 0; i < argc; i++)
+ argv_offsets[i] = addr_native_to_app(argv[i]);
+
+ wasm_runtime_free(argv);
+ return 0;
+}
+
+static wasi_errno_t
+wasi_args_sizes_get(wasm_exec_env_t exec_env, uint32 *argc_app,
+ uint32 *argv_buf_size_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct argv_environ_values *argv_environ;
+ size_t argc, argv_buf_size;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(argc_app, sizeof(uint32))
+ || !validate_native_addr(argv_buf_size_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ argv_environ = wasi_ctx->argv_environ;
+
+ err = wasmtime_ssp_args_sizes_get(argv_environ, &argc, &argv_buf_size);
+ if (err)
+ return err;
+
+ *argc_app = (uint32)argc;
+ *argv_buf_size_app = (uint32)argv_buf_size;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_clock_res_get(wasm_exec_env_t exec_env,
+ wasi_clockid_t clock_id, /* uint32 clock_id */
+ wasi_timestamp_t *resolution /* uint64 *resolution */)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ if (!validate_native_addr(resolution, sizeof(wasi_timestamp_t)))
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_clock_res_get(clock_id, resolution);
+}
+
+static wasi_errno_t
+wasi_clock_time_get(wasm_exec_env_t exec_env,
+ wasi_clockid_t clock_id, /* uint32 clock_id */
+ wasi_timestamp_t precision, /* uint64 precision */
+ wasi_timestamp_t *time /* uint64 *time */)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+
+ if (!validate_native_addr(time, sizeof(wasi_timestamp_t)))
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_clock_time_get(clock_id, precision, time);
+}
+
+static wasi_errno_t
+wasi_environ_get(wasm_exec_env_t exec_env, uint32 *environ_offsets,
+ char *environ_buf)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct argv_environ_values *argv_environ =
+ wasi_ctx_get_argv_environ(module_inst, wasi_ctx);
+ size_t environ_count, environ_buf_size, i;
+ uint64 total_size;
+ char **environs;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_environ_sizes_get(argv_environ, &environ_count,
+ &environ_buf_size);
+ if (err)
+ return err;
+
+ total_size = sizeof(int32) * ((uint64)environ_count + 1);
+ if (total_size >= UINT32_MAX
+ || !validate_native_addr(environ_offsets, (uint32)total_size)
+ || environ_buf_size >= UINT32_MAX
+ || !validate_native_addr(environ_buf, (uint32)environ_buf_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(char *) * (((uint64)environ_count + 1));
+
+ if (total_size >= UINT32_MAX
+ || !(environs = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_environ_get(argv_environ, environs, environ_buf);
+ if (err) {
+ wasm_runtime_free(environs);
+ return err;
+ }
+
+ for (i = 0; i < environ_count; i++)
+ environ_offsets[i] = addr_native_to_app(environs[i]);
+
+ wasm_runtime_free(environs);
+ return 0;
+}
+
+static wasi_errno_t
+wasi_environ_sizes_get(wasm_exec_env_t exec_env, uint32 *environ_count_app,
+ uint32 *environ_buf_size_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct argv_environ_values *argv_environ =
+ wasi_ctx_get_argv_environ(module_inst, wasi_ctx);
+ size_t environ_count, environ_buf_size;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(environ_count_app, sizeof(uint32))
+ || !validate_native_addr(environ_buf_size_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_environ_sizes_get(argv_environ, &environ_count,
+ &environ_buf_size);
+ if (err)
+ return err;
+
+ *environ_count_app = (uint32)environ_count;
+ *environ_buf_size_app = (uint32)environ_buf_size;
+
+ return 0;
+}
+
+static wasi_errno_t
+wasi_fd_prestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_prestat_app_t *prestat_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
+ wasi_prestat_t prestat;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(prestat_app, sizeof(wasi_prestat_app_t)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_fd_prestat_get(prestats, fd, &prestat);
+ if (err)
+ return err;
+
+ prestat_app->pr_type = prestat.pr_type;
+ prestat_app->pr_name_len = (uint32)prestat.u.dir.pr_name_len;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_fd_prestat_dir_name(wasm_exec_env_t exec_env, wasi_fd_t fd, char *path,
+ uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_prestat_dir_name(prestats, fd, path, path_len);
+}
+
+static wasi_errno_t
+wasi_fd_close(wasm_exec_env_t exec_env, wasi_fd_t fd)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_close(curfds, prestats, fd);
+}
+
+static wasi_errno_t
+wasi_fd_datasync(wasm_exec_env_t exec_env, wasi_fd_t fd)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_datasync(curfds, fd);
+}
+
+static wasi_errno_t
+wasi_fd_pread(wasm_exec_env_t exec_env, wasi_fd_t fd, iovec_app_t *iovec_app,
+ uint32 iovs_len, wasi_filesize_t offset, uint32 *nread_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ wasi_iovec_t *iovec, *iovec_begin;
+ uint64 total_size;
+ size_t nread;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nread_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr(iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ iovec = iovec_begin;
+
+ for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset);
+ iovec->buf_len = iovec_app->buf_len;
+ }
+
+ err = wasmtime_ssp_fd_pread(curfds, fd, iovec_begin, iovs_len, offset,
+ &nread);
+ if (err)
+ goto fail;
+
+ *nread_app = (uint32)nread;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(iovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_pwrite(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const iovec_app_t *iovec_app, uint32 iovs_len,
+ wasi_filesize_t offset, uint32 *nwritten_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ wasi_ciovec_t *ciovec, *ciovec_begin;
+ uint64 total_size;
+ size_t nwritten;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr((void *)iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ ciovec = ciovec_begin;
+
+ for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset);
+ ciovec->buf_len = iovec_app->buf_len;
+ }
+
+ err = wasmtime_ssp_fd_pwrite(curfds, fd, ciovec_begin, iovs_len, offset,
+ &nwritten);
+ if (err)
+ goto fail;
+
+ *nwritten_app = (uint32)nwritten;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(ciovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_read(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const iovec_app_t *iovec_app, uint32 iovs_len, uint32 *nread_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ wasi_iovec_t *iovec, *iovec_begin;
+ uint64 total_size;
+ size_t nread;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nread_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr((void *)iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_iovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(iovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ iovec = iovec_begin;
+
+ for (i = 0; i < iovs_len; i++, iovec_app++, iovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ iovec->buf = (void *)addr_app_to_native(iovec_app->buf_offset);
+ iovec->buf_len = iovec_app->buf_len;
+ }
+
+ err = wasmtime_ssp_fd_read(curfds, fd, iovec_begin, iovs_len, &nread);
+ if (err)
+ goto fail;
+
+ *nread_app = (uint32)nread;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(iovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_renumber(wasm_exec_env_t exec_env, wasi_fd_t from, wasi_fd_t to)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_renumber(curfds, prestats, from, to);
+}
+
+static wasi_errno_t
+wasi_fd_seek(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filedelta_t offset,
+ wasi_whence_t whence, wasi_filesize_t *newoffset)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t)))
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_seek(curfds, fd, offset, whence, newoffset);
+}
+
+static wasi_errno_t
+wasi_fd_tell(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t *newoffset)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(newoffset, sizeof(wasi_filesize_t)))
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_tell(curfds, fd, newoffset);
+}
+
+static wasi_errno_t
+wasi_fd_fdstat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_fdstat_t *fdstat_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ wasi_fdstat_t fdstat;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(fdstat_app, sizeof(wasi_fdstat_t)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_fd_fdstat_get(curfds, fd, &fdstat);
+ if (err)
+ return err;
+
+ memcpy(fdstat_app, &fdstat, sizeof(wasi_fdstat_t));
+ return 0;
+}
+
+static wasi_errno_t
+wasi_fd_fdstat_set_flags(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_fdflags_t flags)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_fdstat_set_flags(curfds, fd, flags);
+}
+
+static wasi_errno_t
+wasi_fd_fdstat_set_rights(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_rights_t fs_rights_base,
+ wasi_rights_t fs_rights_inheriting)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_fdstat_set_rights(curfds, fd, fs_rights_base,
+ fs_rights_inheriting);
+}
+
+static wasi_errno_t
+wasi_fd_sync(wasm_exec_env_t exec_env, wasi_fd_t fd)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_sync(curfds, fd);
+}
+
+static wasi_errno_t
+wasi_fd_write(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const iovec_app_t *iovec_app, uint32 iovs_len,
+ uint32 *nwritten_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ wasi_ciovec_t *ciovec, *ciovec_begin;
+ uint64 total_size;
+ size_t nwritten;
+ uint32 i;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(iovec_app_t) * (uint64)iovs_len;
+ if (!validate_native_addr(nwritten_app, (uint32)sizeof(uint32))
+ || total_size >= UINT32_MAX
+ || !validate_native_addr((void *)iovec_app, (uint32)total_size))
+ return (wasi_errno_t)-1;
+
+ total_size = sizeof(wasi_ciovec_t) * (uint64)iovs_len;
+ if (total_size >= UINT32_MAX
+ || !(ciovec_begin = wasm_runtime_malloc((uint32)total_size)))
+ return (wasi_errno_t)-1;
+
+ ciovec = ciovec_begin;
+
+ for (i = 0; i < iovs_len; i++, iovec_app++, ciovec++) {
+ if (!validate_app_addr(iovec_app->buf_offset, iovec_app->buf_len)) {
+ err = (wasi_errno_t)-1;
+ goto fail;
+ }
+ ciovec->buf = (char *)addr_app_to_native(iovec_app->buf_offset);
+ ciovec->buf_len = iovec_app->buf_len;
+ }
+
+ err = wasmtime_ssp_fd_write(curfds, fd, ciovec_begin, iovs_len, &nwritten);
+ if (err)
+ goto fail;
+
+ *nwritten_app = (uint32)nwritten;
+
+ /* success */
+ err = 0;
+
+fail:
+ wasm_runtime_free(ciovec_begin);
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_advise(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset,
+ wasi_filesize_t len, wasi_advice_t advice)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_advise(curfds, fd, offset, len, advice);
+}
+
+static wasi_errno_t
+wasi_fd_allocate(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_filesize_t offset,
+ wasi_filesize_t len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_allocate(curfds, fd, offset, len);
+}
+
+static wasi_errno_t
+wasi_path_create_directory(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const char *path, uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_create_directory(curfds, fd, path, path_len);
+}
+
+static wasi_errno_t
+wasi_path_link(wasm_exec_env_t exec_env, wasi_fd_t old_fd,
+ wasi_lookupflags_t old_flags, const char *old_path,
+ uint32 old_path_len, wasi_fd_t new_fd, const char *new_path,
+ uint32 new_path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_link(curfds, prestats, old_fd, old_flags, old_path,
+ old_path_len, new_fd, new_path, new_path_len);
+}
+
+static wasi_errno_t
+wasi_path_open(wasm_exec_env_t exec_env, wasi_fd_t dirfd,
+ wasi_lookupflags_t dirflags, const char *path, uint32 path_len,
+ wasi_oflags_t oflags, wasi_rights_t fs_rights_base,
+ wasi_rights_t fs_rights_inheriting, wasi_fdflags_t fs_flags,
+ wasi_fd_t *fd_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ wasi_fd_t fd = (wasi_fd_t)-1; /* set fd_app -1 if path open failed */
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(fd_app, sizeof(wasi_fd_t)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_path_open(curfds, dirfd, dirflags, path, path_len,
+ oflags, fs_rights_base, fs_rights_inheriting,
+ fs_flags, &fd);
+
+ *fd_app = fd;
+ return err;
+}
+
+static wasi_errno_t
+wasi_fd_readdir(wasm_exec_env_t exec_env, wasi_fd_t fd, void *buf,
+ uint32 buf_len, wasi_dircookie_t cookie, uint32 *bufused_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ size_t bufused;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(bufused_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_fd_readdir(curfds, fd, buf, buf_len, cookie, &bufused);
+ if (err)
+ return err;
+
+ *bufused_app = (uint32)bufused;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_path_readlink(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path,
+ uint32 path_len, char *buf, uint32 buf_len,
+ uint32 *bufused_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ size_t bufused;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(bufused_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+ err = wasmtime_ssp_path_readlink(curfds, fd, path, path_len, buf, buf_len,
+ &bufused);
+ if (err)
+ return err;
+
+ *bufused_app = (uint32)bufused;
+ return 0;
+}
+
+static wasi_errno_t
+wasi_path_rename(wasm_exec_env_t exec_env, wasi_fd_t old_fd,
+ const char *old_path, uint32 old_path_len, wasi_fd_t new_fd,
+ const char *new_path, uint32 new_path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_rename(curfds, old_fd, old_path, old_path_len,
+ new_fd, new_path, new_path_len);
+}
+
+static wasi_errno_t
+wasi_fd_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_filestat_t *filestat)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(filestat, sizeof(wasi_filestat_t)))
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_filestat_get(curfds, fd, filestat);
+}
+
+static wasi_errno_t
+wasi_fd_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_timestamp_t st_atim, wasi_timestamp_t st_mtim,
+ wasi_fstflags_t fstflags)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_filestat_set_times(curfds, fd, st_atim, st_mtim,
+ fstflags);
+}
+
+static wasi_errno_t
+wasi_fd_filestat_set_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_filesize_t st_size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_fd_filestat_set_size(curfds, fd, st_size);
+}
+
+static wasi_errno_t
+wasi_path_filestat_get(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_lookupflags_t flags, const char *path,
+ uint32 path_len, wasi_filestat_t *filestat)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr(filestat, sizeof(wasi_filestat_t)))
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_filestat_get(curfds, fd, flags, path, path_len,
+ filestat);
+}
+
+static wasi_errno_t
+wasi_path_filestat_set_times(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ wasi_lookupflags_t flags, const char *path,
+ uint32 path_len, wasi_timestamp_t st_atim,
+ wasi_timestamp_t st_mtim, wasi_fstflags_t fstflags)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_filestat_set_times(
+ curfds, fd, flags, path, path_len, st_atim, st_mtim, fstflags);
+}
+
+static wasi_errno_t
+wasi_path_symlink(wasm_exec_env_t exec_env, const char *old_path,
+ uint32 old_path_len, wasi_fd_t fd, const char *new_path,
+ uint32 new_path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ struct fd_prestats *prestats = wasi_ctx_get_prestats(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_symlink(curfds, prestats, old_path, old_path_len,
+ fd, new_path, new_path_len);
+}
+
+static wasi_errno_t
+wasi_path_unlink_file(wasm_exec_env_t exec_env, wasi_fd_t fd, const char *path,
+ uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_unlink_file(curfds, fd, path, path_len);
+}
+
+static wasi_errno_t
+wasi_path_remove_directory(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ const char *path, uint32 path_len)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ return wasmtime_ssp_path_remove_directory(curfds, fd, path, path_len);
+}
+
+#if WASM_ENABLE_THREAD_MGR != 0
+static __wasi_timestamp_t
+get_timeout_for_poll_oneoff(const wasi_subscription_t *in,
+ uint32 nsubscriptions)
+{
+ __wasi_timestamp_t timeout = (__wasi_timestamp_t)-1;
+ uint32 i = 0;
+
+ for (i = 0; i < nsubscriptions; ++i) {
+ const __wasi_subscription_t *s = &in[i];
+ if (s->u.type == __WASI_EVENTTYPE_CLOCK
+ && (s->u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) == 0) {
+ timeout = min_uint64(timeout, s->u.u.clock.timeout);
+ }
+ }
+ return timeout;
+}
+
+static void
+update_clock_subscription_data(wasi_subscription_t *in, uint32 nsubscriptions,
+ const wasi_timestamp_t new_timeout)
+{
+ uint32 i = 0;
+ for (i = 0; i < nsubscriptions; ++i) {
+ __wasi_subscription_t *s = &in[i];
+ if (s->u.type == __WASI_EVENTTYPE_CLOCK) {
+ s->u.u.clock.timeout = new_timeout;
+ }
+ }
+}
+
+static wasi_errno_t
+execute_interruptible_poll_oneoff(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ const __wasi_subscription_t *in, __wasi_event_t *out, size_t nsubscriptions,
+ size_t *nevents, wasm_exec_env_t exec_env)
+{
+ if (nsubscriptions == 0) {
+ *nevents = 0;
+ return __WASI_ESUCCESS;
+ }
+
+ wasi_errno_t err;
+ __wasi_timestamp_t elapsed = 0;
+ bool all_outs_are_type_clock;
+ uint32 i;
+
+ const __wasi_timestamp_t timeout = get_timeout_for_poll_oneoff(
+ in, nsubscriptions),
+ time_quant = 1e9;
+ const uint64 size_to_copy =
+ nsubscriptions * (uint64)sizeof(wasi_subscription_t);
+ __wasi_subscription_t *in_copy = NULL;
+
+ if (size_to_copy >= UINT32_MAX
+ || !(in_copy = (__wasi_subscription_t *)wasm_runtime_malloc(
+ (uint32)size_to_copy))) {
+ return __WASI_ENOMEM;
+ }
+
+ bh_memcpy_s(in_copy, size_to_copy, in, size_to_copy);
+
+ while (timeout == (__wasi_timestamp_t)-1 || elapsed <= timeout) {
+ /* update timeout for clock subscription events */
+ update_clock_subscription_data(
+ in_copy, nsubscriptions, min_uint64(time_quant, timeout - elapsed));
+ err = wasmtime_ssp_poll_oneoff(curfds, in_copy, out, nsubscriptions,
+ nevents);
+ elapsed += time_quant;
+
+ if (err) {
+ wasm_runtime_free(in_copy);
+ return err;
+ }
+
+ if (wasm_cluster_is_thread_terminated(exec_env)) {
+ wasm_runtime_free(in_copy);
+ return EINTR;
+ }
+ else if (*nevents > 0) {
+ all_outs_are_type_clock = true;
+ for (i = 0; i < *nevents; i++) {
+ if (out[i].type != __WASI_EVENTTYPE_CLOCK) {
+ all_outs_are_type_clock = false;
+ break;
+ }
+ }
+
+ if (!all_outs_are_type_clock) {
+ wasm_runtime_free(in_copy);
+ return __WASI_ESUCCESS;
+ }
+ }
+ }
+
+ wasm_runtime_free(in_copy);
+ return __WASI_ESUCCESS;
+}
+#endif
+
+static wasi_errno_t
+wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in,
+ wasi_event_t *out, uint32 nsubscriptions, uint32 *nevents_app)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ size_t nevents = 0;
+ wasi_errno_t err;
+
+ if (!wasi_ctx)
+ return (wasi_errno_t)-1;
+
+ if (!validate_native_addr((void *)in, sizeof(wasi_subscription_t))
+ || !validate_native_addr(out, sizeof(wasi_event_t))
+ || !validate_native_addr(nevents_app, sizeof(uint32)))
+ return (wasi_errno_t)-1;
+
+#if WASM_ENABLE_THREAD_MGR == 0
+ err = wasmtime_ssp_poll_oneoff(curfds, in, out, nsubscriptions, &nevents);
+#else
+ err = execute_interruptible_poll_oneoff(curfds, in, out, nsubscriptions,
+ &nevents, exec_env);
+#endif
+ if (err)
+ return err;
+
+ *nevents_app = (uint32)nevents;
+ return 0;
+}
+
+static void
+wasi_proc_exit(wasm_exec_env_t exec_env, wasi_exitcode_t rval)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ /* Here throwing exception is just to let wasm app exit,
+ the upper layer should clear the exception and return
+ as normal */
+ wasm_runtime_set_exception(module_inst, "wasi proc exit");
+ wasi_ctx->exit_code = rval;
+}
+
+static wasi_errno_t
+wasi_proc_raise(wasm_exec_env_t exec_env, wasi_signal_t sig)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ char buf[32];
+ snprintf(buf, sizeof(buf), "%s%d", "wasi proc raise ", sig);
+ wasm_runtime_set_exception(module_inst, buf);
+
+ return 0;
+}
+
+static wasi_errno_t
+wasi_random_get(wasm_exec_env_t exec_env, void *buf, uint32 buf_len)
+{
+ return wasmtime_ssp_random_get(buf, buf_len);
+}
+
+static wasi_errno_t
+wasi_sock_accept(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_fdflags_t flags,
+ wasi_fd_t *fd_new)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasi_ssp_sock_accept(curfds, fd, flags, fd_new);
+}
+
+static wasi_errno_t
+wasi_sock_addr_local(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ __wasi_addr_t *addr)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(addr, sizeof(__wasi_addr_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasi_ssp_sock_addr_local(curfds, fd, addr);
+}
+
+static wasi_errno_t
+wasi_sock_addr_remote(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ __wasi_addr_t *addr)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(addr, sizeof(__wasi_addr_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasi_ssp_sock_addr_remote(curfds, fd, addr);
+}
+
+static wasi_errno_t
+wasi_sock_addr_resolve(wasm_exec_env_t exec_env, const char *host,
+ const char *service, __wasi_addr_info_hints_t *hints,
+ __wasi_addr_info_t *addr_info,
+ __wasi_size_t addr_info_size,
+ __wasi_size_t *max_info_size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+ char **ns_lookup_list = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ ns_lookup_list = wasi_ctx_get_ns_lookup_list(wasi_ctx);
+
+ return wasi_ssp_sock_addr_resolve(curfds, ns_lookup_list, host, service,
+ hints, addr_info, addr_info_size,
+ max_info_size);
+}
+
+static wasi_errno_t
+wasi_sock_bind(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+ struct addr_pool *addr_pool = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx);
+
+ return wasi_ssp_sock_bind(curfds, addr_pool, fd, addr);
+}
+
+static wasi_errno_t
+wasi_sock_close(wasm_exec_env_t exec_env, wasi_fd_t fd)
+{
+ return __WASI_ENOSYS;
+}
+
+static wasi_errno_t
+wasi_sock_connect(wasm_exec_env_t exec_env, wasi_fd_t fd, wasi_addr_t *addr)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+ struct addr_pool *addr_pool = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx);
+
+ return wasi_ssp_sock_connect(curfds, addr_pool, fd, addr);
+}
+
+static wasi_errno_t
+wasi_sock_get_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_broadcast(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_keep_alive(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool *is_enabled,
+ int *linger_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool))
+ || !validate_native_addr(linger_s, sizeof(int)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_linger(curfds, fd, is_enabled, linger_s);
+}
+
+static wasi_errno_t
+wasi_sock_get_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ size_t *size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(size, sizeof(wasi_size_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_recv_buf_size(curfds, fd, size);
+}
+
+static wasi_errno_t
+wasi_sock_get_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint64_t *timeout_us)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(timeout_us, sizeof(uint64_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_recv_timeout(curfds, fd, timeout_us);
+}
+
+static wasi_errno_t
+wasi_sock_get_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_reuse_addr(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_reuse_port(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ size_t *size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(size, sizeof(__wasi_size_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_send_buf_size(curfds, fd, size);
+}
+
+static wasi_errno_t
+wasi_sock_get_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint64_t *timeout_us)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(timeout_us, sizeof(uint64_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_send_timeout(curfds, fd, timeout_us);
+}
+
+static wasi_errno_t
+wasi_sock_get_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_tcp_fastopen_connect(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_tcp_no_delay(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_tcp_quick_ack(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint32_t *time_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(time_s, sizeof(uint32_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_tcp_keep_idle(curfds, fd, time_s);
+}
+
+static wasi_errno_t
+wasi_sock_get_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint32_t *time_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(time_s, sizeof(uint32_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_tcp_keep_intvl(curfds, fd, time_s);
+}
+
+static wasi_errno_t
+wasi_sock_get_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool ipv6, bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_ip_multicast_loop(curfds, fd, ipv6,
+ is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_get_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t *ttl_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(ttl_s, sizeof(uint8_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_ip_ttl(curfds, fd, ttl_s);
+}
+
+static wasi_errno_t
+wasi_sock_get_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint8_t *ttl_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(ttl_s, sizeof(uint8_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_ip_multicast_ttl(curfds, fd, ttl_s);
+}
+
+static wasi_errno_t
+wasi_sock_get_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool *is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(is_enabled, sizeof(bool)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_get_ipv6_only(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_listen(wasm_exec_env_t exec_env, wasi_fd_t fd, uint32 backlog)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasi_ssp_sock_listen(curfds, fd, backlog);
+}
+
+static wasi_errno_t
+wasi_sock_open(wasm_exec_env_t exec_env, wasi_fd_t poolfd,
+ wasi_address_family_t af, wasi_sock_type_t socktype,
+ wasi_fd_t *sockfd)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasi_ssp_sock_open(curfds, poolfd, af, socktype, sockfd);
+}
+
+static wasi_errno_t
+wasi_sock_set_broadcast(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_broadcast(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_keep_alive(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_keep_alive(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_linger(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled,
+ int linger_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_linger(curfds, fd, is_enabled, linger_s);
+}
+
+static wasi_errno_t
+wasi_sock_set_recv_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_recv_buf_size(curfds, fd, size);
+}
+
+static wasi_errno_t
+wasi_sock_set_recv_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint64_t timeout_us)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_recv_timeout(curfds, fd, timeout_us);
+}
+
+static wasi_errno_t
+wasi_sock_set_reuse_addr(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_reuse_addr(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_reuse_port(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_reuse_port(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_send_buf_size(wasm_exec_env_t exec_env, wasi_fd_t fd, size_t size)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_send_buf_size(curfds, fd, size);
+}
+
+static wasi_errno_t
+wasi_sock_set_send_timeout(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint64_t timeout_us)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_send_timeout(curfds, fd, timeout_us);
+}
+
+static wasi_errno_t
+wasi_sock_set_tcp_fastopen_connect(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_tcp_fastopen_connect(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_tcp_no_delay(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_tcp_no_delay(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_tcp_quick_ack(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_tcp_quick_ack(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_tcp_keep_idle(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint32_t time_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_tcp_keep_idle(curfds, fd, time_s);
+}
+
+static wasi_errno_t
+wasi_sock_set_tcp_keep_intvl(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint32_t time_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_tcp_keep_intvl(curfds, fd, time_s);
+}
+
+static wasi_errno_t
+wasi_sock_set_ip_multicast_loop(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ bool ipv6, bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_ip_multicast_loop(curfds, fd, ipv6,
+ is_enabled);
+}
+
+static wasi_errno_t
+wasi_sock_set_ip_add_membership(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ __wasi_addr_ip_t *imr_multiaddr,
+ uint32_t imr_interface)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(imr_multiaddr, sizeof(__wasi_addr_ip_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_ip_add_membership(curfds, fd, imr_multiaddr,
+ imr_interface);
+}
+
+static wasi_errno_t
+wasi_sock_set_ip_drop_membership(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ __wasi_addr_ip_t *imr_multiaddr,
+ uint32_t imr_interface)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ if (!validate_native_addr(imr_multiaddr, sizeof(__wasi_addr_ip_t)))
+ return __WASI_EINVAL;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_ip_drop_membership(curfds, fd, imr_multiaddr,
+ imr_interface);
+}
+
+static wasi_errno_t
+wasi_sock_set_ip_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd, uint8_t ttl_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_ip_ttl(curfds, fd, ttl_s);
+}
+
+static wasi_errno_t
+wasi_sock_set_ip_multicast_ttl(wasm_exec_env_t exec_env, wasi_fd_t fd,
+ uint8_t ttl_s)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_ip_multicast_ttl(curfds, fd, ttl_s);
+}
+
+static wasi_errno_t
+wasi_sock_set_ipv6_only(wasm_exec_env_t exec_env, wasi_fd_t fd, bool is_enabled)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = NULL;
+
+ if (!wasi_ctx)
+ return __WASI_EACCES;
+
+ curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ return wasmtime_ssp_sock_set_ipv6_only(curfds, fd, is_enabled);
+}
+
+static wasi_errno_t
+allocate_iovec_app_buffer(wasm_module_inst_t module_inst,
+ const iovec_app_t *data, uint32 data_len,
+ uint8 **buf_ptr, uint64 *buf_len)
+{
+ uint64 total_size = 0;
+ uint32 i;
+ uint8 *buf_begin = NULL;
+
+ if (data_len == 0) {
+ return __WASI_EINVAL;
+ }
+
+ total_size = sizeof(iovec_app_t) * (uint64)data_len;
+ if (total_size >= UINT32_MAX
+ || !validate_native_addr((void *)data, (uint32)total_size))
+ return __WASI_EINVAL;
+
+ for (total_size = 0, i = 0; i < data_len; i++, data++) {
+ total_size += data->buf_len;
+ }
+
+ if (total_size == 0) {
+ return __WASI_EINVAL;
+ }
+
+ if (total_size >= UINT32_MAX
+ || !(buf_begin = wasm_runtime_malloc((uint32)total_size))) {
+ return __WASI_ENOMEM;
+ }
+
+ *buf_len = total_size;
+ *buf_ptr = buf_begin;
+
+ return __WASI_ESUCCESS;
+}
+
+static wasi_errno_t
+copy_buffer_to_iovec_app(wasm_module_inst_t module_inst, uint8 *buf_begin,
+ uint32 buf_size, iovec_app_t *data, uint32 data_len,
+ uint32 size_to_copy)
+{
+ uint8 *buf = buf_begin;
+ uint32 i;
+ uint32 size_to_copy_into_iovec;
+
+ if (buf_size < size_to_copy) {
+ return __WASI_EINVAL;
+ }
+
+ for (i = 0; i < data_len; data++, i++) {
+ char *native_addr;
+
+ if (!validate_app_addr(data->buf_offset, data->buf_len)) {
+ return __WASI_EINVAL;
+ }
+
+ if (buf >= buf_begin + buf_size
+ || buf + data->buf_len < buf /* integer overflow */
+ || buf + data->buf_len > buf_begin + buf_size
+ || size_to_copy == 0) {
+ break;
+ }
+
+ /**
+ * If our app buffer size is smaller than the amount to be copied,
+ * only copy the amount in the app buffer. Otherwise, we fill the iovec
+ * buffer and reduce size to copy on the next iteration
+ */
+ size_to_copy_into_iovec = min_uint32(data->buf_len, size_to_copy);
+
+ native_addr = (void *)addr_app_to_native(data->buf_offset);
+ bh_memcpy_s(native_addr, size_to_copy_into_iovec, buf,
+ size_to_copy_into_iovec);
+ buf += size_to_copy_into_iovec;
+ size_to_copy -= size_to_copy_into_iovec;
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+static wasi_errno_t
+wasi_sock_recv_from(wasm_exec_env_t exec_env, wasi_fd_t sock,
+ iovec_app_t *ri_data, uint32 ri_data_len,
+ wasi_riflags_t ri_flags, __wasi_addr_t *src_addr,
+ uint32 *ro_data_len)
+{
+ /**
+ * ri_data_len is the length of a list of iovec_app_t, which head is
+ * ri_data. ro_data_len is the number of bytes received
+ **/
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ uint64 total_size;
+ uint8 *buf_begin = NULL;
+ wasi_errno_t err;
+ size_t recv_bytes = 0;
+
+ if (!wasi_ctx) {
+ return __WASI_EINVAL;
+ }
+
+ if (!validate_native_addr(ro_data_len, (uint32)sizeof(uint32)))
+ return __WASI_EINVAL;
+
+ err = allocate_iovec_app_buffer(module_inst, ri_data, ri_data_len,
+ &buf_begin, &total_size);
+ if (err != __WASI_ESUCCESS) {
+ goto fail;
+ }
+
+ memset(buf_begin, 0, total_size);
+
+ *ro_data_len = 0;
+ err = wasmtime_ssp_sock_recv_from(curfds, sock, buf_begin, total_size,
+ ri_flags, src_addr, &recv_bytes);
+ if (err != __WASI_ESUCCESS) {
+ goto fail;
+ }
+ *ro_data_len = (uint32)recv_bytes;
+
+ err = copy_buffer_to_iovec_app(module_inst, buf_begin, (uint32)total_size,
+ ri_data, ri_data_len, (uint32)recv_bytes);
+
+fail:
+ if (buf_begin) {
+ wasm_runtime_free(buf_begin);
+ }
+ return err;
+}
+
+static wasi_errno_t
+wasi_sock_recv(wasm_exec_env_t exec_env, wasi_fd_t sock, iovec_app_t *ri_data,
+ uint32 ri_data_len, wasi_riflags_t ri_flags, uint32 *ro_data_len,
+ wasi_roflags_t *ro_flags)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ __wasi_addr_t src_addr;
+ wasi_errno_t error;
+
+ if (!validate_native_addr(ro_flags, (uint32)sizeof(wasi_roflags_t)))
+ return __WASI_EINVAL;
+
+ error = wasi_sock_recv_from(exec_env, sock, ri_data, ri_data_len, ri_flags,
+ &src_addr, ro_data_len);
+ *ro_flags = ri_flags;
+
+ return error;
+}
+
+static wasi_errno_t
+convert_iovec_app_to_buffer(wasm_module_inst_t module_inst,
+ const iovec_app_t *si_data, uint32 si_data_len,
+ uint8 **buf_ptr, uint64 *buf_len)
+{
+ uint32 i;
+ const iovec_app_t *si_data_orig = si_data;
+ uint8 *buf = NULL;
+ wasi_errno_t error;
+
+ error = allocate_iovec_app_buffer(module_inst, si_data, si_data_len,
+ buf_ptr, buf_len);
+ if (error != __WASI_ESUCCESS) {
+ return error;
+ }
+
+ buf = *buf_ptr;
+ si_data = si_data_orig;
+ for (i = 0; i < si_data_len; i++, si_data++) {
+ char *native_addr;
+
+ if (!validate_app_addr(si_data->buf_offset, si_data->buf_len)) {
+ wasm_runtime_free(*buf_ptr);
+ return __WASI_EINVAL;
+ }
+
+ native_addr = (char *)addr_app_to_native(si_data->buf_offset);
+ bh_memcpy_s(buf, si_data->buf_len, native_addr, si_data->buf_len);
+ buf += si_data->buf_len;
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+static wasi_errno_t
+wasi_sock_send(wasm_exec_env_t exec_env, wasi_fd_t sock,
+ const iovec_app_t *si_data, uint32 si_data_len,
+ wasi_siflags_t si_flags, uint32 *so_data_len)
+{
+ /**
+ * si_data_len is the length of a list of iovec_app_t, which head is
+ * si_data. so_data_len is the number of bytes sent
+ **/
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ uint64 buf_size = 0;
+ uint8 *buf = NULL;
+ wasi_errno_t err;
+ size_t send_bytes = 0;
+
+ if (!wasi_ctx) {
+ return __WASI_EINVAL;
+ }
+
+ if (!validate_native_addr(so_data_len, sizeof(uint32)))
+ return __WASI_EINVAL;
+
+ err = convert_iovec_app_to_buffer(module_inst, si_data, si_data_len, &buf,
+ &buf_size);
+ if (err != __WASI_ESUCCESS)
+ return err;
+
+ *so_data_len = 0;
+ err = wasmtime_ssp_sock_send(curfds, sock, buf, buf_size, &send_bytes);
+ *so_data_len = (uint32)send_bytes;
+
+ wasm_runtime_free(buf);
+
+ return err;
+}
+
+static wasi_errno_t
+wasi_sock_send_to(wasm_exec_env_t exec_env, wasi_fd_t sock,
+ const iovec_app_t *si_data, uint32 si_data_len,
+ wasi_siflags_t si_flags, const __wasi_addr_t *dest_addr,
+ uint32 *so_data_len)
+{
+ /**
+ * si_data_len is the length of a list of iovec_app_t, which head is
+ * si_data. so_data_len is the number of bytes sent
+ **/
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+ uint64 buf_size = 0;
+ uint8 *buf = NULL;
+ wasi_errno_t err;
+ size_t send_bytes = 0;
+ struct addr_pool *addr_pool = wasi_ctx_get_addr_pool(module_inst, wasi_ctx);
+
+ if (!wasi_ctx) {
+ return __WASI_EINVAL;
+ }
+
+ if (!validate_native_addr(so_data_len, sizeof(uint32)))
+ return __WASI_EINVAL;
+
+ err = convert_iovec_app_to_buffer(module_inst, si_data, si_data_len, &buf,
+ &buf_size);
+ if (err != __WASI_ESUCCESS)
+ return err;
+
+ *so_data_len = 0;
+ err = wasmtime_ssp_sock_send_to(curfds, addr_pool, sock, buf, buf_size,
+ si_flags, dest_addr, &send_bytes);
+ *so_data_len = (uint32)send_bytes;
+
+ wasm_runtime_free(buf);
+
+ return err;
+}
+
+static wasi_errno_t
+wasi_sock_shutdown(wasm_exec_env_t exec_env, wasi_fd_t sock, wasi_sdflags_t how)
+{
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
+ struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
+
+ if (!wasi_ctx)
+ return __WASI_EINVAL;
+
+ return wasmtime_ssp_sock_shutdown(curfds, sock);
+}
+
+static wasi_errno_t
+wasi_sched_yield(wasm_exec_env_t exec_env)
+{
+ return wasmtime_ssp_sched_yield();
+}
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, wasi_##func_name, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_libc_wasi[] = {
+ REG_NATIVE_FUNC(args_get, "(**)i"),
+ REG_NATIVE_FUNC(args_sizes_get, "(**)i"),
+ REG_NATIVE_FUNC(clock_res_get, "(i*)i"),
+ REG_NATIVE_FUNC(clock_time_get, "(iI*)i"),
+ REG_NATIVE_FUNC(environ_get, "(**)i"),
+ REG_NATIVE_FUNC(environ_sizes_get, "(**)i"),
+ REG_NATIVE_FUNC(fd_prestat_get, "(i*)i"),
+ REG_NATIVE_FUNC(fd_prestat_dir_name, "(i*~)i"),
+ REG_NATIVE_FUNC(fd_close, "(i)i"),
+ REG_NATIVE_FUNC(fd_datasync, "(i)i"),
+ REG_NATIVE_FUNC(fd_pread, "(i*iI*)i"),
+ REG_NATIVE_FUNC(fd_pwrite, "(i*iI*)i"),
+ REG_NATIVE_FUNC(fd_read, "(i*i*)i"),
+ REG_NATIVE_FUNC(fd_renumber, "(ii)i"),
+ REG_NATIVE_FUNC(fd_seek, "(iIi*)i"),
+ REG_NATIVE_FUNC(fd_tell, "(i*)i"),
+ REG_NATIVE_FUNC(fd_fdstat_get, "(i*)i"),
+ REG_NATIVE_FUNC(fd_fdstat_set_flags, "(ii)i"),
+ REG_NATIVE_FUNC(fd_fdstat_set_rights, "(iII)i"),
+ REG_NATIVE_FUNC(fd_sync, "(i)i"),
+ REG_NATIVE_FUNC(fd_write, "(i*i*)i"),
+ REG_NATIVE_FUNC(fd_advise, "(iIIi)i"),
+ REG_NATIVE_FUNC(fd_allocate, "(iII)i"),
+ REG_NATIVE_FUNC(path_create_directory, "(i*~)i"),
+ REG_NATIVE_FUNC(path_link, "(ii*~i*~)i"),
+ REG_NATIVE_FUNC(path_open, "(ii*~iIIi*)i"),
+ REG_NATIVE_FUNC(fd_readdir, "(i*~I*)i"),
+ REG_NATIVE_FUNC(path_readlink, "(i*~*~*)i"),
+ REG_NATIVE_FUNC(path_rename, "(i*~i*~)i"),
+ REG_NATIVE_FUNC(fd_filestat_get, "(i*)i"),
+ REG_NATIVE_FUNC(fd_filestat_set_times, "(iIIi)i"),
+ REG_NATIVE_FUNC(fd_filestat_set_size, "(iI)i"),
+ REG_NATIVE_FUNC(path_filestat_get, "(ii*~*)i"),
+ REG_NATIVE_FUNC(path_filestat_set_times, "(ii*~IIi)i"),
+ REG_NATIVE_FUNC(path_symlink, "(*~i*~)i"),
+ REG_NATIVE_FUNC(path_unlink_file, "(i*~)i"),
+ REG_NATIVE_FUNC(path_remove_directory, "(i*~)i"),
+ REG_NATIVE_FUNC(poll_oneoff, "(**i*)i"),
+ REG_NATIVE_FUNC(proc_exit, "(i)"),
+ REG_NATIVE_FUNC(proc_raise, "(i)i"),
+ REG_NATIVE_FUNC(random_get, "(*~)i"),
+ REG_NATIVE_FUNC(sock_accept, "(ii*)i"),
+ REG_NATIVE_FUNC(sock_addr_local, "(i*)i"),
+ REG_NATIVE_FUNC(sock_addr_remote, "(i*)i"),
+ REG_NATIVE_FUNC(sock_addr_resolve, "($$**i*)i"),
+ REG_NATIVE_FUNC(sock_bind, "(i*)i"),
+ REG_NATIVE_FUNC(sock_close, "(i)i"),
+ REG_NATIVE_FUNC(sock_connect, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_broadcast, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_keep_alive, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_linger, "(i**)i"),
+ REG_NATIVE_FUNC(sock_get_recv_buf_size, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_recv_timeout, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_reuse_addr, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_reuse_port, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_send_buf_size, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_send_timeout, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_tcp_fastopen_connect, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_tcp_keep_idle, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_tcp_keep_intvl, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_tcp_no_delay, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_tcp_quick_ack, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_ip_multicast_loop, "(ii*)i"),
+ REG_NATIVE_FUNC(sock_get_ip_multicast_ttl, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_ip_ttl, "(i*)i"),
+ REG_NATIVE_FUNC(sock_get_ipv6_only, "(i*)i"),
+ REG_NATIVE_FUNC(sock_listen, "(ii)i"),
+ REG_NATIVE_FUNC(sock_open, "(iii*)i"),
+ REG_NATIVE_FUNC(sock_recv, "(i*ii**)i"),
+ REG_NATIVE_FUNC(sock_recv_from, "(i*ii**)i"),
+ REG_NATIVE_FUNC(sock_send, "(i*ii*)i"),
+ REG_NATIVE_FUNC(sock_send_to, "(i*ii**)i"),
+ REG_NATIVE_FUNC(sock_set_broadcast, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_keep_alive, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_linger, "(iii)i"),
+ REG_NATIVE_FUNC(sock_set_recv_buf_size, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_recv_timeout, "(iI)i"),
+ REG_NATIVE_FUNC(sock_set_reuse_addr, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_reuse_port, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_send_buf_size, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_send_timeout, "(iI)i"),
+ REG_NATIVE_FUNC(sock_set_tcp_fastopen_connect, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_tcp_keep_idle, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_tcp_keep_intvl, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_tcp_no_delay, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_tcp_quick_ack, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_ip_multicast_loop, "(iii)i"),
+ REG_NATIVE_FUNC(sock_set_ip_multicast_ttl, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_ip_add_membership, "(i*i)i"),
+ REG_NATIVE_FUNC(sock_set_ip_drop_membership, "(i*i)i"),
+ REG_NATIVE_FUNC(sock_set_ip_ttl, "(ii)i"),
+ REG_NATIVE_FUNC(sock_set_ipv6_only, "(ii)i"),
+ REG_NATIVE_FUNC(sock_shutdown, "(ii)i"),
+ REG_NATIVE_FUNC(sched_yield, "()i"),
+};
+
+uint32
+get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis)
+{
+ *p_libc_wasi_apis = native_symbols_libc_wasi;
+ return sizeof(native_symbols_libc_wasi) / sizeof(NativeSymbol);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h
new file mode 100644
index 000000000..be509576b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _LIBC_WASI_WRAPPER_H
+#define _LIBC_WASI_WRAPPER_H
+
+#include "wasmtime_ssp.h"
+#include "posix.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef __wasi_address_family_t wasi_address_family_t;
+typedef __wasi_addr_t wasi_addr_t;
+typedef __wasi_advice_t wasi_advice_t;
+typedef __wasi_ciovec_t wasi_ciovec_t;
+typedef __wasi_clockid_t wasi_clockid_t;
+typedef __wasi_dircookie_t wasi_dircookie_t;
+typedef __wasi_errno_t wasi_errno_t;
+typedef __wasi_event_t wasi_event_t;
+typedef __wasi_exitcode_t wasi_exitcode_t;
+typedef __wasi_fdflags_t wasi_fdflags_t;
+typedef __wasi_fdstat_t wasi_fdstat_t;
+typedef __wasi_fd_t wasi_fd_t;
+typedef __wasi_filedelta_t wasi_filedelta_t;
+typedef __wasi_filesize_t wasi_filesize_t;
+typedef __wasi_filestat_t wasi_filestat_t;
+typedef __wasi_filetype_t wasi_filetype_t;
+typedef __wasi_fstflags_t wasi_fstflags_t;
+typedef __wasi_iovec_t wasi_iovec_t;
+typedef __wasi_ip_port_t wasi_ip_port_t;
+typedef __wasi_lookupflags_t wasi_lookupflags_t;
+typedef __wasi_oflags_t wasi_oflags_t;
+typedef __wasi_preopentype_t wasi_preopentype_t;
+typedef __wasi_prestat_t wasi_prestat_t;
+typedef __wasi_riflags_t wasi_riflags_t;
+typedef __wasi_rights_t wasi_rights_t;
+typedef __wasi_roflags_t wasi_roflags_t;
+typedef __wasi_sdflags_t wasi_sdflags_t;
+typedef __wasi_siflags_t wasi_siflags_t;
+typedef __wasi_signal_t wasi_signal_t;
+typedef __wasi_size_t wasi_size_t;
+typedef __wasi_sock_type_t wasi_sock_type_t;
+typedef __wasi_subscription_t wasi_subscription_t;
+typedef __wasi_timestamp_t wasi_timestamp_t;
+typedef __wasi_whence_t wasi_whence_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _LIBC_WASI_WRAPPER_H */ \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE
new file mode 100644
index 000000000..83386f80a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE
@@ -0,0 +1,7 @@
+Please see the LICENSE file in each top-level directory for the terms applicable to that directory and its relative sub-directories.
+
+The relevant directories and licenses are:
+
+src/ - BSD-2-Clause; see src/LICENSE for details
+include/ - CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
+polyfill/clang/ - MIT; see the header of polyfill/clang/stdatomic.h for details
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE
new file mode 100644
index 000000000..0e259d42c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE
@@ -0,0 +1,121 @@
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+ HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse of data
+ in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation
+ thereof, including any amended or successor version of such
+ directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy, or
+ the present or absence of errors, whether or not discoverable, all to
+ the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person's Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the
+ Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to
+ this CC0 or use of the Work.
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h
new file mode 100644
index 000000000..feadf2f95
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/wasmtime_ssp.h
@@ -0,0 +1,1508 @@
+/*
+ * Part of the Wasmtime Project, under the Apache License v2.0 with
+ * LLVM Exceptions. See
+ * https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE
+ * for license information.
+ *
+ * This file declares an interface similar to WASI, but augmented to expose
+ * some implementation details such as the curfds arguments that we pass
+ * around to avoid storing them in TLS.
+ */
+
+/**
+ * The defitions of type, macro and structure in this file should be
+ * consistent with those in wasi-libc:
+ * https://github.com/WebAssembly/wasi-libc/blob/main/libc-bottom-half/headers/public/wasi/api.h
+ */
+
+#ifndef WASMTIME_SSP_H
+#define WASMTIME_SSP_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/* clang-format off */
+
+#ifdef __cplusplus
+#ifndef _Static_assert
+#define _Static_assert static_assert
+#endif /* _Static_assert */
+
+#ifndef _Alignof
+#define _Alignof alignof
+#endif /* _Alignof */
+
+#ifndef _Noreturn
+#define _Noreturn [[ noreturn ]]
+#endif /* _Noreturn */
+extern "C" {
+#endif
+
+_Static_assert(_Alignof(int8_t) == 1, "non-wasi data layout");
+_Static_assert(_Alignof(uint8_t) == 1, "non-wasi data layout");
+_Static_assert(_Alignof(int16_t) == 2, "non-wasi data layout");
+_Static_assert(_Alignof(uint16_t) == 2, "non-wasi data layout");
+_Static_assert(_Alignof(int32_t) == 4, "non-wasi data layout");
+_Static_assert(_Alignof(uint32_t) == 4, "non-wasi data layout");
+#if 0
+_Static_assert(_Alignof(int64_t) == 8, "non-wasi data layout");
+_Static_assert(_Alignof(uint64_t) == 8, "non-wasi data layout");
+#endif
+
+typedef uint32_t __wasi_size_t;
+_Static_assert(_Alignof(__wasi_size_t) == 4, "non-wasi data layout");
+
+typedef uint8_t __wasi_advice_t;
+#define __WASI_ADVICE_NORMAL (0)
+#define __WASI_ADVICE_SEQUENTIAL (1)
+#define __WASI_ADVICE_RANDOM (2)
+#define __WASI_ADVICE_WILLNEED (3)
+#define __WASI_ADVICE_DONTNEED (4)
+#define __WASI_ADVICE_NOREUSE (5)
+
+typedef uint32_t __wasi_clockid_t;
+#define __WASI_CLOCK_REALTIME (0)
+#define __WASI_CLOCK_MONOTONIC (1)
+#define __WASI_CLOCK_PROCESS_CPUTIME_ID (2)
+#define __WASI_CLOCK_THREAD_CPUTIME_ID (3)
+
+typedef uint64_t __wasi_device_t;
+
+typedef uint64_t __wasi_dircookie_t;
+#define __WASI_DIRCOOKIE_START (0)
+
+typedef uint32_t __wasi_dirnamlen_t;
+
+typedef uint16_t __wasi_errno_t;
+#define __WASI_ESUCCESS (0)
+#define __WASI_E2BIG (1)
+#define __WASI_EACCES (2)
+#define __WASI_EADDRINUSE (3)
+#define __WASI_EADDRNOTAVAIL (4)
+#define __WASI_EAFNOSUPPORT (5)
+#define __WASI_EAGAIN (6)
+#define __WASI_EALREADY (7)
+#define __WASI_EBADF (8)
+#define __WASI_EBADMSG (9)
+#define __WASI_EBUSY (10)
+#define __WASI_ECANCELED (11)
+#define __WASI_ECHILD (12)
+#define __WASI_ECONNABORTED (13)
+#define __WASI_ECONNREFUSED (14)
+#define __WASI_ECONNRESET (15)
+#define __WASI_EDEADLK (16)
+#define __WASI_EDESTADDRREQ (17)
+#define __WASI_EDOM (18)
+#define __WASI_EDQUOT (19)
+#define __WASI_EEXIST (20)
+#define __WASI_EFAULT (21)
+#define __WASI_EFBIG (22)
+#define __WASI_EHOSTUNREACH (23)
+#define __WASI_EIDRM (24)
+#define __WASI_EILSEQ (25)
+#define __WASI_EINPROGRESS (26)
+#define __WASI_EINTR (27)
+#define __WASI_EINVAL (28)
+#define __WASI_EIO (29)
+#define __WASI_EISCONN (30)
+#define __WASI_EISDIR (31)
+#define __WASI_ELOOP (32)
+#define __WASI_EMFILE (33)
+#define __WASI_EMLINK (34)
+#define __WASI_EMSGSIZE (35)
+#define __WASI_EMULTIHOP (36)
+#define __WASI_ENAMETOOLONG (37)
+#define __WASI_ENETDOWN (38)
+#define __WASI_ENETRESET (39)
+#define __WASI_ENETUNREACH (40)
+#define __WASI_ENFILE (41)
+#define __WASI_ENOBUFS (42)
+#define __WASI_ENODEV (43)
+#define __WASI_ENOENT (44)
+#define __WASI_ENOEXEC (45)
+#define __WASI_ENOLCK (46)
+#define __WASI_ENOLINK (47)
+#define __WASI_ENOMEM (48)
+#define __WASI_ENOMSG (49)
+#define __WASI_ENOPROTOOPT (50)
+#define __WASI_ENOSPC (51)
+#define __WASI_ENOSYS (52)
+#define __WASI_ENOTCONN (53)
+#define __WASI_ENOTDIR (54)
+#define __WASI_ENOTEMPTY (55)
+#define __WASI_ENOTRECOVERABLE (56)
+#define __WASI_ENOTSOCK (57)
+#define __WASI_ENOTSUP (58)
+#define __WASI_ENOTTY (59)
+#define __WASI_ENXIO (60)
+#define __WASI_EOVERFLOW (61)
+#define __WASI_EOWNERDEAD (62)
+#define __WASI_EPERM (63)
+#define __WASI_EPIPE (64)
+#define __WASI_EPROTO (65)
+#define __WASI_EPROTONOSUPPORT (66)
+#define __WASI_EPROTOTYPE (67)
+#define __WASI_ERANGE (68)
+#define __WASI_EROFS (69)
+#define __WASI_ESPIPE (70)
+#define __WASI_ESRCH (71)
+#define __WASI_ESTALE (72)
+#define __WASI_ETIMEDOUT (73)
+#define __WASI_ETXTBSY (74)
+#define __WASI_EXDEV (75)
+#define __WASI_ENOTCAPABLE (76)
+
+typedef uint16_t __wasi_eventrwflags_t;
+#define __WASI_EVENT_FD_READWRITE_HANGUP (0x0001)
+
+typedef uint8_t __wasi_eventtype_t;
+#define __WASI_EVENTTYPE_CLOCK (0)
+#define __WASI_EVENTTYPE_FD_READ (1)
+#define __WASI_EVENTTYPE_FD_WRITE (2)
+
+typedef uint32_t __wasi_exitcode_t;
+
+typedef uint32_t __wasi_fd_t;
+
+typedef uint16_t __wasi_fdflags_t;
+#define __WASI_FDFLAG_APPEND (0x0001)
+#define __WASI_FDFLAG_DSYNC (0x0002)
+#define __WASI_FDFLAG_NONBLOCK (0x0004)
+#define __WASI_FDFLAG_RSYNC (0x0008)
+#define __WASI_FDFLAG_SYNC (0x0010)
+
+typedef int64_t __wasi_filedelta_t;
+
+typedef uint64_t __wasi_filesize_t;
+
+typedef uint8_t __wasi_filetype_t;
+#define __WASI_FILETYPE_UNKNOWN (0)
+#define __WASI_FILETYPE_BLOCK_DEVICE (1)
+#define __WASI_FILETYPE_CHARACTER_DEVICE (2)
+#define __WASI_FILETYPE_DIRECTORY (3)
+#define __WASI_FILETYPE_REGULAR_FILE (4)
+#define __WASI_FILETYPE_SOCKET_DGRAM (5)
+#define __WASI_FILETYPE_SOCKET_STREAM (6)
+#define __WASI_FILETYPE_SYMBOLIC_LINK (7)
+
+typedef uint16_t __wasi_fstflags_t;
+#define __WASI_FILESTAT_SET_ATIM (0x0001)
+#define __WASI_FILESTAT_SET_ATIM_NOW (0x0002)
+#define __WASI_FILESTAT_SET_MTIM (0x0004)
+#define __WASI_FILESTAT_SET_MTIM_NOW (0x0008)
+
+typedef uint64_t __wasi_inode_t;
+
+typedef uint64_t __wasi_linkcount_t __attribute__((aligned(8)));
+
+typedef uint32_t __wasi_lookupflags_t;
+#define __WASI_LOOKUP_SYMLINK_FOLLOW (0x00000001)
+
+typedef uint16_t __wasi_oflags_t;
+#define __WASI_O_CREAT (0x0001)
+#define __WASI_O_DIRECTORY (0x0002)
+#define __WASI_O_EXCL (0x0004)
+#define __WASI_O_TRUNC (0x0008)
+
+typedef uint16_t __wasi_riflags_t;
+#define __WASI_SOCK_RECV_PEEK (0x0001)
+#define __WASI_SOCK_RECV_WAITALL (0x0002)
+
+typedef uint64_t __wasi_rights_t;
+
+/**
+ * Observe that WASI defines rights in the plural form
+ * TODO: refactor to use RIGHTS instead of RIGHT
+ */
+#define __WASI_RIGHT_FD_DATASYNC ((__wasi_rights_t)(UINT64_C(1) << 0))
+#define __WASI_RIGHT_FD_READ ((__wasi_rights_t)(UINT64_C(1) << 1))
+#define __WASI_RIGHT_FD_SEEK ((__wasi_rights_t)(UINT64_C(1) << 2))
+#define __WASI_RIGHT_FD_FDSTAT_SET_FLAGS ((__wasi_rights_t)(UINT64_C(1) << 3))
+#define __WASI_RIGHT_FD_SYNC ((__wasi_rights_t)(UINT64_C(1) << 4))
+#define __WASI_RIGHT_FD_TELL ((__wasi_rights_t)(UINT64_C(1) << 5))
+#define __WASI_RIGHT_FD_WRITE ((__wasi_rights_t)(UINT64_C(1) << 6))
+#define __WASI_RIGHT_FD_ADVISE ((__wasi_rights_t)(UINT64_C(1) << 7))
+#define __WASI_RIGHT_FD_ALLOCATE ((__wasi_rights_t)(UINT64_C(1) << 8))
+#define __WASI_RIGHT_PATH_CREATE_DIRECTORY ((__wasi_rights_t)(UINT64_C(1) << 9))
+#define __WASI_RIGHT_PATH_CREATE_FILE ((__wasi_rights_t)(UINT64_C(1) << 10))
+#define __WASI_RIGHT_PATH_LINK_SOURCE ((__wasi_rights_t)(UINT64_C(1) << 11))
+#define __WASI_RIGHT_PATH_LINK_TARGET ((__wasi_rights_t)(UINT64_C(1) << 12))
+#define __WASI_RIGHT_PATH_OPEN ((__wasi_rights_t)(UINT64_C(1) << 13))
+#define __WASI_RIGHT_FD_READDIR ((__wasi_rights_t)(UINT64_C(1) << 14))
+#define __WASI_RIGHT_PATH_READLINK ((__wasi_rights_t)(UINT64_C(1) << 15))
+#define __WASI_RIGHT_PATH_RENAME_SOURCE ((__wasi_rights_t)(UINT64_C(1) << 16))
+#define __WASI_RIGHT_PATH_RENAME_TARGET ((__wasi_rights_t)(UINT64_C(1) << 17))
+#define __WASI_RIGHT_PATH_FILESTAT_GET ((__wasi_rights_t)(UINT64_C(1) << 18))
+#define __WASI_RIGHT_PATH_FILESTAT_SET_SIZE ((__wasi_rights_t)(UINT64_C(1) << 19))
+#define __WASI_RIGHT_PATH_FILESTAT_SET_TIMES ((__wasi_rights_t)(UINT64_C(1) << 20))
+#define __WASI_RIGHT_FD_FILESTAT_GET ((__wasi_rights_t)(UINT64_C(1) << 21))
+#define __WASI_RIGHT_FD_FILESTAT_SET_SIZE ((__wasi_rights_t)(UINT64_C(1) << 22))
+#define __WASI_RIGHT_FD_FILESTAT_SET_TIMES ((__wasi_rights_t)(UINT64_C(1) << 23))
+#define __WASI_RIGHT_PATH_SYMLINK ((__wasi_rights_t)(UINT64_C(1) << 24))
+#define __WASI_RIGHT_PATH_REMOVE_DIRECTORY ((__wasi_rights_t)(UINT64_C(1) << 25))
+#define __WASI_RIGHT_PATH_UNLINK_FILE ((__wasi_rights_t)(UINT64_C(1) << 26))
+#define __WASI_RIGHT_POLL_FD_READWRITE ((__wasi_rights_t)(UINT64_C(1) << 27))
+#define __WASI_RIGHT_SOCK_CONNECT ((__wasi_rights_t)(UINT64_C(1) << 28))
+#define __WASI_RIGHT_SOCK_LISTEN ((__wasi_rights_t)(UINT64_C(1) << 29))
+#define __WASI_RIGHT_SOCK_BIND ((__wasi_rights_t)(UINT64_C(1) << 30))
+#define __WASI_RIGHT_SOCK_ACCEPT ((__wasi_rights_t)(UINT64_C(1) << 31))
+#define __WASI_RIGHT_SOCK_RECV ((__wasi_rights_t)(UINT64_C(1) << 32))
+#define __WASI_RIGHT_SOCK_SEND ((__wasi_rights_t)(UINT64_C(1) << 33))
+#define __WASI_RIGHT_SOCK_ADDR_LOCAL ((__wasi_rights_t)(UINT64_C(1) << 34))
+#define __WASI_RIGHT_SOCK_ADDR_REMOTE ((__wasi_rights_t)(UINT64_C(1) << 35))
+#define __WASI_RIGHT_SOCK_RECV_FROM ((__wasi_rights_t)(UINT64_C(1) << 36))
+#define __WASI_RIGHT_SOCK_SEND_TO ((__wasi_rights_t)(UINT64_C(1) << 37))
+
+typedef uint16_t __wasi_roflags_t;
+#define __WASI_SOCK_RECV_DATA_TRUNCATED (0x0001)
+
+typedef uint8_t __wasi_sdflags_t;
+#define __WASI_SHUT_RD (0x01)
+#define __WASI_SHUT_WR (0x02)
+
+typedef uint16_t __wasi_siflags_t;
+
+typedef uint8_t __wasi_signal_t;
+// 0 is reserved; POSIX has special semantics for kill(pid, 0).
+#define __WASI_SIGHUP (1)
+#define __WASI_SIGINT (2)
+#define __WASI_SIGQUIT (3)
+#define __WASI_SIGILL (4)
+#define __WASI_SIGTRAP (5)
+#define __WASI_SIGABRT (6)
+#define __WASI_SIGBUS (7)
+#define __WASI_SIGFPE (8)
+#define __WASI_SIGKILL (9)
+#define __WASI_SIGUSR1 (10)
+#define __WASI_SIGSEGV (11)
+#define __WASI_SIGUSR2 (12)
+#define __WASI_SIGPIPE (13)
+#define __WASI_SIGALRM (14)
+#define __WASI_SIGTERM (15)
+#define __WASI_SIGCHLD (16)
+#define __WASI_SIGCONT (17)
+#define __WASI_SIGSTOP (18)
+#define __WASI_SIGTSTP (19)
+#define __WASI_SIGTTIN (20)
+#define __WASI_SIGTTOU (21)
+#define __WASI_SIGURG (22)
+#define __WASI_SIGXCPU (23)
+#define __WASI_SIGXFSZ (24)
+#define __WASI_SIGVTALRM (25)
+#define __WASI_SIGPROF (26)
+#define __WASI_SIGWINCH (27)
+#define __WASI_SIGPOLL (28)
+#define __WASI_SIGPWR (29)
+#define __WASI_SIGSYS (30)
+
+typedef uint16_t __wasi_subclockflags_t;
+#define __WASI_SUBSCRIPTION_CLOCK_ABSTIME (0x0001)
+
+typedef uint64_t __wasi_timestamp_t;
+
+typedef uint64_t __wasi_userdata_t;
+
+typedef uint8_t __wasi_whence_t;
+#define __WASI_WHENCE_SET (0)
+#define __WASI_WHENCE_CUR (1)
+#define __WASI_WHENCE_END (2)
+
+typedef uint8_t __wasi_preopentype_t;
+#define __WASI_PREOPENTYPE_DIR (0)
+
+struct fd_table;
+struct fd_prestats;
+struct argv_environ_values;
+struct addr_pool;
+
+typedef struct __wasi_dirent_t {
+ __wasi_dircookie_t d_next;
+ __wasi_inode_t d_ino;
+ __wasi_dirnamlen_t d_namlen;
+ __wasi_filetype_t d_type;
+} __wasi_dirent_t __attribute__((aligned(8)));
+_Static_assert(offsetof(__wasi_dirent_t, d_next) == 0, "non-wasi data layout");
+_Static_assert(offsetof(__wasi_dirent_t, d_ino) == 8, "non-wasi data layout");
+_Static_assert(offsetof(__wasi_dirent_t, d_namlen) == 16, "non-wasi data layout");
+_Static_assert(offsetof(__wasi_dirent_t, d_type) == 20, "non-wasi data layout");
+_Static_assert(sizeof(__wasi_dirent_t) == 24, "non-wasi data layout");
+_Static_assert(_Alignof(__wasi_dirent_t) == 8, "non-wasi data layout");
+
+typedef struct __wasi_event_t {
+ __wasi_userdata_t userdata;
+ __wasi_errno_t error;
+ __wasi_eventtype_t type;
+ uint8_t __paddings[5];
+ union __wasi_event_u {
+ struct __wasi_event_u_fd_readwrite_t {
+ __wasi_filesize_t nbytes;
+ __wasi_eventrwflags_t flags;
+ uint8_t __paddings[6];
+ } fd_readwrite;
+ } u;
+} __wasi_event_t __attribute__((aligned(8)));
+_Static_assert(offsetof(__wasi_event_t, userdata) == 0, "non-wasi data layout");
+_Static_assert(offsetof(__wasi_event_t, error) == 8, "non-wasi data layout");
+_Static_assert(offsetof(__wasi_event_t, type) == 10, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_event_t, u.fd_readwrite.nbytes) == 16, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_event_t, u.fd_readwrite.flags) == 24, "non-wasi data layout");
+_Static_assert(sizeof(__wasi_event_t) == 32, "non-wasi data layout");
+_Static_assert(_Alignof(__wasi_event_t) == 8, "non-wasi data layout");
+
+typedef struct __wasi_prestat_t {
+ __wasi_preopentype_t pr_type;
+ union __wasi_prestat_u {
+ struct __wasi_prestat_u_dir_t {
+ size_t pr_name_len;
+ } dir;
+ } u;
+} __wasi_prestat_t;
+_Static_assert(offsetof(__wasi_prestat_t, pr_type) == 0, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ offsetof(__wasi_prestat_t, u.dir.pr_name_len) == 4, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ offsetof(__wasi_prestat_t, u.dir.pr_name_len) == 8, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ sizeof(__wasi_prestat_t) == 8, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ sizeof(__wasi_prestat_t) == 16, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ _Alignof(__wasi_prestat_t) == 4, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ _Alignof(__wasi_prestat_t) == 8, "non-wasi data layout");
+
+typedef struct __wasi_fdstat_t {
+ __wasi_filetype_t fs_filetype;
+ __wasi_fdflags_t fs_flags;
+ uint8_t __paddings[4];
+ __wasi_rights_t fs_rights_base;
+ __wasi_rights_t fs_rights_inheriting;
+} __wasi_fdstat_t __attribute__((aligned(8)));
+_Static_assert(
+ offsetof(__wasi_fdstat_t, fs_filetype) == 0, "non-wasi data layout");
+_Static_assert(offsetof(__wasi_fdstat_t, fs_flags) == 2, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_fdstat_t, fs_rights_base) == 8, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_fdstat_t, fs_rights_inheriting) == 16,
+ "non-wasi data layout");
+_Static_assert(sizeof(__wasi_fdstat_t) == 24, "non-wasi data layout");
+_Static_assert(_Alignof(__wasi_fdstat_t) == 8, "non-wasi data layout");
+
+typedef struct __wasi_filestat_t {
+ __wasi_device_t st_dev;
+ __wasi_inode_t st_ino;
+ __wasi_filetype_t st_filetype;
+ __wasi_linkcount_t st_nlink;
+ __wasi_filesize_t st_size;
+ __wasi_timestamp_t st_atim;
+ __wasi_timestamp_t st_mtim;
+ __wasi_timestamp_t st_ctim;
+} __wasi_filestat_t __attribute__((aligned(8)));
+_Static_assert(offsetof(__wasi_filestat_t, st_dev) == 0, "non-wasi data layout");
+_Static_assert(offsetof(__wasi_filestat_t, st_ino) == 8, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_filestat_t, st_filetype) == 16, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_filestat_t, st_nlink) == 24, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_filestat_t, st_size) == 32, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_filestat_t, st_atim) == 40, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_filestat_t, st_mtim) == 48, "non-wasi data layout");
+_Static_assert(
+ offsetof(__wasi_filestat_t, st_ctim) == 56, "non-wasi data layout");
+_Static_assert(sizeof(__wasi_filestat_t) == 64, "non-wasi data layout");
+_Static_assert(_Alignof(__wasi_filestat_t) == 8, "non-wasi data layout");
+
+typedef struct __wasi_ciovec_t {
+ const void *buf;
+ size_t buf_len;
+} __wasi_ciovec_t;
+_Static_assert(offsetof(__wasi_ciovec_t, buf) == 0, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ offsetof(__wasi_ciovec_t, buf_len) == 4, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ offsetof(__wasi_ciovec_t, buf_len) == 8, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ sizeof(__wasi_ciovec_t) == 8, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ sizeof(__wasi_ciovec_t) == 16, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ _Alignof(__wasi_ciovec_t) == 4, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ _Alignof(__wasi_ciovec_t) == 8, "non-wasi data layout");
+
+typedef struct __wasi_iovec_t {
+ void *buf;
+ size_t buf_len;
+} __wasi_iovec_t;
+_Static_assert(offsetof(__wasi_iovec_t, buf) == 0, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ offsetof(__wasi_iovec_t, buf_len) == 4, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ offsetof(__wasi_iovec_t, buf_len) == 8, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ sizeof(__wasi_iovec_t) == 8, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ sizeof(__wasi_iovec_t) == 16, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 4 ||
+ _Alignof(__wasi_iovec_t) == 4, "non-wasi data layout");
+_Static_assert(sizeof(void *) != 8 ||
+ _Alignof(__wasi_iovec_t) == 8, "non-wasi data layout");
+
+/**
+ * The contents of a `subscription` when type is `eventtype::clock`.
+ */
+typedef struct __wasi_subscription_clock_t {
+ /**
+ * The clock against which to compare the timestamp.
+ */
+ __wasi_clockid_t clock_id;
+
+ uint8_t __paddings1[4];
+
+ /**
+ * The absolute or relative timestamp.
+ */
+ __wasi_timestamp_t timeout;
+
+ /**
+ * The amount of time that the implementation may wait additionally
+ * to coalesce with other events.
+ */
+ __wasi_timestamp_t precision;
+
+ /**
+ * Flags specifying whether the timeout is absolute or relative
+ */
+ __wasi_subclockflags_t flags;
+
+ uint8_t __paddings2[4];
+
+} __wasi_subscription_clock_t __attribute__((aligned(8)));
+
+_Static_assert(sizeof(__wasi_subscription_clock_t) == 32, "witx calculated size");
+_Static_assert(_Alignof(__wasi_subscription_clock_t) == 8, "witx calculated align");
+_Static_assert(offsetof(__wasi_subscription_clock_t, clock_id) == 0, "witx calculated offset");
+_Static_assert(offsetof(__wasi_subscription_clock_t, timeout) == 8, "witx calculated offset");
+_Static_assert(offsetof(__wasi_subscription_clock_t, precision) == 16, "witx calculated offset");
+_Static_assert(offsetof(__wasi_subscription_clock_t, flags) == 24, "witx calculated offset");
+
+/**
+ * The contents of a `subscription` when type is type is
+ * `eventtype::fd_read` or `eventtype::fd_write`.
+ */
+typedef struct __wasi_subscription_fd_readwrite_t {
+ /**
+ * The file descriptor on which to wait for it to become ready for reading or writing.
+ */
+ __wasi_fd_t fd;
+
+} __wasi_subscription_fd_readwrite_t;
+
+_Static_assert(sizeof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculated size");
+_Static_assert(_Alignof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculated align");
+_Static_assert(offsetof(__wasi_subscription_fd_readwrite_t, fd) == 0, "witx calculated offset");
+
+/**
+ * The contents of a `subscription`.
+ */
+typedef union __wasi_subscription_u_u_t {
+ __wasi_subscription_clock_t clock;
+ __wasi_subscription_fd_readwrite_t fd_readwrite;
+} __wasi_subscription_u_u_t ;
+
+typedef struct __wasi_subscription_u_t {
+ __wasi_eventtype_t type;
+ __wasi_subscription_u_u_t u;
+} __wasi_subscription_u_t __attribute__((aligned(8)));
+
+_Static_assert(sizeof(__wasi_subscription_u_t) == 40, "witx calculated size");
+_Static_assert(_Alignof(__wasi_subscription_u_t) == 8, "witx calculated align");
+_Static_assert(offsetof(__wasi_subscription_u_t, u) == 8, "witx calculated union offset");
+_Static_assert(sizeof(__wasi_subscription_u_u_t) == 32, "witx calculated union size");
+_Static_assert(_Alignof(__wasi_subscription_u_u_t) == 8, "witx calculated union align");
+
+/**
+ * Subscription to an event.
+ */
+typedef struct __wasi_subscription_t {
+ /**
+ * User-provided value that is attached to the subscription in the
+ * implementation and returned through `event::userdata`.
+ */
+ __wasi_userdata_t userdata;
+
+ /**
+ * The type of the event to which to subscribe, and its contents
+ */
+ __wasi_subscription_u_t u;
+
+} __wasi_subscription_t;
+
+_Static_assert(sizeof(__wasi_subscription_t) == 48, "witx calculated size");
+_Static_assert(_Alignof(__wasi_subscription_t) == 8, "witx calculated align");
+_Static_assert(offsetof(__wasi_subscription_t, userdata) == 0, "witx calculated offset");
+_Static_assert(offsetof(__wasi_subscription_t, u) == 8, "witx calculated offset");
+
+/* keep syncing with wasi_socket_ext.h */
+typedef enum {
+ SOCKET_DGRAM = 0,
+ SOCKET_STREAM,
+} __wasi_sock_type_t;
+
+typedef uint16_t __wasi_ip_port_t;
+
+typedef enum { IPv4 = 0, IPv6 } __wasi_addr_type_t;
+
+/* n0.n1.n2.n3 */
+typedef struct __wasi_addr_ip4_t {
+ uint8_t n0;
+ uint8_t n1;
+ uint8_t n2;
+ uint8_t n3;
+} __wasi_addr_ip4_t;
+
+typedef struct __wasi_addr_ip4_port_t {
+ __wasi_addr_ip4_t addr;
+ __wasi_ip_port_t port;
+} __wasi_addr_ip4_port_t;
+
+typedef struct __wasi_addr_ip6_t {
+ uint16_t n0;
+ uint16_t n1;
+ uint16_t n2;
+ uint16_t n3;
+ uint16_t h0;
+ uint16_t h1;
+ uint16_t h2;
+ uint16_t h3;
+} __wasi_addr_ip6_t;
+
+typedef struct __wasi_addr_ip6_port_t {
+ __wasi_addr_ip6_t addr;
+ __wasi_ip_port_t port;
+} __wasi_addr_ip6_port_t;
+
+typedef struct __wasi_addr_ip_t {
+ __wasi_addr_type_t kind;
+ union {
+ __wasi_addr_ip4_t ip4;
+ __wasi_addr_ip6_t ip6;
+ } addr;
+} __wasi_addr_ip_t;
+
+typedef struct __wasi_addr_t {
+ __wasi_addr_type_t kind;
+ union {
+ __wasi_addr_ip4_port_t ip4;
+ __wasi_addr_ip6_port_t ip6;
+ } addr;
+} __wasi_addr_t;
+
+typedef enum { INET4 = 0, INET6 } __wasi_address_family_t;
+
+typedef struct __wasi_addr_info_t {
+ __wasi_addr_t addr;
+ __wasi_sock_type_t type;
+} __wasi_addr_info_t;
+
+typedef struct __wasi_addr_info_hints_t {
+ __wasi_sock_type_t type;
+ __wasi_address_family_t family;
+ // this is to workaround lack of optional parameters
+ uint8_t hints_enabled;
+} __wasi_addr_info_hints_t;
+
+#if defined(WASMTIME_SSP_WASI_API)
+#define WASMTIME_SSP_SYSCALL_NAME(name) \
+ asm("__wasi_" #name)
+#else
+#define WASMTIME_SSP_SYSCALL_NAME(name)
+#endif
+
+__wasi_errno_t wasmtime_ssp_args_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *arg_environ,
+#endif
+ char **argv,
+ char *argv_buf
+) WASMTIME_SSP_SYSCALL_NAME(args_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_args_sizes_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *arg_environ,
+#endif
+ size_t *argc,
+ size_t *argv_buf_size
+) WASMTIME_SSP_SYSCALL_NAME(args_sizes_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_clock_res_get(
+ __wasi_clockid_t clock_id,
+ __wasi_timestamp_t *resolution
+) WASMTIME_SSP_SYSCALL_NAME(clock_res_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_clock_time_get(
+ __wasi_clockid_t clock_id,
+ __wasi_timestamp_t precision,
+ __wasi_timestamp_t *time
+) WASMTIME_SSP_SYSCALL_NAME(clock_time_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_environ_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *arg_environ,
+#endif
+ char **environ,
+ char *environ_buf
+) WASMTIME_SSP_SYSCALL_NAME(environ_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_environ_sizes_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *arg_environ,
+#endif
+ size_t *environ_count,
+ size_t *environ_buf_size
+) WASMTIME_SSP_SYSCALL_NAME(environ_sizes_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_prestat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t fd,
+ __wasi_prestat_t *buf
+) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_prestat_dir_name(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t fd,
+ char *path,
+ size_t path_len
+) WASMTIME_SSP_SYSCALL_NAME(fd_prestat_dir_name) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_close(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+ struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t fd
+) WASMTIME_SSP_SYSCALL_NAME(fd_close) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_datasync(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd
+) WASMTIME_SSP_SYSCALL_NAME(fd_datasync) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_pread(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const __wasi_iovec_t *iovs,
+ size_t iovs_len,
+ __wasi_filesize_t offset,
+ size_t *nread
+) WASMTIME_SSP_SYSCALL_NAME(fd_pread) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_pwrite(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const __wasi_ciovec_t *iovs,
+ size_t iovs_len,
+ __wasi_filesize_t offset,
+ size_t *nwritten
+) WASMTIME_SSP_SYSCALL_NAME(fd_pwrite) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_read(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const __wasi_iovec_t *iovs,
+ size_t iovs_len,
+ size_t *nread
+) WASMTIME_SSP_SYSCALL_NAME(fd_read) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_renumber(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+ struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t from,
+ __wasi_fd_t to
+) WASMTIME_SSP_SYSCALL_NAME(fd_renumber) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_seek(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_filedelta_t offset,
+ __wasi_whence_t whence,
+ __wasi_filesize_t *newoffset
+) WASMTIME_SSP_SYSCALL_NAME(fd_seek) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_tell(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_filesize_t *newoffset
+) WASMTIME_SSP_SYSCALL_NAME(fd_tell) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_fdstat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_fdstat_t *buf
+) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_fdstat_set_flags(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_fdflags_t flags
+) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_flags) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_fdstat_set_rights(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_rights_t fs_rights_base,
+ __wasi_rights_t fs_rights_inheriting
+) WASMTIME_SSP_SYSCALL_NAME(fd_fdstat_set_rights) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_sync(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd
+) WASMTIME_SSP_SYSCALL_NAME(fd_sync) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_write(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const __wasi_ciovec_t *iovs,
+ size_t iovs_len,
+ size_t *nwritten
+) WASMTIME_SSP_SYSCALL_NAME(fd_write) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_advise(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_filesize_t offset,
+ __wasi_filesize_t len,
+ __wasi_advice_t advice
+) WASMTIME_SSP_SYSCALL_NAME(fd_advise) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_allocate(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_filesize_t offset,
+ __wasi_filesize_t len
+) WASMTIME_SSP_SYSCALL_NAME(fd_allocate) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_create_directory(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const char *path,
+ size_t path_len
+) WASMTIME_SSP_SYSCALL_NAME(path_create_directory) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_link(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+ struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t old_fd,
+ __wasi_lookupflags_t old_flags,
+ const char *old_path,
+ size_t old_path_len,
+ __wasi_fd_t new_fd,
+ const char *new_path,
+ size_t new_path_len
+) WASMTIME_SSP_SYSCALL_NAME(path_link) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_open(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t dirfd,
+ __wasi_lookupflags_t dirflags,
+ const char *path,
+ size_t path_len,
+ __wasi_oflags_t oflags,
+ __wasi_rights_t fs_rights_base,
+ __wasi_rights_t fs_rights_inheriting,
+ __wasi_fdflags_t fs_flags,
+ __wasi_fd_t *fd
+) WASMTIME_SSP_SYSCALL_NAME(path_open) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_readdir(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ void *buf,
+ size_t buf_len,
+ __wasi_dircookie_t cookie,
+ size_t *bufused
+) WASMTIME_SSP_SYSCALL_NAME(fd_readdir) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_readlink(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const char *path,
+ size_t path_len,
+ char *buf,
+ size_t buf_len,
+ size_t *bufused
+) WASMTIME_SSP_SYSCALL_NAME(path_readlink) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_rename(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t old_fd,
+ const char *old_path,
+ size_t old_path_len,
+ __wasi_fd_t new_fd,
+ const char *new_path,
+ size_t new_path_len
+) WASMTIME_SSP_SYSCALL_NAME(path_rename) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_filestat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_filestat_t *buf
+) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_filestat_set_times(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_timestamp_t st_atim,
+ __wasi_timestamp_t st_mtim,
+ __wasi_fstflags_t fstflags
+) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_times) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_fd_filestat_set_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_filesize_t st_size
+) WASMTIME_SSP_SYSCALL_NAME(fd_filestat_set_size) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_filestat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_lookupflags_t flags,
+ const char *path,
+ size_t path_len,
+ __wasi_filestat_t *buf
+) WASMTIME_SSP_SYSCALL_NAME(path_filestat_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_filestat_set_times(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ __wasi_lookupflags_t flags,
+ const char *path,
+ size_t path_len,
+ __wasi_timestamp_t st_atim,
+ __wasi_timestamp_t st_mtim,
+ __wasi_fstflags_t fstflags
+) WASMTIME_SSP_SYSCALL_NAME(path_filestat_set_times) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_symlink(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+ struct fd_prestats *prestats,
+#endif
+ const char *old_path,
+ size_t old_path_len,
+ __wasi_fd_t fd,
+ const char *new_path,
+ size_t new_path_len
+) WASMTIME_SSP_SYSCALL_NAME(path_symlink) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_unlink_file(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const char *path,
+ size_t path_len
+) WASMTIME_SSP_SYSCALL_NAME(path_unlink_file) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_path_remove_directory(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd,
+ const char *path,
+ size_t path_len
+) WASMTIME_SSP_SYSCALL_NAME(path_remove_directory) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_poll_oneoff(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ const __wasi_subscription_t *in,
+ __wasi_event_t *out,
+ size_t nsubscriptions,
+ size_t *nevents
+) WASMTIME_SSP_SYSCALL_NAME(poll_oneoff) __attribute__((__warn_unused_result__));
+
+#if 0
+/**
+ * We throw exception in libc-wasi wrapper function wasi_proc_exit()
+ * but not call this function.
+ */
+_Noreturn void wasmtime_ssp_proc_exit(
+ __wasi_exitcode_t rval
+) WASMTIME_SSP_SYSCALL_NAME(proc_exit);
+#endif
+
+__wasi_errno_t wasmtime_ssp_proc_raise(
+ __wasi_signal_t sig
+) WASMTIME_SSP_SYSCALL_NAME(proc_raise) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_random_get(
+ void *buf,
+ size_t buf_len
+) WASMTIME_SSP_SYSCALL_NAME(random_get) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_accept(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_addr_local(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_addr_remote(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_open(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype,
+ __wasi_fd_t *sockfd
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_bind(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct addr_pool *addr_pool,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_addr_resolve(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, char **ns_lookup_list,
+#endif
+ const char *host, const char* service,
+ __wasi_addr_info_hints_t *hints, __wasi_addr_info_t *addr_info,
+ __wasi_size_t addr_info_size, __wasi_size_t *max_info_size
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_connect(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct addr_pool *addr_pool,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_get_recv_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t *size
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_get_reuse_addr(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t *reuse
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_get_reuse_port(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t *reuse
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_get_send_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t *size
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_set_recv_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t size
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_set_reuse_addr(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t reuse
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_set_reuse_port(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t reuse
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_set_send_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t size
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t
+wasi_ssp_sock_listen(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t backlog
+) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_recv(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ void *buf,
+ size_t buf_len,
+ size_t *recv_len
+) WASMTIME_SSP_SYSCALL_NAME(sock_recv) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_recv_from(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ void *buf,
+ size_t buf_len,
+ __wasi_riflags_t ri_flags,
+ __wasi_addr_t *src_addr,
+ size_t *recv_len
+) WASMTIME_SSP_SYSCALL_NAME(sock_recv_from) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_send(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ const void *buf,
+ size_t buf_len,
+ size_t *sent_len
+) WASMTIME_SSP_SYSCALL_NAME(sock_send) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_send_to(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct addr_pool *addr_pool,
+#endif
+ __wasi_fd_t sock,
+ const void *buf,
+ size_t buf_len,
+ __wasi_siflags_t si_flags,
+ const __wasi_addr_t *dest_addr,
+ size_t *sent_len
+) WASMTIME_SSP_SYSCALL_NAME(sock_send_to) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_shutdown(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock
+) WASMTIME_SSP_SYSCALL_NAME(sock_shutdown) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_recv_timeout(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint64_t timeout_us
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_timeout) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_recv_timeout(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint64_t *timeout_us
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_timeout) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_send_timeout(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint64_t timeout_us
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_timeout) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_send_timeout(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint64_t *timeout_us
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_timeout) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_send_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ size_t bufsiz
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_send_buf_size) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_send_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ size_t *bufsiz
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_send_buf_size) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_recv_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ size_t bufsiz
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_recv_buf_size) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_recv_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ size_t *bufsiz
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_recv_buf_size) __attribute__((__warn_unused_result__));
+
+
+__wasi_errno_t wasmtime_ssp_sock_set_keep_alive(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_keep_alive) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_keep_alive(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_keep_alive) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_reuse_addr(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_addr) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_reuse_addr(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_addr) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_reuse_port(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_reuse_port) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_reuse_port(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_reuse_port) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_linger(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled,
+ int linger_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_linger) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_linger(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, bool *is_enabled, int *linger_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_linger) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_broadcast(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_broadcast) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_broadcast(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_broadcast) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_tcp_no_delay(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_no_delay) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_tcp_no_delay(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_no_delay) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_tcp_quick_ack(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_quick_ack) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_tcp_quick_ack(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_quick_ack) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_idle(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint32_t time_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_idle) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_idle(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint32_t *time_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_idle) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_tcp_keep_intvl(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint32_t time_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_keep_intvl) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_tcp_keep_intvl(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint32_t *time_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_keep_intvl) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_tcp_fastopen_connect(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_tcp_fastopen_connect) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_tcp_fastopen_connect(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_tcp_fastopen_connect) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_loop(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool ipv6,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_loop) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_loop(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool ipv6,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_loop) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_ip_add_membership(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ __wasi_addr_ip_t *imr_multiaddr,
+ uint32_t imr_interface
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_add_membership) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_ip_drop_membership(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ __wasi_addr_ip_t *imr_multiaddr,
+ uint32_t imr_interface
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_drop_membership) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_ip_ttl(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint8_t ttl_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_ttl) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_ip_ttl(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint8_t *ttl_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_ttl) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_ip_multicast_ttl(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint8_t ttl_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_ip_multicast_ttl) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_ip_multicast_ttl(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ uint8_t *ttl_s
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_ip_multicast_ttl) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_set_ipv6_only(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_set_ipv6_only) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sock_get_ipv6_only(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock,
+ bool *is_enabled
+) WASMTIME_SSP_SYSCALL_NAME(sock_get_ipv6_only) __attribute__((__warn_unused_result__));
+
+__wasi_errno_t wasmtime_ssp_sched_yield(void)
+ WASMTIME_SSP_SYSCALL_NAME(sched_yield) __attribute__((__warn_unused_result__));
+
+#ifdef __cplusplus
+}
+#endif
+
+#undef WASMTIME_SSP_SYSCALL_NAME
+
+/* clang-format on */
+
+#endif /* end of WASMTIME_SSP_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE
new file mode 100644
index 000000000..04c6f48a2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE
@@ -0,0 +1,24 @@
+All code is distributed under the following license:
+
+ Copyright (c) 2015 Nuxi, https://nuxi.nl/
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md
new file mode 100644
index 000000000..b4d55d803
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/README.md
@@ -0,0 +1,14 @@
+This directory consists of selected files copied from the [src/libemulator]
+directory in the [cloudabi-utils] repository, with minor modifications,
+along with the accompanying LICENSE file from that repository.
+
+The modifications are marked with `WASMTIME_*` preprocessor macros.
+
+The files were copied at git revision
+223dadc53248552db43e012c67ed08cf416a2b12
+which is dated
+Tue Jun 25 17:22:07 2019 -0700
+.
+
+[libemulator]: https://github.com/NuxiNL/cloudabi-utils/tree/223dadc53248552db43e012c67ed08cf416a2b12/src/libemulator
+[cloudabi-utils]: https://github.com/NuxiNL/cloudabi-utils
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h
new file mode 100644
index 000000000..70000ae0b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#if !defined(__GNUC_PREREQ) && (defined(__GNUC__) || defined(__GNUG__)) \
+ && !defined(__clang__) && defined(__GNUC_MINOR__)
+/* Depending on the platform the macro is defined in sys/features.h or
+ features.h Given the macro is simple, we re-implement it here instead of
+ dealing with two different paths.
+ */
+#define __GNUC_PREREQ(maj, min) \
+ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h
new file mode 100644
index 000000000..40b064b81
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h
@@ -0,0 +1,265 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#ifndef LOCKING_H
+#define LOCKING_H
+
+#include "ssp_config.h"
+
+#ifndef __has_extension
+#define __has_extension(x) 0
+#endif
+
+#if __has_extension(c_thread_safety_attributes)
+#define LOCK_ANNOTATE(x) __attribute__((x))
+#else
+#define LOCK_ANNOTATE(x)
+#endif
+
+/* Lock annotation macros. */
+
+#define LOCKABLE LOCK_ANNOTATE(lockable)
+
+#define LOCKS_EXCLUSIVE(...) LOCK_ANNOTATE(exclusive_lock_function(__VA_ARGS__))
+#define LOCKS_SHARED(...) LOCK_ANNOTATE(shared_lock_function(__VA_ARGS__))
+
+#define TRYLOCKS_EXCLUSIVE(...) \
+ LOCK_ANNOTATE(exclusive_trylock_function(__VA_ARGS__))
+#define TRYLOCKS_SHARED(...) LOCK_ANNOTATE(shared_trylock_function(__VA_ARGS__))
+
+#define UNLOCKS(...) LOCK_ANNOTATE(unlock_function(__VA_ARGS__))
+
+#define REQUIRES_EXCLUSIVE(...) \
+ LOCK_ANNOTATE(exclusive_locks_required(__VA_ARGS__))
+#define REQUIRES_SHARED(...) LOCK_ANNOTATE(shared_locks_required(__VA_ARGS__))
+#define REQUIRES_UNLOCKED(...) LOCK_ANNOTATE(locks_excluded(__VA_ARGS__))
+
+#define NO_LOCK_ANALYSIS LOCK_ANNOTATE(no_thread_safety_analysis)
+
+/* Mutex that uses the lock annotations. */
+
+struct LOCKABLE mutex {
+ pthread_mutex_t object;
+};
+
+/* clang-format off */
+#define MUTEX_INITIALIZER \
+ { PTHREAD_MUTEX_INITIALIZER }
+/* clang-format on */
+
+static inline bool
+mutex_init(struct mutex *lock) REQUIRES_UNLOCKED(*lock)
+{
+ return pthread_mutex_init(&lock->object, NULL) == 0 ? true : false;
+}
+
+static inline void
+mutex_destroy(struct mutex *lock) REQUIRES_UNLOCKED(*lock)
+{
+ pthread_mutex_destroy(&lock->object);
+}
+
+static inline void
+mutex_lock(struct mutex *lock) LOCKS_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS
+{
+ pthread_mutex_lock(&lock->object);
+}
+
+static inline void
+mutex_unlock(struct mutex *lock) UNLOCKS(*lock) NO_LOCK_ANALYSIS
+{
+ pthread_mutex_unlock(&lock->object);
+}
+
+/* Read-write lock that uses the lock annotations. */
+
+struct LOCKABLE rwlock {
+ pthread_rwlock_t object;
+};
+
+static inline bool
+rwlock_init(struct rwlock *lock) REQUIRES_UNLOCKED(*lock)
+{
+ return pthread_rwlock_init(&lock->object, NULL) == 0 ? true : false;
+}
+
+static inline void
+rwlock_rdlock(struct rwlock *lock) LOCKS_SHARED(*lock) NO_LOCK_ANALYSIS
+{
+ pthread_rwlock_rdlock(&lock->object);
+}
+
+static inline void
+rwlock_wrlock(struct rwlock *lock) LOCKS_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS
+{
+ pthread_rwlock_wrlock(&lock->object);
+}
+
+static inline void
+rwlock_unlock(struct rwlock *lock) UNLOCKS(*lock) NO_LOCK_ANALYSIS
+{
+ pthread_rwlock_unlock(&lock->object);
+}
+
+static inline void
+rwlock_destroy(struct rwlock *lock) UNLOCKS(*lock) NO_LOCK_ANALYSIS
+{
+ pthread_rwlock_destroy(&lock->object);
+}
+
+/* Condition variable that uses the lock annotations. */
+
+struct LOCKABLE cond {
+ pthread_cond_t object;
+#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \
+ || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP
+ clockid_t clock;
+#endif
+};
+
+static inline bool
+cond_init_monotonic(struct cond *cond)
+{
+ bool ret = false;
+#if CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK
+ pthread_condattr_t attr;
+
+ if (pthread_condattr_init(&attr) != 0)
+ return false;
+
+ if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC) != 0)
+ goto fail;
+
+ if (pthread_cond_init(&cond->object, &attr) != 0)
+ goto fail;
+
+ ret = true;
+fail:
+ pthread_condattr_destroy(&attr);
+#else
+ if (pthread_cond_init(&cond->object, NULL) != 0)
+ return false;
+ ret = true;
+#endif
+
+#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \
+ || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP
+ cond->clock = CLOCK_MONOTONIC;
+#endif
+ return ret;
+}
+
+static inline bool
+cond_init_realtime(struct cond *cond)
+{
+ if (pthread_cond_init(&cond->object, NULL) != 0)
+ return false;
+#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK \
+ || !CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP
+ cond->clock = CLOCK_REALTIME;
+#endif
+ return true;
+}
+
+static inline void
+cond_destroy(struct cond *cond)
+{
+ pthread_cond_destroy(&cond->object);
+}
+
+static inline void
+cond_signal(struct cond *cond)
+{
+ pthread_cond_signal(&cond->object);
+}
+
+#if !CONFIG_HAS_CLOCK_NANOSLEEP
+static inline bool
+cond_timedwait(struct cond *cond, struct mutex *lock, uint64_t timeout,
+ bool abstime) REQUIRES_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS
+{
+ int ret;
+ struct timespec ts = {
+ .tv_sec = (time_t)(timeout / 1000000000),
+ .tv_nsec = (long)(timeout % 1000000000),
+ };
+
+ if (abstime) {
+#if !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK
+ /**
+ * No native support for sleeping on monotonic clocks. Convert the
+ * timeout to a relative value and then to an absolute value for the
+ * realtime clock.
+ */
+ if (cond->clock != CLOCK_REALTIME) {
+ struct timespec ts_monotonic;
+ struct timespec ts_realtime;
+
+ clock_gettime(cond->clock, &ts_monotonic);
+ ts.tv_sec -= ts_monotonic.tv_sec;
+ ts.tv_nsec -= ts_monotonic.tv_nsec;
+ if (ts.tv_nsec < 0) {
+ ts.tv_nsec += 1000000000;
+ --ts.tv_sec;
+ }
+
+ clock_gettime(CLOCK_REALTIME, &ts_realtime);
+ ts.tv_sec += ts_realtime.tv_sec;
+ ts.tv_nsec += ts_realtime.tv_nsec;
+ if (ts.tv_nsec >= 1000000000) {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+ }
+#endif
+ }
+ else {
+#if CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP
+ /* Implementation supports relative timeouts. */
+ ret = pthread_cond_timedwait_relative_np(&cond->object, &lock->object,
+ &ts);
+ bh_assert((ret == 0 || ret == ETIMEDOUT)
+ && "pthread_cond_timedwait_relative_np() failed");
+ return ret == ETIMEDOUT;
+#else
+ /* Convert to absolute timeout. */
+ struct timespec ts_now;
+#if CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK
+ clock_gettime(cond->clock, &ts_now);
+#else
+ clock_gettime(CLOCK_REALTIME, &ts_now);
+#endif
+ ts.tv_sec += ts_now.tv_sec;
+ ts.tv_nsec += ts_now.tv_nsec;
+ if (ts.tv_nsec >= 1000000000) {
+ ts.tv_nsec -= 1000000000;
+ ++ts.tv_sec;
+ }
+#endif
+ }
+
+ ret = pthread_cond_timedwait(&cond->object, &lock->object, &ts);
+ bh_assert((ret == 0 || ret == ETIMEDOUT)
+ && "pthread_cond_timedwait() failed");
+ return ret == ETIMEDOUT;
+}
+#endif
+
+static inline void
+cond_wait(struct cond *cond, struct mutex *lock)
+ REQUIRES_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS
+{
+ pthread_cond_wait(&cond->object, &lock->object);
+}
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c
new file mode 100644
index 000000000..61e841836
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c
@@ -0,0 +1,4072 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016-2018 Nuxi, https://nuxi.nl/
+
+#include "ssp_config.h"
+#include "bh_platform.h"
+#include "wasmtime_ssp.h"
+#include "locking.h"
+#include "posix.h"
+#include "random.h"
+#include "refcount.h"
+#include "rights.h"
+#include "str.h"
+
+#if 0 /* TODO: -std=gnu99 causes compile error, comment them first */
+// struct iovec must have the same layout as __wasi_iovec_t.
+static_assert(offsetof(struct iovec, iov_base) ==
+ offsetof(__wasi_iovec_t, buf),
+ "Offset mismatch");
+static_assert(sizeof(((struct iovec *)0)->iov_base) ==
+ sizeof(((__wasi_iovec_t *)0)->buf),
+ "Size mismatch");
+static_assert(offsetof(struct iovec, iov_len) ==
+ offsetof(__wasi_iovec_t, buf_len),
+ "Offset mismatch");
+static_assert(sizeof(((struct iovec *)0)->iov_len) ==
+ sizeof(((__wasi_iovec_t *)0)->buf_len),
+ "Size mismatch");
+static_assert(sizeof(struct iovec) == sizeof(__wasi_iovec_t),
+ "Size mismatch");
+
+// struct iovec must have the same layout as __wasi_ciovec_t.
+static_assert(offsetof(struct iovec, iov_base) ==
+ offsetof(__wasi_ciovec_t, buf),
+ "Offset mismatch");
+static_assert(sizeof(((struct iovec *)0)->iov_base) ==
+ sizeof(((__wasi_ciovec_t *)0)->buf),
+ "Size mismatch");
+static_assert(offsetof(struct iovec, iov_len) ==
+ offsetof(__wasi_ciovec_t, buf_len),
+ "Offset mismatch");
+static_assert(sizeof(((struct iovec *)0)->iov_len) ==
+ sizeof(((__wasi_ciovec_t *)0)->buf_len),
+ "Size mismatch");
+static_assert(sizeof(struct iovec) == sizeof(__wasi_ciovec_t),
+ "Size mismatch");
+#endif
+
+#if defined(WASMTIME_SSP_STATIC_CURFDS)
+static __thread struct fd_table *curfds;
+static __thread struct fd_prestats *prestats;
+static __thread struct argv_environ_values *argv_environ;
+static __thread struct addr_pool *addr_pool;
+#endif
+
+// Converts a POSIX error code to a CloudABI error code.
+static __wasi_errno_t
+convert_errno(int error)
+{
+ static const __wasi_errno_t errors[] = {
+#define X(v) [v] = __WASI_##v
+ X(E2BIG),
+ X(EACCES),
+ X(EADDRINUSE),
+ X(EADDRNOTAVAIL),
+ X(EAFNOSUPPORT),
+ X(EAGAIN),
+ X(EALREADY),
+ X(EBADF),
+ X(EBADMSG),
+ X(EBUSY),
+ X(ECANCELED),
+ X(ECHILD),
+ X(ECONNABORTED),
+ X(ECONNREFUSED),
+ X(ECONNRESET),
+ X(EDEADLK),
+ X(EDESTADDRREQ),
+ X(EDOM),
+ X(EDQUOT),
+ X(EEXIST),
+ X(EFAULT),
+ X(EFBIG),
+ X(EHOSTUNREACH),
+ X(EIDRM),
+ X(EILSEQ),
+ X(EINPROGRESS),
+ X(EINTR),
+ X(EINVAL),
+ X(EIO),
+ X(EISCONN),
+ X(EISDIR),
+ X(ELOOP),
+ X(EMFILE),
+ X(EMLINK),
+ X(EMSGSIZE),
+ X(EMULTIHOP),
+ X(ENAMETOOLONG),
+ X(ENETDOWN),
+ X(ENETRESET),
+ X(ENETUNREACH),
+ X(ENFILE),
+ X(ENOBUFS),
+ X(ENODEV),
+ X(ENOENT),
+ X(ENOEXEC),
+ X(ENOLCK),
+ X(ENOLINK),
+ X(ENOMEM),
+ X(ENOMSG),
+ X(ENOPROTOOPT),
+ X(ENOSPC),
+ X(ENOSYS),
+#ifdef ENOTCAPABLE
+ X(ENOTCAPABLE),
+#endif
+ X(ENOTCONN),
+ X(ENOTDIR),
+ X(ENOTEMPTY),
+ X(ENOTRECOVERABLE),
+ X(ENOTSOCK),
+ X(ENOTSUP),
+ X(ENOTTY),
+ X(ENXIO),
+ X(EOVERFLOW),
+ X(EOWNERDEAD),
+ X(EPERM),
+ X(EPIPE),
+ X(EPROTO),
+ X(EPROTONOSUPPORT),
+ X(EPROTOTYPE),
+ X(ERANGE),
+ X(EROFS),
+ X(ESPIPE),
+ X(ESRCH),
+ X(ESTALE),
+ X(ETIMEDOUT),
+ X(ETXTBSY),
+ X(EXDEV),
+#undef X
+#if EOPNOTSUPP != ENOTSUP
+ [EOPNOTSUPP] = __WASI_ENOTSUP,
+#endif
+#if EWOULDBLOCK != EAGAIN
+ [EWOULDBLOCK] = __WASI_EAGAIN,
+#endif
+ };
+ if (error < 0 || (size_t)error >= sizeof(errors) / sizeof(errors[0])
+ || errors[error] == 0)
+ return __WASI_ENOSYS;
+ return errors[error];
+}
+
+static bool
+ns_lookup_list_search(char **list, const char *host)
+{
+ size_t host_len = strlen(host), suffix_len;
+
+ while (*list) {
+ if (*list[0] == '*') {
+ suffix_len = strlen(*list) - 1;
+ if (suffix_len <= host_len
+ && strncmp(host + host_len - suffix_len, *list + 1, suffix_len)
+ == 0) {
+ return true;
+ }
+ }
+ else {
+ if (strcmp(*list, host) == 0) {
+ return true;
+ }
+ }
+ list++;
+ }
+
+ return false;
+}
+
+// Converts a POSIX timespec to a CloudABI timestamp.
+static __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
+ + (__wasi_timestamp_t)ts->tv_nsec;
+}
+
+// Converts a CloudABI clock identifier to a POSIX clock identifier.
+static bool
+convert_clockid(__wasi_clockid_t in, clockid_t *out)
+{
+ switch (in) {
+ case __WASI_CLOCK_MONOTONIC:
+ *out = CLOCK_MONOTONIC;
+ return true;
+#if defined(CLOCK_PROCESS_CPUTIME_ID)
+ case __WASI_CLOCK_PROCESS_CPUTIME_ID:
+ *out = CLOCK_PROCESS_CPUTIME_ID;
+ return true;
+#endif
+ case __WASI_CLOCK_REALTIME:
+ *out = CLOCK_REALTIME;
+ return true;
+#if defined(CLOCK_THREAD_CPUTIME_ID)
+ case __WASI_CLOCK_THREAD_CPUTIME_ID:
+ *out = CLOCK_THREAD_CPUTIME_ID;
+ return true;
+#endif
+ default:
+ return false;
+ }
+}
+
+static void
+wasi_addr_to_bh_sockaddr(const __wasi_addr_t *wasi_addr,
+ bh_sockaddr_t *sockaddr)
+{
+ if (wasi_addr->kind == IPv4) {
+ sockaddr->addr_bufer.ipv4 = (wasi_addr->addr.ip4.addr.n0 << 24)
+ | (wasi_addr->addr.ip4.addr.n1 << 16)
+ | (wasi_addr->addr.ip4.addr.n2 << 8)
+ | wasi_addr->addr.ip4.addr.n3;
+ sockaddr->is_ipv4 = true;
+ sockaddr->port = wasi_addr->addr.ip4.port;
+ }
+ else {
+ sockaddr->addr_bufer.ipv6[0] = wasi_addr->addr.ip6.addr.n0;
+ sockaddr->addr_bufer.ipv6[1] = wasi_addr->addr.ip6.addr.n1;
+ sockaddr->addr_bufer.ipv6[2] = wasi_addr->addr.ip6.addr.n2;
+ sockaddr->addr_bufer.ipv6[3] = wasi_addr->addr.ip6.addr.n3;
+ sockaddr->addr_bufer.ipv6[4] = wasi_addr->addr.ip6.addr.h0;
+ sockaddr->addr_bufer.ipv6[5] = wasi_addr->addr.ip6.addr.h1;
+ sockaddr->addr_bufer.ipv6[6] = wasi_addr->addr.ip6.addr.h2;
+ sockaddr->addr_bufer.ipv6[7] = wasi_addr->addr.ip6.addr.h3;
+ sockaddr->is_ipv4 = false;
+ sockaddr->port = wasi_addr->addr.ip6.port;
+ }
+}
+
+// Converts an IPv6 binary address object to WASI address object.
+static void
+bh_sockaddr_to_wasi_addr(const bh_sockaddr_t *sockaddr,
+ __wasi_addr_t *wasi_addr)
+{
+ if (sockaddr->is_ipv4) {
+ wasi_addr->kind = IPv4;
+ wasi_addr->addr.ip4.port = sockaddr->port;
+ wasi_addr->addr.ip4.addr.n0 =
+ (sockaddr->addr_bufer.ipv4 & 0xFF000000) >> 24;
+ wasi_addr->addr.ip4.addr.n1 =
+ (sockaddr->addr_bufer.ipv4 & 0x00FF0000) >> 16;
+ wasi_addr->addr.ip4.addr.n2 =
+ (sockaddr->addr_bufer.ipv4 & 0x0000FF00) >> 8;
+ wasi_addr->addr.ip4.addr.n3 = (sockaddr->addr_bufer.ipv4 & 0x000000FF);
+ }
+ else {
+ wasi_addr->kind = IPv6;
+ wasi_addr->addr.ip6.port = sockaddr->port;
+ wasi_addr->addr.ip6.addr.n0 = sockaddr->addr_bufer.ipv6[0];
+ wasi_addr->addr.ip6.addr.n1 = sockaddr->addr_bufer.ipv6[1];
+ wasi_addr->addr.ip6.addr.n2 = sockaddr->addr_bufer.ipv6[2];
+ wasi_addr->addr.ip6.addr.n3 = sockaddr->addr_bufer.ipv6[3];
+ wasi_addr->addr.ip6.addr.h0 = sockaddr->addr_bufer.ipv6[4];
+ wasi_addr->addr.ip6.addr.h1 = sockaddr->addr_bufer.ipv6[5];
+ wasi_addr->addr.ip6.addr.h2 = sockaddr->addr_bufer.ipv6[6];
+ wasi_addr->addr.ip6.addr.h3 = sockaddr->addr_bufer.ipv6[7];
+ }
+}
+
+static void
+wasi_addr_ip_to_bh_ip_addr_buffer(__wasi_addr_ip_t *addr,
+ bh_ip_addr_buffer_t *out)
+{
+ if (addr->kind == IPv4) {
+ out->ipv4 = htonl((addr->addr.ip4.n0 << 24) | (addr->addr.ip4.n1 << 16)
+ | (addr->addr.ip4.n2 << 8) | addr->addr.ip4.n3);
+ }
+ else {
+ out->ipv6[0] = htons(addr->addr.ip6.n0);
+ out->ipv6[1] = htons(addr->addr.ip6.n1);
+ out->ipv6[2] = htons(addr->addr.ip6.n2);
+ out->ipv6[3] = htons(addr->addr.ip6.n3);
+ out->ipv6[4] = htons(addr->addr.ip6.h0);
+ out->ipv6[5] = htons(addr->addr.ip6.h1);
+ out->ipv6[6] = htons(addr->addr.ip6.h2);
+ out->ipv6[7] = htons(addr->addr.ip6.h3);
+ }
+}
+
+__wasi_errno_t
+wasmtime_ssp_clock_res_get(__wasi_clockid_t clock_id,
+ __wasi_timestamp_t *resolution)
+{
+ clockid_t nclock_id;
+ if (!convert_clockid(clock_id, &nclock_id))
+ return __WASI_EINVAL;
+ struct timespec ts;
+ if (clock_getres(nclock_id, &ts) < 0)
+ return convert_errno(errno);
+ *resolution = convert_timespec(&ts);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_clock_time_get(__wasi_clockid_t clock_id,
+ __wasi_timestamp_t precision,
+ __wasi_timestamp_t *time)
+{
+ clockid_t nclock_id;
+ if (!convert_clockid(clock_id, &nclock_id))
+ return __WASI_EINVAL;
+ struct timespec ts;
+ if (clock_gettime(nclock_id, &ts) < 0)
+ return convert_errno(errno);
+ *time = convert_timespec(&ts);
+ return 0;
+}
+
+struct fd_prestat {
+ const char *dir;
+};
+
+bool
+fd_prestats_init(struct fd_prestats *pt)
+{
+ if (!rwlock_init(&pt->lock))
+ return false;
+ pt->prestats = NULL;
+ pt->size = 0;
+ pt->used = 0;
+#if defined(WASMTIME_SSP_STATIC_CURFDS)
+ prestats = pt;
+#endif
+ return true;
+}
+
+// Grows the preopened resource table to a required lower bound and a
+// minimum number of free preopened resource table entries.
+static bool
+fd_prestats_grow(struct fd_prestats *pt, size_t min, size_t incr)
+ REQUIRES_EXCLUSIVE(pt->lock)
+{
+ if (pt->size <= min || pt->size < (pt->used + incr) * 2) {
+ // Keep on doubling the table size until we've met our constraints.
+ size_t size = pt->size == 0 ? 1 : pt->size;
+ while (size <= min || size < (pt->used + incr) * 2)
+ size *= 2;
+
+ // Grow the file descriptor table's allocation.
+ struct fd_prestat *prestats =
+ wasm_runtime_malloc((uint32)(sizeof(*prestats) * size));
+ if (prestats == NULL)
+ return false;
+
+ if (pt->prestats && pt->size > 0) {
+ bh_memcpy_s(prestats, (uint32)(sizeof(*prestats) * size),
+ pt->prestats, (uint32)(sizeof(*prestats) * pt->size));
+ }
+
+ if (pt->prestats)
+ wasm_runtime_free(pt->prestats);
+
+ // Mark all new file descriptors as unused.
+ for (size_t i = pt->size; i < size; ++i)
+ prestats[i].dir = NULL;
+ pt->prestats = prestats;
+ pt->size = size;
+ }
+ return true;
+}
+
+// Inserts a preopened resource record into the preopened resource table.
+bool
+fd_prestats_insert(struct fd_prestats *pt, const char *dir, __wasi_fd_t fd)
+{
+ // Grow the preopened resource table if needed.
+ rwlock_wrlock(&pt->lock);
+ if (!fd_prestats_grow(pt, fd, 1)) {
+ rwlock_unlock(&pt->lock);
+ return false;
+ }
+
+ pt->prestats[fd].dir = bh_strdup(dir);
+ rwlock_unlock(&pt->lock);
+
+ if (pt->prestats[fd].dir == NULL)
+ return false;
+
+ return true;
+}
+
+// Looks up a preopened resource table entry by number.
+static __wasi_errno_t
+fd_prestats_get_entry(struct fd_prestats *pt, __wasi_fd_t fd,
+ struct fd_prestat **ret) REQUIRES_SHARED(pt->lock)
+{
+ // Test for file descriptor existence.
+ if (fd >= pt->size)
+ return __WASI_EBADF;
+ struct fd_prestat *prestat = &pt->prestats[fd];
+ if (prestat->dir == NULL)
+ return __WASI_EBADF;
+
+ *ret = prestat;
+ return 0;
+}
+
+struct fd_object {
+ struct refcount refcount;
+ __wasi_filetype_t type;
+ int number;
+
+ union {
+ // Data associated with directory file descriptors.
+ struct {
+ struct mutex lock; // Lock to protect members below.
+ DIR *handle; // Directory handle.
+ __wasi_dircookie_t offset; // Offset of the directory.
+ } directory;
+ };
+};
+
+struct fd_entry {
+ struct fd_object *object;
+ __wasi_rights_t rights_base;
+ __wasi_rights_t rights_inheriting;
+};
+
+bool
+fd_table_init(struct fd_table *ft)
+{
+ if (!rwlock_init(&ft->lock))
+ return false;
+ ft->entries = NULL;
+ ft->size = 0;
+ ft->used = 0;
+#if defined(WASMTIME_SSP_STATIC_CURFDS)
+ curfds = ft;
+#endif
+ return true;
+}
+
+// Looks up a file descriptor table entry by number and required rights.
+static __wasi_errno_t
+fd_table_get_entry(struct fd_table *ft, __wasi_fd_t fd,
+ __wasi_rights_t rights_base,
+ __wasi_rights_t rights_inheriting, struct fd_entry **ret)
+ REQUIRES_SHARED(ft->lock)
+{
+ // Test for file descriptor existence.
+ if (fd >= ft->size)
+ return __WASI_EBADF;
+ struct fd_entry *fe = &ft->entries[fd];
+ if (fe->object == NULL)
+ return __WASI_EBADF;
+
+ // Validate rights.
+ if ((~fe->rights_base & rights_base) != 0
+ || (~fe->rights_inheriting & rights_inheriting) != 0)
+ return __WASI_ENOTCAPABLE;
+ *ret = fe;
+ return 0;
+}
+
+// Grows the file descriptor table to a required lower bound and a
+// minimum number of free file descriptor table entries.
+static bool
+fd_table_grow(struct fd_table *ft, size_t min, size_t incr)
+ REQUIRES_EXCLUSIVE(ft->lock)
+{
+ if (ft->size <= min || ft->size < (ft->used + incr) * 2) {
+ // Keep on doubling the table size until we've met our constraints.
+ size_t size = ft->size == 0 ? 1 : ft->size;
+ while (size <= min || size < (ft->used + incr) * 2)
+ size *= 2;
+
+ // Grow the file descriptor table's allocation.
+ struct fd_entry *entries =
+ wasm_runtime_malloc((uint32)(sizeof(*entries) * size));
+ if (entries == NULL)
+ return false;
+
+ if (ft->entries && ft->size > 0) {
+ bh_memcpy_s(entries, (uint32)(sizeof(*entries) * size), ft->entries,
+ (uint32)(sizeof(*entries) * ft->size));
+ }
+
+ if (ft->entries)
+ wasm_runtime_free(ft->entries);
+
+ // Mark all new file descriptors as unused.
+ for (size_t i = ft->size; i < size; ++i)
+ entries[i].object = NULL;
+ ft->entries = entries;
+ ft->size = size;
+ }
+ return true;
+}
+
+// Allocates a new file descriptor object.
+static __wasi_errno_t
+fd_object_new(__wasi_filetype_t type, struct fd_object **fo)
+ TRYLOCKS_SHARED(0, (*fo)->refcount)
+{
+ *fo = wasm_runtime_malloc(sizeof(**fo));
+ if (*fo == NULL)
+ return __WASI_ENOMEM;
+ refcount_init(&(*fo)->refcount, 1);
+ (*fo)->type = type;
+ (*fo)->number = -1;
+ return 0;
+}
+
+// Attaches a file descriptor to the file descriptor table.
+static void
+fd_table_attach(struct fd_table *ft, __wasi_fd_t fd, struct fd_object *fo,
+ __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting)
+ REQUIRES_EXCLUSIVE(ft->lock) CONSUMES(fo->refcount)
+{
+ assert(ft->size > fd && "File descriptor table too small");
+ struct fd_entry *fe = &ft->entries[fd];
+ assert(fe->object == NULL
+ && "Attempted to overwrite an existing descriptor");
+ fe->object = fo;
+ fe->rights_base = rights_base;
+ fe->rights_inheriting = rights_inheriting;
+ ++ft->used;
+ assert(ft->size >= ft->used * 2 && "File descriptor too full");
+}
+
+// Detaches a file descriptor from the file descriptor table.
+static void
+fd_table_detach(struct fd_table *ft, __wasi_fd_t fd, struct fd_object **fo)
+ REQUIRES_EXCLUSIVE(ft->lock) PRODUCES((*fo)->refcount)
+{
+ assert(ft->size > fd && "File descriptor table too small");
+ struct fd_entry *fe = &ft->entries[fd];
+ *fo = fe->object;
+ assert(*fo != NULL && "Attempted to detach nonexistent descriptor");
+ fe->object = NULL;
+ assert(ft->used > 0 && "Reference count mismatch");
+ --ft->used;
+}
+
+// Determines the type of a file descriptor and its maximum set of
+// rights that should be attached to it.
+static __wasi_errno_t
+fd_determine_type_rights(int fd, __wasi_filetype_t *type,
+ __wasi_rights_t *rights_base,
+ __wasi_rights_t *rights_inheriting)
+{
+ struct stat sb;
+ if (fstat(fd, &sb) < 0)
+ return convert_errno(errno);
+ if (S_ISBLK(sb.st_mode)) {
+ *type = __WASI_FILETYPE_BLOCK_DEVICE;
+ *rights_base = RIGHTS_BLOCK_DEVICE_BASE;
+ *rights_inheriting = RIGHTS_BLOCK_DEVICE_INHERITING;
+ }
+ else if (S_ISCHR(sb.st_mode)) {
+ *type = __WASI_FILETYPE_CHARACTER_DEVICE;
+#if CONFIG_HAS_ISATTY
+ if (isatty(fd)) {
+ *rights_base = RIGHTS_TTY_BASE;
+ *rights_inheriting = RIGHTS_TTY_INHERITING;
+ }
+ else
+#endif
+ {
+ *rights_base = RIGHTS_CHARACTER_DEVICE_BASE;
+ *rights_inheriting = RIGHTS_CHARACTER_DEVICE_INHERITING;
+ }
+ }
+ else if (S_ISDIR(sb.st_mode)) {
+ *type = __WASI_FILETYPE_DIRECTORY;
+ *rights_base = RIGHTS_DIRECTORY_BASE;
+ *rights_inheriting = RIGHTS_DIRECTORY_INHERITING;
+ }
+ else if (S_ISREG(sb.st_mode)) {
+ *type = __WASI_FILETYPE_REGULAR_FILE;
+ *rights_base = RIGHTS_REGULAR_FILE_BASE;
+ *rights_inheriting = RIGHTS_REGULAR_FILE_INHERITING;
+ }
+ else if (S_ISSOCK(sb.st_mode)) {
+ int socktype;
+ socklen_t socktypelen = sizeof(socktype);
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &socktype, &socktypelen) < 0)
+ return convert_errno(errno);
+ switch (socktype) {
+ case SOCK_DGRAM:
+ *type = __WASI_FILETYPE_SOCKET_DGRAM;
+ break;
+ case SOCK_STREAM:
+ *type = __WASI_FILETYPE_SOCKET_STREAM;
+ break;
+ default:
+ return __WASI_EINVAL;
+ }
+ *rights_base = RIGHTS_SOCKET_BASE;
+ *rights_inheriting = RIGHTS_SOCKET_INHERITING;
+ }
+ else if (S_ISFIFO(sb.st_mode)) {
+ *type = __WASI_FILETYPE_SOCKET_STREAM;
+ *rights_base = RIGHTS_SOCKET_BASE;
+ *rights_inheriting = RIGHTS_SOCKET_INHERITING;
+ }
+ else {
+ return __WASI_EINVAL;
+ }
+
+ // Strip off read/write bits based on the access mode.
+ switch (fcntl(fd, F_GETFL) & O_ACCMODE) {
+ case O_RDONLY:
+ *rights_base &= ~(__wasi_rights_t)__WASI_RIGHT_FD_WRITE;
+ break;
+ case O_WRONLY:
+ *rights_base &= ~(__wasi_rights_t)__WASI_RIGHT_FD_READ;
+ break;
+ }
+ return 0;
+}
+
+// Returns the underlying file descriptor number of a file descriptor
+// object. This function can only be applied to objects that have an
+// underlying file descriptor number.
+static int
+fd_number(const struct fd_object *fo)
+{
+ int number = fo->number;
+ assert(number >= 0 && "fd_number() called on virtual file descriptor");
+ return number;
+}
+
+#define CLOSE_NON_STD_FD(fd) \
+ do { \
+ if (fd > 2) \
+ close(fd); \
+ } while (0)
+
+// Lowers the reference count on a file descriptor object. When the
+// reference count reaches zero, its resources are cleaned up.
+static void
+fd_object_release(struct fd_object *fo) UNLOCKS(fo->refcount)
+{
+ if (refcount_release(&fo->refcount)) {
+ switch (fo->type) {
+ case __WASI_FILETYPE_DIRECTORY:
+ // For directories we may keep track of a DIR object. Calling
+ // closedir() on it also closes the underlying file descriptor.
+ mutex_destroy(&fo->directory.lock);
+ if (fo->directory.handle == NULL) {
+ CLOSE_NON_STD_FD(fd_number(fo));
+ }
+ else {
+ closedir(fo->directory.handle);
+ }
+ break;
+ default:
+ CLOSE_NON_STD_FD(fd_number(fo));
+ break;
+ }
+ wasm_runtime_free(fo);
+ }
+}
+
+// Inserts an already existing file descriptor into the file descriptor
+// table.
+bool
+fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in, int out)
+{
+ __wasi_filetype_t type;
+ __wasi_rights_t rights_base, rights_inheriting;
+ struct fd_object *fo;
+ __wasi_errno_t error;
+
+ error =
+ fd_determine_type_rights(out, &type, &rights_base, &rights_inheriting);
+ if (error != 0) {
+#ifdef BH_PLATFORM_EGO
+ /**
+ * since it is an already opened file and we can assume the opened file
+ * has all necessary rights no matter how to get
+ */
+ if (error != __WASI_ENOTSUP)
+ return false;
+#else
+ return false;
+#endif
+ }
+
+ error = fd_object_new(type, &fo);
+ if (error != 0)
+ return false;
+ fo->number = out;
+ if (type == __WASI_FILETYPE_DIRECTORY) {
+ if (!mutex_init(&fo->directory.lock)) {
+ fd_object_release(fo);
+ return false;
+ }
+ fo->directory.handle = NULL;
+ }
+
+ // Grow the file descriptor table if needed.
+ rwlock_wrlock(&ft->lock);
+ if (!fd_table_grow(ft, in, 1)) {
+ rwlock_unlock(&ft->lock);
+ fd_object_release(fo);
+ return false;
+ }
+
+ fd_table_attach(ft, in, fo, rights_base, rights_inheriting);
+ rwlock_unlock(&ft->lock);
+ return true;
+}
+
+// Picks an unused slot from the file descriptor table.
+static __wasi_fd_t
+fd_table_unused(struct fd_table *ft) REQUIRES_SHARED(ft->lock)
+{
+ assert(ft->size > ft->used && "File descriptor table has no free slots");
+ for (;;) {
+ __wasi_fd_t fd = (__wasi_fd_t)random_uniform(ft->size);
+ if (ft->entries[fd].object == NULL)
+ return fd;
+ }
+}
+
+// Inserts a file descriptor object into an unused slot of the file
+// descriptor table.
+static __wasi_errno_t
+fd_table_insert(struct fd_table *ft, struct fd_object *fo,
+ __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting,
+ __wasi_fd_t *out) REQUIRES_UNLOCKED(ft->lock)
+ UNLOCKS(fo->refcount)
+{
+ // Grow the file descriptor table if needed.
+ rwlock_wrlock(&ft->lock);
+ if (!fd_table_grow(ft, 0, 1)) {
+ rwlock_unlock(&ft->lock);
+ fd_object_release(fo);
+ return convert_errno(errno);
+ }
+
+ *out = fd_table_unused(ft);
+ fd_table_attach(ft, *out, fo, rights_base, rights_inheriting);
+ rwlock_unlock(&ft->lock);
+ return 0;
+}
+
+// Inserts a numerical file descriptor into the file descriptor table.
+static __wasi_errno_t
+fd_table_insert_fd(struct fd_table *ft, int in, __wasi_filetype_t type,
+ __wasi_rights_t rights_base,
+ __wasi_rights_t rights_inheriting, __wasi_fd_t *out)
+ REQUIRES_UNLOCKED(ft->lock)
+{
+ struct fd_object *fo;
+
+ __wasi_errno_t error = fd_object_new(type, &fo);
+ if (error != 0) {
+ close(in);
+ return error;
+ }
+
+ fo->number = in;
+ if (type == __WASI_FILETYPE_DIRECTORY) {
+ if (!mutex_init(&fo->directory.lock)) {
+ fd_object_release(fo);
+ return (__wasi_errno_t)-1;
+ }
+ fo->directory.handle = NULL;
+ }
+ return fd_table_insert(ft, fo, rights_base, rights_inheriting, out);
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_prestat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t fd, __wasi_prestat_t *buf)
+{
+ rwlock_rdlock(&prestats->lock);
+ struct fd_prestat *prestat;
+ __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat);
+ if (error != 0) {
+ rwlock_unlock(&prestats->lock);
+ return error;
+ }
+
+ *buf = (__wasi_prestat_t){
+ .pr_type = __WASI_PREOPENTYPE_DIR,
+ };
+
+ buf->u.dir.pr_name_len = strlen(prestat->dir);
+
+ rwlock_unlock(&prestats->lock);
+
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_prestat_dir_name(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t fd, char *path, size_t path_len)
+{
+ rwlock_rdlock(&prestats->lock);
+ struct fd_prestat *prestat;
+ __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat);
+ if (error != 0) {
+ rwlock_unlock(&prestats->lock);
+ return error;
+ }
+ if (path_len != strlen(prestat->dir)) {
+ rwlock_unlock(&prestats->lock);
+ return EINVAL;
+ }
+
+ bh_memcpy_s(path, (uint32)path_len, prestat->dir, (uint32)path_len);
+
+ rwlock_unlock(&prestats->lock);
+
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_close(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t fd)
+{
+ // Don't allow closing a pre-opened resource.
+ // TODO: Eventually, we do want to permit this, once libpreopen in
+ // userspace is capable of removing entries from its tables as well.
+ {
+ rwlock_rdlock(&prestats->lock);
+ struct fd_prestat *prestat;
+ __wasi_errno_t error = fd_prestats_get_entry(prestats, fd, &prestat);
+ rwlock_unlock(&prestats->lock);
+ if (error == 0) {
+ return __WASI_ENOTSUP;
+ }
+ }
+
+ // Validate the file descriptor.
+ struct fd_table *ft = curfds;
+ rwlock_wrlock(&ft->lock);
+ struct fd_entry *fe;
+ __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe);
+ if (error != 0) {
+ rwlock_unlock(&ft->lock);
+ return error;
+ }
+
+ // Remove it from the file descriptor table.
+ struct fd_object *fo;
+ fd_table_detach(ft, fd, &fo);
+ rwlock_unlock(&ft->lock);
+ fd_object_release(fo);
+ return 0;
+}
+
+// Look up a file descriptor object in a locked file descriptor table
+// and increases its reference count.
+static __wasi_errno_t
+fd_object_get_locked(struct fd_object **fo, struct fd_table *ft, __wasi_fd_t fd,
+ __wasi_rights_t rights_base,
+ __wasi_rights_t rights_inheriting)
+ TRYLOCKS_EXCLUSIVE(0, (*fo)->refcount) REQUIRES_EXCLUSIVE(ft->lock)
+{
+ // Test whether the file descriptor number is valid.
+ struct fd_entry *fe;
+ __wasi_errno_t error =
+ fd_table_get_entry(ft, fd, rights_base, rights_inheriting, &fe);
+ if (error != 0)
+ return error;
+
+ // Increase the reference count on the file descriptor object. A copy
+ // of the rights are also stored, so callers can still access those if
+ // needed.
+ *fo = fe->object;
+ refcount_acquire(&(*fo)->refcount);
+ return 0;
+}
+
+// Temporarily locks the file descriptor table to look up a file
+// descriptor object, increases its reference count and drops the lock.
+static __wasi_errno_t
+fd_object_get(struct fd_table *curfds, struct fd_object **fo, __wasi_fd_t fd,
+ __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting)
+ TRYLOCKS_EXCLUSIVE(0, (*fo)->refcount)
+{
+ struct fd_table *ft = curfds;
+ rwlock_rdlock(&ft->lock);
+ __wasi_errno_t error =
+ fd_object_get_locked(fo, ft, fd, rights_base, rights_inheriting);
+ rwlock_unlock(&ft->lock);
+ return error;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_datasync(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_DATASYNC, 0);
+ if (error != 0)
+ return error;
+
+#if CONFIG_HAS_FDATASYNC
+ int ret = fdatasync(fd_number(fo));
+#else
+ int ret = fsync(fd_number(fo));
+#endif
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_pread(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt,
+ __wasi_filesize_t offset, size_t *nread)
+{
+ if (iovcnt == 0)
+ return __WASI_EINVAL;
+
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READ, 0);
+ if (error != 0)
+ return error;
+
+#if CONFIG_HAS_PREADV
+ ssize_t len = preadv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt,
+ (off_t)offset);
+ fd_object_release(fo);
+ if (len < 0)
+ return convert_errno(errno);
+ *nread = (size_t)len;
+ return 0;
+#else
+ if (iovcnt == 1) {
+ ssize_t len = pread(fd_number(fo), iov->buf, iov->buf_len, offset);
+ fd_object_release(fo);
+ if (len < 0)
+ return convert_errno(errno);
+ *nread = len;
+ return 0;
+ }
+ else {
+ // Allocate a single buffer to fit all data.
+ size_t totalsize = 0;
+ for (size_t i = 0; i < iovcnt; ++i)
+ totalsize += iov[i].buf_len;
+ char *buf = wasm_runtime_malloc(totalsize);
+ if (buf == NULL) {
+ fd_object_release(fo);
+ return __WASI_ENOMEM;
+ }
+
+ // Perform a single read operation.
+ ssize_t len = pread(fd_number(fo), buf, totalsize, offset);
+ fd_object_release(fo);
+ if (len < 0) {
+ wasm_runtime_free(buf);
+ return convert_errno(errno);
+ }
+
+ // Copy data back to vectors.
+ size_t bufoff = 0;
+ for (size_t i = 0; i < iovcnt; ++i) {
+ if (bufoff + iov[i].buf_len < (size_t)len) {
+ bh_memcpy_s(iov[i].buf, iov[i].buf_len, buf + bufoff,
+ iov[i].buf_len);
+ bufoff += iov[i].buf_len;
+ }
+ else {
+ bh_memcpy_s(iov[i].buf, iov[i].buf_len, buf + bufoff,
+ len - bufoff);
+ break;
+ }
+ }
+ wasm_runtime_free(buf);
+ *nread = len;
+ return 0;
+ }
+#endif
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_pwrite(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt,
+ __wasi_filesize_t offset, size_t *nwritten)
+{
+ if (iovcnt == 0)
+ return __WASI_EINVAL;
+
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_WRITE, 0);
+ if (error != 0)
+ return error;
+
+ ssize_t len;
+#if CONFIG_HAS_PWRITEV
+ len = pwritev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt,
+ (off_t)offset);
+#else
+ if (iovcnt == 1) {
+ len = pwrite(fd_number(fo), iov->buf, iov->buf_len, offset);
+ }
+ else {
+ // Allocate a single buffer to fit all data.
+ size_t totalsize = 0;
+ for (size_t i = 0; i < iovcnt; ++i)
+ totalsize += iov[i].buf_len;
+ char *buf = wasm_runtime_malloc(totalsize);
+ if (buf == NULL) {
+ fd_object_release(fo);
+ return __WASI_ENOMEM;
+ }
+ size_t bufoff = 0;
+ for (size_t i = 0; i < iovcnt; ++i) {
+ bh_memcpy_s(buf + bufoff, totalsize - bufoff, iov[i].buf,
+ iov[i].buf_len);
+ bufoff += iov[i].buf_len;
+ }
+
+ // Perform a single write operation.
+ len = pwrite(fd_number(fo), buf, totalsize, offset);
+ wasm_runtime_free(buf);
+ }
+#endif
+ fd_object_release(fo);
+ if (len < 0)
+ return convert_errno(errno);
+ *nwritten = (size_t)len;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_read(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const __wasi_iovec_t *iov, size_t iovcnt, size_t *nread)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READ, 0);
+ if (error != 0)
+ return error;
+
+ ssize_t len = readv(fd_number(fo), (const struct iovec *)iov, (int)iovcnt);
+ fd_object_release(fo);
+ if (len < 0)
+ return convert_errno(errno);
+ *nread = (size_t)len;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_renumber(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t from, __wasi_fd_t to)
+{
+ // Don't allow renumbering over a pre-opened resource.
+ // TODO: Eventually, we do want to permit this, once libpreopen in
+ // userspace is capable of removing entries from its tables as well.
+ {
+ rwlock_rdlock(&prestats->lock);
+ struct fd_prestat *prestat;
+ __wasi_errno_t error = fd_prestats_get_entry(prestats, to, &prestat);
+ if (error != 0) {
+ error = fd_prestats_get_entry(prestats, from, &prestat);
+ }
+ rwlock_unlock(&prestats->lock);
+ if (error == 0) {
+ return __WASI_ENOTSUP;
+ }
+ }
+
+ struct fd_table *ft = curfds;
+ rwlock_wrlock(&ft->lock);
+ struct fd_entry *fe_from;
+ __wasi_errno_t error = fd_table_get_entry(ft, from, 0, 0, &fe_from);
+ if (error != 0) {
+ rwlock_unlock(&ft->lock);
+ return error;
+ }
+ struct fd_entry *fe_to;
+ error = fd_table_get_entry(ft, to, 0, 0, &fe_to);
+ if (error != 0) {
+ rwlock_unlock(&ft->lock);
+ return error;
+ }
+
+ struct fd_object *fo;
+ fd_table_detach(ft, to, &fo);
+ refcount_acquire(&fe_from->object->refcount);
+ fd_table_attach(ft, to, fe_from->object, fe_from->rights_base,
+ fe_from->rights_inheriting);
+ fd_object_release(fo);
+
+ // Remove the old fd from the file descriptor table.
+ fd_table_detach(ft, from, &fo);
+ fd_object_release(fo);
+ --ft->used;
+
+ rwlock_unlock(&ft->lock);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_seek(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_filedelta_t offset, __wasi_whence_t whence,
+ __wasi_filesize_t *newoffset)
+{
+ int nwhence;
+ switch (whence) {
+ case __WASI_WHENCE_CUR:
+ nwhence = SEEK_CUR;
+ break;
+ case __WASI_WHENCE_END:
+ nwhence = SEEK_END;
+ break;
+ case __WASI_WHENCE_SET:
+ nwhence = SEEK_SET;
+ break;
+ default:
+ return __WASI_EINVAL;
+ }
+
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd,
+ offset == 0 && whence == __WASI_WHENCE_CUR
+ ? __WASI_RIGHT_FD_TELL
+ : __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_TELL,
+ 0);
+ if (error != 0)
+ return error;
+
+ off_t ret = lseek(fd_number(fo), offset, nwhence);
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ *newoffset = (__wasi_filesize_t)ret;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_tell(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_filesize_t *newoffset)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_TELL, 0);
+ if (error != 0)
+ return error;
+
+ off_t ret = lseek(fd_number(fo), 0, SEEK_CUR);
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ *newoffset = (__wasi_filesize_t)ret;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_fdstat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_fdstat_t *buf)
+{
+ struct fd_table *ft = curfds;
+ rwlock_rdlock(&ft->lock);
+ struct fd_entry *fe;
+ __wasi_errno_t error = fd_table_get_entry(ft, fd, 0, 0, &fe);
+ if (error != 0) {
+ rwlock_unlock(&ft->lock);
+ return error;
+ }
+
+ // Extract file descriptor type and rights.
+ struct fd_object *fo = fe->object;
+ *buf = (__wasi_fdstat_t){
+ .fs_filetype = fo->type,
+ .fs_rights_base = fe->rights_base,
+ .fs_rights_inheriting = fe->rights_inheriting,
+ };
+
+ // Fetch file descriptor flags.
+ int ret;
+ switch (fo->type) {
+ default:
+ ret = fcntl(fd_number(fo), F_GETFL);
+ break;
+ }
+ rwlock_unlock(&ft->lock);
+ if (ret < 0)
+ return convert_errno(errno);
+
+ if ((ret & O_APPEND) != 0)
+ buf->fs_flags |= __WASI_FDFLAG_APPEND;
+#ifdef O_DSYNC
+ if ((ret & O_DSYNC) != 0)
+ buf->fs_flags |= __WASI_FDFLAG_DSYNC;
+#endif
+ if ((ret & O_NONBLOCK) != 0)
+ buf->fs_flags |= __WASI_FDFLAG_NONBLOCK;
+#ifdef O_RSYNC
+ if ((ret & O_RSYNC) != 0)
+ buf->fs_flags |= __WASI_FDFLAG_RSYNC;
+#endif
+ if ((ret & O_SYNC) != 0)
+ buf->fs_flags |= __WASI_FDFLAG_SYNC;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_fdstat_set_flags(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_fdflags_t fs_flags)
+{
+ int noflags = 0;
+ if ((fs_flags & __WASI_FDFLAG_APPEND) != 0)
+ noflags |= O_APPEND;
+ if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0)
+#ifdef O_DSYNC
+ noflags |= O_DSYNC;
+#else
+ noflags |= O_SYNC;
+#endif
+ if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0)
+ noflags |= O_NONBLOCK;
+ if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0)
+#ifdef O_RSYNC
+ noflags |= O_RSYNC;
+#else
+ noflags |= O_SYNC;
+#endif
+ if ((fs_flags & __WASI_FDFLAG_SYNC) != 0)
+ noflags |= O_SYNC;
+
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FDSTAT_SET_FLAGS, 0);
+ if (error != 0)
+ return error;
+
+ int ret = fcntl(fd_number(fo), F_SETFL, noflags);
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_fdstat_set_rights(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_rights_t fs_rights_base,
+ __wasi_rights_t fs_rights_inheriting)
+{
+ struct fd_table *ft = curfds;
+ rwlock_wrlock(&ft->lock);
+ struct fd_entry *fe;
+ __wasi_errno_t error =
+ fd_table_get_entry(ft, fd, fs_rights_base, fs_rights_inheriting, &fe);
+ if (error != 0) {
+ rwlock_unlock(&ft->lock);
+ return error;
+ }
+
+ // Restrict the rights on the file descriptor.
+ fe->rights_base = fs_rights_base;
+ fe->rights_inheriting = fs_rights_inheriting;
+ rwlock_unlock(&ft->lock);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_sync(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_SYNC, 0);
+ if (error != 0)
+ return error;
+
+ int ret = fsync(fd_number(fo));
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_write(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const __wasi_ciovec_t *iov, size_t iovcnt, size_t *nwritten)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_WRITE, 0);
+ if (error != 0)
+ return error;
+
+#ifndef BH_VPRINTF
+ ssize_t len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt);
+#else
+ ssize_t len = 0;
+ /* redirect stdout/stderr output to BH_VPRINTF function */
+ if (fd_number(fo) == 1 || fd_number(fo) == 2) {
+ int i;
+ const struct iovec *iov1 = (const struct iovec *)iov;
+
+ for (i = 0; i < (int)iovcnt; i++, iov1++) {
+ if (iov1->iov_len > 0 && iov1->iov_base) {
+ char format[16];
+
+ /* make up format string "%.ns" */
+ snprintf(format, sizeof(format), "%%.%ds", (int)iov1->iov_len);
+ len += (ssize_t)os_printf(format, iov1->iov_base);
+ }
+ }
+ }
+ else {
+ len = writev(fd_number(fo), (const struct iovec *)iov, (int)iovcnt);
+ }
+#endif /* end of BH_VPRINTF */
+ fd_object_release(fo);
+ if (len < 0)
+ return convert_errno(errno);
+ *nwritten = (size_t)len;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_advise(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len,
+ __wasi_advice_t advice)
+{
+#ifdef POSIX_FADV_NORMAL
+ int nadvice;
+ switch (advice) {
+ case __WASI_ADVICE_DONTNEED:
+ nadvice = POSIX_FADV_DONTNEED;
+ break;
+ case __WASI_ADVICE_NOREUSE:
+ nadvice = POSIX_FADV_NOREUSE;
+ break;
+ case __WASI_ADVICE_NORMAL:
+ nadvice = POSIX_FADV_NORMAL;
+ break;
+ case __WASI_ADVICE_RANDOM:
+ nadvice = POSIX_FADV_RANDOM;
+ break;
+ case __WASI_ADVICE_SEQUENTIAL:
+ nadvice = POSIX_FADV_SEQUENTIAL;
+ break;
+ case __WASI_ADVICE_WILLNEED:
+ nadvice = POSIX_FADV_WILLNEED;
+ break;
+ default:
+ return __WASI_EINVAL;
+ }
+
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_ADVISE, 0);
+ if (error != 0)
+ return error;
+
+ int ret = posix_fadvise(fd_number(fo), (off_t)offset, (off_t)len, nadvice);
+ fd_object_release(fo);
+ if (ret != 0)
+ return convert_errno(ret);
+ return 0;
+#else
+ // Advisory information can safely be ignored if unsupported.
+ switch (advice) {
+ case __WASI_ADVICE_DONTNEED:
+ case __WASI_ADVICE_NOREUSE:
+ case __WASI_ADVICE_NORMAL:
+ case __WASI_ADVICE_RANDOM:
+ case __WASI_ADVICE_SEQUENTIAL:
+ case __WASI_ADVICE_WILLNEED:
+ break;
+ default:
+ return __WASI_EINVAL;
+ }
+
+ // At least check for file descriptor existence.
+ struct fd_table *ft = curfds;
+ rwlock_rdlock(&ft->lock);
+ struct fd_entry *fe;
+ __wasi_errno_t error =
+ fd_table_get_entry(ft, fd, __WASI_RIGHT_FD_ADVISE, 0, &fe);
+ rwlock_unlock(&ft->lock);
+ return error;
+#endif
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_allocate(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_filesize_t offset, __wasi_filesize_t len)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_ALLOCATE, 0);
+ if (error != 0)
+ return error;
+
+#if CONFIG_HAS_POSIX_FALLOCATE
+ int ret = posix_fallocate(fd_number(fo), (off_t)offset, (off_t)len);
+#else
+ // At least ensure that the file is grown to the right size.
+ // TODO(ed): See if this can somehow be implemented without any race
+ // conditions. We may end up shrinking the file right now.
+ struct stat sb;
+ int ret = fstat(fd_number(fo), &sb);
+ off_t newsize = (off_t)(offset + len);
+ if (ret == 0 && sb.st_size < newsize)
+ ret = ftruncate(fd_number(fo), newsize);
+#endif
+
+ fd_object_release(fo);
+ if (ret != 0)
+ return convert_errno(ret);
+ return 0;
+}
+
+// Reads the entire contents of a symbolic link, returning the contents
+// in an allocated buffer. The allocated buffer is large enough to fit
+// at least one extra byte, so the caller may append a trailing slash to
+// it. This is needed by path_get().
+static char *
+readlinkat_dup(int fd, const char *path, size_t *p_len)
+{
+ char *buf = NULL;
+ size_t len = 32;
+ size_t len_org = len;
+
+ for (;;) {
+ char *newbuf = wasm_runtime_malloc((uint32)len);
+
+ if (newbuf == NULL) {
+ if (buf)
+ wasm_runtime_free(buf);
+ return NULL;
+ }
+
+ if (buf != NULL) {
+ bh_memcpy_s(newbuf, (uint32)len, buf, (uint32)len_org);
+ wasm_runtime_free(buf);
+ }
+
+ buf = newbuf;
+ ssize_t ret = readlinkat(fd, path, buf, len);
+ if (ret < 0) {
+ wasm_runtime_free(buf);
+ return NULL;
+ }
+ if ((size_t)ret + 1 < len) {
+ buf[ret] = '\0';
+ *p_len = len;
+ return buf;
+ }
+ len_org = len;
+ len *= 2;
+ }
+}
+
+// Lease to a directory, so a path underneath it can be accessed.
+//
+// This structure is used by system calls that operate on pathnames. In
+// this environment, pathnames always consist of a pair of a file
+// descriptor representing the directory where the lookup needs to start
+// and the actual pathname string.
+struct path_access {
+ int fd; // Directory file descriptor.
+ const char *path; // Pathname.
+ bool follow; // Whether symbolic links should be followed.
+ char *path_start; // Internal: pathname to free.
+ struct fd_object *fd_object; // Internal: directory file descriptor object.
+};
+
+// Creates a lease to a file descriptor and pathname pair. If the
+// operating system does not implement Capsicum, it also normalizes the
+// pathname to ensure the target path is placed underneath the
+// directory.
+static __wasi_errno_t
+path_get(struct fd_table *curfds, struct path_access *pa, __wasi_fd_t fd,
+ __wasi_lookupflags_t flags, const char *upath, size_t upathlen,
+ __wasi_rights_t rights_base, __wasi_rights_t rights_inheriting,
+ bool needs_final_component)
+ TRYLOCKS_EXCLUSIVE(0, pa->fd_object->refcount)
+{
+ char *path = str_nullterminate(upath, upathlen);
+ if (path == NULL)
+ return convert_errno(errno);
+
+ // Fetch the directory file descriptor.
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, rights_base, rights_inheriting);
+ if (error != 0) {
+ wasm_runtime_free(path);
+ return error;
+ }
+
+#if CONFIG_HAS_CAP_ENTER
+ // Rely on the kernel to constrain access to automatically constrain
+ // access to files stored underneath this directory.
+ pa->fd = fd_number(fo);
+ pa->path = pa->path_start = path;
+ pa->follow = (flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0;
+ pa->fd_object = fo;
+ return 0;
+#else
+ // The implementation provides no mechanism to constrain lookups to a
+ // directory automatically. Emulate this logic by resolving the
+ // pathname manually.
+
+ // Stack of directory file descriptors. Index 0 always corresponds
+ // with the directory provided to this function. Entering a directory
+ // causes a file descriptor to be pushed, while handling ".." entries
+ // causes an entry to be popped. Index 0 cannot be popped, as this
+ // would imply escaping the base directory.
+ int fds[128];
+ fds[0] = fd_number(fo);
+ size_t curfd = 0;
+
+ // Stack of pathname strings used for symlink expansion. By using a
+ // stack, there is no need to concatenate any pathname strings while
+ // expanding symlinks.
+ char *paths[32];
+ char *paths_start[32];
+ paths[0] = paths_start[0] = path;
+ size_t curpath = 0;
+ size_t expansions = 0;
+ char *symlink;
+ size_t symlink_len;
+
+ for (;;) {
+ // Extract the next pathname component from 'paths[curpath]', null
+ // terminate it and store it in 'file'. 'ends_with_slashes' stores
+ // whether the pathname component is followed by one or more
+ // trailing slashes, as this requires it to be a directory.
+ char *file = paths[curpath];
+ char *file_end = file + strcspn(file, "/");
+ paths[curpath] = file_end + strspn(file_end, "/");
+ bool ends_with_slashes = *file_end == '/';
+ *file_end = '\0';
+
+ // Test for empty pathname strings and absolute paths.
+ if (file == file_end) {
+ error = ends_with_slashes ? __WASI_ENOTCAPABLE : __WASI_ENOENT;
+ goto fail;
+ }
+
+ if (strcmp(file, ".") == 0) {
+ // Skip component.
+ }
+ else if (strcmp(file, "..") == 0) {
+ // Pop a directory off the stack.
+ if (curfd == 0) {
+ // Attempted to go to parent directory of the directory file
+ // descriptor.
+ error = __WASI_ENOTCAPABLE;
+ goto fail;
+ }
+ close(fds[curfd--]);
+ }
+ else if (curpath > 0 || *paths[curpath] != '\0'
+ || (ends_with_slashes && !needs_final_component)) {
+ // A pathname component whose name we're not interested in that is
+ // followed by a slash or is followed by other pathname
+ // components. In other words, a pathname component that must be a
+ // directory. First attempt to obtain a directory file descriptor
+ // for it.
+ int newdir =
+#ifdef O_SEARCH
+ openat(fds[curfd], file, O_SEARCH | O_DIRECTORY | O_NOFOLLOW);
+#else
+ openat(fds[curfd], file, O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
+#endif
+ if (newdir != -1) {
+ // Success. Push it onto the directory stack.
+ if (curfd + 1 == sizeof(fds) / sizeof(fds[0])) {
+ close(newdir);
+ error = __WASI_ENAMETOOLONG;
+ goto fail;
+ }
+ fds[++curfd] = newdir;
+ }
+ else {
+ // Failed to open it. Attempt symlink expansion.
+ if (errno != ELOOP && errno != EMLINK && errno != ENOTDIR) {
+ error = convert_errno(errno);
+ goto fail;
+ }
+ symlink = readlinkat_dup(fds[curfd], file, &symlink_len);
+ if (symlink != NULL)
+ goto push_symlink;
+
+ // readlink returns EINVAL if the path isn't a symlink. In that
+ // case, it's more informative to return ENOTDIR.
+ if (errno == EINVAL)
+ errno = ENOTDIR;
+
+ error = convert_errno(errno);
+ goto fail;
+ }
+ }
+ else {
+ // The final pathname component. Depending on whether it ends with
+ // a slash or the symlink-follow flag is set, perform symlink
+ // expansion.
+ if (ends_with_slashes
+ || (flags & __WASI_LOOKUP_SYMLINK_FOLLOW) != 0) {
+ symlink = readlinkat_dup(fds[curfd], file, &symlink_len);
+ if (symlink != NULL)
+ goto push_symlink;
+ if (errno != EINVAL && errno != ENOENT) {
+ error = convert_errno(errno);
+ goto fail;
+ }
+ }
+
+ // Not a symlink, meaning we're done. Return the filename,
+ // together with the directory containing this file.
+ //
+ // If the file was followed by a trailing slash, we must retain
+ // it, to ensure system calls properly return ENOTDIR.
+ // Unfortunately, this opens up a race condition, because this
+ // means that users of path_get() will perform symlink expansion a
+ // second time. There is nothing we can do to mitigate this, as
+ // far as I know.
+ if (ends_with_slashes)
+ *file_end = '/';
+ pa->path = file;
+ pa->path_start = paths_start[0];
+ goto success;
+ }
+
+ if (*paths[curpath] == '\0') {
+ if (curpath == 0) {
+ // No further pathname components to process. We may end up here
+ // when called on paths like ".", "a/..", but also if the path
+ // had trailing slashes and the caller is not interested in the
+ // name of the pathname component.
+ wasm_runtime_free(paths_start[0]);
+ pa->path = ".";
+ pa->path_start = NULL;
+ goto success;
+ }
+
+ // Finished expanding symlink. Continue processing along the
+ // original path.
+ wasm_runtime_free(paths_start[curpath--]);
+ }
+ continue;
+
+ push_symlink:
+ // Prevent infinite loops by placing an upper limit on the number of
+ // symlink expansions.
+ if (++expansions == 128) {
+ wasm_runtime_free(symlink);
+ error = __WASI_ELOOP;
+ goto fail;
+ }
+
+ if (*paths[curpath] == '\0') {
+ // The original path already finished processing. Replace it by
+ // this symlink entirely.
+ wasm_runtime_free(paths_start[curpath]);
+ }
+ else if (curpath + 1 == sizeof(paths) / sizeof(paths[0])) {
+ // Too many nested symlinks. Stop processing.
+ wasm_runtime_free(symlink);
+ error = __WASI_ELOOP;
+ goto fail;
+ }
+ else {
+ // The original path still has components left. Retain the
+ // components that remain, so we can process them afterwards.
+ ++curpath;
+ }
+
+ // Append a trailing slash to the symlink if the path leading up to
+ // it also contained one. Otherwise we would not throw ENOTDIR if
+ // the target is not a directory.
+ if (ends_with_slashes)
+ bh_strcat_s(symlink, (uint32)symlink_len, "/");
+ paths[curpath] = paths_start[curpath] = symlink;
+ }
+
+success:
+ // Return the lease. Close all directories, except the one the caller
+ // needs to use.
+ for (size_t i = 1; i < curfd; ++i)
+ close(fds[i]);
+ pa->fd = fds[curfd];
+ pa->follow = false;
+ pa->fd_object = fo;
+ return 0;
+
+fail:
+ // Failure. Free all resources.
+ for (size_t i = 1; i <= curfd; ++i)
+ close(fds[i]);
+ for (size_t i = 0; i <= curpath; ++i)
+ wasm_runtime_free(paths_start[i]);
+ fd_object_release(fo);
+ return error;
+#endif
+}
+
+static __wasi_errno_t
+path_get_nofollow(struct fd_table *curfds, struct path_access *pa,
+ __wasi_fd_t fd, const char *path, size_t pathlen,
+ __wasi_rights_t rights_base,
+ __wasi_rights_t rights_inheriting, bool needs_final_component)
+ TRYLOCKS_EXCLUSIVE(0, pa->fd_object->refcount)
+{
+ __wasi_lookupflags_t flags = 0;
+ return path_get(curfds, pa, fd, flags, path, pathlen, rights_base,
+ rights_inheriting, needs_final_component);
+}
+
+static void
+path_put(struct path_access *pa) UNLOCKS(pa->fd_object->refcount)
+{
+ if (pa->path_start)
+ wasm_runtime_free(pa->path_start);
+ if (fd_number(pa->fd_object) != pa->fd)
+ close(pa->fd);
+ fd_object_release(pa->fd_object);
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_create_directory(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const char *path, size_t pathlen)
+{
+ struct path_access pa;
+ __wasi_errno_t error =
+ path_get_nofollow(curfds, &pa, fd, path, pathlen,
+ __WASI_RIGHT_PATH_CREATE_DIRECTORY, 0, true);
+ if (error != 0)
+ return error;
+
+ int ret = mkdirat(pa.fd, pa.path, 0777);
+ path_put(&pa);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+static bool
+validate_path(const char *path, struct fd_prestats *pt)
+{
+ size_t i;
+ char path_resolved[PATH_MAX], prestat_dir_resolved[PATH_MAX];
+ char *path_real, *prestat_dir_real;
+
+ if (!(path_real = realpath(path, path_resolved)))
+ /* path doesn't exist, creating a link to this file
+ is allowed: if this file is to be created in
+ the future, WASI will strictly check whether it
+ can be created or not. */
+ return true;
+
+ for (i = 0; i < pt->size; i++) {
+ if (pt->prestats[i].dir) {
+ if (!(prestat_dir_real =
+ realpath(pt->prestats[i].dir, prestat_dir_resolved)))
+ return false;
+ if (!strncmp(path_real, prestat_dir_real, strlen(prestat_dir_real)))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_link(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct fd_prestats *prestats,
+#endif
+ __wasi_fd_t old_fd, __wasi_lookupflags_t old_flags, const char *old_path,
+ size_t old_path_len, __wasi_fd_t new_fd, const char *new_path,
+ size_t new_path_len)
+{
+ struct path_access old_pa;
+ __wasi_errno_t error =
+ path_get(curfds, &old_pa, old_fd, old_flags, old_path, old_path_len,
+ __WASI_RIGHT_PATH_LINK_SOURCE, 0, false);
+ if (error != 0)
+ return error;
+
+ struct path_access new_pa;
+ error = path_get_nofollow(curfds, &new_pa, new_fd, new_path, new_path_len,
+ __WASI_RIGHT_PATH_LINK_TARGET, 0, true);
+ if (error != 0) {
+ path_put(&old_pa);
+ return error;
+ }
+
+ rwlock_rdlock(&prestats->lock);
+ if (!validate_path(old_pa.path, prestats)
+ || !validate_path(new_pa.path, prestats)) {
+ rwlock_unlock(&prestats->lock);
+ return __WASI_EBADF;
+ }
+ rwlock_unlock(&prestats->lock);
+
+ int ret = linkat(old_pa.fd, old_pa.path, new_pa.fd, new_pa.path,
+ old_pa.follow ? AT_SYMLINK_FOLLOW : 0);
+ if (ret < 0 && errno == ENOTSUP && !old_pa.follow) {
+ // OS X doesn't allow creating hardlinks to symbolic links.
+ // Duplicate the symbolic link instead.
+ size_t target_len;
+ char *target = readlinkat_dup(old_pa.fd, old_pa.path, &target_len);
+ if (target != NULL) {
+ bh_assert(target[target_len] == '\0');
+ rwlock_rdlock(&prestats->lock);
+ if (!validate_path(target, prestats)) {
+ rwlock_unlock(&prestats->lock);
+ wasm_runtime_free(target);
+ return __WASI_EBADF;
+ }
+ rwlock_unlock(&prestats->lock);
+ ret = symlinkat(target, new_pa.fd, new_pa.path);
+ wasm_runtime_free(target);
+ }
+ }
+ path_put(&old_pa);
+ path_put(&new_pa);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_open(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t dirfd, __wasi_lookupflags_t dirflags, const char *path,
+ size_t pathlen, __wasi_oflags_t oflags, __wasi_rights_t fs_rights_base,
+ __wasi_rights_t fs_rights_inheriting, __wasi_fdflags_t fs_flags,
+ __wasi_fd_t *fd)
+{
+ // Rights that should be installed on the new file descriptor.
+ __wasi_rights_t rights_base = fs_rights_base;
+ __wasi_rights_t rights_inheriting = fs_rights_inheriting;
+
+ // Which open() mode should be used to satisfy the needed rights.
+ bool read =
+ (rights_base & (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_READDIR)) != 0;
+ bool write =
+ (rights_base
+ & (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_WRITE
+ | __WASI_RIGHT_FD_ALLOCATE | __WASI_RIGHT_FD_FILESTAT_SET_SIZE))
+ != 0;
+ int noflags = write ? read ? O_RDWR : O_WRONLY : O_RDONLY;
+
+ // Which rights are needed on the directory file descriptor.
+ __wasi_rights_t needed_base = __WASI_RIGHT_PATH_OPEN;
+ __wasi_rights_t needed_inheriting = rights_base | rights_inheriting;
+
+ // Convert open flags.
+ if ((oflags & __WASI_O_CREAT) != 0) {
+ noflags |= O_CREAT;
+ needed_base |= __WASI_RIGHT_PATH_CREATE_FILE;
+ }
+ if ((oflags & __WASI_O_DIRECTORY) != 0)
+ noflags |= O_DIRECTORY;
+ if ((oflags & __WASI_O_EXCL) != 0)
+ noflags |= O_EXCL;
+ if ((oflags & __WASI_O_TRUNC) != 0) {
+ noflags |= O_TRUNC;
+ needed_base |= __WASI_RIGHT_PATH_FILESTAT_SET_SIZE;
+ }
+
+ // Convert file descriptor flags.
+ if ((fs_flags & __WASI_FDFLAG_APPEND) != 0)
+ noflags |= O_APPEND;
+ if ((fs_flags & __WASI_FDFLAG_DSYNC) != 0) {
+#ifdef O_DSYNC
+ noflags |= O_DSYNC;
+#else
+ noflags |= O_SYNC;
+#endif
+ needed_inheriting |= __WASI_RIGHT_FD_DATASYNC;
+ }
+ if ((fs_flags & __WASI_FDFLAG_NONBLOCK) != 0)
+ noflags |= O_NONBLOCK;
+ if ((fs_flags & __WASI_FDFLAG_RSYNC) != 0) {
+#ifdef O_RSYNC
+ noflags |= O_RSYNC;
+#else
+ noflags |= O_SYNC;
+#endif
+ needed_inheriting |= __WASI_RIGHT_FD_SYNC;
+ }
+ if ((fs_flags & __WASI_FDFLAG_SYNC) != 0) {
+ noflags |= O_SYNC;
+ needed_inheriting |= __WASI_RIGHT_FD_SYNC;
+ }
+ if (write && (noflags & (O_APPEND | O_TRUNC)) == 0)
+ needed_inheriting |= __WASI_RIGHT_FD_SEEK;
+
+ struct path_access pa;
+ __wasi_errno_t error =
+ path_get(curfds, &pa, dirfd, dirflags, path, pathlen, needed_base,
+ needed_inheriting, (oflags & __WASI_O_CREAT) != 0);
+ if (error != 0)
+ return error;
+ if (!pa.follow)
+ noflags |= O_NOFOLLOW;
+
+ int nfd = openat(pa.fd, pa.path, noflags, 0666);
+ if (nfd < 0) {
+ int openat_errno = errno;
+ // Linux returns ENXIO instead of EOPNOTSUPP when opening a socket.
+ if (openat_errno == ENXIO) {
+ struct stat sb;
+ int ret = fstatat(pa.fd, pa.path, &sb,
+ pa.follow ? 0 : AT_SYMLINK_NOFOLLOW);
+ path_put(&pa);
+ return ret == 0 && S_ISSOCK(sb.st_mode) ? __WASI_ENOTSUP
+ : __WASI_ENXIO;
+ }
+ // Linux returns ENOTDIR instead of ELOOP when using
+ // O_NOFOLLOW|O_DIRECTORY on a symlink.
+ if (openat_errno == ENOTDIR
+ && (noflags & (O_NOFOLLOW | O_DIRECTORY)) != 0) {
+ struct stat sb;
+ int ret = fstatat(pa.fd, pa.path, &sb, AT_SYMLINK_NOFOLLOW);
+ if (S_ISLNK(sb.st_mode)) {
+ path_put(&pa);
+ return __WASI_ELOOP;
+ }
+ (void)ret;
+ }
+ path_put(&pa);
+ // FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on
+ // a symlink.
+ if (!pa.follow && openat_errno == EMLINK)
+ return __WASI_ELOOP;
+ return convert_errno(openat_errno);
+ }
+ path_put(&pa);
+
+ // Determine the type of the new file descriptor and which rights
+ // contradict with this type.
+ __wasi_filetype_t type;
+ __wasi_rights_t max_base, max_inheriting;
+ error = fd_determine_type_rights(nfd, &type, &max_base, &max_inheriting);
+ if (error != 0) {
+ close(nfd);
+ return error;
+ }
+
+ {
+ struct stat sb;
+
+ if (fstat(nfd, &sb) < 0) {
+ close(nfd);
+ return convert_errno(errno);
+ }
+
+ if (S_ISDIR(sb.st_mode))
+ rights_base |= (__wasi_rights_t)RIGHTS_DIRECTORY_BASE;
+ else if (S_ISREG(sb.st_mode))
+ rights_base |= (__wasi_rights_t)RIGHTS_REGULAR_FILE_BASE;
+ }
+
+ return fd_table_insert_fd(curfds, nfd, type, rights_base & max_base,
+ rights_inheriting & max_inheriting, fd);
+}
+
+// Copies out directory entry metadata or filename, potentially
+// truncating it in the process.
+static void
+fd_readdir_put(void *buf, size_t bufsize, size_t *bufused, const void *elem,
+ size_t elemsize)
+{
+ size_t bufavail = bufsize - *bufused;
+ if (elemsize > bufavail)
+ elemsize = bufavail;
+ bh_memcpy_s((char *)buf + *bufused, (uint32)bufavail, elem,
+ (uint32)elemsize);
+ *bufused += elemsize;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_readdir(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, void *buf, size_t nbyte, __wasi_dircookie_t cookie,
+ size_t *bufused)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_READDIR, 0);
+ if (error != 0) {
+ return error;
+ }
+
+ // Create a directory handle if none has been opened yet.
+ mutex_lock(&fo->directory.lock);
+ DIR *dp = fo->directory.handle;
+ if (dp == NULL) {
+ dp = fdopendir(fd_number(fo));
+ if (dp == NULL) {
+ mutex_unlock(&fo->directory.lock);
+ fd_object_release(fo);
+ return convert_errno(errno);
+ }
+ fo->directory.handle = dp;
+ fo->directory.offset = __WASI_DIRCOOKIE_START;
+ }
+
+ // Seek to the right position if the requested offset does not match
+ // the current offset.
+ if (fo->directory.offset != cookie) {
+ if (cookie == __WASI_DIRCOOKIE_START)
+ rewinddir(dp);
+ else
+ seekdir(dp, (long)cookie);
+ fo->directory.offset = cookie;
+ }
+
+ *bufused = 0;
+ while (*bufused < nbyte) {
+ // Read the next directory entry.
+ errno = 0;
+ struct dirent *de = readdir(dp);
+ if (de == NULL) {
+ mutex_unlock(&fo->directory.lock);
+ fd_object_release(fo);
+ return errno == 0 || *bufused > 0 ? 0 : convert_errno(errno);
+ }
+ fo->directory.offset = (__wasi_dircookie_t)telldir(dp);
+
+ // Craft a directory entry and copy that back.
+ size_t namlen = strlen(de->d_name);
+ __wasi_dirent_t cde = {
+ .d_next = fo->directory.offset,
+#if CONFIG_HAS_D_INO
+ .d_ino = de->d_ino,
+#else
+ .d_ino = 0,
+#endif
+ .d_namlen = (uint32)namlen,
+ };
+ switch (de->d_type) {
+ case DT_BLK:
+ cde.d_type = __WASI_FILETYPE_BLOCK_DEVICE;
+ break;
+ case DT_CHR:
+ cde.d_type = __WASI_FILETYPE_CHARACTER_DEVICE;
+ break;
+ case DT_DIR:
+ cde.d_type = __WASI_FILETYPE_DIRECTORY;
+ break;
+ case DT_FIFO:
+ cde.d_type = __WASI_FILETYPE_SOCKET_STREAM;
+ break;
+ case DT_LNK:
+ cde.d_type = __WASI_FILETYPE_SYMBOLIC_LINK;
+ break;
+ case DT_REG:
+ cde.d_type = __WASI_FILETYPE_REGULAR_FILE;
+ break;
+#ifdef DT_SOCK
+ case DT_SOCK:
+ // Technically not correct, but good enough.
+ cde.d_type = __WASI_FILETYPE_SOCKET_STREAM;
+ break;
+#endif
+ default:
+ cde.d_type = __WASI_FILETYPE_UNKNOWN;
+ break;
+ }
+ fd_readdir_put(buf, nbyte, bufused, &cde, sizeof(cde));
+ fd_readdir_put(buf, nbyte, bufused, de->d_name, namlen);
+ }
+ mutex_unlock(&fo->directory.lock);
+ fd_object_release(fo);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_readlink(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const char *path, size_t pathlen, char *buf, size_t bufsize,
+ size_t *bufused)
+{
+ struct path_access pa;
+ __wasi_errno_t error = path_get_nofollow(
+ curfds, &pa, fd, path, pathlen, __WASI_RIGHT_PATH_READLINK, 0, false);
+ if (error != 0)
+ return error;
+
+ // Linux requires that the buffer size is positive. whereas POSIX does
+ // not. Use a fake buffer to store the results if the size is zero.
+ char fakebuf[1];
+ ssize_t len = readlinkat(pa.fd, pa.path, bufsize == 0 ? fakebuf : buf,
+ bufsize == 0 ? sizeof(fakebuf) : bufsize);
+ path_put(&pa);
+ if (len < 0)
+ return convert_errno(errno);
+ *bufused = (size_t)len < bufsize ? (size_t)len : bufsize;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_rename(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t old_fd, const char *old_path, size_t old_path_len,
+ __wasi_fd_t new_fd, const char *new_path, size_t new_path_len)
+{
+ struct path_access old_pa;
+ __wasi_errno_t error =
+ path_get_nofollow(curfds, &old_pa, old_fd, old_path, old_path_len,
+ __WASI_RIGHT_PATH_RENAME_SOURCE, 0, true);
+ if (error != 0)
+ return error;
+
+ struct path_access new_pa;
+ error = path_get_nofollow(curfds, &new_pa, new_fd, new_path, new_path_len,
+ __WASI_RIGHT_PATH_RENAME_TARGET, 0, true);
+ if (error != 0) {
+ path_put(&old_pa);
+ return error;
+ }
+
+ int ret = renameat(old_pa.fd, old_pa.path, new_pa.fd, new_pa.path);
+ path_put(&old_pa);
+ path_put(&new_pa);
+ if (ret < 0) {
+ return convert_errno(errno);
+ }
+ return 0;
+}
+
+// Converts a POSIX stat structure to a CloudABI filestat structure.
+static void
+convert_stat(const struct stat *in, __wasi_filestat_t *out)
+{
+ *out = (__wasi_filestat_t){
+ .st_dev = in->st_dev,
+ .st_ino = in->st_ino,
+ .st_nlink = (__wasi_linkcount_t)in->st_nlink,
+ .st_size = (__wasi_filesize_t)in->st_size,
+ .st_atim = convert_timespec(&in->st_atim),
+ .st_mtim = convert_timespec(&in->st_mtim),
+ .st_ctim = convert_timespec(&in->st_ctim),
+ };
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_filestat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_filestat_t *buf)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_GET, 0);
+ if (error != 0)
+ return error;
+
+ int ret;
+ switch (fo->type) {
+ default:
+ {
+ struct stat sb;
+ ret = fstat(fd_number(fo), &sb);
+ convert_stat(&sb, buf);
+ break;
+ }
+ }
+ buf->st_filetype = fo->type;
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+static void
+convert_timestamp(__wasi_timestamp_t in, struct timespec *out)
+{
+ // Store sub-second remainder.
+#if defined(__SYSCALL_SLONG_TYPE)
+ out->tv_nsec = (__SYSCALL_SLONG_TYPE)(in % 1000000000);
+#else
+ out->tv_nsec = (long)(in % 1000000000);
+#endif
+ in /= 1000000000;
+
+ // Clamp to the maximum in case it would overflow our system's time_t.
+ out->tv_sec = (time_t)in < BH_TIME_T_MAX ? (time_t)in : BH_TIME_T_MAX;
+}
+
+// Converts the provided timestamps and flags to a set of arguments for
+// futimens() and utimensat().
+static void
+convert_utimens_arguments(__wasi_timestamp_t st_atim,
+ __wasi_timestamp_t st_mtim,
+ __wasi_fstflags_t fstflags, struct timespec *ts)
+{
+ if ((fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0) {
+ ts[0].tv_nsec = UTIME_NOW;
+ }
+ else if ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0) {
+ convert_timestamp(st_atim, &ts[0]);
+ }
+ else {
+ ts[0].tv_nsec = UTIME_OMIT;
+ }
+
+ if ((fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0) {
+ ts[1].tv_nsec = UTIME_NOW;
+ }
+ else if ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0) {
+ convert_timestamp(st_mtim, &ts[1]);
+ }
+ else {
+ ts[1].tv_nsec = UTIME_OMIT;
+ }
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_filestat_set_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_filesize_t st_size)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_SET_SIZE, 0);
+ if (error != 0)
+ return error;
+
+ int ret = ftruncate(fd_number(fo), (off_t)st_size);
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_fd_filestat_set_times(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim,
+ __wasi_fstflags_t fstflags)
+{
+ if ((fstflags
+ & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW
+ | __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW))
+ != 0)
+ return __WASI_EINVAL;
+
+ struct fd_object *fo;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_FD_FILESTAT_SET_TIMES, 0);
+ if (error != 0)
+ return error;
+
+ struct timespec ts[2];
+ convert_utimens_arguments(st_atim, st_mtim, fstflags, ts);
+ int ret = futimens(fd_number(fo), ts);
+
+ fd_object_release(fo);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_filestat_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path,
+ size_t pathlen, __wasi_filestat_t *buf)
+{
+ struct path_access pa;
+ __wasi_errno_t error = path_get(curfds, &pa, fd, flags, path, pathlen,
+ __WASI_RIGHT_PATH_FILESTAT_GET, 0, false);
+ if (error != 0)
+ return error;
+
+ struct stat sb;
+ int ret = fstatat(pa.fd, pa.path, &sb, pa.follow ? 0 : AT_SYMLINK_NOFOLLOW);
+ path_put(&pa);
+ if (ret < 0)
+ return convert_errno(errno);
+ convert_stat(&sb, buf);
+
+ // Convert the file type. In the case of sockets there is no way we
+ // can easily determine the exact socket type.
+ if (S_ISBLK(sb.st_mode))
+ buf->st_filetype = __WASI_FILETYPE_BLOCK_DEVICE;
+ else if (S_ISCHR(sb.st_mode))
+ buf->st_filetype = __WASI_FILETYPE_CHARACTER_DEVICE;
+ else if (S_ISDIR(sb.st_mode))
+ buf->st_filetype = __WASI_FILETYPE_DIRECTORY;
+ else if (S_ISFIFO(sb.st_mode))
+ buf->st_filetype = __WASI_FILETYPE_SOCKET_STREAM;
+ else if (S_ISLNK(sb.st_mode))
+ buf->st_filetype = __WASI_FILETYPE_SYMBOLIC_LINK;
+ else if (S_ISREG(sb.st_mode))
+ buf->st_filetype = __WASI_FILETYPE_REGULAR_FILE;
+ else if (S_ISSOCK(sb.st_mode))
+ buf->st_filetype = __WASI_FILETYPE_SOCKET_STREAM;
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_filestat_set_times(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_lookupflags_t flags, const char *path,
+ size_t pathlen, __wasi_timestamp_t st_atim, __wasi_timestamp_t st_mtim,
+ __wasi_fstflags_t fstflags)
+{
+ if (((fstflags
+ & ~(__WASI_FILESTAT_SET_ATIM | __WASI_FILESTAT_SET_ATIM_NOW
+ | __WASI_FILESTAT_SET_MTIM | __WASI_FILESTAT_SET_MTIM_NOW))
+ != 0)
+ /* ATIM & ATIM_NOW can't be set at the same time */
+ || ((fstflags & __WASI_FILESTAT_SET_ATIM) != 0
+ && (fstflags & __WASI_FILESTAT_SET_ATIM_NOW) != 0)
+ /* MTIM & MTIM_NOW can't be set at the same time */
+ || ((fstflags & __WASI_FILESTAT_SET_MTIM) != 0
+ && (fstflags & __WASI_FILESTAT_SET_MTIM_NOW) != 0))
+ return __WASI_EINVAL;
+
+ struct path_access pa;
+ __wasi_errno_t error =
+ path_get(curfds, &pa, fd, flags, path, pathlen,
+ __WASI_RIGHT_PATH_FILESTAT_SET_TIMES, 0, false);
+ if (error != 0)
+ return error;
+
+ struct timespec ts[2];
+ convert_utimens_arguments(st_atim, st_mtim, fstflags, ts);
+ int ret =
+ utimensat(pa.fd, pa.path, ts, pa.follow ? 0 : AT_SYMLINK_NOFOLLOW);
+
+ path_put(&pa);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_symlink(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct fd_prestats *prestats,
+#endif
+ const char *old_path, size_t old_path_len, __wasi_fd_t fd,
+ const char *new_path, size_t new_path_len)
+{
+ char *target = str_nullterminate(old_path, old_path_len);
+ if (target == NULL)
+ return convert_errno(errno);
+
+ struct path_access pa;
+ __wasi_errno_t error =
+ path_get_nofollow(curfds, &pa, fd, new_path, new_path_len,
+ __WASI_RIGHT_PATH_SYMLINK, 0, true);
+ if (error != 0) {
+ wasm_runtime_free(target);
+ return error;
+ }
+
+ rwlock_rdlock(&prestats->lock);
+ if (!validate_path(target, prestats)) {
+ rwlock_unlock(&prestats->lock);
+ wasm_runtime_free(target);
+ return __WASI_EBADF;
+ }
+ rwlock_unlock(&prestats->lock);
+
+ int ret = symlinkat(target, pa.fd, pa.path);
+ path_put(&pa);
+ wasm_runtime_free(target);
+ if (ret < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_unlink_file(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const char *path, size_t pathlen)
+{
+ struct path_access pa;
+ __wasi_errno_t error = path_get_nofollow(
+ curfds, &pa, fd, path, pathlen, __WASI_RIGHT_PATH_UNLINK_FILE, 0, true);
+ if (error != 0)
+ return error;
+
+ int ret = unlinkat(pa.fd, pa.path, 0);
+#ifndef __linux__
+ // Non-Linux implementations may return EPERM when attempting to remove a
+ // directory without REMOVEDIR. While that's what POSIX specifies, it's
+ // less useful. Adjust this to EISDIR. It doesn't matter that this is not
+ // atomic with the unlinkat, because if the file is removed and a directory
+ // is created before fstatat sees it, we're racing with that change anyway
+ // and unlinkat could have legitimately seen the directory if the race had
+ // turned out differently.
+ if (ret < 0 && errno == EPERM) {
+ struct stat statbuf;
+ if (fstatat(pa.fd, pa.path, &statbuf, AT_SYMLINK_NOFOLLOW) == 0
+ && S_ISDIR(statbuf.st_mode)) {
+ errno = EISDIR;
+ }
+ }
+#endif
+ path_put(&pa);
+ if (ret < 0) {
+ return convert_errno(errno);
+ }
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_path_remove_directory(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, const char *path, size_t pathlen)
+{
+ struct path_access pa;
+ __wasi_errno_t error =
+ path_get_nofollow(curfds, &pa, fd, path, pathlen,
+ __WASI_RIGHT_PATH_REMOVE_DIRECTORY, 0, true);
+ if (error != 0)
+ return error;
+
+ int ret = unlinkat(pa.fd, pa.path, AT_REMOVEDIR);
+#ifndef __linux__
+ // POSIX permits either EEXIST or ENOTEMPTY when the directory is not empty.
+ // Map it to ENOTEMPTY.
+ if (ret < 0 && errno == EEXIST) {
+ errno = ENOTEMPTY;
+ }
+#endif
+ path_put(&pa);
+ if (ret < 0) {
+ return convert_errno(errno);
+ }
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_poll_oneoff(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ const __wasi_subscription_t *in, __wasi_event_t *out, size_t nsubscriptions,
+ size_t *nevents) NO_LOCK_ANALYSIS
+{
+ // Sleeping.
+ if (nsubscriptions == 1 && in[0].u.type == __WASI_EVENTTYPE_CLOCK) {
+ out[0] = (__wasi_event_t){
+ .userdata = in[0].userdata,
+ .type = in[0].u.type,
+ };
+#if CONFIG_HAS_CLOCK_NANOSLEEP
+ clockid_t clock_id;
+ if (convert_clockid(in[0].u.u.clock.clock_id, &clock_id)) {
+ struct timespec ts;
+ convert_timestamp(in[0].u.u.clock.timeout, &ts);
+ int ret = clock_nanosleep(
+ clock_id,
+ (in[0].u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) != 0
+ ? TIMER_ABSTIME
+ : 0,
+ &ts, NULL);
+ if (ret != 0)
+ out[0].error = convert_errno(ret);
+ }
+ else {
+ out[0].error = __WASI_ENOTSUP;
+ }
+#else
+ switch (in[0].u.u.clock.clock_id) {
+ case __WASI_CLOCK_MONOTONIC:
+ if ((in[0].u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME)
+ != 0) {
+ // TODO(ed): Implement.
+ fputs("Unimplemented absolute sleep on monotonic clock\n",
+ stderr);
+ out[0].error = __WASI_ENOSYS;
+ }
+ else {
+ // Perform relative sleeps on the monotonic clock also using
+ // nanosleep(). This is incorrect, but good enough for now.
+ struct timespec ts;
+ convert_timestamp(in[0].u.u.clock.timeout, &ts);
+ nanosleep(&ts, NULL);
+ }
+ break;
+ case __WASI_CLOCK_REALTIME:
+ if ((in[0].u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME)
+ != 0) {
+ // Sleeping to an absolute point in time can only be done
+ // by waiting on a condition variable.
+ struct mutex mutex;
+ struct cond cond;
+
+ if (!mutex_init(&mutex))
+ return -1;
+ if (!cond_init_realtime(&cond)) {
+ mutex_destroy(&mutex);
+ return -1;
+ }
+ mutex_lock(&mutex);
+ cond_timedwait(&cond, &mutex, in[0].u.u.clock.timeout,
+ true);
+ mutex_unlock(&mutex);
+ mutex_destroy(&mutex);
+ cond_destroy(&cond);
+ }
+ else {
+ // Relative sleeps can be done using nanosleep().
+ struct timespec ts;
+ convert_timestamp(in[0].u.u.clock.timeout, &ts);
+ nanosleep(&ts, NULL);
+ }
+ break;
+ default:
+ out[0].error = __WASI_ENOTSUP;
+ break;
+ }
+#endif
+ *nevents = 1;
+ if (out[0].error != 0)
+ return convert_errno(out[0].error);
+ return 0;
+ }
+
+ // Last option: call into poll(). This can only be done in case all
+ // subscriptions consist of __WASI_EVENTTYPE_FD_READ and
+ // __WASI_EVENTTYPE_FD_WRITE entries. There may be up to one
+ // __WASI_EVENTTYPE_CLOCK entry to act as a timeout. These are also
+ // the subscriptions generate by cloudlibc's poll() and select().
+ struct fd_object **fos =
+ wasm_runtime_malloc((uint32)(nsubscriptions * sizeof(*fos)));
+ if (fos == NULL)
+ return __WASI_ENOMEM;
+ struct pollfd *pfds =
+ wasm_runtime_malloc((uint32)(nsubscriptions * sizeof(*pfds)));
+ if (pfds == NULL) {
+ wasm_runtime_free(fos);
+ return __WASI_ENOMEM;
+ }
+
+ // Convert subscriptions to pollfd entries. Increase the reference
+ // count on the file descriptors to ensure they remain valid across
+ // the call to poll().
+ struct fd_table *ft = curfds;
+ rwlock_rdlock(&ft->lock);
+ *nevents = 0;
+ const __wasi_subscription_t *clock_subscription = NULL;
+ for (size_t i = 0; i < nsubscriptions; ++i) {
+ const __wasi_subscription_t *s = &in[i];
+ switch (s->u.type) {
+ case __WASI_EVENTTYPE_FD_READ:
+ case __WASI_EVENTTYPE_FD_WRITE:
+ {
+ __wasi_errno_t error =
+ fd_object_get_locked(&fos[i], ft, s->u.u.fd_readwrite.fd,
+ __WASI_RIGHT_POLL_FD_READWRITE, 0);
+ if (error == 0) {
+ // Proper file descriptor on which we can poll().
+ pfds[i] = (struct pollfd){
+ .fd = fd_number(fos[i]),
+ .events = s->u.type == __WASI_EVENTTYPE_FD_READ
+ ? POLLIN
+ : POLLOUT,
+ };
+ }
+ else {
+ // Invalid file descriptor or rights missing.
+ fos[i] = NULL;
+ pfds[i] = (struct pollfd){ .fd = -1 };
+ out[(*nevents)++] = (__wasi_event_t){
+ .userdata = s->userdata,
+ .error = error,
+ .type = s->u.type,
+ };
+ }
+ break;
+ }
+ case __WASI_EVENTTYPE_CLOCK:
+ if (clock_subscription == NULL
+ && (s->u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME)
+ == 0) {
+ // Relative timeout.
+ fos[i] = NULL;
+ pfds[i] = (struct pollfd){ .fd = -1 };
+ clock_subscription = s;
+ break;
+ }
+ // Fallthrough.
+ default:
+ // Unsupported event.
+ fos[i] = NULL;
+ pfds[i] = (struct pollfd){ .fd = -1 };
+ out[(*nevents)++] = (__wasi_event_t){
+ .userdata = s->userdata,
+ .error = __WASI_ENOSYS,
+ .type = s->u.type,
+ };
+ break;
+ }
+ }
+ rwlock_unlock(&ft->lock);
+
+ // Use a zero-second timeout in case we've already generated events in
+ // the loop above.
+ int timeout;
+ if (*nevents != 0) {
+ timeout = 0;
+ }
+ else if (clock_subscription != NULL) {
+ __wasi_timestamp_t ts = clock_subscription->u.u.clock.timeout / 1000000;
+ timeout = ts > INT_MAX ? -1 : (int)ts;
+ }
+ else {
+ timeout = -1;
+ }
+ int ret = poll(pfds, nsubscriptions, timeout);
+
+ __wasi_errno_t error = 0;
+ if (ret == -1) {
+ error = convert_errno(errno);
+ }
+ else if (ret == 0 && *nevents == 0 && clock_subscription != NULL) {
+ // No events triggered. Trigger the clock event.
+ out[(*nevents)++] = (__wasi_event_t){
+ .userdata = clock_subscription->userdata,
+ .type = __WASI_EVENTTYPE_CLOCK,
+ };
+ }
+ else {
+ // Events got triggered. Don't trigger the clock event.
+ for (size_t i = 0; i < nsubscriptions; ++i) {
+ if (pfds[i].fd >= 0) {
+ __wasi_filesize_t nbytes = 0;
+ if (in[i].u.type == __WASI_EVENTTYPE_FD_READ) {
+ int l;
+ if (ioctl(fd_number(fos[i]), FIONREAD, &l) == 0)
+ nbytes = (__wasi_filesize_t)l;
+ }
+ if ((pfds[i].revents & POLLNVAL) != 0) {
+ // Bad file descriptor. This normally cannot occur, as
+ // referencing the file descriptor object will always ensure
+ // the descriptor is valid. Still, macOS may sometimes
+ // return this on FIFOs when reaching end-of-file.
+ out[(*nevents)++] = (__wasi_event_t){
+ .userdata = in[i].userdata,
+#ifdef __APPLE__
+ .u.fd_readwrite.nbytes = nbytes,
+ .u.fd_readwrite.flags =
+ __WASI_EVENT_FD_READWRITE_HANGUP,
+#else
+ .error = __WASI_EBADF,
+#endif
+ .type = in[i].u.type,
+ };
+ }
+ else if ((pfds[i].revents & POLLERR) != 0) {
+ // File descriptor is in an error state.
+ out[(*nevents)++] = (__wasi_event_t){
+ .userdata = in[i].userdata,
+ .error = __WASI_EIO,
+ .type = in[i].u.type,
+ };
+ }
+ else if ((pfds[i].revents & POLLHUP) != 0) {
+ // End-of-file.
+ out[(*nevents)++] = (__wasi_event_t){
+ .userdata = in[i].userdata,
+ .type = in[i].u.type,
+ .u.fd_readwrite.nbytes = nbytes,
+ .u.fd_readwrite.flags =
+ __WASI_EVENT_FD_READWRITE_HANGUP,
+ };
+ }
+ else if ((pfds[i].revents & (POLLIN | POLLOUT)) != 0) {
+ // Read or write possible.
+ out[(*nevents)++] = (__wasi_event_t){
+ .userdata = in[i].userdata,
+ .type = in[i].u.type,
+ .u.fd_readwrite.nbytes = nbytes,
+ };
+ }
+ }
+ }
+ }
+
+ for (size_t i = 0; i < nsubscriptions; ++i)
+ if (fos[i] != NULL)
+ fd_object_release(fos[i]);
+ wasm_runtime_free(fos);
+ wasm_runtime_free(pfds);
+ return error;
+}
+
+#if 0
+/**
+ * We throw exception in libc-wasi wrapper function wasi_proc_exit()
+ * but not call this function.
+ */
+void wasmtime_ssp_proc_exit(
+ __wasi_exitcode_t rval
+) {
+ _Exit((int32)rval);
+}
+#endif
+
+__wasi_errno_t
+wasmtime_ssp_proc_raise(__wasi_signal_t sig)
+{
+ static const int signals[] = {
+#define X(v) [__WASI_##v] = v
+#if defined(SIGABRT)
+ X(SIGABRT),
+#endif
+#if defined(SIGALRM)
+ X(SIGALRM),
+#endif
+#if defined(SIGBUS)
+ X(SIGBUS),
+#endif
+#if defined(SIGCHLD)
+ X(SIGCHLD),
+#endif
+#if defined(SIGCONT)
+ X(SIGCONT),
+#endif
+#if defined(SIGFPE)
+ X(SIGFPE),
+#endif
+#if defined(SIGHUP)
+ X(SIGHUP),
+#endif
+#if defined(SIGILL)
+ X(SIGILL),
+#endif
+#if defined(SIGINT)
+ X(SIGINT),
+#endif
+#if defined(SIGKILL)
+ X(SIGKILL),
+#endif
+#if defined(SIGPIPE)
+ X(SIGPIPE),
+#endif
+#if defined(SIGQUIT)
+ X(SIGQUIT),
+#endif
+#if defined(SIGSYS)
+ X(SIGSEGV),
+#endif
+#if defined(SIGSTOP)
+ X(SIGSTOP),
+#endif
+#if defined(SIGSYS)
+ X(SIGSYS),
+#endif
+#if defined(SIGTERM)
+ X(SIGTERM),
+#endif
+#if defined(SIGTRAP)
+ X(SIGTRAP),
+#endif
+#if defined(SIGTSTP)
+ X(SIGTSTP),
+#endif
+#if defined(SIGTTIN)
+ X(SIGTTIN),
+#endif
+#if defined(SIGTTOU)
+ X(SIGTTOU),
+#endif
+#if defined(SIGURG)
+ X(SIGURG),
+#endif
+#if defined(SIGUSR1)
+ X(SIGUSR1),
+#endif
+#if defined(SIGUSR2)
+ X(SIGUSR2),
+#endif
+#if defined(SIGVTALRM)
+ X(SIGVTALRM),
+#endif
+#if defined(SIGXCPU)
+ X(SIGXCPU),
+#endif
+#if defined(SIGXFSZ)
+ X(SIGXFSZ),
+#endif
+#undef X
+ };
+ if (sig >= sizeof(signals) / sizeof(signals[0]) || signals[sig] == 0)
+ return __WASI_EINVAL;
+
+#if CONFIG_TLS_USE_GSBASE
+ // TLS on OS X depends on installing a SIGSEGV handler. Reset SIGSEGV
+ // to the default action before raising.
+ if (sig == __WASI_SIGSEGV) {
+ struct sigaction sa = {
+ .sa_handler = SIG_DFL,
+ };
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGSEGV, &sa, NULL);
+ }
+#endif
+
+ if (raise(signals[sig]) < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_random_get(void *buf, size_t nbyte)
+{
+ random_buf(buf, nbyte);
+ return 0;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_accept(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_fdflags_t flags, __wasi_fd_t *fd_new)
+{
+ __wasi_filetype_t wasi_type;
+ __wasi_rights_t max_base, max_inheriting;
+ struct fd_object *fo;
+ bh_socket_t new_sock = -1;
+ int ret;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ACCEPT, 0);
+ if (error != __WASI_ESUCCESS) {
+ goto fail;
+ }
+
+ ret = os_socket_accept(fd_number(fo), &new_sock, NULL, NULL);
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ error = convert_errno(errno);
+ goto fail;
+ }
+
+ error = fd_determine_type_rights(new_sock, &wasi_type, &max_base,
+ &max_inheriting);
+ if (error != __WASI_ESUCCESS) {
+ goto fail;
+ }
+
+ error = fd_table_insert_fd(curfds, new_sock, wasi_type, max_base,
+ max_inheriting, fd_new);
+ if (error != __WASI_ESUCCESS) {
+ /* released in fd_table_insert_fd() */
+ new_sock = -1;
+ goto fail;
+ }
+
+ return __WASI_ESUCCESS;
+
+fail:
+ if (-1 != new_sock) {
+ os_socket_close(new_sock);
+ }
+ return error;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_addr_local(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ struct fd_object *fo;
+ bh_sockaddr_t bh_addr;
+ int ret;
+
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_LOCAL, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ ret = os_socket_addr_local(fd_number(fo), &bh_addr);
+ fd_object_release(fo);
+ if (ret != BHT_OK) {
+ return convert_errno(errno);
+ }
+
+ bh_sockaddr_to_wasi_addr(&bh_addr, addr);
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_addr_remote(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ struct fd_object *fo;
+ bh_sockaddr_t bh_addr;
+ int ret;
+
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_ADDR_LOCAL, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ ret = os_socket_addr_remote(fd_number(fo), &bh_addr);
+ fd_object_release(fo);
+ if (ret != BHT_OK) {
+ return convert_errno(errno);
+ }
+
+ bh_sockaddr_to_wasi_addr(&bh_addr, addr);
+
+ return __WASI_ESUCCESS;
+}
+
+static bool
+wasi_addr_to_string(const __wasi_addr_t *addr, char *buf, size_t buflen)
+{
+ if (addr->kind == IPv4) {
+ const char *format = "%u.%u.%u.%u";
+
+ assert(buflen >= 16);
+
+ snprintf(buf, buflen, format, addr->addr.ip4.addr.n0,
+ addr->addr.ip4.addr.n1, addr->addr.ip4.addr.n2,
+ addr->addr.ip4.addr.n3);
+
+ return true;
+ }
+ else if (addr->kind == IPv6) {
+ const char *format = "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x";
+ __wasi_addr_ip6_t ipv6 = addr->addr.ip6.addr;
+
+ assert(buflen >= 40);
+
+ snprintf(buf, buflen, format, ipv6.n0, ipv6.n1, ipv6.n2, ipv6.n3,
+ ipv6.h0, ipv6.h1, ipv6.h2, ipv6.h3);
+
+ return true;
+ }
+
+ return false;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_bind(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct addr_pool *addr_pool,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ char buf[48] = { 0 };
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int port = addr->kind == IPv4 ? addr->addr.ip4.port : addr->addr.ip6.port;
+ int ret;
+
+ if (!wasi_addr_to_string(addr, buf, sizeof(buf))) {
+ return __WASI_EPROTONOSUPPORT;
+ }
+
+ if (!addr_pool_search(addr_pool, buf)) {
+ return __WASI_EACCES;
+ }
+
+ error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_BIND, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ ret = os_socket_bind(fd_number(fo), buf, &port);
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_addr_resolve(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, char **ns_lookup_list,
+#endif
+ const char *host, const char *service, __wasi_addr_info_hints_t *hints,
+ __wasi_addr_info_t *addr_info, __wasi_size_t addr_info_size,
+ __wasi_size_t *max_info_size)
+{
+ bh_addr_info_t *wamr_addr_info =
+ wasm_runtime_malloc(addr_info_size * sizeof(bh_addr_info_t));
+ uint8_t hints_is_ipv4 = hints->family == INET4;
+ uint8_t hints_is_tcp = hints->type == SOCKET_STREAM;
+ size_t _max_info_size;
+ size_t actual_info_size;
+
+ if (!wamr_addr_info) {
+ return __WASI_ENOMEM;
+ }
+
+ if (!ns_lookup_list_search(ns_lookup_list, host)) {
+ wasm_runtime_free(wamr_addr_info);
+ return __WASI_EACCES;
+ }
+
+ int ret = os_socket_addr_resolve(
+ host, service, hints->hints_enabled ? &hints_is_tcp : NULL,
+ hints->hints_enabled ? &hints_is_ipv4 : NULL, wamr_addr_info,
+ addr_info_size, &_max_info_size);
+
+ if (ret != BHT_OK) {
+ wasm_runtime_free(wamr_addr_info);
+ return convert_errno(errno);
+ }
+
+ *max_info_size = _max_info_size;
+ actual_info_size =
+ addr_info_size < *max_info_size ? addr_info_size : *max_info_size;
+
+ for (size_t i = 0; i < actual_info_size; i++) {
+ addr_info[i].type =
+ wamr_addr_info[i].is_tcp ? SOCKET_STREAM : SOCKET_DGRAM;
+ bh_sockaddr_to_wasi_addr(&wamr_addr_info[i].sockaddr,
+ &addr_info[i].addr);
+ }
+
+ wasm_runtime_free(wamr_addr_info);
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_connect(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct addr_pool *addr_pool,
+#endif
+ __wasi_fd_t fd, __wasi_addr_t *addr)
+{
+ char buf[48] = { 0 };
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+
+ if (!wasi_addr_to_string(addr, buf, sizeof(buf))) {
+ return __WASI_EPROTONOSUPPORT;
+ }
+
+ if (!addr_pool_search(addr_pool, buf)) {
+ return __WASI_EACCES;
+ }
+
+ error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_BIND, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ ret = os_socket_connect(fd_number(fo), buf,
+ addr->kind == IPv4 ? addr->addr.ip4.port
+ : addr->addr.ip6.port);
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_get_recv_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t *size)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval;
+ socklen_t optlen = sizeof(optval);
+
+ ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_RCVBUF, &optval, &optlen);
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ *size = optval;
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_get_reuse_addr(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t *reuse)
+{
+
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval;
+ socklen_t optlen = sizeof(optval);
+
+ ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEADDR, &optval, &optlen);
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ *reuse = optval;
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_get_reuse_port(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t *reuse)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval;
+ socklen_t optlen = sizeof(optval);
+
+#if defined(SO_REUSEPORT) /* NuttX doesn't have SO_REUSEPORT */
+ ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEPORT, &optval, &optlen);
+#else
+ errno = ENOTSUP;
+ ret = BHT_ERROR;
+ optval = 0;
+#endif /* defined(SO_REUSEPORT) */
+
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ *reuse = optval;
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_get_send_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t *size)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval;
+ socklen_t optlen = sizeof(optval);
+
+ ret = getsockopt(fd_number(fo), SOL_SOCKET, SO_SNDBUF, &optval, &optlen);
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ *size = optval;
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_listen(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t backlog)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error =
+ fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_LISTEN, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ ret = os_socket_listen(fd_number(fo), backlog);
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_open(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t poolfd, __wasi_address_family_t af, __wasi_sock_type_t socktype,
+ __wasi_fd_t *sockfd)
+{
+ bh_socket_t sock;
+ bool is_tcp = SOCKET_DGRAM == socktype ? false : true;
+ bool is_ipv4 = INET6 == af ? false : true;
+ int ret;
+ __wasi_filetype_t wasi_type;
+ __wasi_rights_t max_base, max_inheriting;
+ __wasi_errno_t error;
+
+ (void)poolfd;
+
+ ret = os_socket_create(&sock, is_ipv4, is_tcp);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ error =
+ fd_determine_type_rights(sock, &wasi_type, &max_base, &max_inheriting);
+ if (error != __WASI_ESUCCESS) {
+ os_socket_close(sock);
+ return error;
+ }
+
+ if (SOCKET_DGRAM == socktype) {
+ assert(wasi_type == __WASI_FILETYPE_SOCKET_DGRAM);
+ }
+ else {
+ assert(wasi_type == __WASI_FILETYPE_SOCKET_STREAM);
+ }
+
+ // TODO: base rights and inheriting rights ?
+ error = fd_table_insert_fd(curfds, sock, wasi_type, max_base,
+ max_inheriting, sockfd);
+ if (error != __WASI_ESUCCESS) {
+ return error;
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_set_recv_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t size)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval = size;
+
+ ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_RCVBUF, &optval,
+ sizeof(optval));
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_set_reuse_addr(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t reuse)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval = reuse;
+
+ ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEADDR, &optval,
+ sizeof(optval));
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_set_reuse_port(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, uint8_t reuse)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval = reuse;
+
+#if defined(SO_REUSEPORT) /* NuttX doesn't have SO_REUSEPORT */
+ ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_REUSEPORT, &optval,
+ sizeof(optval));
+#else
+ errno = ENOTSUP;
+ ret = BHT_ERROR;
+#endif /* defined(SO_REUSEPORT) */
+
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasi_ssp_sock_set_send_buf_size(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t fd, __wasi_size_t size)
+{
+ struct fd_object *fo;
+ int ret;
+ __wasi_errno_t error = fd_object_get(curfds, &fo, fd, 0, 0);
+ if (error != __WASI_ESUCCESS)
+ return error;
+
+ int optval = size;
+
+ ret = setsockopt(fd_number(fo), SOL_SOCKET, SO_SNDBUF, &optval,
+ sizeof(optval));
+
+ fd_object_release(fo);
+ if (BHT_OK != ret) {
+ return convert_errno(errno);
+ }
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_recv(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, void *buf, size_t buf_len, size_t *recv_len)
+{
+ __wasi_addr_t src_addr;
+
+ return wasmtime_ssp_sock_recv_from(curfds, sock, buf, buf_len, 0, &src_addr,
+ recv_len);
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_recv_from(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, void *buf, size_t buf_len, __wasi_riflags_t ri_flags,
+ __wasi_addr_t *src_addr, size_t *recv_len)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ bh_sockaddr_t sockaddr;
+ int ret;
+
+ error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_READ, 0);
+ if (error != 0) {
+ return error;
+ }
+
+ ret = os_socket_recv_from(fd_number(fo), buf, buf_len, 0, &sockaddr);
+ fd_object_release(fo);
+ if (-1 == ret) {
+ return convert_errno(errno);
+ }
+
+ bh_sockaddr_to_wasi_addr(&sockaddr, src_addr);
+
+ *recv_len = (size_t)ret;
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_send(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, const void *buf, size_t buf_len, size_t *sent_len)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+
+ error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_WRITE, 0);
+ if (error != 0) {
+ return error;
+ }
+
+ ret = os_socket_send(fd_number(fo), buf, buf_len);
+ fd_object_release(fo);
+ if (-1 == ret) {
+ return convert_errno(errno);
+ }
+
+ *sent_len = (size_t)ret;
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_send_to(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds, struct addr_pool *addr_pool,
+#endif
+ __wasi_fd_t sock, const void *buf, size_t buf_len,
+ __wasi_siflags_t si_flags, const __wasi_addr_t *dest_addr, size_t *sent_len)
+{
+ char addr_buf[48] = { 0 };
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+ bh_sockaddr_t sockaddr;
+
+ if (!wasi_addr_to_string(dest_addr, addr_buf, sizeof(addr_buf))) {
+ return __WASI_EPROTONOSUPPORT;
+ }
+
+ if (!addr_pool_search(addr_pool, addr_buf)) {
+ return __WASI_EACCES;
+ }
+
+ error = fd_object_get(curfds, &fo, sock, __WASI_RIGHT_FD_WRITE, 0);
+ if (error != 0) {
+ return error;
+ }
+
+ wasi_addr_to_bh_sockaddr(dest_addr, &sockaddr);
+
+ ret = os_socket_send_to(fd_number(fo), buf, buf_len, 0, &sockaddr);
+ fd_object_release(fo);
+ if (-1 == ret) {
+ return convert_errno(errno);
+ }
+
+ *sent_len = (size_t)ret;
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_shutdown(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+
+ error = fd_object_get(curfds, &fo, sock, 0, 0);
+ if (error != 0)
+ return error;
+
+ ret = os_socket_shutdown(fd_number(fo));
+ fd_object_release(fo);
+ if (BHT_OK != ret)
+ return convert_errno(errno);
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sched_yield(void)
+{
+ if (sched_yield() < 0)
+ return convert_errno(errno);
+ return 0;
+}
+
+__wasi_errno_t
+wasmtime_ssp_args_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *argv_environ,
+#endif
+ char **argv, char *argv_buf)
+{
+ for (size_t i = 0; i < argv_environ->argc; ++i) {
+ argv[i] =
+ argv_buf + (argv_environ->argv_list[i] - argv_environ->argv_buf);
+ }
+ argv[argv_environ->argc] = NULL;
+ bh_memcpy_s(argv_buf, (uint32)argv_environ->argv_buf_size,
+ argv_environ->argv_buf, (uint32)argv_environ->argv_buf_size);
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_args_sizes_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *argv_environ,
+#endif
+ size_t *argc, size_t *argv_buf_size)
+{
+ *argc = argv_environ->argc;
+ *argv_buf_size = argv_environ->argv_buf_size;
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_environ_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *argv_environ,
+#endif
+ char **environ, char *environ_buf)
+{
+ for (size_t i = 0; i < argv_environ->environ_count; ++i) {
+ environ[i] =
+ environ_buf
+ + (argv_environ->environ_list[i] - argv_environ->environ_buf);
+ }
+ environ[argv_environ->environ_count] = NULL;
+ bh_memcpy_s(environ_buf, (uint32)argv_environ->environ_buf_size,
+ argv_environ->environ_buf,
+ (uint32)argv_environ->environ_buf_size);
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_environ_sizes_get(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct argv_environ_values *argv_environ,
+#endif
+ size_t *environ_count, size_t *environ_buf_size)
+{
+ *environ_count = argv_environ->environ_count;
+ *environ_buf_size = argv_environ->environ_buf_size;
+ return __WASI_ESUCCESS;
+}
+
+bool
+argv_environ_init(struct argv_environ_values *argv_environ, char *argv_buf,
+ size_t argv_buf_size, char **argv_list, size_t argc,
+ char *environ_buf, size_t environ_buf_size,
+ char **environ_list, size_t environ_count)
+{
+ memset(argv_environ, 0, sizeof(struct argv_environ_values));
+
+ argv_environ->argv_buf = argv_buf;
+ argv_environ->argv_buf_size = argv_buf_size;
+ argv_environ->argv_list = argv_list;
+ argv_environ->argc = argc;
+ argv_environ->environ_buf = environ_buf;
+ argv_environ->environ_buf_size = environ_buf_size;
+ argv_environ->environ_list = environ_list;
+ argv_environ->environ_count = environ_count;
+ return true;
+}
+
+void
+argv_environ_destroy(struct argv_environ_values *argv_environ)
+{}
+
+void
+fd_table_destroy(struct fd_table *ft)
+{
+ if (ft->entries) {
+ for (uint32 i = 0; i < ft->size; i++) {
+ if (ft->entries[i].object != NULL) {
+ fd_object_release(ft->entries[i].object);
+ }
+ }
+ rwlock_destroy(&ft->lock);
+ wasm_runtime_free(ft->entries);
+ }
+}
+
+void
+fd_prestats_destroy(struct fd_prestats *pt)
+{
+ if (pt->prestats) {
+ for (uint32 i = 0; i < pt->size; i++) {
+ if (pt->prestats[i].dir != NULL) {
+ wasm_runtime_free((void *)pt->prestats[i].dir);
+ }
+ }
+ rwlock_destroy(&pt->lock);
+ wasm_runtime_free(pt->prestats);
+ }
+}
+
+bool
+addr_pool_init(struct addr_pool *addr_pool)
+{
+ memset(addr_pool, 0, sizeof(*addr_pool));
+
+ return true;
+}
+
+bool
+addr_pool_insert(struct addr_pool *addr_pool, const char *addr, uint8 mask)
+{
+ struct addr_pool *cur = addr_pool;
+ struct addr_pool *next;
+ bh_ip_addr_buffer_t target;
+
+ if (!addr_pool) {
+ return false;
+ }
+
+ if (!(next = wasm_runtime_malloc(sizeof(struct addr_pool)))) {
+ return false;
+ }
+
+ next->next = NULL;
+ next->mask = mask;
+
+ if (os_socket_inet_network(true, addr, &target) != BHT_OK) {
+ // If parsing IPv4 fails, try IPv6
+ if (os_socket_inet_network(false, addr, &target) != BHT_OK) {
+ wasm_runtime_free(next);
+ return false;
+ }
+ next->type = IPv6;
+ bh_memcpy_s(next->addr.ip6, sizeof(next->addr.ip6), target.ipv6,
+ sizeof(target.ipv6));
+ }
+ else {
+ next->type = IPv4;
+ next->addr.ip4 = target.ipv4;
+ }
+
+ /* attach with */
+ while (cur->next) {
+ cur = cur->next;
+ }
+ cur->next = next;
+ return true;
+}
+
+static inline size_t
+min(size_t a, size_t b)
+{
+ return a > b ? b : a;
+}
+
+static void
+init_address_mask(uint8_t *buf, size_t buflen, size_t mask)
+{
+ size_t element_size = sizeof(uint8_t) * 8;
+
+ for (size_t i = 0; i < buflen; i++) {
+ if (mask <= i * element_size) {
+ buf[i] = 0;
+ }
+ else {
+ size_t offset = min(mask - i * element_size, element_size);
+ buf[i] = (~0u) << (element_size - offset);
+ }
+ }
+}
+
+/* target must be in network byte order */
+static bool
+compare_address(const struct addr_pool *addr_pool_entry,
+ bh_ip_addr_buffer_t *target)
+{
+ uint8_t maskbuf[16] = { 0 };
+ uint8_t basebuf[16] = { 0 };
+ size_t addr_size;
+ uint8_t max_addr_mask;
+
+ if (addr_pool_entry->type == IPv4) {
+ uint32_t addr_ip4 = htonl(addr_pool_entry->addr.ip4);
+ bh_memcpy_s(basebuf, sizeof(addr_ip4), &addr_ip4, sizeof(addr_ip4));
+ addr_size = 4;
+ }
+ else {
+ uint16_t partial_addr_ip6;
+ for (int i = 0; i < 8; i++) {
+ partial_addr_ip6 = htons(addr_pool_entry->addr.ip6[i]);
+ bh_memcpy_s(&basebuf[i * sizeof(partial_addr_ip6)],
+ sizeof(partial_addr_ip6), &partial_addr_ip6,
+ sizeof(partial_addr_ip6));
+ }
+ addr_size = 16;
+ }
+ max_addr_mask = addr_size * 8;
+
+ /* IPv4 0.0.0.0 or IPv6 :: means any address */
+ if (basebuf[0] == 0 && !memcmp(basebuf, basebuf + 1, addr_size - 1)) {
+ return true;
+ }
+
+ /* No support for invalid mask value */
+ if (addr_pool_entry->mask > max_addr_mask) {
+ return false;
+ }
+
+ init_address_mask(maskbuf, addr_size, addr_pool_entry->mask);
+
+ for (size_t i = 0; i < addr_size; i++) {
+ uint8_t addr_mask = target->data[i] & maskbuf[i];
+ uint8_t range_mask = basebuf[i] & maskbuf[i];
+ if (addr_mask != range_mask) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+addr_pool_search(struct addr_pool *addr_pool, const char *addr)
+{
+ struct addr_pool *cur = addr_pool->next;
+ bh_ip_addr_buffer_t target;
+ __wasi_addr_type_t addr_type;
+
+ if (os_socket_inet_network(true, addr, &target) != BHT_OK) {
+ size_t i;
+
+ if (os_socket_inet_network(false, addr, &target) != BHT_OK) {
+ return false;
+ }
+ addr_type = IPv6;
+ for (i = 0; i < sizeof(target.ipv6) / sizeof(target.ipv6[0]); i++) {
+ target.ipv6[i] = htons(target.ipv6[i]);
+ }
+ }
+ else {
+ addr_type = IPv4;
+ target.ipv4 = htonl(target.ipv4);
+ }
+
+ while (cur) {
+ if (cur->type == addr_type && compare_address(cur, &target)) {
+ return true;
+ }
+
+ cur = cur->next;
+ }
+
+ return false;
+}
+
+void
+addr_pool_destroy(struct addr_pool *addr_pool)
+{
+ struct addr_pool *cur = addr_pool->next;
+
+ while (cur) {
+ struct addr_pool *next = cur->next;
+ wasm_runtime_free(cur);
+ cur = next;
+ }
+}
+
+#ifndef WASMTIME_SSP_STATIC_CURFDS
+#define WASMTIME_SSP_PASSTHROUGH_FD_TABLE struct fd_table *curfds,
+#else
+#define WASMTIME_SSP_PASSTHROUGH_FD_TABLE
+#endif
+
+// Defines a function that passes through the socket option to the OS
+// implementation
+#define WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(FUNC_NAME, OPTION_TYPE) \
+ __wasi_errno_t wasmtime_ssp_sock_##FUNC_NAME( \
+ WASMTIME_SSP_PASSTHROUGH_FD_TABLE __wasi_fd_t sock, \
+ OPTION_TYPE option) \
+ { \
+ struct fd_object *fo; \
+ __wasi_errno_t error; \
+ int ret; \
+ error = fd_object_get(curfds, &fo, sock, 0, 0); \
+ if (error != 0) \
+ return error; \
+ ret = os_socket_##FUNC_NAME(fd_number(fo), option); \
+ fd_object_release(fo); \
+ if (BHT_OK != ret) \
+ return convert_errno(errno); \
+ return __WASI_ESUCCESS; \
+ }
+
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_send_timeout, uint64)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_send_timeout, uint64 *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_recv_timeout, uint64)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_recv_timeout, uint64 *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_send_buf_size, size_t)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_send_buf_size, size_t *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_recv_buf_size, size_t)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_recv_buf_size, size_t *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_broadcast, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_broadcast, bool *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_keep_alive, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_keep_alive, bool *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_reuse_addr, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_reuse_addr, bool *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_reuse_port, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_reuse_port, bool *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_no_delay, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_no_delay, bool *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_quick_ack, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_quick_ack, bool *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_keep_idle, uint32)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_keep_idle, uint32 *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_keep_intvl, uint32)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_keep_intvl, uint32 *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_tcp_fastopen_connect, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_tcp_fastopen_connect, bool *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_ip_ttl, uint8_t)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ip_ttl, uint8_t *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_ip_multicast_ttl, uint8_t)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ip_multicast_ttl, uint8_t *)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(set_ipv6_only, bool)
+WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION(get_ipv6_only, bool *)
+
+#undef WASMTIME_SSP_PASSTHROUGH_FD_TABLE
+#undef WASMTIME_SSP_PASSTHROUGH_SOCKET_OPTION
+
+__wasi_errno_t
+wasmtime_ssp_sock_set_linger(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, bool is_enabled, int linger_s)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+ error = fd_object_get(curfds, &fo, sock, 0, 0);
+ if (error != 0)
+ return error;
+
+ ret = os_socket_set_linger(fd_number(fo), is_enabled, linger_s);
+ fd_object_release(fo);
+ if (BHT_OK != ret)
+ return convert_errno(errno);
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_get_linger(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, bool *is_enabled, int *linger_s)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+ error = fd_object_get(curfds, &fo, sock, 0, 0);
+ if (error != 0)
+ return error;
+
+ ret = os_socket_get_linger(fd_number(fo), is_enabled, linger_s);
+ fd_object_release(fo);
+ if (BHT_OK != ret)
+ return convert_errno(errno);
+
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_set_ip_add_membership(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+ bh_ip_addr_buffer_t addr_info;
+ bool is_ipv6;
+ error = fd_object_get(curfds, &fo, sock, 0, 0);
+ if (error != 0)
+ return error;
+
+ wasi_addr_ip_to_bh_ip_addr_buffer(imr_multiaddr, &addr_info);
+ is_ipv6 = imr_multiaddr->kind == IPv6;
+ ret = os_socket_set_ip_add_membership(fd_number(fo), &addr_info,
+ imr_interface, is_ipv6);
+ fd_object_release(fo);
+ if (BHT_OK != ret)
+ return convert_errno(errno);
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_set_ip_drop_membership(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, __wasi_addr_ip_t *imr_multiaddr, uint32_t imr_interface)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+ bh_ip_addr_buffer_t addr_info;
+ bool is_ipv6;
+ error = fd_object_get(curfds, &fo, sock, 0, 0);
+ if (error != 0)
+ return error;
+
+ wasi_addr_ip_to_bh_ip_addr_buffer(imr_multiaddr, &addr_info);
+ is_ipv6 = imr_multiaddr->kind == IPv6;
+ ret = os_socket_set_ip_drop_membership(fd_number(fo), &addr_info,
+ imr_interface, is_ipv6);
+ fd_object_release(fo);
+ if (BHT_OK != ret)
+ return convert_errno(errno);
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_set_ip_multicast_loop(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, bool ipv6, bool is_enabled)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+ error = fd_object_get(curfds, &fo, sock, 0, 0);
+ if (error != 0)
+ return error;
+
+ ret = os_socket_set_ip_multicast_loop(fd_number(fo), ipv6, is_enabled);
+ fd_object_release(fo);
+ if (BHT_OK != ret)
+ return convert_errno(errno);
+ return __WASI_ESUCCESS;
+}
+
+__wasi_errno_t
+wasmtime_ssp_sock_get_ip_multicast_loop(
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+ struct fd_table *curfds,
+#endif
+ __wasi_fd_t sock, bool ipv6, bool *is_enabled)
+{
+ struct fd_object *fo;
+ __wasi_errno_t error;
+ int ret;
+ error = fd_object_get(curfds, &fo, sock, 0, 0);
+ if (error != 0)
+ return error;
+
+ ret = os_socket_get_ip_multicast_loop(fd_number(fo), ipv6, is_enabled);
+ fd_object_release(fo);
+ if (BHT_OK != ret)
+ return convert_errno(errno);
+
+ return __WASI_ESUCCESS;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h
new file mode 100644
index 000000000..7a593390a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.h
@@ -0,0 +1,89 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016-2018 Nuxi, https://nuxi.nl/
+
+#ifndef POSIX_H
+#define POSIX_H
+
+#include "bh_platform.h"
+#include "locking.h"
+
+struct fd_entry;
+struct fd_prestat;
+struct syscalls;
+
+struct fd_table {
+ struct rwlock lock;
+ struct fd_entry *entries;
+ size_t size;
+ size_t used;
+};
+
+struct fd_prestats {
+ struct rwlock lock;
+ struct fd_prestat *prestats;
+ size_t size;
+ size_t used;
+};
+
+struct argv_environ_values {
+ const char *argv_buf;
+ size_t argv_buf_size;
+ char **argv_list;
+ size_t argc;
+ char *environ_buf;
+ size_t environ_buf_size;
+ char **environ_list;
+ size_t environ_count;
+};
+
+struct addr_pool {
+ /* addr and mask in host order */
+ union {
+ uint32 ip4;
+ uint16 ip6[8];
+ } addr;
+ struct addr_pool *next;
+ __wasi_addr_type_t type;
+ uint8 mask;
+};
+
+bool
+fd_table_init(struct fd_table *);
+bool
+fd_table_insert_existing(struct fd_table *, __wasi_fd_t, int);
+bool
+fd_prestats_init(struct fd_prestats *);
+bool
+fd_prestats_insert(struct fd_prestats *, const char *, __wasi_fd_t);
+bool
+argv_environ_init(struct argv_environ_values *argv_environ, char *argv_buf,
+ size_t argv_buf_size, char **argv_list, size_t argc,
+ char *environ_buf, size_t environ_buf_size,
+ char **environ_list, size_t environ_count);
+void
+argv_environ_destroy(struct argv_environ_values *argv_environ);
+void
+fd_table_destroy(struct fd_table *ft);
+void
+fd_prestats_destroy(struct fd_prestats *pt);
+
+bool
+addr_pool_init(struct addr_pool *);
+bool
+addr_pool_insert(struct addr_pool *, const char *, uint8 mask);
+bool
+addr_pool_search(struct addr_pool *, const char *);
+void
+addr_pool_destroy(struct addr_pool *);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h
new file mode 100644
index 000000000..2d40bc3aa
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/queue.h
@@ -0,0 +1,98 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+// LIST: Double-linked list.
+
+#define LIST_HEAD(name, type) \
+ struct name { \
+ struct type *l_first; \
+ }
+
+/* clang-format off */
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+/* clang-format on */
+
+#define LIST_ENTRY(type) \
+ struct { \
+ struct type *l_next; \
+ struct type **l_prev; \
+ }
+
+#define LIST_FOREACH(var, head, field) \
+ for ((var) = (head)->l_first; (var) != NULL; (var) = (var)->field.l_next)
+
+#define LIST_INIT(head) \
+ do { \
+ (head)->l_first = NULL; \
+ } while (0)
+
+#define LIST_INSERT_HEAD(head, element, field) \
+ do { \
+ (element)->field.l_next = (head)->l_first; \
+ if ((head)->l_first != NULL) \
+ (head)->l_first->field.l_prev = &(element)->field.l_next; \
+ (head)->l_first = (element); \
+ (element)->field.l_prev = &(head)->l_first; \
+ } while (0)
+
+#define LIST_REMOVE(element, field) \
+ do { \
+ if ((element)->field.l_next != NULL) \
+ (element)->field.l_next->field.l_prev = (element)->field.l_prev; \
+ *(element)->field.l_prev = (element)->field.l_next; \
+ } while (0)
+
+// TAILQ: Double-linked list with tail pointer.
+
+#define TAILQ_HEAD(name, type) \
+ struct name { \
+ struct type *t_first; \
+ struct type **t_last; \
+ }
+
+#define TAILQ_ENTRY(type) \
+ struct { \
+ struct type *t_next; \
+ struct type **t_prev; \
+ }
+
+#define TAILQ_EMPTY(head) ((head)->t_first == NULL)
+#define TAILQ_FIRST(head) ((head)->t_first)
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = (head)->t_first; (var) != NULL; (var) = (var)->field.t_next)
+#define TAILQ_INIT(head) \
+ do { \
+ (head)->t_first = NULL; \
+ (head)->t_last = &(head)->t_first; \
+ } while (0)
+#define TAILQ_INSERT_TAIL(head, elm, field) \
+ do { \
+ (elm)->field.t_next = NULL; \
+ (elm)->field.t_prev = (head)->t_last; \
+ *(head)->t_last = (elm); \
+ (head)->t_last = &(elm)->field.t_next; \
+ } while (0)
+#define TAILQ_REMOVE(head, element, field) \
+ do { \
+ if ((element)->field.t_next != NULL) \
+ (element)->field.t_next->field.t_prev = (element)->field.t_prev; \
+ else \
+ (head)->t_last = (element)->field.t_prev; \
+ *(element)->field.t_prev = (element)->field.t_next; \
+ } while (0)
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c
new file mode 100644
index 000000000..01a1dab3a
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c
@@ -0,0 +1,98 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#include "ssp_config.h"
+#include "bh_platform.h"
+#include "random.h"
+
+#if CONFIG_HAS_ARC4RANDOM_BUF
+
+void
+random_buf(void *buf, size_t len)
+{
+ arc4random_buf(buf, len);
+}
+
+#elif CONFIG_HAS_GETRANDOM
+
+#ifndef BH_PLATFORM_LINUX_SGX
+#include <sys/random.h>
+#endif
+
+void
+random_buf(void *buf, size_t len)
+{
+ for (;;) {
+ ssize_t x = getrandom(buf, len, 0);
+ if (x < 0) {
+ if (errno == EINTR)
+ continue;
+ os_printf("getrandom failed: %s", strerror(errno));
+ abort();
+ }
+ if ((size_t)x == len)
+ return;
+ buf = (void *)((unsigned char *)buf + x);
+ len -= (size_t)x;
+ }
+}
+
+#else
+
+static int urandom;
+
+static void
+open_urandom(void)
+{
+ urandom = open("/dev/urandom", O_RDONLY);
+ if (urandom < 0) {
+ os_printf("Failed to open /dev/urandom\n");
+ abort();
+ }
+}
+
+void
+random_buf(void *buf, size_t len)
+{
+ static pthread_once_t open_once = PTHREAD_ONCE_INIT;
+ pthread_once(&open_once, open_urandom);
+
+ if ((size_t)read(urandom, buf, len) != len) {
+ os_printf("Short read on /dev/urandom\n");
+ abort();
+ }
+}
+
+#endif
+
+// Calculates a random number within the range [0, upper - 1] without
+// any modulo bias.
+//
+// The function below repeatedly obtains a random number from
+// arc4random() until it lies within the range [2^k % upper, 2^k). As
+// this range has length k * upper, we can safely obtain a number
+// without any modulo bias.
+uintmax_t
+random_uniform(uintmax_t upper)
+{
+ // Compute 2^k % upper
+ // == (2^k - upper) % upper
+ // == -upper % upper.
+ uintmax_t lower = -upper % upper;
+ for (;;) {
+ uintmax_t value;
+ random_buf(&value, sizeof(value));
+ if (value >= lower)
+ return value % upper;
+ }
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h
new file mode 100644
index 000000000..23c2da4db
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.h
@@ -0,0 +1,21 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#ifndef RANDOM_H
+#define RANDOM_H
+
+void
+random_buf(void *, size_t);
+uintmax_t random_uniform(uintmax_t);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h
new file mode 100644
index 000000000..03b4b87ac
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h
@@ -0,0 +1,139 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#ifndef REFCOUNT_H
+#define REFCOUNT_H
+
+#include "bh_platform.h"
+#include "locking.h"
+#include "gnuc.h"
+
+#define PRODUCES(...) LOCKS_SHARED(__VA_ARGS__) NO_LOCK_ANALYSIS
+#define CONSUMES(...) UNLOCKS(__VA_ARGS__) NO_LOCK_ANALYSIS
+
+#if CONFIG_HAS_STD_ATOMIC != 0
+
+#include <stdatomic.h>
+
+/* Simple reference counter. */
+struct LOCKABLE refcount {
+ atomic_uint count;
+};
+
+/* Initialize the reference counter. */
+static inline void
+refcount_init(struct refcount *r, unsigned int count) PRODUCES(*r)
+{
+ atomic_init(&r->count, count);
+}
+
+/* Increment the reference counter. */
+static inline void
+refcount_acquire(struct refcount *r) PRODUCES(*r)
+{
+ atomic_fetch_add_explicit(&r->count, 1, memory_order_acquire);
+}
+
+/* Decrement the reference counter, returning whether the reference
+ dropped to zero. */
+static inline bool
+refcount_release(struct refcount *r) CONSUMES(*r)
+{
+ int old =
+ (int)atomic_fetch_sub_explicit(&r->count, 1, memory_order_release);
+ bh_assert(old != 0 && "Reference count becoming negative");
+ return old == 1;
+}
+
+#elif defined(BH_PLATFORM_LINUX_SGX)
+
+#include <sgx_spinlock.h>
+
+/* Simple reference counter. */
+struct refcount {
+ sgx_spinlock_t lock;
+ unsigned int count;
+};
+
+/* Initialize the reference counter. */
+static inline void
+refcount_init(struct refcount *r, unsigned int count)
+{
+ r->lock = SGX_SPINLOCK_INITIALIZER;
+ r->count = count;
+}
+
+/* Increment the reference counter. */
+static inline void
+refcount_acquire(struct refcount *r)
+{
+ sgx_spin_lock(&r->lock);
+ r->count++;
+ sgx_spin_unlock(&r->lock);
+}
+
+/* Decrement the reference counter, returning whether the reference
+ dropped to zero. */
+static inline bool
+refcount_release(struct refcount *r)
+{
+ int old;
+ sgx_spin_lock(&r->lock);
+ old = (int)r->count;
+ r->count--;
+ sgx_spin_unlock(&r->lock);
+ bh_assert(old != 0 && "Reference count becoming negative");
+ return old == 1;
+}
+
+#elif defined(__GNUC_PREREQ)
+
+#if __GNUC_PREREQ(4, 7)
+
+struct refcount {
+ unsigned int count;
+};
+
+/* Initialize the reference counter. */
+static inline void
+refcount_init(struct refcount *r, unsigned int count)
+{
+ __atomic_store_n(&r->count, count, __ATOMIC_SEQ_CST);
+}
+
+/* Increment the reference counter. */
+static inline void
+refcount_acquire(struct refcount *r)
+{
+ __atomic_fetch_add(&r->count, 1, __ATOMIC_ACQUIRE);
+}
+
+/* Decrement the reference counter, returning whether the reference
+ dropped to zero. */
+static inline bool
+refcount_release(struct refcount *r)
+{
+ int old = (int)__atomic_fetch_sub(&r->count, 1, __ATOMIC_RELEASE);
+ bh_assert(old != 0 && "Reference count becoming negative");
+ return old == 1;
+}
+
+#else /* else of __GNUC_PREREQ (4.7) */
+#error "Reference counter isn't implemented"
+#endif /* end of __GNUC_PREREQ (4.7) */
+
+#else /* else of CONFIG_HAS_STD_ATOMIC */
+#error "Reference counter isn't implemented"
+#endif /* end of CONFIG_HAS_STD_ATOMIC */
+
+#endif /* end of REFCOUNT_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h
new file mode 100644
index 000000000..4f5838159
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/rights.h
@@ -0,0 +1,100 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#ifndef RIGHTS_H
+#define RIGHTS_H
+
+/* clang-format off */
+
+#define RIGHTS_ALL \
+ (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_READ | \
+ __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
+ __WASI_RIGHT_FD_SYNC | __WASI_RIGHT_FD_TELL | __WASI_RIGHT_FD_WRITE | \
+ __WASI_RIGHT_FD_ADVISE | __WASI_RIGHT_FD_ALLOCATE | \
+ __WASI_RIGHT_PATH_CREATE_DIRECTORY | __WASI_RIGHT_PATH_CREATE_FILE | \
+ __WASI_RIGHT_PATH_LINK_SOURCE | __WASI_RIGHT_PATH_LINK_TARGET | \
+ __WASI_RIGHT_PATH_OPEN | __WASI_RIGHT_FD_READDIR | \
+ __WASI_RIGHT_PATH_READLINK | __WASI_RIGHT_PATH_RENAME_SOURCE | \
+ __WASI_RIGHT_PATH_RENAME_TARGET | __WASI_RIGHT_PATH_FILESTAT_GET | \
+ __WASI_RIGHT_PATH_FILESTAT_SET_SIZE | \
+ __WASI_RIGHT_PATH_FILESTAT_SET_TIMES | \
+ __WASI_RIGHT_FD_FILESTAT_GET | __WASI_RIGHT_FD_FILESTAT_SET_TIMES | \
+ __WASI_RIGHT_FD_FILESTAT_SET_SIZE | \
+ __WASI_RIGHT_PATH_SYMLINK | __WASI_RIGHT_PATH_UNLINK_FILE | \
+ __WASI_RIGHT_PATH_REMOVE_DIRECTORY | \
+ __WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_CONNECT | \
+ __WASI_RIGHT_SOCK_LISTEN | __WASI_RIGHT_SOCK_BIND | \
+ __WASI_RIGHT_SOCK_ACCEPT | __WASI_RIGHT_SOCK_RECV | \
+ __WASI_RIGHT_SOCK_SEND | __WASI_RIGHT_SOCK_ADDR_LOCAL | \
+ __WASI_RIGHT_SOCK_ADDR_REMOTE | __WASI_RIGHT_SOCK_RECV_FROM | \
+ __WASI_RIGHT_SOCK_SEND_TO)
+
+
+// Block and character device interaction is outside the scope of
+// CloudABI. Simply allow everything.
+#define RIGHTS_BLOCK_DEVICE_BASE RIGHTS_ALL
+#define RIGHTS_BLOCK_DEVICE_INHERITING RIGHTS_ALL
+#define RIGHTS_CHARACTER_DEVICE_BASE RIGHTS_ALL
+#define RIGHTS_CHARACTER_DEVICE_INHERITING RIGHTS_ALL
+
+// Only allow directory operations on directories. Directories can only
+// yield file descriptors to other directories and files.
+#define RIGHTS_DIRECTORY_BASE \
+ (__WASI_RIGHT_FD_FDSTAT_SET_FLAGS | __WASI_RIGHT_FD_SYNC | \
+ __WASI_RIGHT_FD_ADVISE | __WASI_RIGHT_PATH_CREATE_DIRECTORY | \
+ __WASI_RIGHT_PATH_CREATE_FILE | __WASI_RIGHT_PATH_LINK_SOURCE | \
+ __WASI_RIGHT_PATH_LINK_TARGET | __WASI_RIGHT_PATH_OPEN | \
+ __WASI_RIGHT_FD_READDIR | __WASI_RIGHT_PATH_READLINK | \
+ __WASI_RIGHT_PATH_RENAME_SOURCE | __WASI_RIGHT_PATH_RENAME_TARGET | \
+ __WASI_RIGHT_PATH_FILESTAT_GET | \
+ __WASI_RIGHT_PATH_FILESTAT_SET_SIZE | \
+ __WASI_RIGHT_PATH_FILESTAT_SET_TIMES | \
+ __WASI_RIGHT_FD_FILESTAT_GET | __WASI_RIGHT_FD_FILESTAT_SET_TIMES | \
+ __WASI_RIGHT_PATH_SYMLINK | __WASI_RIGHT_PATH_UNLINK_FILE | \
+ __WASI_RIGHT_PATH_REMOVE_DIRECTORY | \
+ __WASI_RIGHT_POLL_FD_READWRITE)
+#define RIGHTS_DIRECTORY_INHERITING \
+ (RIGHTS_DIRECTORY_BASE | RIGHTS_REGULAR_FILE_BASE)
+
+// Operations that apply to regular files.
+#define RIGHTS_REGULAR_FILE_BASE \
+ (__WASI_RIGHT_FD_DATASYNC | __WASI_RIGHT_FD_READ | \
+ __WASI_RIGHT_FD_SEEK | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
+ __WASI_RIGHT_FD_SYNC | __WASI_RIGHT_FD_TELL | __WASI_RIGHT_FD_WRITE | \
+ __WASI_RIGHT_FD_ADVISE | __WASI_RIGHT_FD_ALLOCATE | \
+ __WASI_RIGHT_FD_FILESTAT_GET | __WASI_RIGHT_FD_FILESTAT_SET_SIZE | \
+ __WASI_RIGHT_FD_FILESTAT_SET_TIMES | __WASI_RIGHT_POLL_FD_READWRITE)
+#define RIGHTS_REGULAR_FILE_INHERITING 0
+
+// Operations that apply to sockets and socket pairs.
+#define RIGHTS_SOCKET_BASE \
+ (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
+ __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_FILESTAT_GET | \
+ __WASI_RIGHT_POLL_FD_READWRITE | __WASI_RIGHT_SOCK_CONNECT | \
+ __WASI_RIGHT_SOCK_LISTEN | __WASI_RIGHT_SOCK_BIND | \
+ __WASI_RIGHT_SOCK_ACCEPT | __WASI_RIGHT_SOCK_RECV | \
+ __WASI_RIGHT_SOCK_SEND | __WASI_RIGHT_SOCK_ADDR_LOCAL | \
+ __WASI_RIGHT_SOCK_ADDR_REMOTE | __WASI_RIGHT_SOCK_RECV_FROM | \
+ __WASI_RIGHT_SOCK_SEND_TO)
+#define RIGHTS_SOCKET_INHERITING RIGHTS_ALL
+
+// Operations that apply to TTYs.
+#define RIGHTS_TTY_BASE \
+ (__WASI_RIGHT_FD_READ | __WASI_RIGHT_FD_FDSTAT_SET_FLAGS | \
+ __WASI_RIGHT_FD_WRITE | __WASI_RIGHT_FD_FILESTAT_GET | \
+ __WASI_RIGHT_POLL_FD_READWRITE)
+#define RIGHTS_TTY_INHERITING 0
+
+/* clang-format on */
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h
new file mode 100644
index 000000000..7f6e9b941
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h
@@ -0,0 +1,143 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#ifndef SSP_CONFIG_H
+#define SSP_CONFIG_H
+
+#include "gnuc.h"
+#include <stdlib.h>
+
+#if defined(__FreeBSD__) || defined(__APPLE__) \
+ || (defined(ANDROID) && __ANDROID_API__ < 28)
+#define CONFIG_HAS_ARC4RANDOM_BUF 1
+#else
+#define CONFIG_HAS_ARC4RANDOM_BUF 0
+#endif
+
+// On Linux, prefer to use getrandom, though it isn't available in
+// GLIBC before 2.25.
+#if (defined(__linux__) || defined(ESP_PLATFORM)) \
+ && (!defined(__GLIBC__) || __GLIBC__ > 2 \
+ || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))
+#define CONFIG_HAS_GETRANDOM 1
+#else
+#define CONFIG_HAS_GETRANDOM 0
+#endif
+
+#if defined(__CloudABI__)
+#define CONFIG_HAS_CAP_ENTER 1
+#else
+#define CONFIG_HAS_CAP_ENTER 0
+#endif
+
+#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__EMSCRIPTEN__) \
+ && !defined(ESP_PLATFORM) && !defined(DISABLE_CLOCK_NANOSLEEP)
+#define CONFIG_HAS_CLOCK_NANOSLEEP 1
+#else
+#define CONFIG_HAS_CLOCK_NANOSLEEP 0
+#endif
+
+#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(ESP_PLATFORM)
+#define CONFIG_HAS_FDATASYNC 1
+#else
+#define CONFIG_HAS_FDATASYNC 0
+#endif
+
+/*
+ * For NuttX, CONFIG_HAS_ISATTY is provided by its platform header.
+ * (platform_internal.h)
+ */
+#ifndef __NuttX__
+#ifndef __CloudABI__
+#define CONFIG_HAS_ISATTY 1
+#else
+#define CONFIG_HAS_ISATTY 0
+#endif
+#endif
+
+#if !defined(__APPLE__) && !defined(ESP_PLATFORM)
+#define CONFIG_HAS_POSIX_FALLOCATE 1
+#else
+#define CONFIG_HAS_POSIX_FALLOCATE 0
+#endif
+
+#if !defined(__APPLE__) && !defined(ESP_PLATFORM)
+#define CONFIG_HAS_PREADV 1
+#else
+#define CONFIG_HAS_PREADV 0
+#endif
+
+#if defined(__APPLE__) || defined(__CloudABI__)
+#define CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 1
+#else
+#define CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP 0
+#endif
+
+#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX)
+#define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 1
+#else
+#define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 0
+#endif
+
+#if !defined(__APPLE__) && !defined(ESP_PLATFORM)
+#define CONFIG_HAS_PWRITEV 1
+#else
+#define CONFIG_HAS_PWRITEV 0
+#endif
+
+#ifdef __APPLE__
+#define st_atim st_atimespec
+#define st_ctim st_ctimespec
+#define st_mtim st_mtimespec
+#endif
+
+#ifdef __APPLE__
+#define CONFIG_TLS_USE_GSBASE 1
+#else
+#define CONFIG_TLS_USE_GSBASE 0
+#endif
+
+#if !defined(BH_PLATFORM_LINUX_SGX)
+/* Clang's __GNUC_PREREQ macro has a different meaning than GCC one,
+so we have to handle this case specially */
+#if defined(__clang__)
+/* Clang provides stdatomic.h since 3.6.0
+See https://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html */
+#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
+#define CONFIG_HAS_STD_ATOMIC 1
+#else
+#define CONFIG_HAS_STD_ATOMIC 0
+#endif
+#elif defined(__GNUC_PREREQ)
+/* Even though older versions of GCC support C11, atomics were
+not implemented until 4.9. See
+https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58016 */
+#if __GNUC_PREREQ(4, 9)
+#define CONFIG_HAS_STD_ATOMIC 1
+#else /* else of __GNUC_PREREQ(4, 9) */
+#define CONFIG_HAS_STD_ATOMIC 0
+#endif /* end of __GNUC_PREREQ(4, 9) */
+#else /* else of defined(__GNUC_PREREQ) */
+#define CONFIG_HAS_STD_ATOMIC 1
+#endif /* end of defined(__GNUC_PREREQ) */
+#else /* else of !defined(BH_PLATFORM_LINUX_SGX) */
+#define CONFIG_HAS_STD_ATOMIC 0
+#endif /* end of !defined(BH_PLATFORM_LINUX_SGX) */
+
+#if !defined(__NuttX__)
+#define CONFIG_HAS_D_INO 1
+#else
+#define CONFIG_HAS_D_INO 0
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c
new file mode 100644
index 000000000..858d8d5e4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.c
@@ -0,0 +1,47 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#include "ssp_config.h"
+#include "bh_platform.h"
+#include "str.h"
+
+static char *
+bh_strndup(const char *s, size_t n)
+{
+ size_t l = strnlen(s, n);
+ char *s1 = wasm_runtime_malloc((uint32)(l + 1));
+
+ if (!s1)
+ return NULL;
+ bh_memcpy_s(s1, (uint32)(l + 1), s, (uint32)l);
+ s1[l] = 0;
+ return s1;
+}
+
+char *
+str_nullterminate(const char *s, size_t len)
+{
+ /* Copy string */
+ char *ret = bh_strndup(s, len);
+
+ if (ret == NULL)
+ return NULL;
+
+ /* Ensure that it contains no null bytes within */
+ if (strlen(ret) != len) {
+ wasm_runtime_free(ret);
+ errno = EILSEQ;
+ return NULL;
+ }
+ return ret;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h
new file mode 100644
index 000000000..7d633e5c8
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/str.h
@@ -0,0 +1,22 @@
+// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
+// Exceptions. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
+// information.
+//
+// Significant parts of this file are derived from cloudabi-utils. See
+// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
+// for license information.
+//
+// The upstream file contains the following copyright notice:
+//
+// Copyright (c) 2016 Nuxi, https://nuxi.nl/
+
+#ifndef STR_H
+#define STR_H
+
+#include "ssp_config.h"
+
+char *
+str_nullterminate(const char *, size_t);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/SConscript b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/SConscript
new file mode 100644
index 000000000..65f561ae2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/SConscript
@@ -0,0 +1,19 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+
+cwd = GetCurrentDir()
+
+src = Split('''
+thread_manager.c
+''')
+
+CPPPATH = [cwd]
+
+group = DefineGroup('iwasm_lib_thread_mgr', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.c
new file mode 100644
index 000000000..9303eb3f5
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.c
@@ -0,0 +1,1351 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "thread_manager.h"
+
+#if WASM_ENABLE_INTERP != 0
+#include "../interpreter/wasm_runtime.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "../aot/aot_runtime.h"
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+#include "debug_engine.h"
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#include "wasm_shared_memory.h"
+#endif
+
+typedef struct {
+ bh_list_link l;
+ void (*destroy_cb)(WASMCluster *);
+} DestroyCallBackNode;
+
+static bh_list destroy_callback_list_head;
+static bh_list *const destroy_callback_list = &destroy_callback_list_head;
+
+static bh_list cluster_list_head;
+static bh_list *const cluster_list = &cluster_list_head;
+static korp_mutex cluster_list_lock;
+
+typedef void (*list_visitor)(void *, void *);
+
+static uint32 cluster_max_thread_num = CLUSTER_MAX_THREAD_NUM;
+
+/* Set the maximum thread number, if this function is not called,
+ the max thread num is defined by CLUSTER_MAX_THREAD_NUM */
+void
+wasm_cluster_set_max_thread_num(uint32 num)
+{
+ if (num > 0)
+ cluster_max_thread_num = num;
+}
+
+bool
+thread_manager_init()
+{
+ if (bh_list_init(cluster_list) != 0)
+ return false;
+ if (os_mutex_init(&cluster_list_lock) != 0)
+ return false;
+ return true;
+}
+
+void
+thread_manager_destroy()
+{
+ WASMCluster *cluster = bh_list_first_elem(cluster_list);
+ WASMCluster *next;
+ while (cluster) {
+ next = bh_list_elem_next(cluster);
+ wasm_cluster_destroy(cluster);
+ cluster = next;
+ }
+ wasm_cluster_cancel_all_callbacks();
+ os_mutex_destroy(&cluster_list_lock);
+}
+
+static void
+traverse_list(bh_list *l, list_visitor visitor, void *user_data)
+{
+ void *next, *node = bh_list_first_elem(l);
+ while (node) {
+ next = bh_list_elem_next(node);
+ visitor(node, user_data);
+ node = next;
+ }
+}
+
+/* Assumes cluster->lock is locked */
+static bool
+safe_traverse_exec_env_list(WASMCluster *cluster, list_visitor visitor,
+ void *user_data)
+{
+ Vector proc_nodes;
+ void *node;
+ bool ret = true;
+
+ if (!bh_vector_init(&proc_nodes, cluster->exec_env_list.len, sizeof(void *),
+ false)) {
+ ret = false;
+ goto final;
+ }
+
+ node = bh_list_first_elem(&cluster->exec_env_list);
+
+ while (node) {
+ bool already_processed = false;
+ void *proc_node;
+ uint32 i;
+ for (i = 0; i < (uint32)bh_vector_size(&proc_nodes); i++) {
+ if (!bh_vector_get(&proc_nodes, i, &proc_node)) {
+ ret = false;
+ goto final;
+ }
+ if (proc_node == node) {
+ already_processed = true;
+ break;
+ }
+ }
+ if (already_processed) {
+ node = bh_list_elem_next(node);
+ continue;
+ }
+
+ os_mutex_unlock(&cluster->lock);
+ visitor(node, user_data);
+ os_mutex_lock(&cluster->lock);
+ if (!bh_vector_append(&proc_nodes, &node)) {
+ ret = false;
+ goto final;
+ }
+
+ node = bh_list_first_elem(&cluster->exec_env_list);
+ }
+
+final:
+ bh_vector_destroy(&proc_nodes);
+
+ return ret;
+}
+
+/* The caller must lock cluster->lock */
+static bool
+allocate_aux_stack(WASMExecEnv *exec_env, uint32 *start, uint32 *size)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION != 0
+ WASMModuleInstanceCommon *module_inst =
+ wasm_exec_env_get_module_inst(exec_env);
+ uint32 stack_end;
+
+ stack_end = wasm_runtime_module_malloc_internal(module_inst, exec_env,
+ cluster->stack_size, NULL);
+ *start = stack_end + cluster->stack_size;
+ *size = cluster->stack_size;
+
+ return stack_end != 0;
+#else
+ uint32 i;
+
+ /* If the module doesn't have aux stack info,
+ it can't create any threads */
+ if (!cluster->stack_segment_occupied)
+ return false;
+
+ for (i = 0; i < cluster_max_thread_num; i++) {
+ if (!cluster->stack_segment_occupied[i]) {
+ if (start)
+ *start = cluster->stack_tops[i];
+ if (size)
+ *size = cluster->stack_size;
+ cluster->stack_segment_occupied[i] = true;
+ return true;
+ }
+ }
+
+ return false;
+#endif
+}
+
+/* The caller must lock cluster->lock */
+static bool
+free_aux_stack(WASMExecEnv *exec_env, uint32 start)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+
+#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION != 0
+ WASMModuleInstanceCommon *module_inst =
+ wasm_exec_env_get_module_inst(exec_env);
+
+ if (!wasm_exec_env_is_aux_stack_managed_by_runtime(exec_env)) {
+ return true;
+ }
+
+ bh_assert(start >= cluster->stack_size);
+
+ wasm_runtime_module_free_internal(module_inst, exec_env,
+ start - cluster->stack_size);
+
+ return true;
+#else
+ uint32 i;
+
+ for (i = 0; i < cluster_max_thread_num; i++) {
+ if (start == cluster->stack_tops[i]) {
+ cluster->stack_segment_occupied[i] = false;
+ return true;
+ }
+ }
+ return false;
+#endif
+}
+
+WASMCluster *
+wasm_cluster_create(WASMExecEnv *exec_env)
+{
+ WASMCluster *cluster;
+ uint32 aux_stack_start, aux_stack_size;
+
+ bh_assert(exec_env->cluster == NULL);
+ if (!(cluster = wasm_runtime_malloc(sizeof(WASMCluster)))) {
+ LOG_ERROR("thread manager error: failed to allocate memory");
+ return NULL;
+ }
+ memset(cluster, 0, sizeof(WASMCluster));
+
+ exec_env->cluster = cluster;
+
+ bh_list_init(&cluster->exec_env_list);
+ bh_list_insert(&cluster->exec_env_list, exec_env);
+ if (os_mutex_init(&cluster->lock) != 0) {
+ wasm_runtime_free(cluster);
+ LOG_ERROR("thread manager error: failed to init mutex");
+ return NULL;
+ }
+
+ /* Prepare the aux stack top and size for every thread */
+ if (!wasm_exec_env_get_aux_stack(exec_env, &aux_stack_start,
+ &aux_stack_size)) {
+#if WASM_ENABLE_LIB_WASI_THREADS == 0
+ LOG_VERBOSE("No aux stack info for this module, can't create thread");
+#endif
+
+ /* If the module don't have aux stack info, don't throw error here,
+ but remain stack_tops and stack_segment_occupied as NULL */
+ os_mutex_lock(&cluster_list_lock);
+ if (bh_list_insert(cluster_list, cluster) != 0) {
+ os_mutex_unlock(&cluster_list_lock);
+ goto fail;
+ }
+ os_mutex_unlock(&cluster_list_lock);
+
+ return cluster;
+ }
+
+#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION != 0
+ cluster->stack_size = aux_stack_size;
+#else
+ cluster->stack_size = aux_stack_size / (cluster_max_thread_num + 1);
+ if (cluster->stack_size < WASM_THREAD_AUX_STACK_SIZE_MIN) {
+ goto fail;
+ }
+ /* Make stack size 16-byte aligned */
+ cluster->stack_size = cluster->stack_size & (~15);
+#endif
+
+ /* Set initial aux stack top to the instance and
+ aux stack boundary to the main exec_env */
+ if (!wasm_exec_env_set_aux_stack(exec_env, aux_stack_start,
+ cluster->stack_size))
+ goto fail;
+
+#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0
+ if (cluster_max_thread_num != 0) {
+ uint64 total_size = cluster_max_thread_num * sizeof(uint32);
+ uint32 i;
+ if (total_size >= UINT32_MAX
+ || !(cluster->stack_tops =
+ wasm_runtime_malloc((uint32)total_size))) {
+ goto fail;
+ }
+ memset(cluster->stack_tops, 0, (uint32)total_size);
+
+ if (!(cluster->stack_segment_occupied =
+ wasm_runtime_malloc(cluster_max_thread_num * sizeof(bool)))) {
+ goto fail;
+ }
+ memset(cluster->stack_segment_occupied, 0,
+ cluster_max_thread_num * sizeof(bool));
+
+ /* Reserve space for main instance */
+ aux_stack_start -= cluster->stack_size;
+
+ for (i = 0; i < cluster_max_thread_num; i++) {
+ cluster->stack_tops[i] = aux_stack_start - cluster->stack_size * i;
+ }
+ }
+#endif
+
+ os_mutex_lock(&cluster_list_lock);
+ if (bh_list_insert(cluster_list, cluster) != 0) {
+ os_mutex_unlock(&cluster_list_lock);
+ goto fail;
+ }
+ os_mutex_unlock(&cluster_list_lock);
+
+ return cluster;
+
+fail:
+ if (cluster)
+ wasm_cluster_destroy(cluster);
+
+ return NULL;
+}
+
+static void
+destroy_cluster_visitor(void *node, void *user_data)
+{
+ DestroyCallBackNode *destroy_node = (DestroyCallBackNode *)node;
+ WASMCluster *cluster = (WASMCluster *)user_data;
+
+ destroy_node->destroy_cb(cluster);
+}
+
+void
+wasm_cluster_destroy(WASMCluster *cluster)
+{
+ traverse_list(destroy_callback_list, destroy_cluster_visitor,
+ (void *)cluster);
+
+ /* Remove the cluster from the cluster list */
+ os_mutex_lock(&cluster_list_lock);
+ bh_list_remove(cluster_list, cluster);
+ os_mutex_unlock(&cluster_list_lock);
+
+ os_mutex_destroy(&cluster->lock);
+
+#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0
+ if (cluster->stack_tops)
+ wasm_runtime_free(cluster->stack_tops);
+ if (cluster->stack_segment_occupied)
+ wasm_runtime_free(cluster->stack_segment_occupied);
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ wasm_debug_instance_destroy(cluster);
+#endif
+
+ wasm_runtime_free(cluster);
+}
+
+static void
+free_node_visitor(void *node, void *user_data)
+{
+ wasm_runtime_free(node);
+}
+
+void
+wasm_cluster_cancel_all_callbacks()
+{
+ traverse_list(destroy_callback_list, free_node_visitor, NULL);
+ bh_list_init(destroy_callback_list);
+}
+
+WASMCluster *
+wasm_exec_env_get_cluster(WASMExecEnv *exec_env)
+{
+ return exec_env->cluster;
+}
+
+/* The caller must lock cluster->lock */
+static bool
+wasm_cluster_add_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env)
+{
+ bool ret = true;
+
+ exec_env->cluster = cluster;
+
+ if (cluster->exec_env_list.len == cluster_max_thread_num + 1) {
+ LOG_ERROR("thread manager error: "
+ "maximum number of threads exceeded");
+ ret = false;
+ }
+
+ if (ret && bh_list_insert(&cluster->exec_env_list, exec_env) != 0)
+ ret = false;
+
+ return ret;
+}
+
+static bool
+wasm_cluster_del_exec_env_internal(WASMCluster *cluster, WASMExecEnv *exec_env,
+ bool can_destroy_cluster)
+{
+ bool ret = true;
+ bh_assert(exec_env->cluster == cluster);
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ /* Wait for debugger control thread to process the
+ stop event of this thread */
+ if (cluster->debug_inst) {
+ /* lock the debug_inst->wait_lock so
+ other threads can't fire stop events */
+ os_mutex_lock(&cluster->debug_inst->wait_lock);
+ while (cluster->debug_inst->stopped_thread == exec_env) {
+ /* either wakes up by signal or by 1-second timeout */
+ os_cond_reltimedwait(&cluster->debug_inst->wait_cond,
+ &cluster->debug_inst->wait_lock, 1000000);
+ }
+ os_mutex_unlock(&cluster->debug_inst->wait_lock);
+ }
+#endif
+ if (bh_list_remove(&cluster->exec_env_list, exec_env) != 0)
+ ret = false;
+
+ if (can_destroy_cluster) {
+ if (cluster->exec_env_list.len == 0) {
+ /* exec_env_list empty, destroy the cluster */
+ wasm_cluster_destroy(cluster);
+ }
+ }
+ else {
+ /* Don't destroy cluster as cluster->lock is being used */
+ }
+
+ return ret;
+}
+
+/* The caller should lock cluster->lock for thread safety */
+bool
+wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env)
+{
+ return wasm_cluster_del_exec_env_internal(cluster, exec_env, true);
+}
+
+static WASMExecEnv *
+wasm_cluster_search_exec_env(WASMCluster *cluster,
+ WASMModuleInstanceCommon *module_inst)
+{
+ WASMExecEnv *node = NULL;
+
+ os_mutex_lock(&cluster->lock);
+ node = bh_list_first_elem(&cluster->exec_env_list);
+ while (node) {
+ if (node->module_inst == module_inst) {
+ os_mutex_unlock(&cluster->lock);
+ return node;
+ }
+ node = bh_list_elem_next(node);
+ }
+
+ os_mutex_unlock(&cluster->lock);
+ return NULL;
+}
+
+/* search the global cluster list to find if the given
+ module instance have a corresponding exec_env */
+WASMExecEnv *
+wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst)
+{
+ WASMCluster *cluster = NULL;
+ WASMExecEnv *exec_env = NULL;
+
+ os_mutex_lock(&cluster_list_lock);
+ cluster = bh_list_first_elem(cluster_list);
+ while (cluster) {
+ exec_env = wasm_cluster_search_exec_env(cluster, module_inst);
+ if (exec_env) {
+ os_mutex_unlock(&cluster_list_lock);
+ return exec_env;
+ }
+ cluster = bh_list_elem_next(cluster);
+ }
+
+ os_mutex_unlock(&cluster_list_lock);
+ return NULL;
+}
+
+WASMExecEnv *
+wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ wasm_module_inst_t module_inst = get_module_inst(exec_env);
+ wasm_module_t module;
+ wasm_module_inst_t new_module_inst;
+#if WASM_ENABLE_LIBC_WASI != 0
+ WASIContext *wasi_ctx;
+#endif
+ WASMExecEnv *new_exec_env;
+ uint32 aux_stack_start, aux_stack_size;
+ uint32 stack_size = 8192;
+
+ if (!module_inst || !(module = wasm_exec_env_get_module(exec_env))) {
+ return NULL;
+ }
+
+ os_mutex_lock(&cluster->lock);
+
+ if (cluster->has_exception || cluster->processing) {
+ goto fail1;
+ }
+
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst->module_type == Wasm_Module_Bytecode) {
+ stack_size =
+ ((WASMModuleInstance *)module_inst)->default_wasm_stack_size;
+ }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+ if (module_inst->module_type == Wasm_Module_AoT) {
+ stack_size =
+ ((AOTModuleInstance *)module_inst)->default_wasm_stack_size;
+ }
+#endif
+
+ if (!(new_module_inst = wasm_runtime_instantiate_internal(
+ module, true, exec_env, stack_size, 0, NULL, 0))) {
+ goto fail1;
+ }
+
+ /* Set custom_data to new module instance */
+ wasm_runtime_set_custom_data_internal(
+ new_module_inst, wasm_runtime_get_custom_data(module_inst));
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
+ wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
+#endif
+
+ new_exec_env = wasm_exec_env_create_internal(new_module_inst,
+ exec_env->wasm_stack_size);
+ if (!new_exec_env)
+ goto fail2;
+
+ if (!allocate_aux_stack(exec_env, &aux_stack_start, &aux_stack_size)) {
+ LOG_ERROR("thread manager error: "
+ "failed to allocate aux stack space for new thread");
+ goto fail3;
+ }
+
+ /* Set aux stack for current thread */
+ if (!wasm_exec_env_set_aux_stack(new_exec_env, aux_stack_start,
+ aux_stack_size)) {
+ goto fail4;
+ }
+
+ /* Inherit suspend_flags of parent thread */
+ new_exec_env->suspend_flags.flags = exec_env->suspend_flags.flags;
+
+ if (!wasm_cluster_add_exec_env(cluster, new_exec_env))
+ goto fail4;
+
+ os_mutex_unlock(&cluster->lock);
+
+ return new_exec_env;
+
+fail4:
+ /* free the allocated aux stack space */
+ free_aux_stack(exec_env, aux_stack_start);
+fail3:
+ wasm_exec_env_destroy_internal(new_exec_env);
+fail2:
+ wasm_runtime_deinstantiate_internal(new_module_inst, true);
+fail1:
+ os_mutex_unlock(&cluster->lock);
+
+ return NULL;
+}
+
+void
+wasm_cluster_destroy_spawned_exec_env(WASMExecEnv *exec_env)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ wasm_module_inst_t module_inst = wasm_runtime_get_module_inst(exec_env);
+ bh_assert(cluster != NULL);
+
+ os_mutex_lock(&cluster->lock);
+
+ /* Free aux stack space */
+ free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom);
+ /* Remove exec_env */
+ wasm_cluster_del_exec_env_internal(cluster, exec_env, false);
+ /* Destroy exec_env */
+ wasm_exec_env_destroy_internal(exec_env);
+ /* Routine exit, destroy instance */
+ wasm_runtime_deinstantiate_internal(module_inst, true);
+
+ os_mutex_unlock(&cluster->lock);
+}
+
+/* start routine of thread manager */
+static void *
+thread_manager_start_routine(void *arg)
+{
+ void *ret;
+ WASMExecEnv *exec_env = (WASMExecEnv *)arg;
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ WASMModuleInstanceCommon *module_inst =
+ wasm_exec_env_get_module_inst(exec_env);
+
+ bh_assert(cluster != NULL);
+ bh_assert(module_inst != NULL);
+
+ os_mutex_lock(&exec_env->wait_lock);
+ exec_env->handle = os_self_thread();
+ /* Notify the parent thread to continue running */
+ os_cond_signal(&exec_env->wait_cond);
+ os_mutex_unlock(&exec_env->wait_lock);
+
+ ret = exec_env->thread_start_routine(exec_env);
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ os_mutex_lock(&exec_env->wait_lock);
+ if (exec_env->suspend_flags.flags & 0x08)
+ ret = exec_env->thread_ret_value;
+ os_mutex_unlock(&exec_env->wait_lock);
+#endif
+
+ /* Routine exit */
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ wasm_cluster_thread_exited(exec_env);
+#endif
+
+ os_mutex_lock(&cluster_list_lock);
+
+ os_mutex_lock(&cluster->lock);
+
+ /* Detach the native thread here to ensure the resources are freed */
+ if (exec_env->wait_count == 0 && !exec_env->thread_is_detached) {
+ /* Only detach current thread when there is no other thread
+ joining it, otherwise let the system resources for the
+ thread be released after joining */
+ os_thread_detach(exec_env->handle);
+ /* No need to set exec_env->thread_is_detached to true here
+ since we will exit soon */
+ }
+
+ /* Free aux stack space */
+ free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom);
+ /* Remove exec_env */
+ wasm_cluster_del_exec_env_internal(cluster, exec_env, false);
+ /* Destroy exec_env */
+ wasm_exec_env_destroy_internal(exec_env);
+ /* Routine exit, destroy instance */
+ wasm_runtime_deinstantiate_internal(module_inst, true);
+
+ os_mutex_unlock(&cluster->lock);
+
+ os_mutex_unlock(&cluster_list_lock);
+
+ os_thread_exit(ret);
+ return ret;
+}
+
+int32
+wasm_cluster_create_thread(WASMExecEnv *exec_env,
+ wasm_module_inst_t module_inst, bool alloc_aux_stack,
+ void *(*thread_routine)(void *), void *arg)
+{
+ WASMCluster *cluster;
+ WASMExecEnv *new_exec_env;
+ uint32 aux_stack_start = 0, aux_stack_size;
+ korp_tid tid;
+
+ cluster = wasm_exec_env_get_cluster(exec_env);
+ bh_assert(cluster);
+
+ os_mutex_lock(&cluster->lock);
+
+ if (cluster->has_exception || cluster->processing) {
+ goto fail1;
+ }
+
+ new_exec_env =
+ wasm_exec_env_create_internal(module_inst, exec_env->wasm_stack_size);
+ if (!new_exec_env)
+ goto fail1;
+
+ if (alloc_aux_stack) {
+ if (!allocate_aux_stack(exec_env, &aux_stack_start, &aux_stack_size)) {
+ LOG_ERROR("thread manager error: "
+ "failed to allocate aux stack space for new thread");
+ goto fail2;
+ }
+
+ /* Set aux stack for current thread */
+ if (!wasm_exec_env_set_aux_stack(new_exec_env, aux_stack_start,
+ aux_stack_size)) {
+ goto fail3;
+ }
+ }
+ else {
+ /* Disable aux stack */
+ new_exec_env->aux_stack_boundary.boundary = 0;
+ new_exec_env->aux_stack_bottom.bottom = UINT32_MAX;
+ }
+
+ /* Inherit suspend_flags of parent thread */
+ new_exec_env->suspend_flags.flags = exec_env->suspend_flags.flags;
+
+ if (!wasm_cluster_add_exec_env(cluster, new_exec_env))
+ goto fail3;
+
+ new_exec_env->thread_start_routine = thread_routine;
+ new_exec_env->thread_arg = arg;
+
+ os_mutex_lock(&new_exec_env->wait_lock);
+
+ if (0
+ != os_thread_create(&tid, thread_manager_start_routine,
+ (void *)new_exec_env,
+ APP_THREAD_STACK_SIZE_DEFAULT)) {
+ os_mutex_unlock(&new_exec_env->wait_lock);
+ goto fail4;
+ }
+
+ /* Wait until the new_exec_env->handle is set to avoid it is
+ illegally accessed after unlocking cluster->lock */
+ os_cond_wait(&new_exec_env->wait_cond, &new_exec_env->wait_lock);
+ os_mutex_unlock(&new_exec_env->wait_lock);
+
+ os_mutex_unlock(&cluster->lock);
+
+ return 0;
+
+fail4:
+ wasm_cluster_del_exec_env_internal(cluster, new_exec_env, false);
+fail3:
+ /* free the allocated aux stack space */
+ if (alloc_aux_stack)
+ free_aux_stack(exec_env, aux_stack_start);
+fail2:
+ wasm_exec_env_destroy_internal(new_exec_env);
+fail1:
+ os_mutex_unlock(&cluster->lock);
+
+ return -1;
+}
+
+bool
+wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst,
+ const WASMModuleInstanceCommon *module_inst_src)
+{
+ /* workaround about passing instantiate-linking information */
+ CApiFuncImport **new_c_api_func_imports = NULL;
+ CApiFuncImport *c_api_func_imports;
+ uint32 import_func_count = 0;
+ uint32 size_in_bytes = 0;
+
+#if WASM_ENABLE_INTERP != 0
+ if (module_inst_src->module_type == Wasm_Module_Bytecode) {
+ new_c_api_func_imports =
+ &(((WASMModuleInstance *)module_inst_dst)->e->c_api_func_imports);
+ c_api_func_imports = ((const WASMModuleInstance *)module_inst_src)
+ ->e->c_api_func_imports;
+ import_func_count =
+ ((WASMModule *)(((const WASMModuleInstance *)module_inst_src)
+ ->module))
+ ->import_function_count;
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (module_inst_src->module_type == Wasm_Module_AoT) {
+ AOTModuleInstanceExtra *e =
+ (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_dst)->e;
+ new_c_api_func_imports = &(e->c_api_func_imports);
+
+ e = (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst_src)->e;
+ c_api_func_imports = e->c_api_func_imports;
+
+ import_func_count =
+ ((AOTModule *)(((AOTModuleInstance *)module_inst_src)->module))
+ ->import_func_count;
+ }
+#endif
+
+ if (import_func_count != 0 && c_api_func_imports) {
+ size_in_bytes = sizeof(CApiFuncImport) * import_func_count;
+ *new_c_api_func_imports = wasm_runtime_malloc(size_in_bytes);
+ if (!(*new_c_api_func_imports))
+ return false;
+
+ bh_memcpy_s(*new_c_api_func_imports, size_in_bytes, c_api_func_imports,
+ size_in_bytes);
+ }
+ return true;
+}
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+WASMCurrentEnvStatus *
+wasm_cluster_create_exenv_status()
+{
+ WASMCurrentEnvStatus *status;
+
+ if (!(status = wasm_runtime_malloc(sizeof(WASMCurrentEnvStatus)))) {
+ return NULL;
+ }
+
+ status->step_count = 0;
+ status->signal_flag = 0;
+ status->running_status = 0;
+ return status;
+}
+
+void
+wasm_cluster_destroy_exenv_status(WASMCurrentEnvStatus *status)
+{
+ wasm_runtime_free(status);
+}
+
+inline static bool
+wasm_cluster_thread_is_running(WASMExecEnv *exec_env)
+{
+ return exec_env->current_status->running_status == STATUS_RUNNING
+ || exec_env->current_status->running_status == STATUS_STEP;
+}
+
+void
+wasm_cluster_clear_thread_signal(WASMExecEnv *exec_env)
+{
+ exec_env->current_status->signal_flag = 0;
+}
+
+void
+wasm_cluster_thread_send_signal(WASMExecEnv *exec_env, uint32 signo)
+{
+ exec_env->current_status->signal_flag = signo;
+}
+
+static void
+notify_debug_instance(WASMExecEnv *exec_env)
+{
+ WASMCluster *cluster;
+
+ cluster = wasm_exec_env_get_cluster(exec_env);
+ bh_assert(cluster);
+
+ if (!cluster->debug_inst) {
+ return;
+ }
+
+ on_thread_stop_event(cluster->debug_inst, exec_env);
+}
+
+static void
+notify_debug_instance_exit(WASMExecEnv *exec_env)
+{
+ WASMCluster *cluster;
+
+ cluster = wasm_exec_env_get_cluster(exec_env);
+ bh_assert(cluster);
+
+ if (!cluster->debug_inst) {
+ return;
+ }
+
+ on_thread_exit_event(cluster->debug_inst, exec_env);
+}
+
+void
+wasm_cluster_thread_waiting_run(WASMExecEnv *exec_env)
+{
+ exec_env->current_status->running_status = STATUS_STOP;
+ notify_debug_instance(exec_env);
+
+ while (!wasm_cluster_thread_is_running(exec_env)) {
+ os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock);
+ }
+}
+
+void
+wasm_cluster_send_signal_all(WASMCluster *cluster, uint32 signo)
+{
+ WASMExecEnv *exec_env = bh_list_first_elem(&cluster->exec_env_list);
+ while (exec_env) {
+ wasm_cluster_thread_send_signal(exec_env, signo);
+ exec_env = bh_list_elem_next(exec_env);
+ }
+}
+
+void
+wasm_cluster_thread_exited(WASMExecEnv *exec_env)
+{
+ exec_env->current_status->running_status = STATUS_EXIT;
+ notify_debug_instance_exit(exec_env);
+}
+
+void
+wasm_cluster_thread_continue(WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&exec_env->wait_lock);
+ wasm_cluster_clear_thread_signal(exec_env);
+ exec_env->current_status->running_status = STATUS_RUNNING;
+ os_cond_signal(&exec_env->wait_cond);
+ os_mutex_unlock(&exec_env->wait_lock);
+}
+
+void
+wasm_cluster_thread_step(WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&exec_env->wait_lock);
+ exec_env->current_status->running_status = STATUS_STEP;
+ os_cond_signal(&exec_env->wait_cond);
+ os_mutex_unlock(&exec_env->wait_lock);
+}
+
+void
+wasm_cluster_set_debug_inst(WASMCluster *cluster, WASMDebugInstance *inst)
+{
+ cluster->debug_inst = inst;
+}
+
+#endif /* end of WASM_ENABLE_DEBUG_INTERP */
+
+/* Check whether the exec_env is in one of all clusters, the caller
+ should add lock to the cluster list before calling us */
+static bool
+clusters_have_exec_env(WASMExecEnv *exec_env)
+{
+ WASMCluster *cluster = bh_list_first_elem(cluster_list);
+ WASMExecEnv *node;
+
+ while (cluster) {
+ os_mutex_lock(&cluster->lock);
+ node = bh_list_first_elem(&cluster->exec_env_list);
+
+ while (node) {
+ if (node == exec_env) {
+ bh_assert(exec_env->cluster == cluster);
+ os_mutex_unlock(&cluster->lock);
+ return true;
+ }
+ node = bh_list_elem_next(node);
+ }
+ os_mutex_unlock(&cluster->lock);
+
+ cluster = bh_list_elem_next(cluster);
+ }
+
+ return false;
+}
+
+int32
+wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val)
+{
+ korp_tid handle;
+
+ os_mutex_lock(&cluster_list_lock);
+
+ if (!clusters_have_exec_env(exec_env) || exec_env->thread_is_detached) {
+ /* Invalid thread, thread has exited or thread has been detached */
+ if (ret_val)
+ *ret_val = NULL;
+ os_mutex_unlock(&cluster_list_lock);
+ return 0;
+ }
+
+ os_mutex_lock(&exec_env->wait_lock);
+ exec_env->wait_count++;
+ handle = exec_env->handle;
+ os_mutex_unlock(&exec_env->wait_lock);
+
+ os_mutex_unlock(&cluster_list_lock);
+
+ return os_thread_join(handle, ret_val);
+}
+
+int32
+wasm_cluster_detach_thread(WASMExecEnv *exec_env)
+{
+ int32 ret = 0;
+
+ os_mutex_lock(&cluster_list_lock);
+ if (!clusters_have_exec_env(exec_env)) {
+ /* Invalid thread or the thread has exited */
+ os_mutex_unlock(&cluster_list_lock);
+ return 0;
+ }
+ if (exec_env->wait_count == 0 && !exec_env->thread_is_detached) {
+ /* Only detach current thread when there is no other thread
+ joining it, otherwise let the system resources for the
+ thread be released after joining */
+ ret = os_thread_detach(exec_env->handle);
+ exec_env->thread_is_detached = true;
+ }
+ os_mutex_unlock(&cluster_list_lock);
+ return ret;
+}
+
+void
+wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval)
+{
+ WASMCluster *cluster;
+ WASMModuleInstanceCommon *module_inst;
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+ if (exec_env->jmpbuf_stack_top) {
+ /* Store the return value in exec_env */
+ exec_env->thread_ret_value = retval;
+ exec_env->suspend_flags.flags |= 0x08;
+
+#ifndef BH_PLATFORM_WINDOWS
+ /* Pop all jmpbuf_node except the last one */
+ while (exec_env->jmpbuf_stack_top->prev) {
+ wasm_exec_env_pop_jmpbuf(exec_env);
+ }
+ os_longjmp(exec_env->jmpbuf_stack_top->jmpbuf, 1);
+ return;
+#endif
+ }
+#endif
+
+ cluster = wasm_exec_env_get_cluster(exec_env);
+ bh_assert(cluster);
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ wasm_cluster_clear_thread_signal(exec_env);
+ wasm_cluster_thread_exited(exec_env);
+#endif
+
+ /* App exit the thread, free the resources before exit native thread */
+
+ os_mutex_lock(&cluster_list_lock);
+
+ os_mutex_lock(&cluster->lock);
+
+ /* Detach the native thread here to ensure the resources are freed */
+ if (exec_env->wait_count == 0 && !exec_env->thread_is_detached) {
+ /* Only detach current thread when there is no other thread
+ joining it, otherwise let the system resources for the
+ thread be released after joining */
+ os_thread_detach(exec_env->handle);
+ /* No need to set exec_env->thread_is_detached to true here
+ since we will exit soon */
+ }
+
+ module_inst = exec_env->module_inst;
+
+ /* Free aux stack space */
+ free_aux_stack(exec_env, exec_env->aux_stack_bottom.bottom);
+ /* Remove exec_env */
+ wasm_cluster_del_exec_env_internal(cluster, exec_env, false);
+ /* Destroy exec_env */
+ wasm_exec_env_destroy_internal(exec_env);
+ /* Routine exit, destroy instance */
+ wasm_runtime_deinstantiate_internal(module_inst, true);
+
+ os_mutex_unlock(&cluster->lock);
+
+ os_mutex_unlock(&cluster_list_lock);
+
+ os_thread_exit(retval);
+}
+
+static void
+set_thread_cancel_flags(WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&exec_env->wait_lock);
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ wasm_cluster_thread_send_signal(exec_env, WAMR_SIG_TERM);
+#endif
+ exec_env->suspend_flags.flags |= 0x01;
+
+ os_mutex_unlock(&exec_env->wait_lock);
+}
+
+int32
+wasm_cluster_cancel_thread(WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&cluster_list_lock);
+
+ if (!exec_env->cluster) {
+ os_mutex_unlock(&cluster_list_lock);
+ return 0;
+ }
+
+ if (!clusters_have_exec_env(exec_env)) {
+ /* Invalid thread or the thread has exited */
+ goto final;
+ }
+
+ set_thread_cancel_flags(exec_env);
+
+final:
+ os_mutex_unlock(&cluster_list_lock);
+
+ return 0;
+}
+
+static void
+terminate_thread_visitor(void *node, void *user_data)
+{
+ WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+ WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
+
+ if (curr_exec_env == exec_env)
+ return;
+
+ wasm_cluster_cancel_thread(curr_exec_env);
+ wasm_cluster_join_thread(curr_exec_env, NULL);
+}
+
+void
+wasm_cluster_terminate_all(WASMCluster *cluster)
+{
+ os_mutex_lock(&cluster->lock);
+ cluster->processing = true;
+
+ safe_traverse_exec_env_list(cluster, terminate_thread_visitor, NULL);
+
+ cluster->processing = false;
+ os_mutex_unlock(&cluster->lock);
+}
+
+void
+wasm_cluster_terminate_all_except_self(WASMCluster *cluster,
+ WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&cluster->lock);
+ cluster->processing = true;
+
+ safe_traverse_exec_env_list(cluster, terminate_thread_visitor,
+ (void *)exec_env);
+
+ cluster->processing = false;
+ os_mutex_unlock(&cluster->lock);
+}
+
+static void
+wait_for_thread_visitor(void *node, void *user_data)
+{
+ WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+ WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
+
+ if (curr_exec_env == exec_env)
+ return;
+
+ wasm_cluster_join_thread(curr_exec_env, NULL);
+}
+
+void
+wams_cluster_wait_for_all(WASMCluster *cluster)
+{
+ os_mutex_lock(&cluster->lock);
+ cluster->processing = true;
+
+ safe_traverse_exec_env_list(cluster, wait_for_thread_visitor, NULL);
+
+ cluster->processing = false;
+ os_mutex_unlock(&cluster->lock);
+}
+
+void
+wasm_cluster_wait_for_all_except_self(WASMCluster *cluster,
+ WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&cluster->lock);
+ cluster->processing = true;
+
+ safe_traverse_exec_env_list(cluster, wait_for_thread_visitor,
+ (void *)exec_env);
+
+ cluster->processing = false;
+ os_mutex_unlock(&cluster->lock);
+}
+
+bool
+wasm_cluster_register_destroy_callback(void (*callback)(WASMCluster *))
+{
+ DestroyCallBackNode *node;
+
+ if (!(node = wasm_runtime_malloc(sizeof(DestroyCallBackNode)))) {
+ LOG_ERROR("thread manager error: failed to allocate memory");
+ return false;
+ }
+ node->destroy_cb = callback;
+ bh_list_insert(destroy_callback_list, node);
+ return true;
+}
+
+void
+wasm_cluster_suspend_thread(WASMExecEnv *exec_env)
+{
+ /* Set the suspend flag */
+ exec_env->suspend_flags.flags |= 0x02;
+}
+
+static void
+suspend_thread_visitor(void *node, void *user_data)
+{
+ WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+ WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
+
+ if (curr_exec_env == exec_env)
+ return;
+
+ wasm_cluster_suspend_thread(curr_exec_env);
+}
+
+void
+wasm_cluster_suspend_all(WASMCluster *cluster)
+{
+ os_mutex_lock(&cluster->lock);
+ traverse_list(&cluster->exec_env_list, suspend_thread_visitor, NULL);
+ os_mutex_unlock(&cluster->lock);
+}
+
+void
+wasm_cluster_suspend_all_except_self(WASMCluster *cluster,
+ WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&cluster->lock);
+ traverse_list(&cluster->exec_env_list, suspend_thread_visitor,
+ (void *)exec_env);
+ os_mutex_unlock(&cluster->lock);
+}
+
+void
+wasm_cluster_resume_thread(WASMExecEnv *exec_env)
+{
+ exec_env->suspend_flags.flags &= ~0x02;
+ os_cond_signal(&exec_env->wait_cond);
+}
+
+static void
+resume_thread_visitor(void *node, void *user_data)
+{
+ WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+
+ wasm_cluster_resume_thread(curr_exec_env);
+}
+
+void
+wasm_cluster_resume_all(WASMCluster *cluster)
+{
+ os_mutex_lock(&cluster->lock);
+ traverse_list(&cluster->exec_env_list, resume_thread_visitor, NULL);
+ os_mutex_unlock(&cluster->lock);
+}
+
+static void
+set_exception_visitor(void *node, void *user_data)
+{
+ WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+ WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
+ WASMModuleInstanceCommon *module_inst = get_module_inst(exec_env);
+ WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst;
+
+ if (curr_exec_env != exec_env) {
+ WASMModuleInstance *curr_wasm_inst =
+ (WASMModuleInstance *)get_module_inst(curr_exec_env);
+
+ /* Only spread non "wasi proc exit" exception */
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ WASMSharedMemNode *shared_mem_node = wasm_module_get_shared_memory(
+ (WASMModuleCommon *)curr_wasm_inst->module);
+ if (shared_mem_node)
+ os_mutex_lock(&shared_mem_node->shared_mem_lock);
+#endif
+ if (!strstr(wasm_inst->cur_exception, "wasi proc exit")) {
+ bh_memcpy_s(curr_wasm_inst->cur_exception,
+ sizeof(curr_wasm_inst->cur_exception),
+ wasm_inst->cur_exception,
+ sizeof(wasm_inst->cur_exception));
+ }
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (shared_mem_node)
+ os_mutex_unlock(&shared_mem_node->shared_mem_lock);
+#endif
+
+ /* Terminate the thread so it can exit from dead loops */
+ set_thread_cancel_flags(curr_exec_env);
+ }
+}
+
+static void
+clear_exception_visitor(void *node, void *user_data)
+{
+ WASMExecEnv *exec_env = (WASMExecEnv *)user_data;
+ WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+
+ if (curr_exec_env != exec_env) {
+ WASMModuleInstance *curr_wasm_inst =
+ (WASMModuleInstance *)get_module_inst(curr_exec_env);
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ WASMSharedMemNode *shared_mem_node = wasm_module_get_shared_memory(
+ (WASMModuleCommon *)curr_wasm_inst->module);
+ if (shared_mem_node)
+ os_mutex_lock(&shared_mem_node->shared_mem_lock);
+#endif
+ curr_wasm_inst->cur_exception[0] = '\0';
+#if WASM_ENABLE_SHARED_MEMORY != 0
+ if (shared_mem_node)
+ os_mutex_unlock(&shared_mem_node->shared_mem_lock);
+#endif
+ }
+}
+
+void
+wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear)
+{
+ WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+ bh_assert(cluster);
+
+ os_mutex_lock(&cluster->lock);
+ cluster->has_exception = !clear;
+ traverse_list(&cluster->exec_env_list,
+ clear ? clear_exception_visitor : set_exception_visitor,
+ exec_env);
+ os_mutex_unlock(&cluster->lock);
+}
+
+static void
+set_custom_data_visitor(void *node, void *user_data)
+{
+ WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
+ WASMModuleInstanceCommon *module_inst = get_module_inst(curr_exec_env);
+
+ wasm_runtime_set_custom_data_internal(module_inst, user_data);
+}
+
+void
+wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
+ void *custom_data)
+{
+ WASMExecEnv *exec_env = wasm_clusters_search_exec_env(module_inst);
+
+ if (exec_env == NULL) {
+ /* Maybe threads have not been started yet. */
+ wasm_runtime_set_custom_data_internal(module_inst, custom_data);
+ }
+ else {
+ WASMCluster *cluster;
+
+ cluster = wasm_exec_env_get_cluster(exec_env);
+ bh_assert(cluster);
+
+ os_mutex_lock(&cluster->lock);
+ traverse_list(&cluster->exec_env_list, set_custom_data_visitor,
+ custom_data);
+ os_mutex_unlock(&cluster->lock);
+ }
+}
+
+bool
+wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env)
+{
+ os_mutex_lock(&exec_env->wait_lock);
+ bool is_thread_terminated =
+ (exec_env->suspend_flags.flags & 0x01) ? true : false;
+ os_mutex_unlock(&exec_env->wait_lock);
+
+ return is_thread_terminated;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.h
new file mode 100644
index 000000000..2060869c2
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_manager.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _THREAD_MANAGER_H
+#define _THREAD_MANAGER_H
+
+#include "bh_common.h"
+#include "bh_log.h"
+#include "wasm_export.h"
+#include "../interpreter/wasm.h"
+#include "../common/wasm_runtime_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+typedef struct WASMDebugInstance WASMDebugInstance;
+#endif
+
+struct WASMCluster {
+ struct WASMCluster *next;
+
+ korp_mutex lock;
+ bh_list exec_env_list;
+
+#if WASM_ENABLE_HEAP_AUX_STACK_ALLOCATION == 0
+ /* The aux stack of a module with shared memory will be
+ divided into several segments. This array store the
+ stack top of different segments */
+ uint32 *stack_tops;
+ /* Record which segments are occupied */
+ bool *stack_segment_occupied;
+#endif
+ /* Size of every stack segment */
+ uint32 stack_size;
+ /* When has_exception == true, this cluster should refuse any spawn thread
+ * requests, this flag can be cleared by calling
+ * wasm_runtime_clear_exception on instances of any threads of this cluster
+ */
+ bool has_exception;
+ /* When processing is true, this cluster should refuse any spawn thread
+ * requests. This is a short-lived state, must be cleared immediately once
+ * the processing finished.
+ * This is used to avoid dead lock when one thread waiting another thread
+ * with lock, see wams_cluster_wait_for_all and wasm_cluster_terminate_all
+ */
+ bool processing;
+#if WASM_ENABLE_DEBUG_INTERP != 0
+ WASMDebugInstance *debug_inst;
+#endif
+};
+
+void
+wasm_cluster_set_max_thread_num(uint32 num);
+
+bool
+thread_manager_init();
+
+void
+thread_manager_destroy();
+
+/* Create cluster */
+WASMCluster *
+wasm_cluster_create(WASMExecEnv *exec_env);
+
+/* Destroy cluster */
+void
+wasm_cluster_destroy(WASMCluster *cluster);
+
+/* Get the cluster of the current exec_env */
+WASMCluster *
+wasm_exec_env_get_cluster(WASMExecEnv *exec_env);
+
+/* Forward registered functions to a new thread */
+bool
+wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst,
+ const WASMModuleInstanceCommon *module_inst_src);
+
+int32
+wasm_cluster_create_thread(WASMExecEnv *exec_env,
+ wasm_module_inst_t module_inst, bool alloc_aux_stack,
+ void *(*thread_routine)(void *), void *arg);
+
+int32
+wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val);
+
+int32
+wasm_cluster_detach_thread(WASMExecEnv *exec_env);
+
+int32
+wasm_cluster_cancel_thread(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval);
+
+bool
+wasm_cluster_register_destroy_callback(void (*callback)(WASMCluster *));
+
+void
+wasm_cluster_cancel_all_callbacks();
+
+void
+wasm_cluster_suspend_all(WASMCluster *cluster);
+
+void
+wasm_cluster_suspend_all_except_self(WASMCluster *cluster,
+ WASMExecEnv *exec_env);
+
+void
+wasm_cluster_suspend_thread(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_resume_thread(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_resume_all(WASMCluster *cluster);
+
+void
+wasm_cluster_terminate_all(WASMCluster *cluster);
+
+void
+wasm_cluster_terminate_all_except_self(WASMCluster *cluster,
+ WASMExecEnv *exec_env);
+
+void
+wams_cluster_wait_for_all(WASMCluster *cluster);
+
+void
+wasm_cluster_wait_for_all_except_self(WASMCluster *cluster,
+ WASMExecEnv *exec_env);
+
+bool
+wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env);
+
+WASMExecEnv *
+wasm_clusters_search_exec_env(WASMModuleInstanceCommon *module_inst);
+
+void
+wasm_cluster_spread_exception(WASMExecEnv *exec_env, bool clear);
+
+WASMExecEnv *
+wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_destroy_spawned_exec_env(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
+ void *custom_data);
+
+bool
+wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env);
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
+#define WAMR_SIG_TRAP (5)
+#define WAMR_SIG_STOP (19)
+#define WAMR_SIG_TERM (15)
+#define WAMR_SIG_SINGSTEP (0x1ff)
+
+#define STATUS_RUNNING (0)
+#define STATUS_STOP (1)
+#define STATUS_EXIT (2)
+#define STATUS_STEP (3)
+
+#define IS_WAMR_TERM_SIG(signo) ((signo) == WAMR_SIG_TERM)
+
+#define IS_WAMR_STOP_SIG(signo) \
+ ((signo) == WAMR_SIG_STOP || (signo) == WAMR_SIG_TRAP)
+
+struct WASMCurrentEnvStatus {
+ uint64 signal_flag : 32;
+ uint64 step_count : 16;
+ uint64 running_status : 16;
+};
+
+WASMCurrentEnvStatus *
+wasm_cluster_create_exenv_status();
+
+void
+wasm_cluster_destroy_exenv_status(WASMCurrentEnvStatus *status);
+
+void
+wasm_cluster_send_signal_all(WASMCluster *cluster, uint32 signo);
+
+/* This function must be called with exec_env->wait_lock locked, otherwise we
+ * may miss the signal from debugger thread, see
+ * https://github.com/bytecodealliance/wasm-micro-runtime/issues/1860 */
+void
+wasm_cluster_thread_waiting_run(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_wait_thread_status(WASMExecEnv *exec_env, uint32 *status);
+
+void
+wasm_cluster_thread_exited(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_thread_continue(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_thread_send_signal(WASMExecEnv *exec_env, uint32 signo);
+
+void
+wasm_cluster_thread_step(WASMExecEnv *exec_env);
+
+void
+wasm_cluster_set_debug_inst(WASMCluster *cluster, WASMDebugInstance *inst);
+
+#endif /* end of WASM_ENABLE_DEBUG_INTERP != 0 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _THREAD_MANAGER_H */
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_mgr.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_mgr.cmake
new file mode 100644
index 000000000..c37a336b4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/thread-mgr/thread_mgr.cmake
@@ -0,0 +1,13 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (THREAD_MGR_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions (-DWASM_ENABLE_THREAD_MGR=1)
+
+include_directories(${THREAD_MGR_DIR})
+
+file (GLOB source_all ${THREAD_MGR_DIR}/*.c)
+
+set (THREAD_MGR_SOURCE ${source_all})
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/README.md b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/README.md
new file mode 100644
index 000000000..ac737c281
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/README.md
@@ -0,0 +1,96 @@
+# WASI-NN
+
+## How to use
+
+Enable WASI-NN in the WAMR by spefiying it in the cmake building configuration as follows,
+
+```
+set (WAMR_BUILD_WASI_NN 1)
+```
+
+The definition of the functions provided by WASI-NN is in the header file `core/iwasm/libraries/wasi-nn/wasi_nn.h`.
+
+By only including this file in your WASM application you will bind WASI-NN into your module.
+
+## Tests
+
+To run the tests we assume that the current directory is the root of the repository.
+
+
+### Build the runtime
+
+Build the runtime image for your execution target type.
+
+`EXECUTION_TYPE` can be:
+* `cpu`
+* `nvidia-gpu`
+* `vx-delegate`
+
+```
+EXECUTION_TYPE=cpu
+docker build -t wasi-nn-${EXECUTION_TYPE} -f core/iwasm/libraries/wasi-nn/test/Dockerfile.${EXECUTION_TYPE} .
+```
+
+
+### Build wasm app
+
+```
+docker build -t wasi-nn-compile -f core/iwasm/libraries/wasi-nn/test/Dockerfile.compile .
+```
+
+```
+docker run -v $PWD/core/iwasm/libraries/wasi-nn:/wasi-nn wasi-nn-compile
+```
+
+
+### Run wasm app
+
+If all the tests have run properly you will the the following message in the terminal,
+
+```
+Tests: passed!
+```
+
+* CPU
+
+```
+docker run \
+ -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets wasi-nn-cpu \
+ --dir=/assets \
+ --env="TARGET=cpu" \
+ /assets/test_tensorflow.wasm
+```
+
+* (NVIDIA) GPU
+
+```
+docker run \
+ --runtime=nvidia \
+ -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets wasi-nn-nvidia-gpu \
+ --dir=/assets \
+ --env="TARGET=gpu" \
+ /assets/test_tensorflow.wasm
+```
+
+* vx-delegate for NPU (x86 simulater)
+
+```
+docker run \
+ -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets wasi-nn-vx-delegate \
+ --dir=/assets \
+ --env="TARGET=gpu" \
+ /assets/test_tensorflow.wasm
+```
+
+
+
+Requirements:
+* [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker).
+
+## What is missing
+
+Supported:
+
+* Graph encoding: `tensorflowlite`.
+* Execution target: `cpu` and `gpu`.
+* Tensor type: `fp32`.
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake
new file mode 100644
index 000000000..bbeac3b14
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake
@@ -0,0 +1,41 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+
+find_library(TENSORFLOW_LITE
+ NAMES tensorflow-lite
+)
+
+if(NOT EXISTS ${TENSORFLOW_LITE})
+ if (NOT EXISTS "${WAMR_ROOT_DIR}/core/deps/tensorflow-src")
+ execute_process(COMMAND ${WAMR_ROOT_DIR}/core/deps/install_tensorflow.sh
+ RESULT_VARIABLE TENSORFLOW_RESULT
+ )
+ else ()
+ message("Tensorflow is already downloaded.")
+ endif()
+ set(TENSORFLOW_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src")
+
+ if (WASI_NN_ENABLE_GPU EQUAL 1)
+ # Tensorflow specific:
+ # * https://www.tensorflow.org/lite/guide/build_cmake#available_options_to_build_tensorflow_lite
+ set (TFLITE_ENABLE_GPU ON)
+ endif ()
+
+ include_directories (${CMAKE_CURRENT_BINARY_DIR}/flatbuffers/include)
+ include_directories (${TENSORFLOW_SOURCE_DIR})
+ add_subdirectory(
+ "${TENSORFLOW_SOURCE_DIR}/tensorflow/lite"
+ "${CMAKE_CURRENT_BINARY_DIR}/tensorflow-lite" EXCLUDE_FROM_ALL)
+
+else()
+ find_path(TENSORFLOW_LITE_INCLUDE_DIR
+ NAMES tensorflow/lite/interpreter.h
+ )
+ find_path(FLATBUFFER_INCLUDE_DIR
+ NAMES flatbuffers/flatbuffers.h
+ )
+ include_directories (${TENSORFLOW_LITE_INCLUDE_DIR})
+ include_directories (${FLATBUFFER_INCLUDE_DIR})
+endif()
+
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/logger.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/logger.h
new file mode 100644
index 000000000..a196429a0
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/logger.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_LOGGER_H
+#define WASI_NN_LOGGER_H
+
+#include <stdio.h>
+#include <string.h>
+
+#define __FILENAME__ \
+ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+
+/* Disable a level by removing the define */
+#ifndef NN_LOG_LEVEL
+/*
+ 0 -> debug, info, warn, err
+ 1 -> info, warn, err
+ 2 -> warn, err
+ 3 -> err
+ 4 -> NO LOGS
+*/
+#define NN_LOG_LEVEL 0
+#endif
+
+// Definition of the levels
+#if NN_LOG_LEVEL <= 3
+#define NN_ERR_PRINTF(fmt, ...) \
+ do { \
+ printf("[%s:%d ERROR] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
+ printf("\n"); \
+ fflush(stdout); \
+ } while (0)
+#else
+#define NN_ERR_PRINTF(fmt, ...)
+#endif
+#if NN_LOG_LEVEL <= 2
+#define NN_WARN_PRINTF(fmt, ...) \
+ do { \
+ printf("[%s:%d WARNING] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
+ printf("\n"); \
+ fflush(stdout); \
+ } while (0)
+#else
+#define NN_WARN_PRINTF(fmt, ...)
+#endif
+#if NN_LOG_LEVEL <= 1
+#define NN_INFO_PRINTF(fmt, ...) \
+ do { \
+ printf("[%s:%d INFO] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
+ printf("\n"); \
+ fflush(stdout); \
+ } while (0)
+#else
+#define NN_INFO_PRINTF(fmt, ...)
+#endif
+#if NN_LOG_LEVEL <= 0
+#define NN_DBG_PRINTF(fmt, ...) \
+ do { \
+ printf("[%s:%d DEBUG] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
+ printf("\n"); \
+ fflush(stdout); \
+ } while (0)
+#else
+#define NN_DBG_PRINTF(fmt, ...)
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c
new file mode 100644
index 000000000..fe04b657b
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasi_nn_app_native.h"
+
+static error
+graph_builder_app_native(wasm_module_inst_t instance,
+ graph_builder_wasm *builder_wasm,
+ graph_builder *builder)
+{
+ if (!wasm_runtime_validate_app_addr(instance, builder_wasm->buf_offset,
+ builder_wasm->size * sizeof(uint8_t))) {
+ NN_ERR_PRINTF("builder_wasm->buf_offset is invalid");
+ return invalid_argument;
+ }
+
+ builder->buf = (uint8_t *)wasm_runtime_addr_app_to_native(
+ instance, builder_wasm->buf_offset);
+ builder->size = builder_wasm->size;
+ return success;
+}
+
+error
+graph_builder_array_app_native(wasm_module_inst_t instance,
+ graph_builder_array_wasm *builder_array_wasm,
+ graph_builder_array *builder_array)
+{
+ if (!wasm_runtime_validate_native_addr(instance, builder_array_wasm,
+ sizeof(graph_builder_array_wasm))) {
+ NN_ERR_PRINTF("builder_array_wasm is invalid");
+ return invalid_argument;
+ }
+
+ NN_DBG_PRINTF("Graph builder array contains %d elements",
+ builder_array_wasm->size);
+
+ if (!wasm_runtime_validate_app_addr(
+ instance, builder_array_wasm->buf_offset,
+ builder_array_wasm->size * sizeof(graph_builder_wasm))) {
+ NN_ERR_PRINTF("builder_array_wasm->buf_offset is invalid");
+ return invalid_argument;
+ }
+
+ graph_builder_wasm *builder_wasm =
+ (graph_builder_wasm *)wasm_runtime_addr_app_to_native(
+ instance, builder_array_wasm->buf_offset);
+
+ graph_builder *builder = (graph_builder *)wasm_runtime_malloc(
+ builder_array_wasm->size * sizeof(graph_builder));
+ if (builder == NULL)
+ return missing_memory;
+
+ for (uint32_t i = 0; i < builder_array_wasm->size; ++i) {
+ error res;
+ if (success
+ != (res = graph_builder_app_native(instance, &builder_wasm[i],
+ &builder[i]))) {
+ wasm_runtime_free(builder);
+ return res;
+ }
+
+ NN_DBG_PRINTF("Graph builder %d contains %d elements", i,
+ builder->size);
+ }
+
+ builder_array->buf = builder;
+ builder_array->size = builder_array_wasm->size;
+ return success;
+}
+
+static error
+tensor_data_app_native(wasm_module_inst_t instance, uint32_t total_elements,
+ tensor_wasm *input_tensor_wasm, tensor_data *data)
+{
+ if (!wasm_runtime_validate_app_addr(
+ instance, input_tensor_wasm->data_offset, total_elements)) {
+ NN_ERR_PRINTF("input_tensor_wasm->data_offset is invalid");
+ return invalid_argument;
+ }
+ *data = (tensor_data)wasm_runtime_addr_app_to_native(
+ instance, input_tensor_wasm->data_offset);
+ return success;
+}
+
+static error
+tensor_dimensions_app_native(wasm_module_inst_t instance,
+ tensor_wasm *input_tensor_wasm,
+ tensor_dimensions **dimensions)
+{
+ if (!wasm_runtime_validate_app_addr(instance,
+ input_tensor_wasm->dimensions_offset,
+ sizeof(tensor_dimensions_wasm))) {
+ NN_ERR_PRINTF("input_tensor_wasm->dimensions_offset is invalid");
+ return invalid_argument;
+ }
+
+ tensor_dimensions_wasm *dimensions_wasm =
+ (tensor_dimensions_wasm *)wasm_runtime_addr_app_to_native(
+ instance, input_tensor_wasm->dimensions_offset);
+
+ if (!wasm_runtime_validate_app_addr(instance, dimensions_wasm->buf_offset,
+ sizeof(tensor_dimensions))) {
+ NN_ERR_PRINTF("dimensions_wasm->buf_offset is invalid");
+ return invalid_argument;
+ }
+
+ *dimensions =
+ (tensor_dimensions *)wasm_runtime_malloc(sizeof(tensor_dimensions));
+ if (dimensions == NULL)
+ return missing_memory;
+
+ (*dimensions)->size = dimensions_wasm->size;
+ (*dimensions)->buf = (uint32_t *)wasm_runtime_addr_app_to_native(
+ instance, dimensions_wasm->buf_offset);
+
+ NN_DBG_PRINTF("Number of dimensions: %d", (*dimensions)->size);
+ return success;
+}
+
+error
+tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm,
+ tensor *input_tensor)
+{
+ NN_DBG_PRINTF("Converting tensor_wasm to tensor");
+ if (!wasm_runtime_validate_native_addr(instance, input_tensor_wasm,
+ sizeof(tensor_wasm))) {
+ NN_ERR_PRINTF("input_tensor_wasm is invalid");
+ return invalid_argument;
+ }
+
+ error res;
+
+ tensor_dimensions *dimensions = NULL;
+ if (success
+ != (res = tensor_dimensions_app_native(instance, input_tensor_wasm,
+ &dimensions))) {
+ NN_ERR_PRINTF("error when parsing dimensions");
+ return res;
+ }
+
+ uint32_t total_elements = 1;
+ for (uint32_t i = 0; i < dimensions->size; ++i) {
+ total_elements *= dimensions->buf[i];
+ NN_DBG_PRINTF("Dimension %d: %d", i, dimensions->buf[i]);
+ }
+ NN_DBG_PRINTF("Tensor type: %d", input_tensor_wasm->type);
+ NN_DBG_PRINTF("Total number of elements: %d", total_elements);
+
+ tensor_data data = NULL;
+ if (success
+ != (res = tensor_data_app_native(instance, total_elements,
+ input_tensor_wasm, &data))) {
+ wasm_runtime_free(dimensions);
+ return res;
+ }
+
+ input_tensor->type = input_tensor_wasm->type;
+ input_tensor->dimensions = dimensions;
+ input_tensor->data = data;
+ return success;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h
new file mode 100644
index 000000000..15154bd31
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_APP_NATIVE
+#define WASI_NN_APP_NATIVE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "wasi_nn.h"
+#include "logger.h"
+
+#include "bh_platform.h"
+#include "wasm_export.h"
+
+typedef struct {
+ uint32_t buf_offset;
+ uint32_t size;
+} graph_builder_wasm;
+
+typedef struct {
+ uint32_t buf_offset;
+ uint32_t size;
+} graph_builder_array_wasm;
+
+typedef struct {
+ uint32_t buf_offset;
+ uint32_t size;
+} tensor_dimensions_wasm;
+
+typedef struct {
+ uint32_t dimensions_offset;
+ tensor_type type;
+ uint32_t data_offset;
+} tensor_wasm;
+
+error
+graph_builder_array_app_native(wasm_module_inst_t instance,
+ graph_builder_array_wasm *builder,
+ graph_builder_array *builder_native);
+
+error
+tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor,
+ tensor *input_tensor_native);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn.c
new file mode 100644
index 000000000..466630f99
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "wasi_nn.h"
+#include "wasi_nn_app_native.h"
+#include "logger.h"
+#include "wasi_nn_tensorflowlite.hpp"
+
+#include "bh_platform.h"
+#include "wasm_export.h"
+#include "wasm_runtime.h"
+#include "aot_runtime.h"
+
+/* Definition of 'wasi_nn.h' structs in WASM app format (using offset) */
+
+typedef error (*LOAD)(void *, graph_builder_array *, graph_encoding,
+ execution_target, graph *);
+typedef error (*INIT_EXECUTION_CONTEXT)(void *, graph,
+ graph_execution_context *);
+typedef error (*SET_INPUT)(void *, graph_execution_context, uint32_t, tensor *);
+typedef error (*COMPUTE)(void *, graph_execution_context);
+typedef error (*GET_OUTPUT)(void *, graph_execution_context, uint32_t,
+ tensor_data, uint32_t *);
+
+typedef struct {
+ LOAD load;
+ INIT_EXECUTION_CONTEXT init_execution_context;
+ SET_INPUT set_input;
+ COMPUTE compute;
+ GET_OUTPUT get_output;
+} api_function;
+
+/* Global variables */
+
+static api_function lookup[] = {
+ { NULL, NULL, NULL, NULL, NULL },
+ { NULL, NULL, NULL, NULL, NULL },
+ { NULL, NULL, NULL, NULL, NULL },
+ { NULL, NULL, NULL, NULL, NULL },
+ { tensorflowlite_load, tensorflowlite_init_execution_context,
+ tensorflowlite_set_input, tensorflowlite_compute,
+ tensorflowlite_get_output }
+};
+
+/* Utils */
+
+static bool
+is_encoding_implemented(graph_encoding encoding)
+{
+ return lookup[encoding].load && lookup[encoding].init_execution_context
+ && lookup[encoding].set_input && lookup[encoding].compute
+ && lookup[encoding].get_output;
+}
+
+static error
+is_model_initialized(WASINNContext *wasi_nn_ctx)
+{
+ if (!wasi_nn_ctx->is_initialized) {
+ NN_ERR_PRINTF("Model not initialized.");
+ return runtime_error;
+ }
+ return success;
+}
+
+WASINNContext *
+wasm_runtime_get_wasi_nn_ctx(wasm_module_inst_t instance)
+{
+ WASINNContext *wasi_nn_ctx = NULL;
+#if WASM_ENABLE_INTERP != 0
+ if (instance->module_type == Wasm_Module_Bytecode) {
+ NN_DBG_PRINTF("Getting ctx from WASM");
+ WASMModuleInstance *module_inst = (WASMModuleInstance *)instance;
+ wasi_nn_ctx = ((WASMModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx;
+ }
+#endif
+#if WASM_ENABLE_AOT != 0
+ if (instance->module_type == Wasm_Module_AoT) {
+ NN_DBG_PRINTF("Getting ctx from AOT");
+ AOTModuleInstance *module_inst = (AOTModuleInstance *)instance;
+ wasi_nn_ctx = ((AOTModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx;
+ }
+#endif
+ bh_assert(wasi_nn_ctx != NULL);
+ NN_DBG_PRINTF("Returning ctx");
+ return wasi_nn_ctx;
+}
+
+/* WASI-NN implementation */
+
+error
+wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder,
+ graph_encoding encoding, execution_target target, graph *g)
+{
+ NN_DBG_PRINTF("Running wasi_nn_load [encoding=%d, target=%d]...", encoding,
+ target);
+
+ if (!is_encoding_implemented(encoding)) {
+ NN_ERR_PRINTF("Encoding not supported.");
+ return invalid_encoding;
+ }
+
+ wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+ bh_assert(instance);
+
+ error res;
+ graph_builder_array builder_native = { 0 };
+ if (success
+ != (res = graph_builder_array_app_native(instance, builder,
+ &builder_native)))
+ return res;
+
+ if (!wasm_runtime_validate_native_addr(instance, g, sizeof(graph))) {
+ NN_ERR_PRINTF("graph is invalid");
+ res = invalid_argument;
+ goto fail;
+ }
+
+ WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+ res = lookup[encoding].load(wasi_nn_ctx->tflite_ctx, &builder_native,
+ encoding, target, g);
+
+ NN_DBG_PRINTF("wasi_nn_load finished with status %d [graph=%d]", res, *g);
+
+ wasi_nn_ctx->current_encoding = encoding;
+ wasi_nn_ctx->is_initialized = true;
+
+fail:
+ // XXX: Free intermediate structure pointers
+ if (builder_native.buf)
+ wasm_runtime_free(builder_native.buf);
+
+ return res;
+}
+
+error
+wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g,
+ graph_execution_context *ctx)
+{
+ NN_DBG_PRINTF("Running wasi_nn_init_execution_context [graph=%d]...", g);
+
+ wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+ bh_assert(instance);
+ WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+
+ error res;
+ if (success != (res = is_model_initialized(wasi_nn_ctx)))
+ return res;
+
+ if (!wasm_runtime_validate_native_addr(instance, ctx,
+ sizeof(graph_execution_context))) {
+ NN_ERR_PRINTF("ctx is invalid");
+ return invalid_argument;
+ }
+
+ res = lookup[wasi_nn_ctx->current_encoding].init_execution_context(
+ wasi_nn_ctx->tflite_ctx, g, ctx);
+
+ NN_DBG_PRINTF(
+ "wasi_nn_init_execution_context finished with status %d [ctx=%d]", res,
+ *ctx);
+ return res;
+}
+
+error
+wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx,
+ uint32_t index, tensor_wasm *input_tensor)
+{
+ NN_DBG_PRINTF("Running wasi_nn_set_input [ctx=%d, index=%d]...", ctx,
+ index);
+
+ wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+ bh_assert(instance);
+ WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+
+ error res;
+ if (success != (res = is_model_initialized(wasi_nn_ctx)))
+ return res;
+
+ tensor input_tensor_native = { 0 };
+ if (success
+ != (res = tensor_app_native(instance, input_tensor,
+ &input_tensor_native)))
+ return res;
+
+ res = lookup[wasi_nn_ctx->current_encoding].set_input(
+ wasi_nn_ctx->tflite_ctx, ctx, index, &input_tensor_native);
+
+ // XXX: Free intermediate structure pointers
+ if (input_tensor_native.dimensions)
+ wasm_runtime_free(input_tensor_native.dimensions);
+
+ NN_DBG_PRINTF("wasi_nn_set_input finished with status %d", res);
+ return res;
+}
+
+error
+wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx)
+{
+ NN_DBG_PRINTF("Running wasi_nn_compute [ctx=%d]...", ctx);
+
+ wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+ bh_assert(instance);
+ WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+
+ error res;
+ if (success != (res = is_model_initialized(wasi_nn_ctx)))
+ return res;
+
+ res = lookup[wasi_nn_ctx->current_encoding].compute(wasi_nn_ctx->tflite_ctx,
+ ctx);
+ NN_DBG_PRINTF("wasi_nn_compute finished with status %d", res);
+ return res;
+}
+
+error
+wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx,
+ uint32_t index, tensor_data output_tensor,
+ uint32_t *output_tensor_size)
+{
+ NN_DBG_PRINTF("Running wasi_nn_get_output [ctx=%d, index=%d]...", ctx,
+ index);
+
+ wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+ bh_assert(instance);
+ WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+
+ error res;
+ if (success != (res = is_model_initialized(wasi_nn_ctx)))
+ return res;
+
+ if (!wasm_runtime_validate_native_addr(instance, output_tensor_size,
+ sizeof(uint32_t))) {
+ NN_ERR_PRINTF("output_tensor_size is invalid");
+ return invalid_argument;
+ }
+
+ res = lookup[wasi_nn_ctx->current_encoding].get_output(
+ wasi_nn_ctx->tflite_ctx, ctx, index, output_tensor, output_tensor_size);
+ NN_DBG_PRINTF("wasi_nn_get_output finished with status %d [data_size=%d]",
+ res, *output_tensor_size);
+ return res;
+}
+
+/* Non-exposed public functions */
+
+WASINNContext *
+wasi_nn_initialize()
+{
+ NN_DBG_PRINTF("Initializing wasi-nn");
+ WASINNContext *wasi_nn_ctx =
+ (WASINNContext *)wasm_runtime_malloc(sizeof(WASINNContext));
+ if (wasi_nn_ctx == NULL) {
+ NN_ERR_PRINTF("Error when allocating memory for WASI-NN context");
+ return NULL;
+ }
+ wasi_nn_ctx->is_initialized = true;
+ wasi_nn_ctx->current_encoding = 3;
+ tensorflowlite_initialize(&wasi_nn_ctx->tflite_ctx);
+ return wasi_nn_ctx;
+}
+
+void
+wasi_nn_destroy(WASINNContext *wasi_nn_ctx)
+{
+ if (wasi_nn_ctx == NULL) {
+ NN_ERR_PRINTF(
+ "Error when deallocating memory. WASI-NN context is NULL");
+ return;
+ }
+ NN_DBG_PRINTF("Freeing wasi-nn");
+ NN_DBG_PRINTF("-> is_initialized: %d", wasi_nn_ctx->is_initialized);
+ NN_DBG_PRINTF("-> current_encoding: %d", wasi_nn_ctx->current_encoding);
+ tensorflowlite_destroy(wasi_nn_ctx->tflite_ctx);
+ wasm_runtime_free(wasi_nn_ctx);
+}
+
+/* Register WASI-NN in WAMR */
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, wasi_nn_##func_name, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_wasi_nn[] = {
+ REG_NATIVE_FUNC(load, "(*ii*)i"),
+ REG_NATIVE_FUNC(init_execution_context, "(i*)i"),
+ REG_NATIVE_FUNC(set_input, "(ii*)i"),
+ REG_NATIVE_FUNC(compute, "(i)i"),
+ REG_NATIVE_FUNC(get_output, "(ii**)i"),
+};
+
+uint32_t
+get_wasi_nn_export_apis(NativeSymbol **p_libc_wasi_apis)
+{
+ *p_libc_wasi_apis = native_symbols_wasi_nn;
+ return sizeof(native_symbols_wasi_nn) / sizeof(NativeSymbol);
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h
new file mode 100644
index 000000000..52d16bd1d
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_PRIVATE_H
+#define WASI_NN_PRIVATE_H
+
+#include "wasi_nn_types.h"
+
+typedef struct {
+ bool is_initialized;
+ graph_encoding current_encoding;
+ void *tflite_ctx;
+} WASINNContext;
+
+/**
+ * @brief Initialize wasi-nn
+ *
+ */
+WASINNContext *
+wasi_nn_initialize();
+/**
+ * @brief Destroy wasi-nn on app exists
+ *
+ */
+
+void
+wasi_nn_destroy(WASINNContext *wasi_nn_ctx);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp
new file mode 100644
index 000000000..dfd21787c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasi_nn.h"
+#include "wasi_nn_tensorflowlite.hpp"
+#include "logger.h"
+
+#include "bh_common.h"
+#include "bh_platform.h"
+#include "platform_common.h"
+
+#include <tensorflow/lite/interpreter.h>
+#include <tensorflow/lite/kernels/register.h>
+#include <tensorflow/lite/model.h>
+#include <tensorflow/lite/optional_debug_tools.h>
+#include <tensorflow/lite/error_reporter.h>
+
+#if defined(WASI_NN_ENABLE_GPU)
+#include <tensorflow/lite/delegates/gpu/delegate.h>
+#endif
+
+#if defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE)
+#include <tensorflow/lite/delegates/external/external_delegate.h>
+#endif
+
+/* Maximum number of graphs per WASM instance */
+#define MAX_GRAPHS_PER_INST 10
+/* Maximum number of graph execution context per WASM instance*/
+#define MAX_GRAPH_EXEC_CONTEXTS_PER_INST 10
+
+typedef struct {
+ std::unique_ptr<tflite::Interpreter> interpreter;
+} Interpreter;
+
+typedef struct {
+ char *model_pointer;
+ std::unique_ptr<tflite::FlatBufferModel> model;
+ execution_target target;
+} Model;
+
+typedef struct {
+ uint32_t current_models;
+ Model models[MAX_GRAPHS_PER_INST];
+ uint32_t current_interpreters;
+ Interpreter interpreters[MAX_GRAPH_EXEC_CONTEXTS_PER_INST];
+ korp_mutex g_lock;
+ TfLiteDelegate *delegate;
+} TFLiteContext;
+
+/* Utils */
+
+static error
+initialize_g(TFLiteContext *tfl_ctx, graph *g)
+{
+ os_mutex_lock(&tfl_ctx->g_lock);
+ if (tfl_ctx->current_models == MAX_GRAPHS_PER_INST) {
+ os_mutex_unlock(&tfl_ctx->g_lock);
+ NN_ERR_PRINTF("Excedded max graphs per WASM instance");
+ return runtime_error;
+ }
+ *g = tfl_ctx->current_models++;
+ os_mutex_unlock(&tfl_ctx->g_lock);
+ return success;
+}
+static error
+initialize_graph_ctx(TFLiteContext *tfl_ctx, graph g,
+ graph_execution_context *ctx)
+{
+ os_mutex_lock(&tfl_ctx->g_lock);
+ if (tfl_ctx->current_interpreters == MAX_GRAPH_EXEC_CONTEXTS_PER_INST) {
+ os_mutex_unlock(&tfl_ctx->g_lock);
+ NN_ERR_PRINTF("Excedded max graph execution context per WASM instance");
+ return runtime_error;
+ }
+ *ctx = tfl_ctx->current_interpreters++;
+ os_mutex_unlock(&tfl_ctx->g_lock);
+ return success;
+}
+
+static error
+is_valid_graph(TFLiteContext *tfl_ctx, graph g)
+{
+ if (g >= MAX_GRAPHS_PER_INST) {
+ NN_ERR_PRINTF("Invalid graph: %d >= %d.", g, MAX_GRAPHS_PER_INST);
+ return runtime_error;
+ }
+ if (tfl_ctx->models[g].model_pointer == NULL) {
+ NN_ERR_PRINTF("Context (model) non-initialized.");
+ return runtime_error;
+ }
+ if (tfl_ctx->models[g].model == NULL) {
+ NN_ERR_PRINTF("Context (tflite model) non-initialized.");
+ return runtime_error;
+ }
+ return success;
+}
+
+static error
+is_valid_graph_execution_context(TFLiteContext *tfl_ctx,
+ graph_execution_context ctx)
+{
+ if (ctx >= MAX_GRAPH_EXEC_CONTEXTS_PER_INST) {
+ NN_ERR_PRINTF("Invalid graph execution context: %d >= %d", ctx,
+ MAX_GRAPH_EXEC_CONTEXTS_PER_INST);
+ return runtime_error;
+ }
+ if (tfl_ctx->interpreters[ctx].interpreter == NULL) {
+ NN_ERR_PRINTF("Context (interpreter) non-initialized.");
+ return runtime_error;
+ }
+ return success;
+}
+
+/* WASI-NN (tensorflow) implementation */
+
+error
+tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
+ graph_encoding encoding, execution_target target, graph *g)
+{
+ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
+
+ if (builder->size != 1) {
+ NN_ERR_PRINTF("Unexpected builder format.");
+ return invalid_argument;
+ }
+
+ if (encoding != tensorflowlite) {
+ NN_ERR_PRINTF("Encoding is not tensorflowlite.");
+ return invalid_argument;
+ }
+
+ if (target != cpu && target != gpu) {
+ NN_ERR_PRINTF("Only CPU and GPU target is supported.");
+ return invalid_argument;
+ }
+
+ error res;
+ if (success != (res = initialize_g(tfl_ctx, g)))
+ return res;
+
+ uint32_t size = builder->buf[0].size;
+
+ // Save model
+ tfl_ctx->models[*g].model_pointer = (char *)wasm_runtime_malloc(size);
+ if (tfl_ctx->models[*g].model_pointer == NULL) {
+ NN_ERR_PRINTF("Error when allocating memory for model.");
+ return missing_memory;
+ }
+
+ bh_memcpy_s(tfl_ctx->models[*g].model_pointer, size, builder->buf[0].buf,
+ size);
+
+ // Save model flatbuffer
+ tfl_ctx->models[*g].model =
+ std::move(tflite::FlatBufferModel::BuildFromBuffer(
+ tfl_ctx->models[*g].model_pointer, size, NULL));
+
+ if (tfl_ctx->models[*g].model == NULL) {
+ NN_ERR_PRINTF("Loading model error.");
+ wasm_runtime_free(tfl_ctx->models[*g].model_pointer);
+ tfl_ctx->models[*g].model_pointer = NULL;
+ return missing_memory;
+ }
+
+ // Save target
+ tfl_ctx->models[*g].target = target;
+ return success;
+}
+
+error
+tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
+ graph_execution_context *ctx)
+{
+ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
+
+ error res;
+ if (success != (res = is_valid_graph(tfl_ctx, g)))
+ return res;
+
+ if (success != (res = initialize_graph_ctx(tfl_ctx, g, ctx)))
+ return res;
+
+ // Build the interpreter with the InterpreterBuilder.
+ tflite::ops::builtin::BuiltinOpResolver resolver;
+ tflite::InterpreterBuilder tflite_builder(*tfl_ctx->models[g].model,
+ resolver);
+ tflite_builder(&tfl_ctx->interpreters[*ctx].interpreter);
+ if (tfl_ctx->interpreters[*ctx].interpreter == NULL) {
+ NN_ERR_PRINTF("Error when generating the interpreter.");
+ return missing_memory;
+ }
+
+ bool use_default = false;
+ switch (tfl_ctx->models[g].target) {
+ case gpu:
+ {
+#if defined(WASI_NN_ENABLE_GPU)
+ NN_WARN_PRINTF("GPU enabled.");
+ // https://www.tensorflow.org/lite/performance/gpu
+ TfLiteGpuDelegateOptionsV2 options =
+ TfLiteGpuDelegateOptionsV2Default();
+ options.inference_preference =
+ TFLITE_GPU_INFERENCE_PREFERENCE_SUSTAINED_SPEED;
+ options.inference_priority1 =
+ TFLITE_GPU_INFERENCE_PRIORITY_MIN_LATENCY;
+ tfl_ctx->delegate = TfLiteGpuDelegateV2Create(&options);
+ if (tfl_ctx->delegate == NULL) {
+ NN_ERR_PRINTF("Error when generating GPU delegate.");
+ use_default = true;
+ return missing_memory;
+ }
+ if (tfl_ctx->interpreters[*ctx]
+ .interpreter->ModifyGraphWithDelegate(tfl_ctx->delegate)
+ != kTfLiteOk) {
+ NN_ERR_PRINTF("Error when enabling GPU delegate.");
+ use_default = true;
+ }
+#elif defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE)
+ NN_WARN_PRINTF("external delegation enabled.");
+ TfLiteExternalDelegateOptions options =
+ TfLiteExternalDelegateOptionsDefault(WASI_NN_EXT_DELEGATE_PATH);
+ tfl_ctx->delegate = TfLiteExternalDelegateCreate(&options);
+ if (tfl_ctx->delegate == NULL) {
+ NN_ERR_PRINTF("Error when generating External delegate.");
+ use_default = true;
+ return missing_memory;
+ }
+ if (tfl_ctx->interpreters[*ctx]
+ .interpreter->ModifyGraphWithDelegate(tfl_ctx->delegate)
+ != kTfLiteOk) {
+ NN_ERR_PRINTF("Error when enabling External delegate.");
+ use_default = true;
+ }
+#else
+ NN_WARN_PRINTF("GPU not enabled.");
+ use_default = true;
+#endif
+ break;
+ }
+ default:
+ use_default = true;
+ }
+ if (use_default)
+ NN_WARN_PRINTF("Default encoding is CPU.");
+
+ tfl_ctx->interpreters[*ctx].interpreter->AllocateTensors();
+ return success;
+}
+
+error
+tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx,
+ uint32_t index, tensor *input_tensor)
+{
+ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
+
+ error res;
+ if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
+ return res;
+
+ uint32_t num_tensors =
+ tfl_ctx->interpreters[ctx].interpreter->inputs().size();
+ NN_DBG_PRINTF("Number of tensors (%d)", num_tensors);
+ if (index + 1 > num_tensors) {
+ return runtime_error;
+ }
+
+ auto tensor = tfl_ctx->interpreters[ctx].interpreter->input_tensor(index);
+ if (tensor == NULL) {
+ NN_ERR_PRINTF("Missing memory");
+ return missing_memory;
+ }
+
+ uint32_t model_tensor_size = 1;
+ for (int i = 0; i < tensor->dims->size; ++i)
+ model_tensor_size *= (uint32_t)tensor->dims->data[i];
+
+ uint32_t input_tensor_size = 1;
+ for (uint32_t i = 0; i < input_tensor->dimensions->size; i++)
+ input_tensor_size *= (uint32_t)input_tensor->dimensions->buf[i];
+
+ if (model_tensor_size != input_tensor_size) {
+ NN_ERR_PRINTF("Input tensor shape from the model is different than the "
+ "one provided");
+ return invalid_argument;
+ }
+
+ auto *input =
+ tfl_ctx->interpreters[ctx].interpreter->typed_input_tensor<float>(
+ index);
+ if (input == NULL)
+ return missing_memory;
+
+ bh_memcpy_s(input, model_tensor_size * sizeof(float), input_tensor->data,
+ model_tensor_size * sizeof(float));
+ return success;
+}
+
+error
+tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx)
+{
+ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
+
+ error res;
+ if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
+ return res;
+
+ tfl_ctx->interpreters[ctx].interpreter->Invoke();
+ return success;
+}
+
+error
+tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx,
+ uint32_t index, tensor_data output_tensor,
+ uint32_t *output_tensor_size)
+{
+ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
+
+ error res;
+ if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
+ return res;
+
+ uint32_t num_output_tensors =
+ tfl_ctx->interpreters[ctx].interpreter->outputs().size();
+ NN_DBG_PRINTF("Number of tensors (%d)", num_output_tensors);
+
+ if (index + 1 > num_output_tensors) {
+ return runtime_error;
+ }
+
+ auto tensor = tfl_ctx->interpreters[ctx].interpreter->output_tensor(index);
+ if (tensor == NULL) {
+ NN_ERR_PRINTF("Missing memory");
+ return missing_memory;
+ }
+
+ uint32_t model_tensor_size = 1;
+ for (int i = 0; i < (int)tensor->dims->size; ++i)
+ model_tensor_size *= (uint32_t)tensor->dims->data[i];
+
+ if (*output_tensor_size < model_tensor_size) {
+ NN_ERR_PRINTF("Insufficient memory to copy tensor %d", index);
+ return missing_memory;
+ }
+
+ float *tensor_f =
+ tfl_ctx->interpreters[ctx].interpreter->typed_output_tensor<float>(
+ index);
+ for (uint32_t i = 0; i < model_tensor_size; ++i)
+ NN_DBG_PRINTF("output: %f", tensor_f[i]);
+
+ *output_tensor_size = model_tensor_size;
+ bh_memcpy_s(output_tensor, model_tensor_size * sizeof(float), tensor_f,
+ model_tensor_size * sizeof(float));
+ return success;
+}
+
+void
+tensorflowlite_initialize(void **tflite_ctx)
+{
+ TFLiteContext *tfl_ctx = new TFLiteContext();
+ if (tfl_ctx == NULL) {
+ NN_ERR_PRINTF("Error when allocating memory for tensorflowlite.");
+ return;
+ }
+
+ NN_DBG_PRINTF("Initializing models.");
+ tfl_ctx->current_models = 0;
+ for (int i = 0; i < MAX_GRAPHS_PER_INST; ++i) {
+ tfl_ctx->models[i].model_pointer = NULL;
+ }
+ NN_DBG_PRINTF("Initializing interpreters.");
+ tfl_ctx->current_interpreters = 0;
+
+ if (os_mutex_init(&tfl_ctx->g_lock) != 0) {
+ NN_ERR_PRINTF("Error while initializing the lock");
+ }
+
+ tfl_ctx->delegate = NULL;
+
+ *tflite_ctx = (void *)tfl_ctx;
+}
+
+void
+tensorflowlite_destroy(void *tflite_ctx)
+{
+ /*
+ TensorFlow Lite memory is internally managed by tensorflow
+
+ Related issues:
+ * https://github.com/tensorflow/tensorflow/issues/15880
+ */
+ TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
+
+ if (tfl_ctx->delegate != NULL) {
+#if defined(WASI_NN_ENABLE_GPU)
+ TfLiteGpuDelegateV2Delete(tfl_ctx->delegate);
+#elif defined(WASI_NN_ENABLE_EXTERNAL_DELEGATE)
+ TfLiteExternalDelegateDelete(tfl_ctx->delegate);
+#endif
+ }
+
+ NN_DBG_PRINTF("Freeing memory.");
+ for (int i = 0; i < MAX_GRAPHS_PER_INST; ++i) {
+ tfl_ctx->models[i].model.reset();
+ if (tfl_ctx->models[i].model_pointer)
+ wasm_runtime_free(tfl_ctx->models[i].model_pointer);
+ tfl_ctx->models[i].model_pointer = NULL;
+ }
+ for (int i = 0; i < MAX_GRAPH_EXEC_CONTEXTS_PER_INST; ++i) {
+ tfl_ctx->interpreters[i].interpreter.reset();
+ }
+ os_mutex_destroy(&tfl_ctx->g_lock);
+ delete tfl_ctx;
+ NN_DBG_PRINTF("Memory free'd.");
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp
new file mode 100644
index 000000000..9605420dd
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_TENSORFLOWLITE_HPP
+#define WASI_NN_TENSORFLOWLITE_HPP
+
+#include "wasi_nn.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+error
+tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
+ graph_encoding encoding, execution_target target, graph *g);
+
+error
+tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
+ graph_execution_context *ctx);
+
+error
+tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx,
+ uint32_t index, tensor *input_tensor);
+
+error
+tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx);
+
+error
+tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx,
+ uint32_t index, tensor_data output_tensor,
+ uint32_t *output_tensor_size);
+
+void
+tensorflowlite_initialize(void **tflite_ctx);
+
+void
+tensorflowlite_destroy(void *tflite_ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/CMakeLists.txt b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/CMakeLists.txt
new file mode 100644
index 000000000..33fad71eb
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/CMakeLists.txt
@@ -0,0 +1,173 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required (VERSION 2.9)
+
+project (iwasm)
+
+set (CMAKE_VERBOSE_MAKEFILE OFF)
+# Reset default linker flags
+set (CMAKE_C_STANDARD 99)
+set (CMAKE_CXX_STANDARD 14)
+set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
+
+if (NOT DEFINED WAMR_BUILD_PLATFORM)
+ set (WAMR_BUILD_PLATFORM "linux")
+endif ()
+
+# Set WAMR_BUILD_TARGET, currently values supported:
+# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]",
+# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]"
+if (NOT DEFINED WAMR_BUILD_TARGET)
+ if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)")
+ set (WAMR_BUILD_TARGET "AARCH64")
+ elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
+ set (WAMR_BUILD_TARGET "RISCV64")
+ elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
+ # Build as X86_64 by default in 64-bit platform
+ set (WAMR_BUILD_TARGET "X86_64")
+ elseif (CMAKE_SIZEOF_VOID_P EQUAL 4)
+ # Build as X86_32 by default in 32-bit platform
+ set (WAMR_BUILD_TARGET "X86_32")
+ else ()
+ message(SEND_ERROR "Unsupported build target platform!")
+ endif ()
+endif ()
+
+if (NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE Release)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_INTERP)
+ # Enable Interpreter by default
+ set (WAMR_BUILD_INTERP 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_AOT)
+ # Enable AOT by default.
+ set (WAMR_BUILD_AOT 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_JIT)
+ # Disable JIT by default.
+ set (WAMR_BUILD_JIT 0)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_FAST_JIT)
+ # Disable Fast JIT by default
+ set (WAMR_BUILD_FAST_JIT 0)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN)
+ # Enable libc builtin support by default
+ set (WAMR_BUILD_LIBC_BUILTIN 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_LIBC_WASI)
+ # Enable libc wasi support by default
+ set (WAMR_BUILD_LIBC_WASI 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_FAST_INTERP)
+ # Enable fast interpreter
+ set (WAMR_BUILD_FAST_INTERP 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_MULTI_MODULE)
+ # Disable multiple modules by default
+ set (WAMR_BUILD_MULTI_MODULE 0)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD)
+ # Disable pthread library by default
+ set (WAMR_BUILD_LIB_PTHREAD 0)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_MINI_LOADER)
+ # Disable wasm mini loader by default
+ set (WAMR_BUILD_MINI_LOADER 0)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_SIMD)
+ # Enable SIMD by default
+ set (WAMR_BUILD_SIMD 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_REF_TYPES)
+ # Disable reference types by default
+ set (WAMR_BUILD_REF_TYPES 0)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP)
+ # Disable Debug feature by default
+ set (WAMR_BUILD_DEBUG_INTERP 0)
+endif ()
+
+if (WAMR_BUILD_DEBUG_INTERP EQUAL 1)
+ set (WAMR_BUILD_FAST_INTERP 0)
+ set (WAMR_BUILD_MINI_LOADER 0)
+ set (WAMR_BUILD_SIMD 0)
+endif ()
+
+set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../..)
+
+include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
+add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
+
+set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -pie -fPIE")
+
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security -Wshadow")
+# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion")
+
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wformat -Wformat-security -Wno-unused")
+
+if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
+ if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register")
+ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mindirect-branch-register")
+ # UNDEFINED BEHAVIOR, refer to https://en.cppreference.com/w/cpp/language/ub
+ if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT WAMR_BUILD_JIT EQUAL 1)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined \
+ -fno-sanitize=bounds,bounds-strict,alignment \
+ -fno-sanitize-recover")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined \
+ -fno-sanitize=bounds,bounds-strict,alignment \
+ -fno-sanitize-recover")
+ endif()
+ else ()
+ # UNDEFINED BEHAVIOR, refer to https://en.cppreference.com/w/cpp/language/ub
+ if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT WAMR_BUILD_JIT EQUAL 1)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined \
+ -fno-sanitize=bounds,alignment \
+ -fno-sanitize-recover")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined \
+ -fno-sanitize=bounds,alignment \
+ -fno-sanitize-recover")
+ endif()
+ endif ()
+endif ()
+
+# The following flags are to enhance security, but it may impact performance,
+# we disable them by default.
+#if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
+# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftrapv -D_FORTIFY_SOURCE=2")
+#endif ()
+#set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4")
+#set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now")
+
+include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
+
+add_executable (iwasm ${WAMR_ROOT_DIR}/product-mini/platforms/${WAMR_BUILD_PLATFORM}/main.c ${UNCOMMON_SHARED_SOURCE})
+
+install (TARGETS iwasm DESTINATION bin)
+
+target_link_libraries (iwasm vmlib ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} ${TENSORFLOW_LIB} -lm -ldl -lpthread)
+
+add_library (libiwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE})
+
+install (TARGETS libiwasm DESTINATION lib)
+
+set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm)
+
+target_link_libraries (libiwasm ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread)
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/build.sh b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/build.sh
new file mode 100755
index 000000000..33879eaf7
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/build.sh
@@ -0,0 +1,21 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+# WASM application that uses WASI-NN
+
+/opt/wasi-sdk/bin/clang \
+ -Wl,--allow-undefined \
+ -Wl,--strip-all,--no-entry \
+ --sysroot=/opt/wasi-sdk/share/wasi-sysroot \
+ -I.. -I../src/utils \
+ -o test_tensorflow.wasm \
+ test_tensorflow.c utils.c
+
+# TFLite models to use in the tests
+
+cd models
+python3 average.py
+python3 max.py
+python3 mult_dimension.py
+python3 mult_outputs.py
+python3 sum.py
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/average.py b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/average.py
new file mode 100755
index 000000000..a21fe7520
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/average.py
@@ -0,0 +1,16 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import tensorflow as tf
+from utils import save_model
+
+model = tf.keras.Sequential([
+ tf.keras.layers.InputLayer(input_shape=[5, 5, 1]),
+ tf.keras.layers.AveragePooling2D(
+ pool_size=(5, 5), strides=None, padding="valid", data_format=None)
+
+])
+
+# Export model to tflite
+
+save_model(model, "average.tflite")
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/max.py b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/max.py
new file mode 100755
index 000000000..a3ec45677
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/max.py
@@ -0,0 +1,17 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import tensorflow as tf
+
+from utils import save_model
+
+model = tf.keras.Sequential([
+ tf.keras.layers.InputLayer(input_shape=[5, 5, 1]),
+ tf.keras.layers.MaxPooling2D(
+ pool_size=(5, 5), strides=None, padding="valid", data_format=None)
+
+])
+
+# Export model to tflite
+
+save_model(model, "max.tflite")
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_dimension.py b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_dimension.py
new file mode 100644
index 000000000..f521a93af
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_dimension.py
@@ -0,0 +1,15 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import tensorflow as tf
+from utils import save_model
+
+model = tf.keras.Sequential([
+ tf.keras.layers.InputLayer(input_shape=[3, 3, 1]),
+ tf.keras.layers.Conv2D(1, (1, 1), kernel_initializer=tf.keras.initializers.Constant(
+ value=1), bias_initializer='zeros'
+ )
+])
+# Export model to tflite
+
+save_model(model, "mult_dim.tflite")
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_outputs.py b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_outputs.py
new file mode 100755
index 000000000..98a50129c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/mult_outputs.py
@@ -0,0 +1,33 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import tensorflow as tf
+import numpy as np
+from keras.layers import AveragePooling2D, Conv2D
+
+from tensorflow.keras import Input, Model
+
+from utils import save_model
+
+
+inputs = Input(shape=(4, 4, 1))
+
+output1 = Conv2D(1, (4, 1), kernel_initializer=tf.keras.initializers.Constant(
+ value=1), bias_initializer='zeros'
+)(inputs)
+output2 = AveragePooling2D(pool_size=(
+ 4, 1), strides=None, padding="valid", data_format=None)(inputs)
+
+model = Model(inputs=inputs, outputs=[output1, output2])
+
+inp = np.arange(16).reshape((1, 4, 4, 1))
+
+print(inp)
+
+res = model.predict(inp)
+
+print(res)
+print(res[0].shape)
+print(res[1].shape)
+
+save_model(model, "mult_out.tflite")
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/sum.py b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/sum.py
new file mode 100755
index 000000000..503125b34
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/sum.py
@@ -0,0 +1,17 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import tensorflow as tf
+
+from utils import save_model
+
+model = tf.keras.Sequential([
+ tf.keras.layers.InputLayer(input_shape=[5, 5, 1]),
+ tf.keras.layers.Conv2D(1, (5, 5), kernel_initializer=tf.keras.initializers.Constant(
+ value=1), bias_initializer='zeros'
+ )
+])
+
+# Export model to tflite
+
+save_model(model, "sum.tflite")
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/utils.py b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/utils.py
new file mode 100644
index 000000000..8335f05da
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/models/utils.py
@@ -0,0 +1,13 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+import tensorflow as tf
+import pathlib
+
+
+def save_model(model, filename):
+ converter = tf.lite.TFLiteConverter.from_keras_model(model)
+ tflite_model = converter.convert()
+ tflite_models_dir = pathlib.Path("./")
+ tflite_model_file = tflite_models_dir/filename
+ tflite_model_file.write_bytes(tflite_model)
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/requirements.txt b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/requirements.txt
new file mode 100644
index 000000000..4cf2910db
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/requirements.txt
@@ -0,0 +1 @@
+tensorflow==2.11.1 \ No newline at end of file
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/test_tensorflow.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/test_tensorflow.c
new file mode 100644
index 000000000..2fa516538
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/test_tensorflow.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+
+#include "utils.h"
+#include "logger.h"
+
+void
+test_sum(execution_target target)
+{
+ int dims[] = { 1, 5, 5, 1 };
+ input_info input = create_input(dims);
+
+ uint32_t output_size = 0;
+ float *output = run_inference(target, input.input_tensor, input.dim,
+ &output_size, "/assets/models/sum.tflite", 1);
+
+ assert(output_size == 1);
+ assert(fabs(output[0] - 300.0) < EPSILON);
+
+ free(input.dim);
+ free(input.input_tensor);
+ free(output);
+}
+
+void
+test_max(execution_target target)
+{
+ int dims[] = { 1, 5, 5, 1 };
+ input_info input = create_input(dims);
+
+ uint32_t output_size = 0;
+ float *output = run_inference(target, input.input_tensor, input.dim,
+ &output_size, "/assets/models/max.tflite", 1);
+
+ assert(output_size == 1);
+ assert(fabs(output[0] - 24.0) < EPSILON);
+ NN_INFO_PRINTF("Result: max is %f", output[0]);
+
+ free(input.dim);
+ free(input.input_tensor);
+ free(output);
+}
+
+void
+test_average(execution_target target)
+{
+ int dims[] = { 1, 5, 5, 1 };
+ input_info input = create_input(dims);
+
+ uint32_t output_size = 0;
+ float *output =
+ run_inference(target, input.input_tensor, input.dim, &output_size,
+ "/assets/models/average.tflite", 1);
+
+ assert(output_size == 1);
+ assert(fabs(output[0] - 12.0) < EPSILON);
+ NN_INFO_PRINTF("Result: average is %f", output[0]);
+
+ free(input.dim);
+ free(input.input_tensor);
+ free(output);
+}
+
+void
+test_mult_dimensions(execution_target target)
+{
+ int dims[] = { 1, 3, 3, 1 };
+ input_info input = create_input(dims);
+
+ uint32_t output_size = 0;
+ float *output =
+ run_inference(target, input.input_tensor, input.dim, &output_size,
+ "/assets/models/mult_dim.tflite", 1);
+
+ assert(output_size == 9);
+ for (int i = 0; i < 9; i++)
+ assert(fabs(output[i] - i) < EPSILON);
+
+ free(input.dim);
+ free(input.input_tensor);
+ free(output);
+}
+
+void
+test_mult_outputs(execution_target target)
+{
+ int dims[] = { 1, 4, 4, 1 };
+ input_info input = create_input(dims);
+
+ uint32_t output_size = 0;
+ float *output =
+ run_inference(target, input.input_tensor, input.dim, &output_size,
+ "/assets/models/mult_out.tflite", 2);
+
+ assert(output_size == 8);
+ // first tensor check
+ for (int i = 0; i < 4; i++)
+ assert(fabs(output[i] - (i * 4 + 24)) < EPSILON);
+ // second tensor check
+ for (int i = 0; i < 4; i++)
+ assert(fabs(output[i + 4] - (i + 6)) < EPSILON);
+
+ free(input.dim);
+ free(input.input_tensor);
+ free(output);
+}
+
+int
+main()
+{
+ char *env = getenv("TARGET");
+ if (env == NULL) {
+ NN_INFO_PRINTF("Usage:\n--env=\"TARGET=[cpu|gpu]\"");
+ return 1;
+ }
+ execution_target target;
+ if (strcmp(env, "cpu") == 0)
+ target = cpu;
+ else if (strcmp(env, "gpu") == 0)
+ target = gpu;
+ else {
+ NN_ERR_PRINTF("Wrong target!");
+ return 1;
+ }
+ NN_INFO_PRINTF("################### Testing sum...");
+ test_sum(target);
+ NN_INFO_PRINTF("################### Testing max...");
+ test_max(target);
+ NN_INFO_PRINTF("################### Testing average...");
+ test_average(target);
+ NN_INFO_PRINTF("################### Testing multiple dimensions...");
+ test_mult_dimensions(target);
+ NN_INFO_PRINTF("################### Testing multiple outputs...");
+ test_mult_outputs(target);
+
+ NN_INFO_PRINTF("Tests: passed!");
+ return 0;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.c
new file mode 100644
index 000000000..e0704cab4
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "utils.h"
+#include "logger.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+error
+wasm_load(char *model_name, graph *g, execution_target target)
+{
+ FILE *pFile = fopen(model_name, "r");
+ if (pFile == NULL)
+ return invalid_argument;
+
+ uint8_t *buffer;
+ size_t result;
+
+ // allocate memory to contain the whole file:
+ buffer = (uint8_t *)malloc(sizeof(uint8_t) * MAX_MODEL_SIZE);
+ if (buffer == NULL) {
+ fclose(pFile);
+ return missing_memory;
+ }
+
+ result = fread(buffer, 1, MAX_MODEL_SIZE, pFile);
+ if (result <= 0) {
+ fclose(pFile);
+ free(buffer);
+ return missing_memory;
+ }
+
+ graph_builder_array arr;
+
+ arr.size = 1;
+ arr.buf = (graph_builder *)malloc(sizeof(graph_builder));
+ if (arr.buf == NULL) {
+ fclose(pFile);
+ free(buffer);
+ return missing_memory;
+ }
+
+ arr.buf[0].size = result;
+ arr.buf[0].buf = buffer;
+
+ error res = load(&arr, tensorflowlite, target, g);
+
+ fclose(pFile);
+ free(buffer);
+ free(arr.buf);
+ return res;
+}
+
+error
+wasm_init_execution_context(graph g, graph_execution_context *ctx)
+{
+ return init_execution_context(g, ctx);
+}
+
+error
+wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim)
+{
+ tensor_dimensions dims;
+ dims.size = INPUT_TENSOR_DIMS;
+ dims.buf = (uint32_t *)malloc(dims.size * sizeof(uint32_t));
+ if (dims.buf == NULL)
+ return missing_memory;
+
+ tensor tensor;
+ tensor.dimensions = &dims;
+ for (int i = 0; i < tensor.dimensions->size; ++i)
+ tensor.dimensions->buf[i] = dim[i];
+ tensor.type = fp32;
+ tensor.data = (uint8_t *)input_tensor;
+ error err = set_input(ctx, 0, &tensor);
+
+ free(dims.buf);
+ return err;
+}
+
+error
+wasm_compute(graph_execution_context ctx)
+{
+ return compute(ctx);
+}
+
+error
+wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor,
+ uint32_t *out_size)
+{
+ return get_output(ctx, index, (uint8_t *)out_tensor, out_size);
+}
+
+float *
+run_inference(execution_target target, float *input, uint32_t *input_size,
+ uint32_t *output_size, char *model_name,
+ uint32_t num_output_tensors)
+{
+ graph graph;
+ if (wasm_load(model_name, &graph, target) != success) {
+ NN_ERR_PRINTF("Error when loading model.");
+ exit(1);
+ }
+
+ graph_execution_context ctx;
+ if (wasm_init_execution_context(graph, &ctx) != success) {
+ NN_ERR_PRINTF("Error when initialixing execution context.");
+ exit(1);
+ }
+
+ if (wasm_set_input(ctx, input, input_size) != success) {
+ NN_ERR_PRINTF("Error when setting input tensor.");
+ exit(1);
+ }
+
+ if (wasm_compute(ctx) != success) {
+ NN_ERR_PRINTF("Error when running inference.");
+ exit(1);
+ }
+
+ float *out_tensor = (float *)malloc(sizeof(float) * MAX_OUTPUT_TENSOR_SIZE);
+ if (out_tensor == NULL) {
+ NN_ERR_PRINTF("Error when allocating memory for output tensor.");
+ exit(1);
+ }
+
+ uint32_t offset = 0;
+ for (int i = 0; i < num_output_tensors; ++i) {
+ *output_size = MAX_OUTPUT_TENSOR_SIZE - *output_size;
+ if (wasm_get_output(ctx, i, &out_tensor[offset], output_size)
+ != success) {
+ NN_ERR_PRINTF("Error when getting output.");
+ exit(1);
+ }
+
+ offset += *output_size;
+ }
+ *output_size = offset;
+ return out_tensor;
+}
+
+input_info
+create_input(int *dims)
+{
+ input_info input = { .dim = NULL, .input_tensor = NULL, .elements = 1 };
+
+ input.dim = malloc(INPUT_TENSOR_DIMS * sizeof(uint32_t));
+ if (input.dim)
+ for (int i = 0; i < INPUT_TENSOR_DIMS; ++i) {
+ input.dim[i] = dims[i];
+ input.elements *= dims[i];
+ }
+
+ input.input_tensor = malloc(input.elements * sizeof(float));
+ for (int i = 0; i < input.elements; ++i)
+ input.input_tensor[i] = i;
+
+ return input;
+}
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.h
new file mode 100644
index 000000000..6373be542
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/test/utils.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_UTILS
+#define WASI_NN_UTILS
+
+#include <stdint.h>
+
+#include "wasi_nn.h"
+
+#define MAX_MODEL_SIZE 85000000
+#define MAX_OUTPUT_TENSOR_SIZE 200
+#define INPUT_TENSOR_DIMS 4
+#define EPSILON 1e-8
+
+typedef struct {
+ float *input_tensor;
+ uint32_t *dim;
+ uint32_t elements;
+} input_info;
+
+/* wasi-nn wrappers */
+
+error
+wasm_load(char *model_name, graph *g, execution_target target);
+
+error
+wasm_init_execution_context(graph g, graph_execution_context *ctx);
+
+error
+wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim);
+
+error
+wasm_compute(graph_execution_context ctx);
+
+error
+wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor,
+ uint32_t *out_size);
+
+/* Utils */
+
+float *
+run_inference(execution_target target, float *input, uint32_t *input_size,
+ uint32_t *output_size, char *model_name,
+ uint32_t num_output_tensors);
+
+input_info
+create_input(int *dims);
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.cmake b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.cmake
new file mode 100644
index 000000000..019782c2e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.cmake
@@ -0,0 +1,22 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
+
+# Find tensorflow-lite
+find_package(tensorflow_lite REQUIRED)
+
+set (WASI_NN_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+include_directories (${WASI_NN_DIR})
+include_directories (${WASI_NN_DIR}/src)
+include_directories (${WASI_NN_DIR}/src/utils)
+
+set (
+ LIBC_WASI_NN_SOURCE
+ ${WASI_NN_DIR}/src/wasi_nn.c
+ ${WASI_NN_DIR}/src/wasi_nn_tensorflowlite.cpp
+ ${WASI_NN_DIR}/src/utils/wasi_nn_app_native.c
+)
+
+set (TENSORFLOW_LIB tensorflow-lite)
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.h
new file mode 100644
index 000000000..2bf0a192c
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+/**
+ * Following definition from:
+ * [Oct 25th, 2022]
+ * https://github.com/WebAssembly/wasi-nn/blob/0f77c48ec195748990ff67928a4b3eef5f16c2de/wasi-nn.wit.md
+ */
+
+#ifndef WASI_NN_H
+#define WASI_NN_H
+
+#include <stdint.h>
+#include "wasi_nn_types.h"
+
+/**
+ * @brief Load an opaque sequence of bytes to use for inference.
+ *
+ * @param builder Model builder.
+ * @param encoding Model encoding.
+ * @param target Execution target.
+ * @param g Graph.
+ * @return error Execution status.
+ */
+error
+load(graph_builder_array *builder, graph_encoding encoding,
+ execution_target target, graph *g)
+ __attribute__((import_module("wasi_nn")));
+
+/**
+ * INFERENCE
+ *
+ */
+
+// Bind a `graph` to the input and output tensors for an inference.
+typedef uint32_t graph_execution_context;
+
+/**
+ * @brief Create an execution instance of a loaded graph.
+ *
+ * @param g Graph.
+ * @param ctx Execution context.
+ * @return error Execution status.
+ */
+error
+init_execution_context(graph g, graph_execution_context *ctx)
+ __attribute__((import_module("wasi_nn")));
+
+/**
+ * @brief Define the inputs to use for inference.
+ *
+ * @param ctx Execution context.
+ * @param index Input tensor index.
+ * @param tensor Input tensor.
+ * @return error Execution status.
+ */
+error
+set_input(graph_execution_context ctx, uint32_t index, tensor *tensor)
+ __attribute__((import_module("wasi_nn")));
+
+/**
+ * @brief Compute the inference on the given inputs.
+ *
+ * @param ctx Execution context.
+ * @return error Execution status.
+ */
+error
+compute(graph_execution_context ctx) __attribute__((import_module("wasi_nn")));
+
+/**
+ * @brief Extract the outputs after inference.
+ *
+ * @param ctx Execution context.
+ * @param index Output tensor index.
+ * @param output_tensor Buffer where output tensor with index `index` is
+ * copied.
+ * @param output_tensor_size Pointer to `output_tensor` maximum size.
+ * After the function call it is updated with the
+ * copied number of bytes.
+ * @return error Execution status.
+ */
+error
+get_output(graph_execution_context ctx, uint32_t index,
+ tensor_data output_tensor, uint32_t *output_tensor_size)
+ __attribute__((import_module("wasi_nn")));
+
+#endif
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn_types.h b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn_types.h
new file mode 100644
index 000000000..a2cebe49e
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/libraries/wasi-nn/wasi_nn_types.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_TYPES_H
+#define WASI_NN_TYPES_H
+
+/**
+ * ERRORS
+ *
+ */
+
+// Error codes returned by functions in this API.
+typedef enum {
+ // No error occurred.
+ success = 0,
+ // Caller module passed an invalid argument.
+ invalid_argument,
+ // Invalid encoding.
+ invalid_encoding,
+ // Caller module is missing a memory export.
+ missing_memory,
+ // Device or resource busy.
+ busy,
+ // Runtime Error.
+ runtime_error,
+} error;
+
+/**
+ * TENSOR
+ *
+ */
+
+// The dimensions of a tensor.
+//
+// The array length matches the tensor rank and each element in the array
+// describes the size of each dimension.
+typedef struct {
+ uint32_t *buf;
+ uint32_t size;
+} tensor_dimensions;
+
+// The type of the elements in a tensor.
+typedef enum { fp16 = 0, fp32, up8, ip32 } tensor_type;
+
+// The tensor data.
+//
+// Initially conceived as a sparse representation, each empty cell would be
+// filled with zeros and the array length must match the product of all of the
+// dimensions and the number of bytes in the type (e.g., a 2x2 tensor with
+// 4-byte f32 elements would have a data array of length 16). Naturally, this
+// representation requires some knowledge of how to lay out data in
+// memory--e.g., using row-major ordering--and could perhaps be improved.
+typedef uint8_t *tensor_data;
+
+// A tensor.
+typedef struct {
+ // Describe the size of the tensor (e.g., 2x2x2x2 -> [2, 2, 2, 2]). To
+ // represent a tensor containing a single value, use `[1]` for the tensor
+ // dimensions.
+ tensor_dimensions *dimensions;
+ // Describe the type of element in the tensor (e.g., f32).
+ tensor_type type;
+ // Contains the tensor data.
+ tensor_data data;
+} tensor;
+
+/**
+ * GRAPH
+ *
+ */
+
+// The graph initialization data.
+//
+// This consists of an array of buffers because implementing backends may encode
+// their graph IR in parts (e.g., OpenVINO stores its IR and weights
+// separately).
+typedef struct {
+ uint8_t *buf;
+ uint32_t size;
+} graph_builder;
+
+typedef struct {
+ graph_builder *buf;
+ uint32_t size;
+} graph_builder_array;
+
+// An execution graph for performing inference (i.e., a model).
+typedef uint32_t graph;
+
+// Describes the encoding of the graph. This allows the API to be implemented by
+// various backends that encode (i.e., serialize) their graph IR with different
+// formats.
+typedef enum {
+ openvino = 0,
+ onnx,
+ tensorflow,
+ pytorch,
+ tensorflowlite
+} graph_encoding;
+
+// Define where the graph should be executed.
+typedef enum execution_target { cpu = 0, gpu, tpu } execution_target;
+
+#endif