mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-06 20:58:28 +00:00
234 lines
6.2 KiB
C
234 lines
6.2 KiB
C
|
|
#include "wasmer.h"
|
|
//#include "my_wasm.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define own
|
|
|
|
|
|
#define WASI
|
|
|
|
#ifdef WASI_PIRITA
|
|
extern size_t VOLUMES_LENGTH asm("VOLUMES_LENGTH");
|
|
extern char VOLUMES_DATA asm("VOLUMES_DATA");
|
|
// DECLARE_MODULES
|
|
#else
|
|
extern size_t WASMER_MODULE_LENGTH asm("WASMER_MODULE_LENGTH");
|
|
extern char WASMER_MODULE_DATA asm("WASMER_MODULE_DATA");
|
|
#endif
|
|
|
|
static void print_wasmer_error() {
|
|
int error_len = wasmer_last_error_length();
|
|
printf("Error len: `%d`\n", error_len);
|
|
char *error_str = (char *)malloc(error_len);
|
|
wasmer_last_error_message(error_str, error_len);
|
|
printf("%s\n", error_str);
|
|
free(error_str);
|
|
}
|
|
|
|
#ifdef WASI
|
|
static void pass_mapdir_arg(wasi_config_t *wasi_config, char *mapdir) {
|
|
int colon_location = strchr(mapdir, ':') - mapdir;
|
|
if (colon_location == 0) {
|
|
// error malformed argument
|
|
fprintf(stderr, "Expected mapdir argument of the form alias:directory\n");
|
|
exit(-1);
|
|
}
|
|
|
|
char *alias = (char *)malloc(colon_location + 1);
|
|
memcpy(alias, mapdir, colon_location);
|
|
alias[colon_location] = '\0';
|
|
|
|
int dir_len = strlen(mapdir) - colon_location;
|
|
char *dir = (char *)malloc(dir_len + 1);
|
|
memcpy(dir, &mapdir[colon_location + 1], dir_len);
|
|
dir[dir_len] = '\0';
|
|
|
|
wasi_config_mapdir(wasi_config, alias, dir);
|
|
free(alias);
|
|
free(dir);
|
|
}
|
|
|
|
// We try to parse out `--dir` and `--mapdir` ahead of time and process those
|
|
// specially. All other arguments are passed to the guest program.
|
|
static void handle_arguments(wasi_config_t *wasi_config, int argc,
|
|
char *argv[]) {
|
|
for (int i = 1; i < argc; ++i) {
|
|
// We probably want special args like `--dir` and `--mapdir` to not be
|
|
// passed directly
|
|
if (strcmp(argv[i], "--dir") == 0) {
|
|
// next arg is a preopen directory
|
|
if ((i + 1) < argc) {
|
|
i++;
|
|
wasi_config_preopen_dir(wasi_config, argv[i]);
|
|
} else {
|
|
fprintf(stderr, "--dir expects a following argument specifying which "
|
|
"directory to preopen\n");
|
|
exit(-1);
|
|
}
|
|
} else if (strcmp(argv[i], "--mapdir") == 0) {
|
|
// next arg is a mapdir
|
|
if ((i + 1) < argc) {
|
|
i++;
|
|
pass_mapdir_arg(wasi_config, argv[i]);
|
|
} else {
|
|
fprintf(stderr,
|
|
"--mapdir expects a following argument specifying which "
|
|
"directory to preopen in the form alias:directory\n");
|
|
exit(-1);
|
|
}
|
|
} else if (strncmp(argv[i], "--dir=", strlen("--dir=")) == 0) {
|
|
// this arg is a preopen dir
|
|
char *dir = argv[i] + strlen("--dir=");
|
|
wasi_config_preopen_dir(wasi_config, dir);
|
|
} else if (strncmp(argv[i], "--mapdir=", strlen("--mapdir=")) == 0) {
|
|
// this arg is a mapdir
|
|
char *mapdir = argv[i] + strlen("--mapdir=");
|
|
pass_mapdir_arg(wasi_config, mapdir);
|
|
} else {
|
|
// guest argument
|
|
wasi_config_arg(wasi_config, argv[i]);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
int main(int argc, char *argv[]) {
|
|
wasm_config_t *config = wasm_config_new();
|
|
wasm_engine_t *engine = wasm_engine_new_with_config(config);
|
|
wasm_store_t *store = wasm_store_new(engine);
|
|
wasm_module_t *module = NULL;
|
|
|
|
const char* selected_atom = "main";
|
|
for (int i = 1; i < argc; i++) {
|
|
if (strcmp(argv[i], "--command") == 0 && i + 1 < argc) {
|
|
selected_atom = argv[i + 1];
|
|
break;
|
|
}
|
|
}
|
|
|
|
// INSTANTIATE_MODULES
|
|
|
|
// We have now finished the memory buffer book keeping and we have a valid
|
|
// Module.
|
|
|
|
#ifdef WASI_PIRITA
|
|
wasi_config_t *wasi_config = wasi_config_new(argv[0]);
|
|
handle_arguments(wasi_config, argc, argv);
|
|
|
|
wasm_byte_vec_t volume_bytes = {
|
|
.size = VOLUMES_LENGTH,
|
|
.data = &VOLUMES_DATA,
|
|
};
|
|
|
|
wasi_filesystem_t* filesystem = wasi_filesystem_init_static_memory(&volume_bytes);
|
|
if (!filesystem) {
|
|
printf("Error parsing filesystem from bytes\n");
|
|
return 1;
|
|
}
|
|
|
|
wasm_extern_vec_t imports;
|
|
wasi_env_t* wasi_env = wasi_env_with_filesystem(
|
|
wasi_config,
|
|
store,
|
|
module,
|
|
filesystem,
|
|
&imports,
|
|
selected_atom,
|
|
);
|
|
if (!wasi_env) {
|
|
printf("Error setting filesystem\n");
|
|
return 1;
|
|
}
|
|
#else
|
|
wasi_config_t *wasi_config = wasi_config_new(argv[0]);
|
|
handle_arguments(wasi_config, argc, argv);
|
|
|
|
wasi_env_t *wasi_env = wasi_env_new(store, wasi_config);
|
|
if (!wasi_env) {
|
|
fprintf(stderr, "Error building WASI env!\n");
|
|
print_wasmer_error();
|
|
return 1;
|
|
}
|
|
|
|
wasm_importtype_vec_t import_types;
|
|
wasm_module_imports(module, &import_types);
|
|
|
|
wasm_extern_vec_t imports;
|
|
wasm_extern_vec_new_uninitialized(&imports, import_types.size);
|
|
wasm_importtype_vec_delete(&import_types);
|
|
|
|
#ifdef WASI
|
|
bool get_imports_result = wasi_get_imports(store, wasi_env, module, &imports);
|
|
|
|
if (!get_imports_result) {
|
|
fprintf(stderr, "Error getting WASI imports!\n");
|
|
print_wasmer_error();
|
|
|
|
return 1;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
wasm_instance_t *instance = wasm_instance_new(store, module, &imports, NULL);
|
|
|
|
if (!instance) {
|
|
fprintf(stderr, "Failed to create instance\n");
|
|
print_wasmer_error();
|
|
return -1;
|
|
}
|
|
|
|
#ifdef WASI
|
|
// Read the exports.
|
|
wasm_extern_vec_t exports;
|
|
wasm_instance_exports(instance, &exports);
|
|
wasm_memory_t* mem = NULL;
|
|
for (size_t i = 0; i < exports.size; i++) {
|
|
mem = wasm_extern_as_memory(exports.data[i]);
|
|
if (mem) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!mem) {
|
|
fprintf(stderr, "Failed to create instance: Could not find memory in exports\n");
|
|
print_wasmer_error();
|
|
return -1;
|
|
}
|
|
wasi_env_set_memory(wasi_env, mem);
|
|
|
|
own wasm_func_t *start_function = wasi_get_start_function(instance);
|
|
if (!start_function) {
|
|
fprintf(stderr, "`_start` function not found\n");
|
|
print_wasmer_error();
|
|
return -1;
|
|
}
|
|
|
|
wasm_val_vec_t args = WASM_EMPTY_VEC;
|
|
wasm_val_vec_t results = WASM_EMPTY_VEC;
|
|
own wasm_trap_t *trap = wasm_func_call(start_function, &args, &results);
|
|
if (trap) {
|
|
fprintf(stderr, "Trap is not NULL: TODO:\n");
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
// TODO: handle non-WASI start (maybe with invoke?)
|
|
|
|
#ifdef WASI_PIRITA
|
|
wasi_filesystem_delete(filesystem);
|
|
#endif
|
|
#ifdef WASI
|
|
wasi_env_delete(wasi_env);
|
|
wasm_extern_vec_delete(&exports);
|
|
#endif
|
|
wasm_instance_delete(instance);
|
|
wasm_module_delete(module);
|
|
wasm_store_delete(store);
|
|
wasm_engine_delete(engine);
|
|
return 0;
|
|
}
|