Skip to content

Commit

Permalink
wamr handler
Browse files Browse the repository at this point in the history
Signed-off-by: Maciej <[email protected]>

wamr is working!

Signed-off-by: Maciej <[email protected]>

cleanup the code

Signed-off-by: Maciej <[email protected]>

clang-format

Signed-off-by: Maciej <[email protected]>

remove unnecessary functions load

Signed-off-by: Maciej <[email protected]>

Signed-off-by: Maciej <[email protected]>
  • Loading branch information
Maciej committed Jul 23, 2024
1 parent 1623f53 commit 3161616
Show file tree
Hide file tree
Showing 4 changed files with 260 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ libcrun_SOURCES = src/libcrun/utils.c \
src/libcrun/handlers/wasmedge.c \
src/libcrun/handlers/wasmer.c \
src/libcrun/handlers/wasmtime.c \
src/libcrun/handlers/wamr.c \
src/libcrun/intelrdt.c \
src/libcrun/io_priority.c \
src/libcrun/linux.c \
Expand Down
4 changes: 4 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ dnl include support for wasmedge (EXPERIMENTAL)
AC_ARG_WITH([wasmedge], AS_HELP_STRING([--with-wasmedge], [build with WasmEdge support]))
AS_IF([test "x$with_wasmedge" = "xyes"], AC_CHECK_HEADERS([wasmedge/wasmedge.h], AC_DEFINE([HAVE_WASMEDGE], 1, [Define if WasmEdge is available]), [AC_MSG_ERROR([*** Missing wasmedge headers])]))

dnl include support for wamr (EXPERIMENTAL)
AC_ARG_WITH([wamr], AS_HELP_STRING([--with-wamr], [build with WAMR support]))
AS_IF([test "x$with_wamr" = "xyes"], AC_CHECK_HEADERS([wasm_export.h], AC_DEFINE([HAVE_WAMR], 1, [Define if WAMR is available]), [AC_MSG_ERROR([*** Missing WAMR headers])]))

