WebAssembly Micro Runtime first version
This commit is contained in:
25
core/iwasm/runtime/platform/linux/platform.cmake
Normal file
25
core/iwasm/runtime/platform/linux/platform.cmake
Normal file
@ -0,0 +1,25 @@
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
add_definitions (-D__POSIX__ -D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=199309L)
|
||||
|
||||
set (PLATFORM_LIB_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
include_directories(${PLATFORM_LIB_DIR})
|
||||
include_directories(${PLATFORM_LIB_DIR}/../include)
|
||||
|
||||
file (GLOB_RECURSE source_all ${PLATFORM_LIB_DIR}/*.c)
|
||||
|
||||
set (WASM_PLATFORM_LIB_SOURCE ${source_all})
|
||||
|
||||
333
core/iwasm/runtime/platform/linux/wasm-native.c
Normal file
333
core/iwasm/runtime/platform/linux/wasm-native.c
Normal file
@ -0,0 +1,333 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE /* for O_DIRECT */
|
||||
#endif
|
||||
|
||||
#include "wasm-native.h"
|
||||
#include "wasm-runtime.h"
|
||||
#include "wasm_log.h"
|
||||
#include "wasm_memory.h"
|
||||
#include "wasm_platform_log.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#define get_module_inst() \
|
||||
wasm_runtime_get_current_module_inst()
|
||||
|
||||
#define validate_app_addr(offset, size) \
|
||||
wasm_runtime_validate_app_addr(module_inst, offset, size)
|
||||
|
||||
#define addr_app_to_native(offset) \
|
||||
wasm_runtime_addr_app_to_native(module_inst, offset)
|
||||
|
||||
#define addr_native_to_app(ptr) \
|
||||
wasm_runtime_addr_native_to_app(module_inst, ptr)
|
||||
|
||||
#define module_malloc(size) \
|
||||
wasm_runtime_module_malloc(module_inst, size)
|
||||
|
||||
#define module_free(offset) \
|
||||
wasm_runtime_module_free(module_inst, offset)
|
||||
|
||||
|
||||
static int32
|
||||
__syscall0_wrapper(int32 arg0)
|
||||
{
|
||||
switch (arg0) {
|
||||
case 199: /* getuid */
|
||||
/* TODO */
|
||||
default:
|
||||
printf("##_syscall0 called, syscall id: %d\n", arg0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32
|
||||
__syscall1_wrapper(int32 arg0, int32 arg1)
|
||||
{
|
||||
switch (arg0) {
|
||||
case 6: /* close */
|
||||
/* TODO */
|
||||
default:
|
||||
printf("##_syscall1 called, syscall id: %d\n", arg0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32
|
||||
__syscall2_wrapper(int32 arg0, int32 arg1, int32 arg2)
|
||||
{
|
||||
switch (arg0) {
|
||||
case 183: /* getcwd */
|
||||
/* TODO */
|
||||
default:
|
||||
printf("##_syscall2 called, syscall id: %d\n", arg0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32
|
||||
__syscall3_wrapper(int32 arg0, int32 arg1, int32 arg2, int32 arg3)
|
||||
{
|
||||
WASMModuleInstance *module_inst = get_module_inst();
|
||||
|
||||
switch (arg0) {
|
||||
case 54: /* ioctl */
|
||||
{
|
||||
/* Implement syscall 54 and syscall 146 to support printf()
|
||||
for non SIDE_MODULE=1 mode */
|
||||
struct winsize *wsz;
|
||||
|
||||
if (!validate_app_addr(arg3, sizeof(struct winsize)))
|
||||
return 0;
|
||||
|
||||
wsz = (struct winsize*)addr_app_to_native(arg3);
|
||||
return syscall(54, arg1, arg2, wsz);
|
||||
}
|
||||
|
||||
case 145: /* readv */
|
||||
case 146: /* writev */
|
||||
{
|
||||
/* Implement syscall 54 and syscall 146 to support printf()
|
||||
for non SIDE_MODULE=1 mode */
|
||||
uint32 iovcnt = arg3, i;
|
||||
struct iovec *vec_begin, *vec;
|
||||
|
||||
if (!validate_app_addr(arg2, sizeof(struct iovec)))
|
||||
return 0;
|
||||
|
||||
vec_begin = vec = (struct iovec*)addr_app_to_native(arg2);
|
||||
for (i = 0; i < iovcnt; i++, vec++) {
|
||||
if (vec->iov_len > 0) {
|
||||
if (!validate_app_addr((int32)vec->iov_base, 1))
|
||||
return 0;
|
||||
vec->iov_base = addr_app_to_native((int32)vec->iov_base);
|
||||
}
|
||||
}
|
||||
if (arg0 == 145)
|
||||
return syscall(145, arg1, vec_begin, arg3);
|
||||
else
|
||||
return syscall(146, arg1, vec_begin, arg3);
|
||||
}
|
||||
|
||||
case 3: /* read*/
|
||||
case 5: /* open */
|
||||
case 221: /* fcntl */
|
||||
/* TODO */
|
||||
default:
|
||||
printf("##_syscall3 called, syscall id: %d\n", arg0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32
|
||||
__syscall4_wrapper(int32 arg0, int32 arg1, int32 arg2,
|
||||
int32 arg3, int32 arg4)
|
||||
{
|
||||
printf("##_syscall4 called, syscall id: %d\n", arg0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32
|
||||
__syscall5_wrapper(int32 arg0, int32 arg1, int32 arg2,
|
||||
int32 arg3, int32 arg4, int32 arg5)
|
||||
{
|
||||
switch (arg0) {
|
||||
case 140: /* llseek */
|
||||
/* TODO */
|
||||
default:
|
||||
printf("##_syscall5 called, args[0]: %d\n", arg0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define GET_EMCC_SYSCALL_ARGS() \
|
||||
WASMModuleInstance *module_inst = get_module_inst(); \
|
||||
int32 *args; \
|
||||
if (!validate_app_addr(args_off, 1)) \
|
||||
return 0; \
|
||||
args = addr_app_to_native(args_off) \
|
||||
|
||||
#define EMCC_SYSCALL_WRAPPER0(id) \
|
||||
static int32 ___syscall##id##_wrapper(int32 _id) { \
|
||||
return __syscall0_wrapper(id); \
|
||||
}
|
||||
|
||||
#define EMCC_SYSCALL_WRAPPER1(id) \
|
||||
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
|
||||
GET_EMCC_SYSCALL_ARGS(); \
|
||||
return __syscall1_wrapper(id, args[0]); \
|
||||
}
|
||||
|
||||
#define EMCC_SYSCALL_WRAPPER2(id) \
|
||||
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
|
||||
GET_EMCC_SYSCALL_ARGS(); \
|
||||
return __syscall2_wrapper(id, args[0], args[1]); \
|
||||
}
|
||||
|
||||
#define EMCC_SYSCALL_WRAPPER3(id) \
|
||||
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
|
||||
GET_EMCC_SYSCALL_ARGS(); \
|
||||
return __syscall3_wrapper(id, args[0], args[1], args[2]); \
|
||||
}
|
||||
|
||||
#define EMCC_SYSCALL_WRAPPER4(id) \
|
||||
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
|
||||
GET_EMCC_SYSCALL_ARGS(); \
|
||||
return __syscall4_wrapper(id, args[0], args[1], args[2], args[3]);\
|
||||
}
|
||||
|
||||
#define EMCC_SYSCALL_WRAPPER5(id) \
|
||||
static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
|
||||
GET_EMCC_SYSCALL_ARGS(); \
|
||||
return __syscall5_wrapper(id, args[0], args[1], args[2], \
|
||||
args[3], args[4]); \
|
||||
}
|
||||
|
||||
EMCC_SYSCALL_WRAPPER0(199)
|
||||
|
||||
EMCC_SYSCALL_WRAPPER1(6)
|
||||
|
||||
EMCC_SYSCALL_WRAPPER2(183)
|
||||
|
||||
EMCC_SYSCALL_WRAPPER3(3)
|
||||
EMCC_SYSCALL_WRAPPER3(5)
|
||||
EMCC_SYSCALL_WRAPPER3(54)
|
||||
EMCC_SYSCALL_WRAPPER3(145)
|
||||
EMCC_SYSCALL_WRAPPER3(146)
|
||||
EMCC_SYSCALL_WRAPPER3(221)
|
||||
|
||||
EMCC_SYSCALL_WRAPPER5(140)
|
||||
|
||||
static int32
|
||||
getTotalMemory_wrapper()
|
||||
{
|
||||
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
|
||||
WASMMemoryInstance *memory = module_inst->default_memory;
|
||||
return NumBytesPerPage * memory->cur_page_count;
|
||||
}
|
||||
|
||||
static int32
|
||||
enlargeMemory_wrapper()
|
||||
{
|
||||
bool ret;
|
||||
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
|
||||
WASMMemoryInstance *memory = module_inst->default_memory;
|
||||
uint32 DYNAMICTOP_PTR_offset = module_inst->DYNAMICTOP_PTR_offset;
|
||||
uint32 addr_data_offset = *(uint32*)(memory->global_data + DYNAMICTOP_PTR_offset);
|
||||
uint32 *DYNAMICTOP_PTR = (uint32*)(memory->memory_data + addr_data_offset);
|
||||
uint32 memory_size_expected = *DYNAMICTOP_PTR;
|
||||
uint32 total_page_count = (memory_size_expected + NumBytesPerPage - 1) / NumBytesPerPage;
|
||||
|
||||
if (total_page_count < memory->cur_page_count) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
ret = wasm_runtime_enlarge_memory(module_inst, total_page_count -
|
||||
memory->cur_page_count);
|
||||
return ret ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_abort_wrapper(int32 code)
|
||||
{
|
||||
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
|
||||
char buf[32];
|
||||
|
||||
snprintf(buf, sizeof(buf), "env.abort(%i)", code);
|
||||
wasm_runtime_set_exception(module_inst, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
abortOnCannotGrowMemory_wrapper()
|
||||
{
|
||||
WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
|
||||
wasm_runtime_set_exception(module_inst, "abort on cannot grow memory");
|
||||
}
|
||||
|
||||
static void
|
||||
___setErrNo_wrapper(int32 error_no)
|
||||
{
|
||||
errno = error_no;
|
||||
}
|
||||
|
||||
/* TODO: add function parameter/result types check */
|
||||
#define REG_NATIVE_FUNC(module_name, func_name) \
|
||||
{#module_name, #func_name, func_name##_wrapper}
|
||||
|
||||
typedef struct WASMNativeFuncDef {
|
||||
const char *module_name;
|
||||
const char *func_name;
|
||||
void *func_ptr;
|
||||
} WASMNativeFuncDef;
|
||||
|
||||
static WASMNativeFuncDef native_func_defs[] = {
|
||||
REG_NATIVE_FUNC(env, __syscall0),
|
||||
REG_NATIVE_FUNC(env, __syscall1),
|
||||
REG_NATIVE_FUNC(env, __syscall2),
|
||||
REG_NATIVE_FUNC(env, __syscall3),
|
||||
REG_NATIVE_FUNC(env, __syscall4),
|
||||
REG_NATIVE_FUNC(env, __syscall5),
|
||||
REG_NATIVE_FUNC(env, ___syscall3),
|
||||
REG_NATIVE_FUNC(env, ___syscall5),
|
||||
REG_NATIVE_FUNC(env, ___syscall6),
|
||||
REG_NATIVE_FUNC(env, ___syscall54),
|
||||
REG_NATIVE_FUNC(env, ___syscall140),
|
||||
REG_NATIVE_FUNC(env, ___syscall145),
|
||||
REG_NATIVE_FUNC(env, ___syscall146),
|
||||
REG_NATIVE_FUNC(env, ___syscall183),
|
||||
REG_NATIVE_FUNC(env, ___syscall199),
|
||||
REG_NATIVE_FUNC(env, ___syscall221),
|
||||
REG_NATIVE_FUNC(env, _abort),
|
||||
REG_NATIVE_FUNC(env, abortOnCannotGrowMemory),
|
||||
REG_NATIVE_FUNC(env, enlargeMemory),
|
||||
REG_NATIVE_FUNC(env, getTotalMemory),
|
||||
REG_NATIVE_FUNC(env, ___setErrNo),
|
||||
};
|
||||
|
||||
void*
|
||||
wasm_platform_native_func_lookup(const char *module_name,
|
||||
const char *func_name)
|
||||
{
|
||||
uint32 size = sizeof(native_func_defs) / sizeof(WASMNativeFuncDef);
|
||||
WASMNativeFuncDef *func_def = native_func_defs;
|
||||
WASMNativeFuncDef *func_def_end = func_def + size;
|
||||
|
||||
if (!module_name || !func_name)
|
||||
return NULL;
|
||||
|
||||
while (func_def < func_def_end) {
|
||||
if (!strcmp(func_def->module_name, module_name)
|
||||
&& !strcmp(func_def->func_name, func_name))
|
||||
return (void*)(uintptr_t)func_def->func_ptr;
|
||||
func_def++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
96
core/iwasm/runtime/platform/linux/wasm_platform.c
Normal file
96
core/iwasm/runtime/platform/linux/wasm_platform.c
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "wasm_log.h"
|
||||
#include "wasm_platform.h"
|
||||
#include "wasm_memory.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
bool is_little_endian = false;
|
||||
|
||||
bool __is_little_endian()
|
||||
{
|
||||
union w
|
||||
{
|
||||
int a;
|
||||
char b;
|
||||
}c;
|
||||
|
||||
c.a = 1;
|
||||
return (c.b == 1);
|
||||
}
|
||||
|
||||
int
|
||||
wasm_platform_init()
|
||||
{
|
||||
if (__is_little_endian())
|
||||
is_little_endian = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char*
|
||||
wasm_read_file_to_buffer(const char *filename, int *ret_size)
|
||||
{
|
||||
char *buffer;
|
||||
int file;
|
||||
int file_size, read_size;
|
||||
struct stat stat_buf;
|
||||
|
||||
if (!filename || !ret_size) {
|
||||
LOG_ERROR("Read file to buffer failed: invalid filename or ret size.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((file = open(filename, O_RDONLY, 0)) == -1) {
|
||||
LOG_ERROR("Read file to buffer failed: open file %s failed.\n",
|
||||
filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fstat(file, &stat_buf) != 0) {
|
||||
LOG_ERROR("Read file to buffer failed: fstat file %s failed.\n",
|
||||
filename);
|
||||
close(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file_size = stat_buf.st_size;
|
||||
|
||||
if (!(buffer = wasm_malloc(file_size))) {
|
||||
LOG_ERROR("Read file to buffer failed: alloc memory failed.\n");
|
||||
close(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
read_size = read(file, buffer, file_size);
|
||||
close(file);
|
||||
|
||||
if (read_size < file_size) {
|
||||
LOG_ERROR("Read file to buffer failed: read file content failed.\n");
|
||||
wasm_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*ret_size = file_size;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
104
core/iwasm/runtime/platform/linux/wasm_platform.h
Normal file
104
core/iwasm/runtime/platform/linux/wasm_platform.h
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _WASM_PLATFORM_H
|
||||
#define _WASM_PLATFORM_H
|
||||
|
||||
#include "wasm_config.h"
|
||||
#include "wasm_types.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
typedef uint64_t uint64;
|
||||
typedef int64_t int64;
|
||||
typedef float float32;
|
||||
typedef double float64;
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL ((void*) 0)
|
||||
#endif
|
||||
|
||||
#define WASM_PLATFORM "Linux"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <pthread.h>
|
||||
#include <limits.h>
|
||||
#include <semaphore.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
/**
|
||||
* Return the offset of the given field in the given type.
|
||||
*
|
||||
* @param Type the type containing the filed
|
||||
* @param field the field in the type
|
||||
*
|
||||
* @return the offset of field in Type
|
||||
*/
|
||||
#ifndef offsetof
|
||||
#define offsetof(Type, field) ((size_t)(&((Type *)0)->field))
|
||||
#endif
|
||||
|
||||
typedef pthread_t korp_tid;
|
||||
typedef pthread_mutex_t korp_mutex;
|
||||
|
||||
int wasm_platform_init();
|
||||
|
||||
extern bool is_little_endian;
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* The following operations declared in string.h may be defined as
|
||||
macros on Linux, so don't declare them as functions here. */
|
||||
/* memset */
|
||||
/* memcpy */
|
||||
/* memmove */
|
||||
|
||||
/* #include <stdio.h> */
|
||||
|
||||
/* Unit test framework is based on C++, where the declaration of
|
||||
snprintf is different. */
|
||||
#ifndef __cplusplus
|
||||
int snprintf(char *buffer, size_t count, const char *format, ...);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* #include <math.h> */
|
||||
|
||||
#ifndef __cplusplus
|
||||
double sqrt(double x);
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
extern int fopen_s(FILE ** pFile, const char *filename, const char *mode);
|
||||
|
||||
char*
|
||||
wasm_read_file_to_buffer(const char *filename, int *ret_size);
|
||||
|
||||
void*
|
||||
wasm_dlsym(void *handle, const char *symbol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user