Skip to content

Commit

Permalink
Merge branch 'master' into feature/metering
Browse files Browse the repository at this point in the history
  • Loading branch information
bjfish authored Jun 7, 2019
2 parents e87d507 + ade70c6 commit f6ecfa4
Show file tree
Hide file tree
Showing 11 changed files with 628 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Blocks of changes will separated by version increments.

## **[Unreleased]**

- [#484](https://github.com/wasmerio/wasmer/pull/484) Fix bugs in emscripten socket syscalls
- [#476](https://github.com/wasmerio/wasmer/pull/476) Fix bug with wasi::environ_get, fix off by one error in wasi::environ_sizes_get
- [#470](https://github.com/wasmerio/wasmer/pull/470) Add mapdir support to Emscripten, implement getdents for Unix
- [#467](https://github.com/wasmerio/wasmer/pull/467) `wasmer_instantiate` returns better error messages in the runtime C API
Expand Down
34 changes: 25 additions & 9 deletions lib/emscripten/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,13 +425,25 @@ pub fn ___syscall146(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
}

pub fn ___syscall168(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
debug!("emscripten::___syscall168");
debug!("emscripten::___syscall168 - stub");
-1
}

pub fn ___syscall191(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
debug!("emscripten::___syscall191 - stub");
-1
pub fn ___syscall191(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
let _resource: i32 = varargs.get(ctx);
debug!(
"emscripten::___syscall191 - mostly stub, resource: {}",
_resource
);
let rlim_emptr: i32 = varargs.get(ctx);
let rlim_ptr = emscripten_memory_pointer!(ctx.memory(0), rlim_emptr) as *mut u8;
let rlim = unsafe { slice::from_raw_parts_mut(rlim_ptr, 16) };

// set all to RLIM_INIFINTY
LittleEndian::write_i64(&mut rlim[..], -1);
LittleEndian::write_i64(&mut rlim[8..], -1);

0
}

pub fn ___syscall199(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
Expand Down Expand Up @@ -543,19 +555,23 @@ pub fn ___syscall340(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
debug!("emscripten::___syscall340 (prlimit64), {}", _which);
// NOTE: Doesn't really matter. Wasm modules cannot exceed WASM_PAGE_SIZE anyway.
let _pid: i32 = varargs.get(ctx);
let _resource: i32 = varargs.get(ctx);
let resource: i32 = varargs.get(ctx);
let _new_limit: u32 = varargs.get(ctx);
let old_limit: u32 = varargs.get(ctx);

let val = match resource {
// RLIMIT_NOFILE
7 => 1024,
_ => -1, // RLIM_INFINITY
};

if old_limit != 0 {
// just report no limits
let buf_ptr = emscripten_memory_pointer!(ctx.memory(0), old_limit) as *mut u8;
let buf = unsafe { slice::from_raw_parts_mut(buf_ptr, 16) };

LittleEndian::write_i32(&mut buf[..], -1); // RLIM_INFINITY
LittleEndian::write_i32(&mut buf[4..], -1); // RLIM_INFINITY
LittleEndian::write_i32(&mut buf[8..], -1); // RLIM_INFINITY
LittleEndian::write_i32(&mut buf[12..], -1); // RLIM_INFINITY
LittleEndian::write_i64(&mut buf[..], val);
LittleEndian::write_i64(&mut buf[8..], val);
}

0
Expand Down
18 changes: 15 additions & 3 deletions lib/emscripten/src/syscalls/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,15 +610,24 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
// recvfrom (socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t) -> ssize_t
let socket = socket_varargs.get(ctx);
let buf: u32 = socket_varargs.get(ctx);
let flags = socket_varargs.get(ctx);
let len: i32 = socket_varargs.get(ctx);
let flags: i32 = socket_varargs.get(ctx);
let address: u32 = socket_varargs.get(ctx);
let address_len: u32 = socket_varargs.get(ctx);
let buf_addr = emscripten_memory_pointer!(ctx.memory(0), buf) as _;
let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut sockaddr;
let address_len_addr =
emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut socklen_t;
unsafe { recvfrom(socket, buf_addr, flags, len, address, address_len_addr) as i32 }
unsafe {
recvfrom(
socket,
buf_addr,
len as usize,
flags,
address,
address_len_addr,
) as i32
}
}
14 => {
debug!("socket: setsockopt");
Expand Down Expand Up @@ -764,7 +773,10 @@ pub fn ___syscall142(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
let exceptfds: u32 = varargs.get(ctx);
let _timeout: i32 = varargs.get(ctx);

assert!(nfds <= 64, "`nfds` must be less than or equal to 64");
if nfds > 1024 {
// EINVAL
return -22;
}
assert!(exceptfds == 0, "`exceptfds` is not supporrted");

let readfds_ptr = emscripten_memory_pointer!(ctx.memory(0), readfds) as _;
Expand Down
2 changes: 2 additions & 0 deletions lib/runtime-c-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ pub mod instance;
pub mod memory;
pub mod module;
pub mod table;
#[cfg(all(unix, target_arch = "x86_64"))]
pub mod trampoline;
pub mod value;

#[allow(non_camel_case_types)]
Expand Down
84 changes: 84 additions & 0 deletions lib/runtime-c-api/src/trampoline.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
//! Trampoline emitter for transforming function calls.
use std::ffi::c_void;
use std::mem;
use wasmer_runtime_core::trampoline::*;

#[repr(C)]
pub struct wasmer_trampoline_buffer_builder_t;

#[repr(C)]
pub struct wasmer_trampoline_buffer_t;

#[repr(C)]
pub struct wasmer_trampoline_callable_t;

/// Creates a new trampoline builder.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub extern "C" fn wasmer_trampoline_buffer_builder_new() -> *mut wasmer_trampoline_buffer_builder_t
{
Box::into_raw(Box::new(TrampolineBufferBuilder::new())) as *mut _
}

/// Adds a context trampoline to the builder.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn wasmer_trampoline_buffer_builder_add_context_trampoline(
builder: *mut wasmer_trampoline_buffer_builder_t,
func: *const wasmer_trampoline_callable_t,
ctx: *const c_void,
) -> usize {
let builder = &mut *(builder as *mut TrampolineBufferBuilder);
builder.add_context_trampoline(func as *const CallTarget, ctx as *const CallContext)
}

/// Adds a callinfo trampoline to the builder.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn wasmer_trampoline_buffer_builder_add_callinfo_trampoline(
builder: *mut wasmer_trampoline_buffer_builder_t,
func: *const wasmer_trampoline_callable_t,
ctx: *const c_void,
num_params: u32,
) -> usize {
let builder = &mut *(builder as *mut TrampolineBufferBuilder);
builder.add_callinfo_trampoline(mem::transmute(func), ctx as *const CallContext, num_params)
}

/// Finalizes the trampoline builder into an executable buffer.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn wasmer_trampoline_buffer_builder_build(
builder: *mut wasmer_trampoline_buffer_builder_t,
) -> *mut wasmer_trampoline_buffer_t {
let builder = Box::from_raw(builder as *mut TrampolineBufferBuilder);
Box::into_raw(Box::new(builder.build())) as *mut _
}

/// Destroys the trampoline buffer if not null.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn wasmer_trampoline_buffer_destroy(buffer: *mut wasmer_trampoline_buffer_t) {
if !buffer.is_null() {
Box::from_raw(buffer);
}
}

/// Returns the callable pointer for the trampoline with index `idx`.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn wasmer_trampoline_buffer_get_trampoline(
buffer: *const wasmer_trampoline_buffer_t,
idx: usize,
) -> *const wasmer_trampoline_callable_t {
let buffer = &*(buffer as *const TrampolineBuffer);
buffer.get_trampoline(idx) as _
}

/// Returns the context added by `add_context_trampoline`, from within the callee function.
#[no_mangle]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn wasmer_trampoline_get_context() -> *mut c_void {
get_context() as *const c_void as *mut c_void
}
132 changes: 132 additions & 0 deletions lib/runtime-c-api/tests/test-import-function-callinfo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#include <stdio.h>
#include "../wasmer.h"
#include <assert.h>
#include <stdint.h>
#include <string.h>

static bool print_str_called = false;
static int memory_len = 0;
static int ptr_len = 0;
static char actual_str[14] = {};
static int actual_context_data_value = 0;

typedef struct {
int value;
} context_data;

struct print_str_context {
int call_count;
};

void print_str(struct print_str_context *local_context, uint64_t *args)
{
local_context->call_count++;

wasmer_instance_context_t *ctx = (void *) args[0];
int32_t ptr = args[1];
int32_t len = args[2];

const wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0);
uint32_t mem_len = wasmer_memory_length(memory);
uint8_t *mem_bytes = wasmer_memory_data(memory);
for (int32_t idx = 0; idx < len; idx++)
{
actual_str[idx] = mem_bytes[ptr + idx];
}
actual_str[13] = '\0';
printf("In print_str, memory len: %d, ptr_len: %d\n, str %s", mem_len, len, actual_str);
print_str_called = true;
memory_len = mem_len;
ptr_len = len;

actual_context_data_value = ((context_data *) wasmer_instance_context_data_get(ctx))->value;
}

int main()
{
wasmer_value_tag params_sig[] = {WASM_I32, WASM_I32};
wasmer_value_tag returns_sig[] = {};
struct print_str_context local_context = {
.call_count = 0
};

printf("Creating trampoline buffer\n");
wasmer_trampoline_buffer_builder_t *tbb = wasmer_trampoline_buffer_builder_new();
unsigned long print_str_idx = wasmer_trampoline_buffer_builder_add_callinfo_trampoline(
tbb,
(wasmer_trampoline_callable_t *) print_str,
(void *) &local_context,
3
);
wasmer_trampoline_buffer_t *tb = wasmer_trampoline_buffer_builder_build(tbb);
const wasmer_trampoline_callable_t *print_str_callable = wasmer_trampoline_buffer_get_trampoline(tb, print_str_idx);

printf("Creating new func\n");
wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) print_str_callable, params_sig, 2, returns_sig, 0);
wasmer_import_t import;