dnl include support for libkrun (EXPERIMENTAL)
AC_ARG_WITH([libkrun], AS_HELP_STRING([--with-libkrun], [build with libkrun support]))
AS_IF([test "x$with_libkrun" = "xyes"], AC_CHECK_HEADERS([libkrun.h], AC_DEFINE([HAVE_LIBKRUN], 1, [Define if libkrun is available]), [AC_MSG_ERROR([*** Missing libkrun headers])]))
Expand Down
6 changes: 6 additions & 0 deletions src/libcrun/custom-handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ extern struct custom_handler_s handler_wasmedge;
#if HAVE_DLOPEN && HAVE_WASMER
extern struct custom_handler_s handler_wasmer;
#endif
#if HAVE_DLOPEN && HAVE_WAMR
extern struct custom_handler_s handler_wamr;
#endif
#if HAVE_DLOPEN && HAVE_MONO
extern struct custom_handler_s handler_mono;
#endif
Expand All @@ -65,6 +68,9 @@ static struct custom_handler_s *static_handlers[] = {
#if HAVE_DLOPEN && HAVE_WASMTIME
&handler_wasmtime,
#endif
#if HAVE_DLOPEN && HAVE_WAMR
&handler_wamr,
#endif
#if HAVE_DLOPEN && HAVE_MONO
&handler_mono,
#endif
Expand Down
249 changes: 249 additions & 0 deletions src/libcrun/handlers/wamr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
/*
* crun - OCI runtime written in C
*
* Copyright (C) 2024 Maciej Kozub <[email protected]>
* crun is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* crun is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with crun. If not, see <http://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE

#include <config.h>
#include "../custom-handler.h"
#include "../container.h"
#include "../utils.h"
#include "../linux.h"
#include "handler-utils.h"
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>

#ifdef HAVE_DLOPEN
# include <dlfcn.h>
#endif

#ifdef HAVE_WAMR
# include <wasm_export.h>
#endif

#if HAVE_DLOPEN && HAVE_WAMR

static int
libwamr_load (void **cookie, libcrun_error_t *err)
{
void *handle;

handle = dlopen ("libiwasm.so", RTLD_NOW);
if (handle == NULL)
return crun_make_error (err, 0, "could not load `libiwasm.so`: `%s`", dlerror ());
*cookie = handle;

return 0;
}

static int
libwamr_unload (void *cookie, libcrun_error_t *err)
{
int r;

if (cookie)
{
r = dlclose (cookie);
if (UNLIKELY (r < 0))
return crun_make_error (err, 0, "could not unload handle: `%s`", dlerror ());
}
return 0;
}

// Function to read a WebAssembly binary file into a buffer
char *
read_wasm_binary_to_buffer (const char *pathname, uint32_t *size)
{

FILE *file;
char *buffer;
size_t file_size;

// Open the file in binary mode
file = fopen (pathname, "rb");
if (! file)
{
error (EXIT_FAILURE, 0, "Failed to open file");
return NULL;
}

// Seek to the end of the file to determine the size
fseek (file, 0, SEEK_END);
file_size = ftell (file);
fseek (file, 0, SEEK_SET);

// Allocate memory for the buffer
buffer = (char *) malloc (file_size);
if (! buffer)
{
error (EXIT_FAILURE, 0, "Failed to allocate memory");
fclose (file);
return NULL;
}

// Read the file into the buffer
if (fread (buffer, 1, file_size, file) != file_size)
{
error (EXIT_FAILURE, 0, "Failed to read file");
free (buffer);
fclose (file);
return NULL;
}
// Close the file
fclose (file);

// Set the size output parameter
*size = file_size;

// Return the buffer
return buffer;
}

static int
libwamr_exec (void *cookie, __attribute__ ((unused)) libcrun_container_t *container, const char *pathname, char *const argv[])
{
// load symbols from the shared library libiwasm.so
bool (*wasm_runtime_init) ();
RuntimeInitArgs init_args;
wasm_module_t module;
wasm_module_t (*wasm_runtime_load) (uint8_t * buf, uint32_t size, char *error_buf, uint32_t error_buf_size);
wasm_module_inst_t module_inst;
wasm_module_inst_t (*wasm_runtime_instantiate) (const wasm_module_t module, uint32_t default_stack_size, uint32_t host_managed_heap_size, char *error_buf, uint32_t error_buf_size);
wasm_function_inst_t func;
wasm_function_inst_t (*wasm_runtime_lookup_function) (wasm_module_inst_t const module_inst, const char *name);
wasm_exec_env_t exec_env;
wasm_exec_env_t (*wasm_runtime_create_exec_env) (wasm_module_inst_t module_inst, uint32_t stack_size);
bool (*wasm_runtime_call_wasm) (wasm_exec_env_t exec_env, wasm_function_inst_t function, uint32_t argc, uint32_t argv[]);
void (*wasm_runtime_destroy_exec_env) (wasm_exec_env_t exec_env);
void (*wasm_runtime_deinstantiate) (wasm_module_inst_t module_inst);
void (*wasm_runtime_unload) (wasm_module_t module);
void (*wasm_runtime_destroy) ();
void (*wasm_runtime_set_wasi_args) (wasm_module_t module, const char *dir_list[], uint32_t dir_count, const char *map_dir_list[], uint32_t map_dir_count, const char *env[], uint32_t env_count, char *argv[], int argc);

wasm_runtime_init = dlsym (cookie, "wasm_runtime_init");
wasm_runtime_load = dlsym (cookie, "wasm_runtime_load");
wasm_runtime_instantiate = dlsym (cookie, "wasm_runtime_instantiate");
wasm_runtime_lookup_function = dlsym (cookie, "wasm_runtime_lookup_function");
wasm_runtime_create_exec_env = dlsym (cookie, "wasm_runtime_create_exec_env");
wasm_runtime_call_wasm = dlsym (cookie, "wasm_runtime_call_wasm");
wasm_runtime_destroy_exec_env = dlsym (cookie, "wasm_runtime_destroy_exec_env");
wasm_runtime_deinstantiate = dlsym (cookie, "wasm_runtime_deinstantiate");
wasm_runtime_unload = dlsym (cookie, "wasm_runtime_unload");
wasm_runtime_destroy = dlsym (cookie, "wasm_runtime_destroy");
wasm_runtime_set_wasi_args = dlsym (cookie, "wasm_runtime_set_wasi_args");

if (wasm_runtime_init == NULL)
error (EXIT_FAILURE, 0, "could not find wasm_runtime_init symbol in `libiwasm.so`");
if (wasm_runtime_load == NULL)
error (EXIT_FAILURE, 0, "could not find wasm_runtime_load symbol in `libiwasm.so`");
if (wasm_runtime_instantiate == NULL)
error (EXIT_FAILURE, 0, "could not find wasm_runtime_instantiate symbol in `libiwasm.so`");
if (wasm_runtime_lookup_function == NULL)
error (EXIT_FAILURE, 0, "could not find wasm_runtime_lookup_function symbol in `libiwasm.so`");
if (wasm_runtime_create_exec_env == NULL)
error (EXIT_FAILURE, 0, "could not find wasm_runtime_create_exec_env symbol in `libiwasm.so`");
if (wasm_runtime_call_wasm == NULL)
error (EXIT_FAILURE, 0, "could not find wasm_runtime_call_wasm symbol in `libiwasm.so`");
if (wasm_runtime_destroy_exec_env == NULL)
error (EXIT_FAILURE, 0, "could not find wasm_runtime_destroy_exec_env symbol in `libiwasm.so`");
if (wasm_runtime_deinstantiate == NULL)
error (EXIT_FAILURE, 0, "could not find wasm_runtime_deinstantiate symbol in `libiwasm.so`");
if (wasm_runtime_unload == NULL)
error (EXIT_FAILURE, 0, "could not find wasm_runtime_unload symbol in `libiwasm.so`");
if (wasm_runtime_destroy == NULL)
error (EXIT_FAILURE, 0, "could not find wasm_runtime_destroy symbol in `libiwasm.so`");
if (wasm_runtime_set_wasi_args == NULL)
error (EXIT_FAILURE, 0, "could not find wasm_runtime_set_wasi_args symbol in `libiwasm.so`");

char *buffer, error_buf[128];
uint32_t buffer_size, stack_size = 8096, heap_size = 8096;

const char *dirs[2] = { "/", "." };
char **container_env = container->container_def->process->env;
size_t env_count = container->container_def->process->env_len;

int arg_count = 0;
char *const *arg;
for (arg = argv; *arg != NULL; ++arg)
arg_count++;

/* initialize the wasm runtime by default configurations */
if (! wasm_runtime_init ())
error (EXIT_FAILURE, 0, "Failed to initialize the wasm runtime");

/* read WASM file into a memory buffer */
buffer = read_wasm_binary_to_buffer (pathname, &buffer_size);
if (! buffer || buffer_size == 0)
error (EXIT_FAILURE, 0, "Failed to read file");

/* parse the WASM file from buffer and create a WASM module */
module = wasm_runtime_load (buffer, buffer_size, error_buf, sizeof (error_buf));
if (! module)
error (EXIT_FAILURE, 0, "Failed to load WASM file");

/* instantiate the WASI environment */
wasm_runtime_set_wasi_args (module, dirs, 1, NULL, 0, container_env, env_count, (char **) argv, arg_count);

/* create an instance of the WASM module (WASM linear memory is ready) */
module_inst = wasm_runtime_instantiate (module, stack_size, heap_size, error_buf, sizeof (error_buf));
if (! module_inst)
error (EXIT_FAILURE, 0, "Failed to instantiate the WASM module");

/* lookup a WASM function by its name; the function signature can be NULL here */
func = wasm_runtime_lookup_function (module_inst, "_start");
if (! func || func == NULL)
error (EXIT_FAILURE, 0, "Failed to lookup the WASM function");

/* creat an execution environment to execute the WASM functions */
exec_env = wasm_runtime_create_exec_env (module_inst, stack_size);
if (! exec_env)
error (EXIT_FAILURE, 0, "Failed to create the execution environment");

/* call the WASM function */
if (! wasm_runtime_call_wasm (exec_env, func, 0, NULL))
error (EXIT_FAILURE, 0, "Failed to call the WASM function");

wasm_runtime_destroy_exec_env (exec_env);
wasm_runtime_deinstantiate (module_inst);
wasm_runtime_unload (module);
wasm_runtime_destroy ();

exit (EXIT_SUCCESS);
}

static int
wamr_can_handle_container (libcrun_container_t *container, libcrun_error_t *err)
{
return wasm_can_handle_container (container, err);
}

struct custom_handler_s handler_wamr = {
.name = "wamr",
.alias = "wasm",
.feature_string = "WASM:wamr",
.load = libwamr_load,
.unload = libwamr_unload,
.run_func = libwamr_exec,
.can_handle_container = wamr_can_handle_container,
};

#endif

0 comments on commit 3161616

Please sign in to comment.