/* ** wasm-rt.cpp ** ** This file is part of mkxp. ** ** Copyright (C) 2013 - 2021 Amaryllis Kulla ** ** mkxp is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 2 of the License, or ** (at your option) any later version. ** ** mkxp 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 General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with mkxp. If not, see . */ #include #include #include "core.h" #include "wasm-rt.h" #define WASM_PAGE_SIZE ((uint64_t)65536U) #define WASM_MIN_PAGES ((uint32_t)1024U) // tentative extern "C" bool wasm_rt_is_initialized(void) { return true; } extern "C" WASM_RT_NO_RETURN void wasm_rt_trap(wasm_rt_trap_t error) { mkxp_retro::log_printf(RETRO_LOG_ERROR, "Sandbox error %d\n", error); std::abort(); } extern "C" void wasm_rt_allocate_memory(wasm_rt_memory_t *memory, uint32_t initial_pages, uint32_t max_pages, bool is64) { if ((memory->size = (uint64_t)initial_pages * WASM_PAGE_SIZE) > SIZE_MAX) { throw std::bad_alloc(); } memory->data = (uint8_t *)std::malloc(std::max((size_t)memory->size, (size_t)WASM_MIN_PAGES)); if (memory->data == NULL) { throw std::bad_alloc(); } memory->pages = initial_pages; } extern "C" uint32_t wasm_rt_grow_memory(wasm_rt_memory_t *memory, uint32_t pages) { uint32_t new_pages = memory->pages + pages; if (new_pages < memory->pages) { // Unsigned integer overflow return -1; } uint64_t new_size = (uint64_t)new_pages * WASM_PAGE_SIZE; if (new_size > SIZE_MAX) { return -1; } uint8_t *new_data = new_pages <= WASM_MIN_PAGES ? memory->data : (uint8_t *)std::realloc(memory->data, (size_t)new_size); if (new_data == NULL) { return -1; } #ifdef MKXPZ_BIG_ENDIAN std::memmove(new_data + (size_t)pages * WASM_PAGE_SIZE, new_data, (size_t)memory->size); #endif // MKXPZ_BIG_ENDIAN uint32_t old_pages = memory->pages; memory->pages = new_pages; memory->size = new_size; memory->data = new_data; return old_pages; } extern "C" void wasm_rt_free_memory(wasm_rt_memory_t *memory) { std::free(memory->data); } extern "C" void wasm_rt_allocate_funcref_table(wasm_rt_funcref_table_t *table, uint32_t elements, uint32_t max_elements) { table->private_data = new std::vector(elements); table->data = ((std::vector *)table->private_data)->data(); table->size = elements; } extern "C" void wasm_rt_free_funcref_table(wasm_rt_funcref_table_t *table) { delete (std::vector *)table->private_data; } extern "C" uint32_t wasm_rt_push_funcref(wasm_rt_funcref_table_t *table, wasm_rt_funcref_t funcref) { if (table->size == (uint32_t)-1) { throw std::bad_alloc(); } ((std::vector *)table->private_data)->push_back(funcref); table->data = ((std::vector *)table->private_data)->data(); return table->size++; }