diff --git a/lib/emscripten/src/emscripten_target.rs b/lib/emscripten/src/emscripten_target.rs index 7e0b81af29b..6b13beec8da 100644 --- a/lib/emscripten/src/emscripten_target.rs +++ b/lib/emscripten/src/emscripten_target.rs @@ -15,12 +15,12 @@ pub fn exit_with_live_runtime(_ctx: &mut Ctx) { } pub fn setTempRet0(ctx: &mut Ctx, val: i32) { - debug!("emscripten::setTempRet0: {}", val); + trace!("emscripten::setTempRet0: {}", val); get_emscripten_data(ctx).temp_ret_0 = val; } pub fn getTempRet0(ctx: &mut Ctx) -> i32 { - debug!("emscripten::getTempRet0"); + trace!("emscripten::getTempRet0"); get_emscripten_data(ctx).temp_ret_0 } @@ -69,7 +69,7 @@ pub fn _dladdr(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { 0 } pub fn _pthread_attr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 { - debug!("emscripten::_pthread_attr_destroy"); + trace!("emscripten::_pthread_attr_destroy"); 0 } pub fn _pthread_attr_getstack( @@ -88,136 +88,136 @@ pub fn _pthread_attr_getstack( 0 } pub fn _pthread_attr_init(_ctx: &mut Ctx, _a: i32) -> i32 { - debug!("emscripten::_pthread_attr_init({})", _a); + trace!("emscripten::_pthread_attr_init({})", _a); 0 } pub fn _pthread_attr_setstacksize(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { - debug!("emscripten::_pthread_attr_setstacksize"); + trace!("emscripten::_pthread_attr_setstacksize"); 0 } pub fn _pthread_cleanup_pop(_ctx: &mut Ctx, _a: i32) -> () { - debug!("emscripten::_pthread_cleanup_pop"); + trace!("emscripten::_pthread_cleanup_pop"); } pub fn _pthread_cleanup_push(_ctx: &mut Ctx, _a: i32, _b: i32) -> () { - debug!("emscripten::_pthread_cleanup_push"); + trace!("emscripten::_pthread_cleanup_push"); } pub fn _pthread_cond_destroy(_ctx: &mut Ctx, _a: i32) -> i32 { - debug!("emscripten::_pthread_cond_destroy"); + trace!("emscripten::_pthread_cond_destroy"); 0 } pub fn _pthread_cond_init(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { - debug!("emscripten::_pthread_cond_init"); + trace!("emscripten::_pthread_cond_init"); 0 } pub fn _pthread_cond_signal(_ctx: &mut Ctx, _a: i32) -> i32 { - debug!("emscripten::_pthread_cond_signal"); + trace!("emscripten::_pthread_cond_signal"); 0 } pub fn _pthread_cond_timedwait(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32) -> i32 { - debug!("emscripten::_pthread_cond_timedwait"); + trace!("emscripten::_pthread_cond_timedwait"); 0 } pub fn _pthread_cond_wait(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { - debug!("emscripten::_pthread_cond_wait"); + trace!("emscripten::_pthread_cond_wait"); 0 } pub fn _pthread_condattr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 { - debug!("emscripten::_pthread_condattr_destroy"); + trace!("emscripten::_pthread_condattr_destroy"); 0 } pub fn _pthread_condattr_init(_ctx: &mut Ctx, _a: i32) -> i32 { - debug!("emscripten::_pthread_condattr_init"); + trace!("emscripten::_pthread_condattr_init"); 0 } pub fn _pthread_condattr_setclock(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { - debug!("emscripten::_pthread_condattr_setclock"); + trace!("emscripten::_pthread_condattr_setclock"); 0 } pub fn _pthread_create(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32, _d: i32) -> i32 { - debug!("emscripten::_pthread_create"); + trace!("emscripten::_pthread_create"); 0 } pub fn _pthread_detach(_ctx: &mut Ctx, _a: i32) -> i32 { - debug!("emscripten::_pthread_detach"); + trace!("emscripten::_pthread_detach"); 0 } pub fn _pthread_equal(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { - debug!("emscripten::_pthread_equal"); + trace!("emscripten::_pthread_equal"); 0 } pub fn _pthread_exit(_ctx: &mut Ctx, _a: i32) -> () { - debug!("emscripten::_pthread_exit"); + trace!("emscripten::_pthread_exit"); } pub fn _pthread_getattr_np(_ctx: &mut Ctx, _thread: i32, _attr: i32) -> i32 { - debug!("emscripten::_pthread_getattr_np({}, {})", _thread, _attr); + trace!("emscripten::_pthread_getattr_np({}, {})", _thread, _attr); 0 } pub fn _pthread_getspecific(_ctx: &mut Ctx, _a: i32) -> i32 { - debug!("emscripten::_pthread_getspecific"); + trace!("emscripten::_pthread_getspecific"); 0 } pub fn _pthread_join(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { - debug!("emscripten::_pthread_join"); + trace!("emscripten::_pthread_join"); 0 } pub fn _pthread_key_create(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { - debug!("emscripten::_pthread_key_create"); + trace!("emscripten::_pthread_key_create"); 0 } pub fn _pthread_mutex_destroy(_ctx: &mut Ctx, _a: i32) -> i32 { - debug!("emscripten::_pthread_mutex_destroy"); + trace!("emscripten::_pthread_mutex_destroy"); 0 } pub fn _pthread_mutex_init(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { - debug!("emscripten::_pthread_mutex_init"); + trace!("emscripten::_pthread_mutex_init"); 0 } pub fn _pthread_mutexattr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 { - debug!("emscripten::_pthread_mutexattr_destroy"); + trace!("emscripten::_pthread_mutexattr_destroy"); 0 } pub fn _pthread_mutexattr_init(_ctx: &mut Ctx, _a: i32) -> i32 { - debug!("emscripten::_pthread_mutexattr_init"); + trace!("emscripten::_pthread_mutexattr_init"); 0 } pub fn _pthread_mutexattr_settype(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { - debug!("emscripten::_pthread_mutexattr_settype"); + trace!("emscripten::_pthread_mutexattr_settype"); 0 } pub fn _pthread_once(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { - debug!("emscripten::_pthread_once"); + trace!("emscripten::_pthread_once"); 0 } pub fn _pthread_rwlock_destroy(_ctx: &mut Ctx, _rwlock: i32) -> i32 { - debug!("emscripten::_pthread_rwlock_destroy({})", _rwlock); + trace!("emscripten::_pthread_rwlock_destroy({})", _rwlock); 0 } pub fn _pthread_rwlock_init(_ctx: &mut Ctx, _rwlock: i32, _attr: i32) -> i32 { - debug!("emscripten::_pthread_rwlock_init({}, {})", _rwlock, _attr); + trace!("emscripten::_pthread_rwlock_init({}, {})", _rwlock, _attr); 0 } pub fn _pthread_rwlock_rdlock(_ctx: &mut Ctx, _a: i32) -> i32 { - debug!("emscripten::_pthread_rwlock_rdlock"); + trace!("emscripten::_pthread_rwlock_rdlock"); 0 } pub fn _pthread_rwlock_unlock(_ctx: &mut Ctx, _a: i32) -> i32 { - debug!("emscripten::_pthread_rwlock_unlock"); + trace!("emscripten::_pthread_rwlock_unlock"); 0 } pub fn _pthread_rwlock_wrlock(_ctx: &mut Ctx, _rwlock: i32) -> i32 { - debug!("emscripten::_pthread_rwlock_wrlock({})", _rwlock); + trace!("emscripten::_pthread_rwlock_wrlock({})", _rwlock); 0 } pub fn _pthread_setcancelstate(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { - debug!("emscripten::_pthread_setcancelstate"); + trace!("emscripten::_pthread_setcancelstate"); 0 } pub fn _pthread_setspecific(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 { - debug!("emscripten::_pthread_setspecific"); + trace!("emscripten::_pthread_setspecific"); 0 } pub fn _pthread_sigmask(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32) -> i32 { - debug!("emscripten::_pthread_sigmask"); + trace!("emscripten::_pthread_sigmask"); 0 } pub fn ___gxx_personality_v0( @@ -233,11 +233,6 @@ pub fn ___gxx_personality_v0( 0 } -pub fn _gai_strerror(_ctx: &mut Ctx, _ecode: i32) -> i32 { - debug!("emscripten::_gai_strerror({})", _ecode); - 0 -} - #[cfg(target_os = "linux")] pub fn _getdtablesize(_ctx: &mut Ctx) -> i32 { debug!("emscripten::getdtablesize"); diff --git a/lib/emscripten/src/env/mod.rs b/lib/emscripten/src/env/mod.rs index 98bc39dc8f0..1b958db9e2f 100644 --- a/lib/emscripten/src/env/mod.rs +++ b/lib/emscripten/src/env/mod.rs @@ -13,18 +13,22 @@ pub use self::windows::*; use libc::c_char; use crate::{allocate_on_stack, EmscriptenData}; -use std::os::raw::c_int; -use wasmer_runtime_core::vm::Ctx; -pub fn _getaddrinfo(_ctx: &mut Ctx, _one: i32, _two: i32, _three: i32, _four: i32) -> i32 { - debug!("emscripten::_getaddrinfo"); - -1 -} +use std::os::raw::c_int; +use wasmer_runtime_core::{ + memory::ptr::{Array, WasmPtr}, + types::ValueType, + vm::Ctx, +}; pub fn call_malloc(ctx: &mut Ctx, size: u32) -> u32 { get_emscripten_data(ctx).malloc.call(size).unwrap() } +pub fn call_malloc_with_cast(ctx: &mut Ctx, size: u32) -> WasmPtr { + WasmPtr::new(get_emscripten_data(ctx).malloc.call(size).unwrap()) +} + pub fn call_memalign(ctx: &mut Ctx, alignment: u32, size: u32) -> u32 { if let Some(memalign) = &get_emscripten_data(ctx).memalign { memalign.call(alignment, size).unwrap() @@ -152,3 +156,37 @@ pub fn _fpathconf(_ctx: &mut Ctx, _fildes: c_int, name: c_int) -> c_int { } } } + +#[derive(Debug, Clone, Copy)] +#[repr(C)] +pub struct EmAddrInfo { + // int + pub ai_flags: i32, + // int + pub ai_family: i32, + // int + pub ai_socktype: i32, + // int + pub ai_protocol: i32, + // socklen_t + pub ai_addrlen: u32, + // struct sockaddr* + pub ai_addr: WasmPtr, + // char* + pub ai_canonname: WasmPtr, + // struct addrinfo* + pub ai_next: WasmPtr, +} + +unsafe impl ValueType for EmAddrInfo {} + +// NOTE: from looking at emscripten JS, this should be a union +// TODO: review this, highly likely to have bugs +#[derive(Debug, Clone, Copy)] +#[repr(C)] +pub struct EmSockAddr { + pub sa_family: i16, + pub sa_data: [c_char; 14], +} + +unsafe impl ValueType for EmSockAddr {} diff --git a/lib/emscripten/src/env/unix/mod.rs b/lib/emscripten/src/env/unix/mod.rs index 7c846150f32..35c2b1852d8 100644 --- a/lib/emscripten/src/env/unix/mod.rs +++ b/lib/emscripten/src/env/unix/mod.rs @@ -3,13 +3,17 @@ use libc::{ c_int, getenv, getgrnam as libc_getgrnam, getpwnam as libc_getpwnam, putenv, setenv, sysconf, unsetenv, }; +use std::cell::Cell; use std::ffi::CStr; use std::mem; use std::os::raw::c_char; -use crate::env::call_malloc; +use crate::env::{call_malloc, call_malloc_with_cast, EmAddrInfo, EmSockAddr}; use crate::utils::{copy_cstr_into_wasm, copy_terminated_array_of_cstrs}; -use wasmer_runtime_core::vm::Ctx; +use wasmer_runtime_core::{ + memory::ptr::{Array, WasmPtr}, + vm::Ctx, +}; // #[no_mangle] /// emscripten: _getenv // (name: *const char) -> *const c_char; @@ -140,3 +144,179 @@ pub fn _sysconf(_ctx: &mut Ctx, name: c_int) -> i32 { // TODO: Implement like emscripten expects regarding memory/page size unsafe { sysconf(name) as i32 } // TODO review i64 } + +// this may be a memory leak, probably not though because emscripten does the same thing +pub fn _gai_strerror(ctx: &mut Ctx, ecode: i32) -> i32 { + debug!("emscripten::_gai_strerror({})", ecode); + + let cstr = unsafe { std::ffi::CStr::from_ptr(libc::gai_strerror(ecode)) }; + let bytes = cstr.to_bytes_with_nul(); + let string_on_guest: WasmPtr = call_malloc_with_cast(ctx, bytes.len() as _); + + let writer = unsafe { + string_on_guest + .deref_mut(ctx.memory(0), 0, bytes.len() as _) + .unwrap() + }; + for (i, byte) in bytes.iter().enumerate() { + writer[i].set(*byte as i8); + } + + string_on_guest.offset() as _ +} + +pub fn _getaddrinfo( + ctx: &mut Ctx, + node_ptr: WasmPtr, + service_str_ptr: WasmPtr, + hints_ptr: WasmPtr, + res_val_ptr: WasmPtr>, +) -> i32 { + use libc::{addrinfo, freeaddrinfo}; + debug!("emscripten::_getaddrinfo"); + let memory = ctx.memory(0); + debug!(" => node = {}", unsafe { + node_ptr + .deref(memory) + .map(|np| { + std::ffi::CStr::from_ptr(np as *const Cell as *const c_char) + .to_string_lossy() + }) + .unwrap_or(std::borrow::Cow::Borrowed("null")) + }); + debug!(" => server_str = {}", unsafe { + service_str_ptr + .deref(memory) + .map(|np| { + std::ffi::CStr::from_ptr(np as *const Cell as *const c_char) + .to_string_lossy() + }) + .unwrap_or(std::borrow::Cow::Borrowed("null")) + }); + + let hints = hints_ptr.deref(memory).map(|hints_memory| { + let hints_guest = hints_memory.get(); + unsafe { + let mut hints_native: addrinfo = std::mem::uninitialized(); + hints_native.ai_flags = hints_guest.ai_flags; + hints_native.ai_family = hints_guest.ai_family; + hints_native.ai_socktype = hints_guest.ai_socktype; + hints_native.ai_protocol = hints_guest.ai_protocol; + hints_native.ai_addrlen = 0; + hints_native.ai_addr = std::ptr::null_mut(); + hints_native.ai_canonname = std::ptr::null_mut(); + hints_native.ai_next = std::ptr::null_mut(); + + hints_native + } + }); + + let mut out_ptr: *mut addrinfo = std::ptr::null_mut(); + + // allocate equivalent memory for res_val_ptr + let result = unsafe { + libc::getaddrinfo( + (node_ptr + .deref(memory) + .map(|m| m as *const Cell as *const c_char)) + .unwrap_or(std::ptr::null()), + (service_str_ptr + .deref(memory) + .map(|m| m as *const Cell as *const c_char)) + .unwrap_or(std::ptr::null()), + hints + .as_ref() + .map(|h| h as *const addrinfo) + .unwrap_or(std::ptr::null()), + &mut out_ptr as *mut *mut addrinfo, + ) + }; + if result != 0 { + return result; + } + + // walk linked list and copy over, freeing them from the kernel + let head_of_list = unsafe { + let mut current_host_node = out_ptr; + let mut head_of_list = None; + let mut previous_guest_node: Option> = None; + + while !current_host_node.is_null() { + let current_guest_node_ptr: WasmPtr = + call_malloc_with_cast(ctx, std::mem::size_of::() as _); + if head_of_list.is_none() { + head_of_list = Some(current_guest_node_ptr); + } + + // connect list + if let Some(prev_guest) = previous_guest_node { + let mut pg = prev_guest.deref_mut(ctx.memory(0)).unwrap().get_mut(); + pg.ai_next = current_guest_node_ptr; + } + + // update values + + let host_addrlen = (*current_host_node).ai_addrlen; + // allocate addr and copy data + let guest_sockaddr_ptr = { + let host_sockaddr_ptr = (*current_host_node).ai_addr; + let guest_sockaddr_ptr: WasmPtr = + call_malloc_with_cast(ctx, host_addrlen as _); + let guest_sockaddr = guest_sockaddr_ptr + .deref_mut(ctx.memory(0)) + .unwrap() + .get_mut(); + + guest_sockaddr.sa_family = (*host_sockaddr_ptr).sa_family as i16; + guest_sockaddr.sa_data = (*host_sockaddr_ptr).sa_data.clone(); + guest_sockaddr_ptr + }; + + // allocate canon name on guest and copy data over + let guest_canonname_ptr = { + let str_ptr = (*current_host_node).ai_canonname; + if !str_ptr.is_null() { + let canonname_cstr = std::ffi::CStr::from_ptr(str_ptr); + let canonname_bytes = canonname_cstr.to_bytes_with_nul(); + let str_size = canonname_bytes.len(); + let guest_canonname: WasmPtr = + call_malloc_with_cast(ctx, str_size as _); + + let guest_canonname_writer = guest_canonname + .deref(ctx.memory(0), 0, str_size as _) + .unwrap(); + for (i, b) in canonname_bytes.into_iter().enumerate() { + guest_canonname_writer[i].set(*b as i8) + } + + guest_canonname + } else { + WasmPtr::new(0) + } + }; + + let mut current_guest_node = current_guest_node_ptr + .deref_mut(ctx.memory(0)) + .unwrap() + .get_mut(); + current_guest_node.ai_flags = (*current_host_node).ai_flags; + current_guest_node.ai_family = (*current_host_node).ai_family; + current_guest_node.ai_socktype = (*current_host_node).ai_socktype; + current_guest_node.ai_protocol = (*current_host_node).ai_protocol; + current_guest_node.ai_addrlen = host_addrlen; + current_guest_node.ai_addr = guest_sockaddr_ptr; + current_guest_node.ai_canonname = guest_canonname_ptr; + current_guest_node.ai_next = WasmPtr::new(0); + + previous_guest_node = Some(current_guest_node_ptr); + current_host_node = (*current_host_node).ai_next; + } + // this frees all connected nodes on the linked list + freeaddrinfo(out_ptr); + head_of_list.unwrap_or(WasmPtr::new(0)) + }; + + res_val_ptr.deref(ctx.memory(0)).unwrap().set(head_of_list); + + 0 +} diff --git a/lib/emscripten/src/env/windows/mod.rs b/lib/emscripten/src/env/windows/mod.rs index f738eccbbd4..d6ba0b0da27 100644 --- a/lib/emscripten/src/env/windows/mod.rs +++ b/lib/emscripten/src/env/windows/mod.rs @@ -5,9 +5,9 @@ use std::ffi::CString; use std::mem; use std::os::raw::c_char; -use crate::env::call_malloc; +use crate::env::{call_malloc, EmAddrInfo}; use crate::utils::{copy_cstr_into_wasm, read_string_from_wasm}; -use wasmer_runtime_core::vm::Ctx; +use wasmer_runtime_core::{memory::ptr::WasmPtr, vm::Ctx}; extern "C" { #[link_name = "_putenv"] @@ -131,3 +131,19 @@ pub fn _sysconf(_ctx: &mut Ctx, name: c_int) -> c_long { // stub because sysconf is not valid on windows 0 } + +pub fn _gai_strerror(_ctx: &mut Ctx, _ecode: i32) -> i32 { + debug!("emscripten::_gai_strerror({}) - stub", _ecode); + -1 +} + +pub fn _getaddrinfo( + _ctx: &mut Ctx, + _node_ptr: WasmPtr, + _service_str_ptr: WasmPtr, + _hints_ptr: WasmPtr, + _res_val_ptr: WasmPtr>, +) -> i32 { + debug!("emscripten::_getaddrinfo -- stub"); + -1 +} diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index e7b51a26a91..944fcfa1d33 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -887,7 +887,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "_pthread_setspecific" => func!(crate::emscripten_target::_pthread_setspecific), "_pthread_sigmask" => func!(crate::emscripten_target::_pthread_sigmask), "___gxx_personality_v0" => func!(crate::emscripten_target::___gxx_personality_v0), - "_gai_strerror" => func!(crate::emscripten_target::_gai_strerror), + "_gai_strerror" => func!(crate::env::_gai_strerror), "_getdtablesize" => func!(crate::emscripten_target::_getdtablesize), "_gethostbyaddr" => func!(crate::emscripten_target::_gethostbyaddr), "_gethostbyname" => func!(crate::emscripten_target::_gethostbyname), diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index 743264bf2d3..1c041c434ac 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -434,6 +434,9 @@ pub fn ___syscall54(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int } } +const SOCK_NON_BLOCK: i32 = 2048; +const SOCK_CLOEXC: i32 = 0x80000; + // socketcall #[allow(clippy::cast_ptr_alignment)] pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { @@ -467,13 +470,22 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in debug!("socket: socket"); // socket (domain: c_int, ty: c_int, protocol: c_int) -> c_int let domain: i32 = socket_varargs.get(ctx); - let ty: i32 = socket_varargs.get(ctx); + let ty_and_flags: i32 = socket_varargs.get(ctx); let protocol: i32 = socket_varargs.get(ctx); + let ty = ty_and_flags & (!SOCK_NON_BLOCK) & (!SOCK_CLOEXC); let fd = unsafe { socket(domain, ty, protocol) }; - // set_cloexec - unsafe { - ioctl(fd, FIOCLEX); - }; + + if ty_and_flags & SOCK_CLOEXC != 0 { + // set_cloexec + unsafe { + ioctl(fd, FIOCLEX); + }; + } + + if ty_and_flags & SOCK_NON_BLOCK != 0 { + // do something here + unimplemented!("non blocking sockets"); + } type T = u32; let payload = 1 as *const T as _; @@ -642,18 +654,18 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in // setsockopt (socket: c_int, level: c_int, name: c_int, value: *const c_void, option_len: socklen_t) -> c_int let socket = socket_varargs.get(ctx); - // SOL_SOCKET = 0xffff (BSD, Linux) - let level: i32 = SOL_SOCKET; - let _: u32 = socket_varargs.get(ctx); - // SO_REUSEADDR = 0x4 (BSD, Linux) - let name: i32 = SO_REUSEADDR; - let _: u32 = socket_varargs.get(ctx); + let level: i32 = socket_varargs.get(ctx); + // SOL_SOCKET = 0xffff (BSD, OSX) + let level = if level == 1 { SOL_SOCKET } else { level }; + let name: i32 = socket_varargs.get(ctx); + // SO_REUSEADDR = 0x4 (BSD, OSX) + let name = if name == 2 { SO_REUSEADDR } else { name }; let value: u32 = socket_varargs.get(ctx); let option_len = socket_varargs.get(ctx); let value_addr = emscripten_memory_pointer!(ctx.memory(0), value) as _; // Endian problem let ret = unsafe { setsockopt(socket, level, name, value_addr, option_len) }; - debug!("=> socketfd: {}, level: {} (SOL_SOCKET/0xffff), name: {} (SO_REUSEADDR/4), value_addr: {:?}, option_len: {} = status: {}", socket, level, name, value_addr, option_len, ret); + debug!("=> socketfd: {}, level: {}, name: {}, value_addr: {:?}, option_len: {} = status: {}", socket, level, name, value_addr, option_len, ret); ret } 15 => { diff --git a/lib/runtime-core/src/memory/ptr.rs b/lib/runtime-core/src/memory/ptr.rs index 892668ce5b1..fd249b5e3a6 100644 --- a/lib/runtime-core/src/memory/ptr.rs +++ b/lib/runtime-core/src/memory/ptr.rs @@ -57,6 +57,18 @@ impl WasmPtr { Some(&*cell_ptr) } } + + #[inline] + pub unsafe fn deref_mut<'a>(self, memory: &'a Memory) -> Option<&'a mut Cell> { + if (self.offset as usize) + mem::size_of::() >= memory.size().bytes().0 { + return None; + } + let cell_ptr = align_pointer( + memory.view::().as_ptr().add(self.offset as usize) as usize, + mem::align_of::(), + ) as *mut Cell; + Some(&mut *cell_ptr) + } } impl WasmPtr { @@ -81,6 +93,31 @@ impl WasmPtr { Some(cell_ptrs) } } + + #[inline] + pub unsafe fn deref_mut<'a>( + self, + memory: &'a Memory, + index: u32, + length: u32, + ) -> Option<&'a mut [Cell]> { + // gets the size of the item in the array with padding added such that + // for any index, we will always result an aligned memory access + let item_size = mem::size_of::() + (mem::size_of::() % mem::align_of::()); + let slice_full_len = index as usize + length as usize; + + if (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0 { + return None; + } + + let cell_ptr = align_pointer( + memory.view::().as_ptr().add(self.offset as usize) as usize, + mem::align_of::(), + ) as *mut Cell; + let cell_ptrs = &mut std::slice::from_raw_parts_mut(cell_ptr, slice_full_len) + [index as usize..slice_full_len]; + Some(cell_ptrs) + } } unsafe impl WasmExternType for WasmPtr {