summaryrefslogtreecommitdiffstats
path: root/fluent-bit/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'fluent-bit/src/wasm')
-rw-r--r--fluent-bit/src/wasm/CMakeLists.txt111
-rw-r--r--fluent-bit/src/wasm/flb_wasm.c316
2 files changed, 427 insertions, 0 deletions
diff --git a/fluent-bit/src/wasm/CMakeLists.txt b/fluent-bit/src/wasm/CMakeLists.txt
new file mode 100644
index 00000000..b345c4b4
--- /dev/null
+++ b/fluent-bit/src/wasm/CMakeLists.txt
@@ -0,0 +1,111 @@
+string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
+if (FLB_SYSTEM_WINDOWS)
+ enable_language(ASM_MASM)
+endif()
+if (APPLE)
+ add_definitions(-DBH_PLATFORM_DARWIN)
+endif ()
+
+set (CMAKE_C_STANDARD 99)
+
+if (FLB_SYSTEM_WINDOWS)
+ add_definitions(-DCOMPILING_WASM_RUNTIME_API=1)
+endif ()
+
+# WAMR features switch
+
+# 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")
+ if (FLB_SYSTEM_MACOS)
+ message(STATUS "macOS arm64 platform is poor support for AOT loading. Now disabling for it.")
+ set (WAMR_DISABLE_AOT_LOADING 1)
+ FLB_DEFINITION(FLB_WAMR_DISABLE_AOT_LOADING)
+ endif ()
+ # For raspbian/buster: armv6l-unknown-linux-gnueabihf
+ elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv6.*|armv7.*)")
+ set (WAMR_BUILD_TARGET "ARM")
+ 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 ()
+
+set (WAMR_BUILD_MINI_LOADER 0)
+set (WAMR_BUILD_INTERP 1)
+set (WAMR_BUILD_FAST_INTERP 1)
+if (NOT DEFINED WAMR_DISABLE_AOT_LOADING)
+ set (WAMR_BUILD_AOT 1)
+endif ()
+set (WAMR_BUILD_JIT 0)
+set (WAMR_BUILD_LIBC_BUILTIN 1)
+if (MSVC)
+ # Currently, LIBC_UVWASI build is disabled.
+ # FIXME: Need to investigate how to build libuv and uvwasi without fetching repos.
+ set (WAMR_BUILD_LIBC_UVWASI 0)
+else ()
+ set (WAMR_BUILD_LIBC_WASI 1)
+endif ()
+if (NOT MSVC)
+ set (WAMR_BUILD_LIB_PTHREAD 1)
+endif ()
+set (WAMR_BUILD_REF_TYPES 0)
+
+if (NOT MSVC)
+ # linker flags
+ set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie -fPIE")
+ if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
+ set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
+ endif ()
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wformat -Wformat-security")
+ 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"))
+ check_c_compiler_flag(-mindirect-branch-register FLB_WASM_INDIRECT_BRANCH_REGISTER_SUPPORTED)
+ if (FLB_WASM_INDIRECT_BRANCH_REGISTER_SUPPORTED)
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register")
+ endif ()
+ endif ()
+ endif ()
+endif ()
+
+set (WAMR_BUILD_SIMD 0)
+set (WAMR_ROOT_DIR ../../${FLB_PATH_LIB_WASM_MICRO_RUNTIME})
+
+# build out vmlib-static
+include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
+add_library(vmlib-static STATIC ${WAMR_RUNTIME_LIB_SOURCE})
+
+# Application related
+include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
+
+set(src
+ flb_wasm.c
+ ${UNCOMMON_SHARED_SOURCE}) # link wasm-micro-runtime's uncommon object symbols (for bh_read_file_to_buffer)
+
+add_library(flb-wasm-static STATIC ${src})
+
+if (FLB_JEMALLOC AND ${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ set(${JEMALLOC_LIBS} libjemalloc)
+ add_dependencies(flb-wasm-static libjemalloc)
+ include_directories("${CMAKE_BINARY_DIR}/include/")
+endif ()
+
+if (WAMR_BUILD_LIBC_UVWASI)
+ target_link_libraries(flb-wasm-static vmlib-static ${UV_A_LIBS})
+else ()
+ target_link_libraries(flb-wasm-static vmlib-static ${JEMALLOC_LIBS})
+endif()
diff --git a/fluent-bit/src/wasm/flb_wasm.c b/fluent-bit/src/wasm/flb_wasm.c
new file mode 100644
index 00000000..2f75c9bb
--- /dev/null
+++ b/fluent-bit/src/wasm/flb_wasm.c
@@ -0,0 +1,316 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2015-2022 The Fluent Bit Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Don't use and expose bh_ prefixed headers in flb_wasm.h.
+ Their definitions are tightly coupled in wasm-micro-runtime library. */
+#include "bh_read_file.h"
+#include "bh_getopt.h"
+
+#include <fluent-bit/flb_info.h>
+#include <fluent-bit/flb_mem.h>
+#include <fluent-bit/flb_log.h>
+#include <fluent-bit/flb_slist.h>
+#include <fluent-bit/wasm/flb_wasm.h>
+
+#ifdef FLB_SYSTEM_WINDOWS
+#define STDIN_FILENO (_fileno( stdin ))
+#define STDOUT_FILENO (_fileno( stdout ))
+#define STDERR_FILENO (_fileno( stderr ))
+#else
+#include <unistd.h>
+#endif
+
+void flb_wasm_init(struct flb_config *config)
+{
+ mk_list_init(&config->wasm_list);
+}
+
+static int flb_wasm_load_wasm_binary(const char *wasm_path, int8_t **out_buf, uint32_t *out_size)
+{
+ char *buffer;
+ uint32_t buf_size;
+ buffer = bh_read_file_to_buffer(wasm_path, &buf_size);
+ if (!buffer) {
+ flb_error("Open wasm file [%s] failed.", wasm_path);
+ goto error;
+ }
+
+#if defined(FLB_WAMR_DISABLE_AOT_LOADING)
+ if ((get_package_type((const uint8_t *)buffer, buf_size) != Wasm_Module_Bytecode)) {
+ flb_error("WASM bytecode is expected but other file format");
+ goto error;
+ }
+#else
+ if ((get_package_type((const uint8_t *)buffer, buf_size) != Wasm_Module_Bytecode) &&
+ (get_package_type((const uint8_t *)buffer, buf_size) != Wasm_Module_AoT)) {
+ flb_error("WASM bytecode or AOT object is expected but other file format");
+ goto error;
+ }
+#endif
+
+ *out_buf = buffer;
+ *out_size = buf_size;
+
+ return buffer != NULL;
+
+error:
+ if (buffer != NULL) {
+ BH_FREE(buffer);
+ }
+
+ return FLB_FALSE;
+}
+
+struct flb_wasm *flb_wasm_instantiate(struct flb_config *config, const char *wasm_path,
+ struct mk_list *accessible_dir_list,
+ int stdinfd, int stdoutfd, int stderrfd)
+{
+ struct flb_wasm *fw;
+ uint32_t buf_size, stack_size = 8 * 1024, heap_size = 8 * 1024;
+ int8_t *buffer = NULL;
+ char error_buf[128];
+#if WASM_ENABLE_LIBC_WASI != 0
+ struct mk_list *head;
+ struct flb_slist_entry *wasi_dir;
+ const size_t accessible_dir_list_size = mk_list_size(accessible_dir_list);
+ const char **wasi_dir_list = NULL;
+ size_t dir_index = 0;
+#endif
+
+ wasm_module_t module = NULL;
+ wasm_module_inst_t module_inst = NULL;
+ wasm_exec_env_t exec_env = NULL;
+
+ RuntimeInitArgs wasm_args;
+
+ fw = flb_malloc(sizeof(struct flb_wasm));
+ if (!fw) {
+ flb_errno();
+ return NULL;
+ }
+ fw->tag_buffer = 0;
+ fw->record_buffer = 0;
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ wasi_dir_list = flb_malloc(sizeof(char *) * accessible_dir_list_size);
+ if (!wasi_dir_list) {
+ flb_errno();
+ flb_free(fw);
+ return NULL;
+ }
+ mk_list_foreach(head, accessible_dir_list) {
+ wasi_dir = mk_list_entry(head, struct flb_slist_entry, _head);
+ wasi_dir_list[dir_index] = wasi_dir->str;
+ dir_index++;
+ }
+#endif
+
+ fw->config = config;
+
+ memset(&wasm_args, 0, sizeof(RuntimeInitArgs));
+
+ wasm_args.mem_alloc_type = Alloc_With_Allocator;
+ wasm_args.mem_alloc_option.allocator.malloc_func = flb_malloc;
+ wasm_args.mem_alloc_option.allocator.realloc_func = flb_realloc;
+ wasm_args.mem_alloc_option.allocator.free_func = flb_free;
+
+ if (!wasm_runtime_full_init(&wasm_args)) {
+ flb_error("Init runtime environment failed.");
+ return NULL;
+ }
+
+ if(!flb_wasm_load_wasm_binary(wasm_path, &buffer, &buf_size)) {
+ goto error;
+ }
+
+ module = wasm_runtime_load((uint8_t *)buffer, buf_size, error_buf, sizeof(error_buf));
+ if (!module) {
+ flb_error("Load wasm module failed. error: %s", error_buf);
+ goto error;
+ }
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ wasm_runtime_set_wasi_args_ex(module, wasi_dir_list, accessible_dir_list_size, NULL, 0,
+ NULL, 0, NULL, 0,
+ (stdinfd != -1) ? stdinfd : STDIN_FILENO,
+ (stdoutfd != -1) ? stdoutfd : STDOUT_FILENO,
+ (stderrfd != -1) ? stderrfd : STDERR_FILENO);
+#endif
+
+ module_inst = wasm_runtime_instantiate(module, stack_size, heap_size,
+ error_buf, sizeof(error_buf));
+ if (!module_inst) {
+ flb_error("Instantiate wasm module failed. error: %s", error_buf);
+ goto error;
+ }
+
+ exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);
+ if (!exec_env) {
+ flb_error("Create wasm execution environment failed.");
+ goto error;
+ }
+
+ fw->buffer = buffer;
+ fw->module = module;
+ fw->module_inst = module_inst;
+ fw->exec_env = exec_env;
+
+ mk_list_add(&fw->_head, &config->wasm_list);
+
+#if WASM_ENABLE_LIBC_WASI != 0
+ flb_free(wasi_dir_list);
+#endif
+
+ return fw;
+
+error:
+#if WASM_ENABLE_LIBC_WASI != 0
+ if (wasi_dir_list != NULL) {
+ flb_free(wasi_dir_list);
+ }
+#endif
+ if (exec_env) {
+ wasm_runtime_destroy_exec_env(exec_env);
+ }
+ if (module_inst) {
+ wasm_runtime_deinstantiate(module_inst);
+ }
+ if (module) {
+ wasm_runtime_unload(module);
+ }
+ if (buffer != NULL) {
+ BH_FREE(buffer);
+ }
+ if (fw != NULL) {
+ flb_free(fw);
+ }
+
+ wasm_runtime_destroy();
+
+ return NULL;
+}
+
+char *flb_wasm_call_function_format_json(struct flb_wasm *fw, const char *function_name,
+ const char* tag_data, size_t tag_len,
+ struct flb_time t,
+ const char* record_data, size_t record_len)
+{
+ const char *exception;
+ uint8_t *func_result;
+ wasm_function_inst_t func = NULL;
+ /* We should pass the length that is null terminator included into
+ * WASM runtime. This is why we add +1 for tag_len and record_len.
+ */
+ fw->tag_buffer = wasm_runtime_module_dup_data(fw->module_inst, tag_data, tag_len+1);
+ fw->record_buffer = wasm_runtime_module_dup_data(fw->module_inst, record_data, record_len+1);
+ uint32_t func_args[6] = {fw->tag_buffer, tag_len,
+ t.tm.tv_sec, t.tm.tv_nsec,
+ fw->record_buffer, record_len};
+ size_t args_size = sizeof(func_args) / sizeof(uint32_t);
+
+ if (!(func = wasm_runtime_lookup_function(fw->module_inst, function_name, NULL))) {
+ flb_error("The %s wasm function is not found.", function_name);
+ return NULL;
+ }
+
+ if (!wasm_runtime_call_wasm(fw->exec_env, func, args_size, func_args)) {
+ exception = wasm_runtime_get_exception(fw->module_inst);
+ flb_error("Got exception running wasm code: %s", exception);
+ wasm_runtime_clear_exception(fw->module_inst);
+ return NULL;
+ }
+
+ // The return value is stored in the first element of the function argument array.
+ // It's a WASM pointer to null-terminated c char string.
+ // WAMR allows us to map WASM pointers to native pointers.
+ if (!wasm_runtime_validate_app_str_addr(fw->module_inst, func_args[0])) {
+ flb_warn("[wasm] returned value is invalid");
+ return NULL;
+ }
+ func_result = wasm_runtime_addr_app_to_native(fw->module_inst, func_args[0]);
+
+ if (func_result == NULL) {
+ return NULL;
+ }
+
+ return (char *)flb_strdup(func_result);
+}
+
+int flb_wasm_call_wasi_main(struct flb_wasm *fw)
+{
+#if WASM_ENABLE_LIBC_WASI != 0
+ wasm_function_inst_t func = NULL;
+
+ if (!(func = wasm_runtime_lookup_wasi_start_function(fw->module_inst))) {
+ flb_error("The wasi mode main function is not found.");
+ return -1;
+ }
+
+ return wasm_runtime_call_wasm(fw->exec_env, func, 0, NULL);
+#else
+ return -1;
+#endif
+}
+
+void flb_wasm_buffer_free(struct flb_wasm *fw)
+{
+ if (fw->tag_buffer != 0) {
+ wasm_runtime_module_free(fw->module_inst, fw->tag_buffer);
+ }
+ if (fw->record_buffer != 0) {
+ wasm_runtime_module_free(fw->module_inst, fw->record_buffer);
+ }
+}
+
+void flb_wasm_destroy(struct flb_wasm *fw)
+{
+ if (fw->exec_env) {
+ wasm_runtime_destroy_exec_env(fw->exec_env);
+ }
+ if (fw->module_inst) {
+ flb_wasm_buffer_free(fw);
+ wasm_runtime_deinstantiate(fw->module_inst);
+ }
+ if (fw->module) {
+ wasm_runtime_unload(fw->module);
+ }
+ if (fw->buffer) {
+ BH_FREE(fw->buffer);
+ }
+ wasm_runtime_destroy();
+
+ mk_list_del(&fw->_head);
+ flb_free(fw);
+}
+
+int flb_wasm_destroy_all(struct flb_config *ctx)
+{
+ int c = 0;
+ struct mk_list *tmp;
+ struct mk_list *head;
+ struct flb_wasm *fw;
+
+ mk_list_foreach_safe(head, tmp, &ctx->wasm_list) {
+ fw = mk_list_entry(head, struct flb_wasm, _head);
+ flb_wasm_destroy(fw);
+ c++;
+ }
+
+ return c;
+}