char *module_name = "env";
wasmer_byte_array module_name_bytes;
module_name_bytes.bytes = (const uint8_t *) module_name;
module_name_bytes.bytes_len = strlen(module_name);
char *import_name = "print_str";
wasmer_byte_array import_name_bytes;
import_name_bytes.bytes = (const uint8_t *) import_name;
import_name_bytes.bytes_len = strlen(import_name);

import.module_name = module_name_bytes;
import.import_name = import_name_bytes;
import.tag = WASM_FUNCTION;
import.value.func = func;
wasmer_import_t imports[] = {import};

// Read the wasm file bytes
FILE *file = fopen("assets/wasm_sample_app.wasm", "r");
fseek(file, 0, SEEK_END);
long len = ftell(file);
uint8_t *bytes = malloc(len);
fseek(file, 0, SEEK_SET);
fread(bytes, 1, len, file);
fclose(file);

printf("Instantiating\n");
wasmer_instance_t *instance = NULL;
wasmer_result_t compile_result = wasmer_instantiate(&instance, bytes, len, imports, 1);
printf("Compile result: %d\n", compile_result);

assert(compile_result == WASMER_OK);

context_data* context_data = malloc(sizeof(context_data));
int context_data_value = 42;
context_data->value = context_data_value;
wasmer_instance_context_data_set(instance, context_data);

wasmer_value_t params[] = {};
wasmer_value_t results[] = {};
wasmer_result_t call_result = wasmer_instance_call(instance, "hello_wasm", params, 0, results, 0);
printf("Call result: %d\n", call_result);

int error_len = wasmer_last_error_length();
printf("Error len: `%d`\n", error_len);
char *error_str = malloc(error_len);
wasmer_last_error_message(error_str, error_len);
printf("Error str: `%s`\n", error_str);

assert(call_result == WASMER_OK);

assert(print_str_called);
assert(memory_len == 17);
assert(ptr_len == 13);
assert(0 == strcmp(actual_str, "Hello, World!"));
assert(context_data_value == actual_context_data_value);
assert(local_context.call_count == 1);

printf("Destroying trampoline buffer\n");
wasmer_trampoline_buffer_destroy(tb);
printf("Destroying func\n");
wasmer_import_func_destroy(func);
printf("Destroy instance\n");
wasmer_instance_destroy(instance);
free(context_data);
return 0;
}
25 changes: 24 additions & 1 deletion lib/runtime-c-api/tests/test-import-function.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,15 @@ typedef struct {
int value;
} context_data;

struct print_str_context {
int call_count;
};

void print_str(wasmer_instance_context_t *ctx, int32_t ptr, int32_t len)
{
struct print_str_context *local_context = wasmer_trampoline_get_context();
local_context->call_count++;

const wasmer_memory_t *memory = wasmer_instance_context_memory(ctx, 0);
uint32_t mem_len = wasmer_memory_length(memory);
uint8_t *mem_bytes = wasmer_memory_data(memory);
Expand All @@ -36,9 +43,22 @@ int main()
{
wasmer_value_tag params_sig[] = {WASM_I32, WASM_I32};
wasmer_value_tag returns_sig[] = {};
struct print_str_context local_context = {
.call_count = 0
};

printf("Creating trampoline buffer\n");
wasmer_trampoline_buffer_builder_t *tbb = wasmer_trampoline_buffer_builder_new();
unsigned long print_str_idx = wasmer_trampoline_buffer_builder_add_context_trampoline(
tbb,
(wasmer_trampoline_callable_t *) print_str,
(void *) &local_context
);
wasmer_trampoline_buffer_t *tb = wasmer_trampoline_buffer_builder_build(tbb);
const wasmer_trampoline_callable_t *print_str_callable = wasmer_trampoline_buffer_get_trampoline(tb, print_str_idx);

printf("Creating new func\n");
wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) print_str, params_sig, 2, returns_sig, 0);
wasmer_import_func_t *func = wasmer_import_func_new((void (*)(void *)) print_str_callable, params_sig, 2, returns_sig, 0);
wasmer_import_t import;

char *module_name = "env";
Expand Down Expand Up @@ -95,7 +115,10 @@ int main()
assert(ptr_len == 13);
assert(0 == strcmp(actual_str, "Hello, World!"));
assert(context_data_value == actual_context_data_value);
assert(local_context.call_count == 1);

printf("Destroying trampoline buffer\n");
wasmer_trampoline_buffer_destroy(tb);
printf("Destroying func\n");
wasmer_import_func_destroy(func);
printf("Destroy instance\n");
Expand Down
Loading

0 comments on commit f6ecfa4

Please sign in to comment.