Skip to content
Snippets Groups Projects
Commit 462719ba authored by Kai Bleeke's avatar Kai Bleeke
Browse files

fix: extremely cursed data sharing with memfd and mmap

parent 00517142
Branches fourth-sheet
No related tags found
No related merge requests found
File deleted
#include "wasm_c_api_internal.h"
#include "wasm_exec_env.h"
#include "wasm_export.h"
#include "wasm_runtime.h"
#include "wasm_shared_memory.h"
#include <cstdlib>
#include <iostream>
#include <map>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <chrono>
#include <unistd.h>
#include <utility>
#include <sys/mman.h>
typedef std::chrono::high_resolution_clock::time_point TimeVar;
#define duration(a) \
std::chrono::duration_cast<std::chrono::nanoseconds>(a).count()
#define timeNow() std::chrono::high_resolution_clock::now()
char *read_wasm_binary_to_buffer(const char *path, uint32_t *size) {
FILE *fd = fopen(path, "rb");
if (!fd) {
fprintf(stderr, "failed to open the %s file\n", path);
perror("fopen failed!\n");
return NULL;
}
if (fseek(fd, 0, SEEK_END) != 0) {
perror("fseek failed\n");
return NULL;
}
long fsize = ftell(fd);
if (fseek(fd, 0, SEEK_SET) != 0) // rewind(fd); can be used here too
{
perror("fseek failed\n");
return NULL;
}
char *buffer = (char *)malloc(fsize + 1);
if (!buffer) {
perror("malloc for file buffer failed!\n");
return NULL;
}
size_t read_bytes = fread(buffer, 1, fsize, fd);
if (read_bytes != (size_t)fsize) {
free(buffer);
fprintf(stderr,
"file read didnt read the whole file size and returned only %zu "
"instead of %zu \n",
read_bytes, fsize);
exit(EXIT_FAILURE);
}
fclose(fd);
*size = fsize; //+ 1;
// buffer[fsize] = 0;
return buffer;
}
int shared_memfd = -1;
uint32_t module_map_shared(wasm_exec_env_t env) {
wasm_module_inst_t instance = get_module_inst(env);
WASMModuleInstance *inst = (WASMModuleInstance *) instance;
uint8_t *data_end = inst->default_memory->memory_data_end;
printf("memory start %p\n", inst->default_memory->memory_data);
printf("memory end %p\n", inst->default_memory->memory_data_end);
printf("heap start %p\n", inst->default_memory->heap_data);
printf("heap end %p\n", inst->default_memory->heap_data_end);
// Find some memory at the end of the instance that is aligned to a page boundary.
// MAP_FIXED requires a page boundary
// This conflicts with the allocator in the module and is extremely cursed
// TODO: find something in the module that is not under control of the (in-module) allocator
uintptr_t data_before = (uintptr_t) data_end - 1024;
uint8_t *page_bound = (uint8_t *) (data_before & ~(4 * 1024 - 1));
void *mapped = mmap(page_bound, 1024, PROT_READ, MAP_SHARED | MAP_FIXED,
shared_memfd, 0);
if (mapped == nullptr) {
perror("map failed\n");
}
printf("native_addr %p\n", page_bound);
printf("mapped %p\n", mapped);
uint32_t wasm_ptr = wasm_runtime_addr_native_to_app(instance, mapped);
printf("wasm addr 0x%x\n", wasm_ptr);
return wasm_ptr;
}
int main(int argc, char *argv[]) {
shared_memfd = memfd_create("sharedmem", 0);
if (shared_memfd < 0) {
perror("memfd failed");
exit(EXIT_FAILURE);
}
ftruncate(shared_memfd, 1024);
void *host_mapping =
mmap(nullptr, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, shared_memfd, 0);
strcpy((char *)host_mapping, "test123");
printf("host mapping: %s\n", (char*) host_mapping);
static NativeSymbol native_symbols[] = {
{"native_map_shared", (void *)module_map_shared, "()i", NULL}};
char *buffer, error_buf[128];
wasm_module_t module;
wasm_module_inst_t module_inst;
wasm_function_inst_t func;
wasm_exec_env_t exec_env;
uint32_t size, stack_size = 8092, heap_size = 8092;
/* initialize the wasm runtime by default configurations */
if (!wasm_runtime_init()) {
fprintf(stderr, "wasm runtime initialisation failed\n");
exit(EXIT_FAILURE);
}
/* read WASM file into a memory buffer */
buffer = read_wasm_binary_to_buffer(argv[1], &size);
if (buffer == NULL) {
fprintf(stderr,
"the returned buffer for reading the wasm module is null\n");
exit(EXIT_FAILURE);
}
/* add line below if we want to export native functions to WASM app */
int n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol);
if (!wasm_runtime_register_natives("env", native_symbols, n_native_symbols)) {
free(buffer);
exit(EXIT_FAILURE);
}
/* parse the WASM file from buffer and create a WASM module */
module =
wasm_runtime_load((uint8_t *)buffer, size, error_buf, sizeof(error_buf));
if (module == NULL) {
fprintf(stderr,
"failed to load the module %s from the buffer with the error %s\n",
argv[1], error_buf);
exit(EXIT_FAILURE);
}
/* 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 == NULL) {
fprintf(stderr, "module instantiation failed!\n");
exit(EXIT_FAILURE);
}
/* lookup a WASM function by its name
The function signature can NULL here */
func = wasm_runtime_lookup_function(module_inst, "main", "()i");
if (func == NULL) {
printf("multadd function not found\n");
return -1;
}
/* creat an execution environment to execute the WASM functions */
exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);
if (exec_env == NULL) {
printf("execution environmnet creation failed\n");
return -1;
}
uint32_t args[1] = {0};
#ifdef BENCH_ITERATIONS
TimeVar t1 = timeNow();
#endif
if (wasm_runtime_call_wasm(exec_env, func, 0, args)) {
/* the return value is stored in argv[0] */
// printf("the main function returned %ld \n", args[0]);
#ifdef BENCH_ITERATIONS
auto time_elapsed = duration(timeNow() - t1);
std::cout << "total execution time is " << time_elapsed << "ns and "
<< time_elapsed / BENCH_ITERATIONS
<< "ns per function call on average" << std::endl;
#endif
} else {
/* exception is thrown if call fails */
printf("%s\n", wasm_runtime_get_exception(module_inst));
}
wasm_runtime_destroy();
return 0;
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment