* feat: Preliminary WASI with fib workload

* refactor: Clarify initialize globals

* chore: Update empty to WASI

* chore: cleanup fib test

* chore: cleanup build tooling

* chore: cleanup test Makefiles and some nits

* chore: Update LLVM and install WASI-SDK

* chore: Update build tools and specs

* docs: Update example module spec in README

* refactor: Clean up HTTP handling

* feat: Implement exit WASI call

* style: apply clang-format

* ci: rewrite compile sledge step

* build: Remove LLVM install shims

* build: Try manually adding libunwind

* build: Try adding libunwind-dev

* ci: break out aWsm compile step

* fix: Correct test build error

* fix: Correct error in WASI fd_write

* chore: Increase gocr http buffer size

* test: Correct image resize test

* chore: Remove zombie wasmception functions

* chore: Reduce dummy args to single arg

* chore: Add debugging makefile fivebyeight

* chore: Remove erronious PHONYs in tests Makefile

* ci: Disable gocr tests

* chore: Add wat Make rule to fibonacci test

* chore: fix apt package name

* chore: Enable clean of failed ck install

* chore: use LLVM 12

* test: Disable gocr tests

* chore: Enhance test makefile

* chore: Add CFILES as sledgert dep

* chore: Add NULL check for function table pointer

* chore: Add missing header

* chore: uncomment cleanup in imageresize test

* refactor: Remove unused linear memory functions

* build: Add bimodal debug makefile

* chore: Add linear memory debug logs

* refactor: Cleanup region initialization

* build: Correct PHONY in runtime Makefile

* chore: deb install script for outside of container

* refactor: Remove zombie extern.

* feat: WebAssembly traps

* refactor: Use C18 features

* chore: Remove git diff annotations

* fix: tweaks to run all sample apps with WASI

* test: convert shell script to Makefile

* build: clean generated ck Makefile

* chore: Use awsm branch with fixes

* chore: Revert name changes

* fix: Correct type issues

* refactor: Reverse additional name change

* refactor: Remove awsm compat shims

* chore: Remove libc association

* build: Better detect header file changes

* refactor: current_wasm_module_instance_trap

* test: reenable tests

* chore: Delete copied script

* build: Fix test workloads

* fix: Implement HTTP 500

* fix: Protect against overflow on comparison

* build: Replace test.sh with makefile

* refactor: blow away tmp directory conflicts

* refactor: centralize wasm in single submodule

* feat: libsledge and sledge ABI

* chore: move tests

* refactor: tests

* chore: update wasm_apps with new sample data

* doc: Initial ABI README

* feat: globals table

* docs: Merge aWsm ABI docs

* docs: libsledge ABI

* build: rename apps to keep consistent

* build: Disable wasm proposals

* build: Update wasm apps and fix typo

* test: test makefiles

* test: Additional test makefiles

* build: top-level build and install rules wo Docker

* docs: Add wasm lld comment

* build: top level makefile

* chore: merge debug flags

* fix: Correct out of bounds error

* feat: indirection to awsm ABI

* fix: Correct link hack with proper flag

* fix: gps typo

* chore: format nit

* ci: update makefile rules

* ci: check WASI_SDK_PATH

* fix: Adjust paths

* ci: fix make rule name

* refactor: Attempt to use generic vec

* refactor: Remove type-specific vec

* fix: Resolve assorted TODOs

* chore: fix clang format issue

* ci: Invalidate app cache on libsledge changes

* fix: Correct wasm trap check

* fix: free wasm globals

* docs: example of running top level tests via make

* chore: option to log unsupported wasi

* test: add preempt client generator for fib bimodal

* refactor: Allocate wasm memory with 4096 align

* fix: Handle build without runtime globals

* refactor: bypass runtime call for first global

* fix: Correct sandbox logging

* test: fix incorrect paths in test.mk

* refactor: cleanup basic traps logic

* test: trap_divzero

* fix: Correct inverted trap control flow

* ci: Invalidate awsm cache

* ci: divide by zero trap

* chore: Assorted cleanup

* ci: Install httpie

* chore: Remove stdio calls in libsledge

* chore: update submodules
master
Sean McBride 3 years ago committed by GitHub
parent a35d749db9
commit eb74a306ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -72,6 +72,7 @@ jobs:
fonts-cascadia-code \
fonts-roboto \
gnuplot \
httpie \
imagemagick \
netpbm \
pango1.0-tools \
@ -177,3 +178,7 @@ jobs:
# run: |
# make -f test.mk TODO
# if: success() || failure()
- name: Wasm Trap Divide by Zero
run: |
make -f test.mk trap_divzero
if: success() || failure()

@ -79,3 +79,6 @@ gps_ekf.install: ../runtime/bin/gps_ekf.wasm.so
.PHONY: license_plate_detection.install
license_plate_detection.install: ../runtime/bin/license_plate_detection.wasm.so
.PHONY: trap_divzero.install
trap_divzero.install: ../runtime/bin/trap_divzero.wasm.so

@ -34,9 +34,9 @@ Here is a list of WebAssembly instructions that depend on symbols from libsledge
The ABI includes the
| Instruction | aWsm ABI | libc Dependencies | SLEdge ABI |
| ------------- | ------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| call_indirect | `get_function_from_table` | `stderr`, `fprintf` | `sledge_abi__current_wasm_module_instance.table`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_INVALID_INDEX`, `WASM_TRAP_MISMATCHED_FUNCTION_TYPE` |
| Instruction | aWsm ABI | libc Dependencies | SLEdge ABI |
| ------------- | ------------------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| call_indirect | `get_function_from_table` | `stderr`, `fprintf` | `sledge_abi__current_wasm_module_instance.table`, `sledge_abi__wasm_trap_raise`, `WASM_TRAP_INVALID_INDEX`, `WASM_TRAP_MISMATCHED_TYPE` |
### [Variable Instructions](https://webassembly.github.io/spec/core/syntax/instructions.html#variable-instructions)

@ -3,7 +3,6 @@
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <threads.h>
/* Do not include runtime headers here! */
@ -43,16 +42,29 @@ struct sledge_abi__wasm_module_instance {
/* Private runtime state follows */
};
/* Based on example traps listed at https://webassembly.org/docs/security/ */
enum sledge_abi__wasm_trap
{
WASM_TRAP_EXIT = 1,
WASM_TRAP_INVALID_INDEX = 2,
WASM_TRAP_MISMATCHED_TYPE = 3,
WASM_TRAP_PROTECTED_CALL_STACK_OVERFLOW = 4,
WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY = 5,
WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION = 6,
WASM_TRAP_COUNT
};
/* Symbols expected from sledgert */
extern void sledge_abi__wasm_trap_raise(enum sledge_abi__wasm_trap trapno);
extern int32_t sledge_abi__wasm_memory_expand(struct sledge_abi__wasm_memory *wasm_memory, uint32_t page_count);
void sledge_abi__wasm_memory_initialize_region(struct sledge_abi__wasm_memory *wasm_memory, uint32_t offset,
uint32_t region_size, uint8_t region[]);
extern int32_t sledge_abi__wasm_globals_get_i32(uint32_t idx);
extern int64_t sledge_abi__wasm_globals_get_i64(uint32_t idx);
extern int32_t sledge_abi__wasm_globals_set_i32(uint32_t idx, int32_t value, bool is_mutable);
extern int32_t sledge_abi__wasm_globals_set_i64(uint32_t idx, int64_t value, bool is_mutable);
extern void sledge_abi__wasm_globals_set_i32(uint32_t idx, int32_t value, bool is_mutable);
extern void sledge_abi__wasm_globals_set_i64(uint32_t idx, int64_t value, bool is_mutable);
/* Wasm initialization functions generated by the aWsm compiler */
extern void sledge_abi__init_globals(void);

@ -18,7 +18,12 @@ INLINE float
get_f32(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
assert((uint64_t)offset + sizeof(float) <= sledge_abi__current_wasm_module_instance.memory.size);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(float)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
return *(float *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
@ -26,7 +31,12 @@ INLINE double
get_f64(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
assert((uint64_t)offset + sizeof(double) <= sledge_abi__current_wasm_module_instance.memory.size);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(double)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
return *(double *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
@ -34,7 +44,12 @@ INLINE int8_t
get_i8(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
assert((uint64_t)offset + sizeof(int8_t) <= sledge_abi__current_wasm_module_instance.memory.size);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int8_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
return *(int8_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
@ -42,7 +57,12 @@ INLINE int16_t
get_i16(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
assert((uint64_t)offset + sizeof(int16_t) <= sledge_abi__current_wasm_module_instance.memory.size);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int16_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
return *(int16_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
@ -50,7 +70,12 @@ INLINE int32_t
get_i32(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
assert((uint64_t)offset + sizeof(int32_t) <= sledge_abi__current_wasm_module_instance.memory.size);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int32_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
return *(int32_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
@ -58,7 +83,12 @@ INLINE int64_t
get_i64(uint32_t offset)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
assert((uint64_t)offset + sizeof(int64_t) <= sledge_abi__current_wasm_module_instance.memory.size);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int64_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
return *(int64_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset];
}
@ -67,7 +97,12 @@ INLINE void
set_f32(uint32_t offset, float value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
assert((uint64_t)offset + sizeof(float) <= sledge_abi__current_wasm_module_instance.memory.size);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(float)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
*(float *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
@ -75,7 +110,12 @@ INLINE void
set_f64(uint32_t offset, double value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
assert((uint64_t)offset + sizeof(double) <= sledge_abi__current_wasm_module_instance.memory.size);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(double)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
*(double *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
@ -83,7 +123,12 @@ INLINE void
set_i8(uint32_t offset, int8_t value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
assert((uint64_t)offset + sizeof(int8_t) <= sledge_abi__current_wasm_module_instance.memory.size);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int8_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
*(int8_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
@ -91,7 +136,12 @@ INLINE void
set_i16(uint32_t offset, int16_t value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
assert((uint64_t)offset + sizeof(int16_t) <= sledge_abi__current_wasm_module_instance.memory.size);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int16_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
*(int16_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
@ -99,7 +149,12 @@ INLINE void
set_i32(uint32_t offset, int32_t value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
assert((uint64_t)offset + sizeof(int32_t) <= sledge_abi__current_wasm_module_instance.memory.size);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int32_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
*(int32_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
@ -107,10 +162,16 @@ INLINE void
set_i64(uint32_t offset, int64_t value)
{
assert(sledge_abi__current_wasm_module_instance.memory.buffer != NULL);
assert((uint64_t)offset + sizeof(int64_t) <= sledge_abi__current_wasm_module_instance.memory.size);
if (unlikely((uint64_t)offset + (uint64_t)sizeof(int64_t)
> sledge_abi__current_wasm_module_instance.memory.size)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY);
}
*(int64_t *)&sledge_abi__current_wasm_module_instance.memory.buffer[offset] = value;
}
/**
* @brief Stub that implements the WebAssembly memory.grow instruction
*

@ -54,56 +54,60 @@ rotr_u64(uint64_t n, uint64_t c_u64)
INLINE uint32_t
u32_div(uint32_t a, uint32_t b)
{
assert(b);
if (unlikely(b == 0)) sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a / b;
}
INLINE uint32_t
u32_rem(uint32_t a, uint32_t b)
{
assert(b);
if (unlikely(b == 0)) sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a % b;
}
INLINE int32_t
i32_div(int32_t a, int32_t b)
{
assert(b && (a != INT32_MIN || b != -1));
if (unlikely(b == 0 || (a == INT32_MIN && b == -1)))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a / b;
}
INLINE int32_t
i32_rem(int32_t a, int32_t b)
{
assert(b && (a != INT32_MIN || b != -1));
if (unlikely(b == 0 || (a == INT32_MIN && b == -1)))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a % b;
}
INLINE uint64_t
u64_div(uint64_t a, uint64_t b)
{
assert(b);
if (unlikely(b == 0)) sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a / b;
}
INLINE uint64_t
u64_rem(uint64_t a, uint64_t b)
{
assert(b);
if (unlikely(b == 0)) sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a % b;
}
INLINE int64_t
i64_div(int64_t a, int64_t b)
{
assert(b && (a != INT64_MIN || b != -1));
if (unlikely(b == 0 || (a == INT64_MIN && b == -1)))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a / b;
}
INLINE int64_t
i64_rem(int64_t a, int64_t b)
{
assert(b && (a != INT64_MIN || b != -1));
if (unlikely(b == 0 || (a == INT64_MIN && b == -1)))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return a % b;
}
@ -113,56 +117,64 @@ i64_rem(int64_t a, int64_t b)
uint32_t
u32_trunc_f32(float f)
{
assert(0 <= f && f <= (float)UINT32_MAX);
if (unlikely(f < 0 || f > (float)UINT32_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return (uint32_t)f;
}
int32_t
i32_trunc_f32(float f)
{
assert(INT32_MIN <= f && f <= (float)INT32_MAX);
if (unlikely(f < INT32_MIN || f > (float)INT32_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return (int32_t)f;
}
uint32_t
u32_trunc_f64(double f)
{
assert(0 <= f && f <= (double)UINT32_MAX);
if (unlikely(f < 0 || f > (double)UINT32_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return (uint32_t)f;
}
int32_t
i32_trunc_f64(double f)
{
assert(INT32_MIN <= f && f <= (double)INT32_MAX);
if (unlikely(f < (double)INT32_MIN || f > (double)INT32_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return (int32_t)f;
}
uint64_t
u64_trunc_f32(float f)
{
assert(0 <= f && f <= (float)UINT64_MAX);
if (unlikely(f < 0 || f > (float)UINT64_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return (uint64_t)f;
}
int64_t
i64_trunc_f32(float f)
{
assert(INT64_MIN <= f && f <= (float)INT64_MAX);
if (unlikely(f < (float)INT64_MIN || f > (float)INT64_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return (int64_t)f;
}
uint64_t
u64_trunc_f64(double f)
{
assert(0 <= f && f <= (double)UINT64_MAX);
if (unlikely(f < 0 || f > (float)UINT64_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return (uint64_t)f;
}
int64_t
i64_trunc_f64(double f)
{
assert(INT64_MIN <= f && f <= (double)INT64_MAX);
if (unlikely(f < (double)INT64_MIN || f > (double)INT64_MAX))
sledge_abi__wasm_trap_raise(WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION);
return (int64_t)f;
}

@ -11,12 +11,14 @@ static INLINE void *
wasm_table_get(struct sledge_abi__wasm_table *wasm_table, uint32_t idx, uint32_t type_id)
{
assert(wasm_table != NULL);
assert(idx < wasm_table->capacity);
if (unlikely(idx >= wasm_table->capacity)) { sledge_abi__wasm_trap_raise(WASM_TRAP_INVALID_INDEX); }
struct sledge_abi__wasm_table_entry f = wasm_table->buffer[idx];
assert(f.type_id == type_id);
assert(f.func_pointer != NULL);
if (unlikely(f.type_id != type_id)) { sledge_abi__wasm_trap_raise(WASM_TRAP_MISMATCHED_TYPE); }
if (unlikely(f.func_pointer == NULL)) { sledge_abi__wasm_trap_raise(WASM_TRAP_MISMATCHED_TYPE); }
return f.func_pointer;
}
@ -44,12 +46,15 @@ get_function_from_table(uint32_t idx, uint32_t type_id)
{
assert(sledge_abi__current_wasm_module_instance.table != NULL);
assert(idx < sledge_abi__current_wasm_module_instance.table->capacity);
if (unlikely(idx >= sledge_abi__current_wasm_module_instance.table->capacity)) {
sledge_abi__wasm_trap_raise(WASM_TRAP_INVALID_INDEX);
}
struct sledge_abi__wasm_table_entry f = sledge_abi__current_wasm_module_instance.table->buffer[idx];
assert(f.type_id == type_id);
assert(f.func_pointer != NULL);
if (unlikely(f.type_id != type_id)) { sledge_abi__wasm_trap_raise(WASM_TRAP_MISMATCHED_TYPE); }
if (unlikely(f.func_pointer == NULL)) { sledge_abi__wasm_trap_raise(WASM_TRAP_MISMATCHED_TYPE); }
return f.func_pointer;
}

@ -35,8 +35,7 @@ set_global_i32(uint32_t idx, int32_t value)
} else {
/* aWsm does not currently pass the is_mutable flag, so all runtime globals are assumed to be mutable.
This is true if aWsm uses the flags to inline constant globals */
int rc = sledge_abi__wasm_globals_set_i32(idx, value, true);
assert(rc == 0);
sledge_abi__wasm_globals_set_i32(idx, value, true);
}
}
@ -48,7 +47,6 @@ set_global_i64(uint32_t idx, int64_t value)
} else {
/* aWsm does not currently pass the is_mutable flag, so all runtime globals are assumed to be mutable.
This is true if aWsm uses the flags to inline constant globals */
int rc = sledge_abi__wasm_globals_set_i64(idx, value, true);
assert(rc == 0);
sledge_abi__wasm_globals_set_i64(idx, value, true);
}
}

@ -1,5 +1,6 @@
#pragma once
#include <setjmp.h>
#include <ucontext.h>
#include "arch/reg_t.h"
@ -10,4 +11,5 @@ struct arch_context {
arch_context_variant_t variant;
reg_t regs[UREG_COUNT];
mcontext_t mctx;
jmp_buf start_buf;
};

@ -96,3 +96,16 @@ current_sandbox_memory_writeback(void)
memcpy(&current_sandbox->memory->abi, &sledge_abi__current_wasm_module_instance.abi.memory,
sizeof(struct sledge_abi__wasm_memory));
}
static inline void
current_sandbox_trap(enum sledge_abi__wasm_trap trapno)
{
assert(trapno != 0);
assert(trapno < WASM_TRAP_COUNT);
struct sandbox *sandbox = current_sandbox_get();
assert(sandbox != NULL);
assert(sandbox->state == SANDBOX_RUNNING_USER || sandbox->state == SANDBOX_RUNNING_SYS);
longjmp(sandbox->ctxt.start_buf, trapno);
}

@ -19,8 +19,6 @@
* Unmaps linear memory, removes from the runqueue (if on it), and adds to the completion queue
* Because the stack is still in use, freeing the stack is deferred until later
*
* TODO: Is the sandbox adding itself to the completion queue here? Is this a problem? Issue #94
*
* @param sandbox the sandbox erroring out
* @param last_state the state the sandbox is transitioning from. This is expressed as a constant to
* enable the compiler to perform constant propagation optimizations.

@ -54,33 +54,36 @@ wasm_globals_update_if_used(struct vec_wasm_global_t *globals, uint32_t idx, uin
if (likely(global->type != WASM_GLOBAL_TYPE_UNUSED)) *dest = (uint64_t)global->value.i64;
}
static inline int32_t
wasm_globals_get_i32(struct vec_wasm_global_t *globals, uint32_t idx)
static inline int
wasm_globals_get_i32(struct vec_wasm_global_t *globals, uint32_t idx, int32_t *return_val)
{
wasm_global_t *global = vec_wasm_global_t_get(globals, idx);
assert(global != NULL);
assert(global->type == WASM_GLOBAL_TYPE_I32);
if (unlikely(global == NULL)) return -1;
if (unlikely(global->type != WASM_GLOBAL_TYPE_I32)) return -2;
return global->value.i32;
*return_val = global->value.i32;
return 0;
}
static inline int64_t
wasm_globals_get_i64(struct vec_wasm_global_t *globals, uint32_t idx)
static inline int
wasm_globals_get_i64(struct vec_wasm_global_t *globals, uint32_t idx, int64_t *return_val)
{
wasm_global_t *global = vec_wasm_global_t_get(globals, idx);
assert(global != NULL);
assert(global->type == WASM_GLOBAL_TYPE_I64);
if (unlikely(global == NULL)) return -1;
if (unlikely(global->type != WASM_GLOBAL_TYPE_I64)) return -2;
return global->value.i64;
*return_val = global->value.i64;
return 0;
}
static inline int32_t
// 0 on success, -1 on out of bounds, -2 on mismatched type
static inline int
wasm_globals_set_i32(struct vec_wasm_global_t *globals, uint32_t idx, int32_t value, bool is_mutable)
{
wasm_global_t *current = vec_wasm_global_t_get(globals, idx);
assert(current->type == WASM_GLOBAL_TYPE_UNUSED || current->mut == true);
if (unlikely(current->type != WASM_GLOBAL_TYPE_UNUSED && current->mut == false)) return -2;
int rc = vec_wasm_global_t_insert(globals, idx,
(wasm_global_t){
@ -88,12 +91,14 @@ wasm_globals_set_i32(struct vec_wasm_global_t *globals, uint32_t idx, int32_t va
return rc;
}
static inline int32_t
// 0 on success, -1 on out of bounds, -2 on mismatched type
static inline int
wasm_globals_set_i64(struct vec_wasm_global_t *globals, uint32_t idx, int64_t value, bool is_mutable)
{
wasm_global_t *current = vec_wasm_global_t_get(globals, idx);
assert(current->type == WASM_GLOBAL_TYPE_UNUSED || current->mut == true);
if (unlikely(current->type != WASM_GLOBAL_TYPE_UNUSED && current->mut == false)) return -2;
// Returns -1 if idx > capacity
int rc = vec_wasm_global_t_insert(globals, idx,
(wasm_global_t){
.mut = is_mutable, .type = WASM_GLOBAL_TYPE_I64, .value = value });

@ -7,6 +7,10 @@
#include "sledge_abi.h"
#include "wasm_types.h"
/* Redeclared due to circular header dependency */
extern void sledge_abi__current_wasm_module_instance_trap(enum sledge_abi__wasm_trap trapno);
/* memory also provides the table access functions */
#define INDIRECT_TABLE_SIZE (1 << 10)
@ -76,7 +80,11 @@ static INLINE void *
wasm_table_get(struct sledge_abi__wasm_table *wasm_table, uint32_t idx, uint32_t type_id)
{
assert(wasm_table != NULL);
assert(idx < wasm_table->capacity);
if (unlikely(idx >= wasm_table->capacity)) {
fprintf(stderr, "idx: %u, Table size: %u\n", idx, INDIRECT_TABLE_SIZE);
sledge_abi__current_wasm_module_instance_trap(WASM_TRAP_INVALID_INDEX);
}
struct sledge_abi__wasm_table_entry f = wasm_table->buffer[idx];
assert(f.type_id == type_id);
@ -90,7 +98,12 @@ static INLINE void
wasm_table_set(struct sledge_abi__wasm_table *wasm_table, uint32_t idx, uint32_t type_id, char *pointer)
{
assert(wasm_table != NULL);
assert(idx < wasm_table->capacity);
if (unlikely(idx >= wasm_table->capacity)) {
fprintf(stderr, "idx: %u, Table size: %u\n", idx, INDIRECT_TABLE_SIZE);
sledge_abi__current_wasm_module_instance_trap(WASM_TRAP_INVALID_INDEX);
}
assert(pointer != NULL);
/* TODO: atomic for multiple concurrent invocations? Issue #97 */

@ -1,4 +1,6 @@
#include <threads.h>
#include <setjmp.h>
#include <threads.h>
#include "current_sandbox.h"
#include "current_sandbox_send_response.h"
@ -77,6 +79,51 @@ current_sandbox_exit()
assert(0);
}
void
current_sandbox_wasm_trap_handler(int trapno)
{
char *error_message = NULL;
struct sandbox *sandbox = current_sandbox_get();
sandbox_syscall(sandbox);
switch (trapno) {
case WASM_TRAP_EXIT:
break;
case WASM_TRAP_INVALID_INDEX:
error_message = "WebAssembly Trap: Invalid Index\n";
client_socket_send(sandbox->client_socket_descriptor, http_header_build(500), http_header_len(500),
current_sandbox_sleep);
break;
case WASM_TRAP_MISMATCHED_TYPE:
error_message = "WebAssembly Trap: Mismatched Type\n";
client_socket_send(sandbox->client_socket_descriptor, http_header_build(500), http_header_len(500),
current_sandbox_sleep);
break;
case WASM_TRAP_PROTECTED_CALL_STACK_OVERFLOW:
error_message = "WebAssembly Trap: Protected Call Stack Overflow\n";
client_socket_send(sandbox->client_socket_descriptor, http_header_build(500), http_header_len(500),
current_sandbox_sleep);
break;
case WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY:
error_message = "WebAssembly Trap: Out of Bounds Linear Memory Access\n";
client_socket_send(sandbox->client_socket_descriptor, http_header_build(500), http_header_len(500),
current_sandbox_sleep);
break;
case WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION:
error_message = "WebAssembly Trap: Illegal Arithmetic Operation\n";
client_socket_send(sandbox->client_socket_descriptor, http_header_build(500), http_header_len(500),
current_sandbox_sleep);
break;
}
debuglog("%s", error_message);
sandbox_close_http(sandbox);
generic_thread_dump_lock_overhead();
current_sandbox_exit();
assert(0);
}
static inline struct sandbox *
current_sandbox_init()
{
@ -127,8 +174,6 @@ err:
sandbox_close_http(sandbox);
generic_thread_dump_lock_overhead();
current_sandbox_exit();
assert(0);
return NULL;
}
@ -178,8 +223,15 @@ err:
void
current_sandbox_start(void)
{
struct sandbox *sandbox = current_sandbox_init();
struct module *current_module = sandbox_get_module(sandbox);
sandbox->return_value = module_entrypoint(current_module);
struct sandbox *sandbox = current_sandbox_init();
int rc = setjmp(sandbox->ctxt.start_buf);
if (rc == 0) {
struct module *current_module = sandbox_get_module(sandbox);
sandbox->return_value = module_entrypoint(current_module);
} else {
current_sandbox_wasm_trap_handler(rc);
}
current_sandbox_fini();
}

@ -16,3 +16,16 @@ thread_local struct wasm_module_instance sledge_abi__current_wasm_module_instanc
.abi.wasmg_0 = 0xDEADBEEF,
.wasi_context = NULL,
};
void
sledge_abi__current_wasm_module_instance_trap(enum sledge_abi__wasm_trap trapno)
{
assert(trapno != 0);
assert(trapno < WASM_TRAP_COUNT);
struct sandbox *sandbox = current_sandbox_get();
assert(sandbox != NULL);
assert(sandbox->state == SANDBOX_RUNNING_USER || sandbox->state == SANDBOX_RUNNING_SYS);
longjmp(sandbox->ctxt.start_buf, trapno);
}

@ -5,6 +5,7 @@
#include <limits.h>
#include <math.h>
#include <printf.h>
#include <setjmp.h>
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
@ -933,9 +934,6 @@ wasi_snapshot_preview1_backing_path_link(wasi_context_t *context, __wasi_fd_t ol
* @param path_baseptr path of the file or directory to open relative to the fd directory.
* @param path_len
* @param oflags The method by which to open the file.
*
*
* @param fs_rights_base
* @param fs_rights_inheriting
* @param fdflags
@ -945,7 +943,6 @@ wasi_snapshot_preview1_backing_path_link(wasi_context_t *context, __wasi_fd_t ol
__wasi_errno_t
wasi_snapshot_preview1_backing_path_open(wasi_context_t *context, __wasi_fd_t dirfd, __wasi_lookupflags_t dirflags,
const char *path, __wasi_size_t path_len, __wasi_oflags_t oflags,
__wasi_rights_t fs_rights_base, __wasi_rights_t fs_rights_inheriting,
__wasi_fdflags_t fdflags, __wasi_fd_t *fd)
{
@ -1067,7 +1064,9 @@ wasi_snapshot_preview1_backing_poll_oneoff(wasi_context_t *context, const __wasi
noreturn void
wasi_snapshot_preview1_backing_proc_exit(wasi_context_t *context, __wasi_exitcode_t exitcode)
{
assert(0);
struct sandbox *s = current_sandbox_get();
s->return_value = exitcode;
longjmp(s->ctxt.start_buf, WASM_TRAP_EXIT);
}
/**

@ -6,6 +6,12 @@
#include "wasi.h"
#include "wasi_serdes.h"
EXPORT void
sledge_abi__wasm_trap_raise(enum sledge_abi__wasm_trap trapno)
{
return current_sandbox_trap(trapno);
}
/**
* @brief Get the memory ptr for runtime object
*
@ -84,10 +90,14 @@ sledge_abi__wasm_globals_get_i32(uint32_t idx)
struct sandbox *sandbox = current_sandbox_get();
sandbox_syscall(sandbox);
int32_t value = wasm_globals_get_i32(&sandbox->globals, idx);
int32_t result;
int rc = wasm_globals_get_i32(&sandbox->globals, idx, &result);
sandbox_return(sandbox);
return value;
if (rc == -1) sledge_abi__wasm_trap_raise(WASM_TRAP_INVALID_INDEX);
if (rc == -2) sledge_abi__wasm_trap_raise(WASM_TRAP_MISMATCHED_TYPE);
return result;
}
EXPORT int64_t
@ -96,13 +106,17 @@ sledge_abi__wasm_globals_get_i64(uint32_t idx)
struct sandbox *sandbox = current_sandbox_get();
sandbox_syscall(sandbox);
int64_t value = wasm_globals_get_i64(&sandbox->globals, idx);
int64_t result;
int rc = wasm_globals_get_i64(&sandbox->globals, idx, &result);
sandbox_return(sandbox);
return value;
if (rc == -1) sledge_abi__wasm_trap_raise(WASM_TRAP_INVALID_INDEX);
if (rc == -2) sledge_abi__wasm_trap_raise(WASM_TRAP_MISMATCHED_TYPE);
return result;
}
EXPORT int32_t
EXPORT void
sledge_abi__wasm_globals_set_i32(uint32_t idx, int32_t value, bool is_mutable)
{
struct sandbox *sandbox = current_sandbox_get();
@ -111,10 +125,12 @@ sledge_abi__wasm_globals_set_i32(uint32_t idx, int32_t value, bool is_mutable)
int32_t rc = wasm_globals_set_i32(&sandbox->globals, idx, value, true);
sandbox_return(sandbox);
return rc;
if (rc == -1) sledge_abi__wasm_trap_raise(WASM_TRAP_INVALID_INDEX);
if (rc == -2) sledge_abi__wasm_trap_raise(WASM_TRAP_MISMATCHED_TYPE);
}
EXPORT int32_t
// 0 on success, -1 on out of bounds, -2 on mismatched type
EXPORT void
sledge_abi__wasm_globals_set_i64(uint32_t idx, int64_t value, bool is_mutable)
{
struct sandbox *sandbox = current_sandbox_get();
@ -123,7 +139,8 @@ sledge_abi__wasm_globals_set_i64(uint32_t idx, int64_t value, bool is_mutable)
int32_t rc = wasm_globals_set_i64(&sandbox->globals, idx, value, true);
sandbox_return(sandbox);
return rc;
if (rc == -1) sledge_abi__wasm_trap_raise(WASM_TRAP_INVALID_INDEX);
if (rc == -2) sledge_abi__wasm_trap_raise(WASM_TRAP_MISMATCHED_TYPE);
}
/**

@ -115,6 +115,13 @@ empty__concurrency: ./runtime/bin/empty.wasm.so
# cd ./tests/empty/concurrency/ && ./install.sh
cd ./tests/empty/concurrency/ && ./run.sh
./runtime/bin/trap_divzero.wasm.so:
make trap_divzero.install -C ./applications
PHONY: trap_divzero
trap_divzero: ./runtime/bin/trap_divzero.wasm.so
cd ./tests/traps/ && ./run.sh
all: \
gocr__all \
ekf__all \

@ -0,0 +1,4 @@
*res.dat
rt.log
log.csv
res/*

@ -0,0 +1,61 @@
RUNTIME_DIR=../../runtime/
SLEDGE_BINARY_DIR=${RUNTIME_DIR}/bin
SLEDGE_TESTS_DIR=${RUNTIME_DIR}/tests
HOSTNAME=localhost
DURATION_SEC=15
all: run
clean:
make -C ${RUNTIME_DIR} clean
make -C ${SLEDGE_TESTS_DIR} clean
rm -f ${SLEDGE_BINARY_DIR}/trap_divzero.wasm.so
${SLEDGE_BINARY_DIR}/sledgert:
make -C ${RUNTIME_DIR} runtime
.PHONY: sledgert
sledgert: ${SLEDGE_BINARY_DIR}/sledgert
${SLEDGE_BINARY_DIR}/trap_divzero.wasm.so:
make -C ../../../applications trap_divzero.install
.PHONY: trap_divzero
trap_divzero: ${SLEDGE_BINARY_DIR}/trap_divzero.wasm.so
run: sledgert trap_divzero
LD_LIBRARY_PATH=${SLEDGE_BINARY_DIR} ${SLEDGE_BINARY_DIR}/sledgert spec.json
debug: sledgert trap_divzero
SLEDGE_DISABLE_PREEMPTION=true SLEDGE_NWORKERS=1 \
LD_LIBRARY_PATH=${SLEDGE_BINARY_DIR} gdb ${SLEDGE_BINARY_DIR}/sledgert \
--eval-command="handle SIGUSR1 noprint nostop" \
--eval-command="handle SIGPIPE noprint nostop" \
--eval-command="set pagination off" \
--eval-command="run spec.json"
client-ok:
echo "1" | http :10000
client-trap:
echo "0" | http :10000
test:
echo "4" | http :10000
echo "0" | http :10000
echo "3" | http :10000
echo "0" | http :10000
echo "2" | http :10000
echo "0" | http :10000
echo "1" | http :10000
echo "0" | http :10000
echo "1" | http :10000
echo "0" | http :10000
echo "2" | http :10000
echo "0" | http :10000
echo "3" | http :10000
echo "0" | http :10000
echo "4" | http :10000
client-fib10-multi:
hey -z ${DURATION_SEC}s -cpus 4 -c 100 -t 0 -o csv -m GET -d "10\n" "http://${HOSTNAME}:10010"

@ -0,0 +1,2 @@
SLEDGE_SCHEDULER=EDF
SLEDGE_DISABLE_PREEMPTION=true

@ -0,0 +1,3 @@
SLEDGE_SCHEDULER=EDF
SLEDGE_DISABLE_PREEMPTION=false
SLEDGE_SIGALRM_HANDLER=TRIAGED

@ -0,0 +1,2 @@
SLEDGE_SCHEDULER=FIFO
SLEDGE_DISABLE_PREEMPTION=true

@ -0,0 +1,2 @@
SLEDGE_SCHEDULER=FIFO
SLEDGE_DISABLE_PREEMPTION=false

@ -0,0 +1,32 @@
#!/bin/bash
__run_sh__base_path="$(dirname "$(realpath --logical "${BASH_SOURCE[0]}")")"
__run_sh__bash_libraries_relative_path="../bash_libraries"
__run_sh__bash_libraries_absolute_path=$(cd "$__run_sh__base_path" && cd "$__run_sh__bash_libraries_relative_path" && pwd)
export PATH="$__run_sh__bash_libraries_absolute_path:$PATH"
source framework.sh || exit 1
source validate_dependencies.sh || exit 1
experiment_client() {
local -r hostname="$1"
for ((i = 1; i <= 10; i++)); do
echo "$i" | http -p h "${hostname}:10000" | grep 200 || {
echo "FAIL"
return 1
}
echo "0" | http -p h "${hostname}:10000" | grep 500 || {
echo "FAIL"
return 1
}
done
echo "SUCCESS"
return 0
}
validate_dependencies http
framework_init "$@"

@ -0,0 +1,13 @@
[
{
"name": "fibonacci_40",
"path": "trap_divzero.wasm.so",
"port": 10000,
"expected-execution-us": 10000000,
"admissions-percentile": 70,
"relative-deadline-us": 20000000,
"http-req-size": 1024,
"http-resp-size": 1024,
"http-resp-content-type": "text/plain"
}
]
Loading…
Cancel
Save