diff --git a/src/apis/emscripten/env.rs b/src/apis/emscripten/env.rs index 179067926..8d5d76583 100644 --- a/src/apis/emscripten/env.rs +++ b/src/apis/emscripten/env.rs @@ -1,15 +1,12 @@ use super::super::host; /// NOTE: These syscalls only support wasm_32 for now because they take u32 offset -use libc::{ - c_int, getpwnam as libc_getpwnam, - getgrnam as libc_getgrnam, -}; +use libc::{c_int, getgrnam as libc_getgrnam, getpwnam as libc_getpwnam}; use std::ffi::CStr; -use std::os::raw::c_char; use std::mem; +use std::os::raw::c_char; -use crate::webassembly::Instance; use super::utils::{copy_cstr_into_wasm, copy_terminated_array_of_cstrs}; +use crate::webassembly::Instance; /// emscripten: _getenv pub extern "C" fn _getenv(name_ptr: c_int, instance: &mut Instance) -> c_int { @@ -47,9 +44,11 @@ pub extern "C" fn _getpwnam(name_ptr: c_int, instance: &mut Instance) -> c_int { unsafe { let passwd = &*libc_getpwnam(name.as_ptr()); - let passwd_struct_offset = (instance.emscripten_data.malloc)(mem::size_of::() as _, instance); + let passwd_struct_offset = + (instance.emscripten_data.malloc)(mem::size_of::() as _, instance); - let passwd_struct_ptr = instance.memory_offset_addr(0, passwd_struct_offset as _) as *mut GuestPasswd; + let passwd_struct_ptr = + instance.memory_offset_addr(0, passwd_struct_offset as _) as *mut GuestPasswd; (*passwd_struct_ptr).pw_name = copy_cstr_into_wasm(instance, passwd.pw_name); (*passwd_struct_ptr).pw_passwd = copy_cstr_into_wasm(instance, passwd.pw_passwd); (*passwd_struct_ptr).pw_gecos = copy_cstr_into_wasm(instance, passwd.pw_gecos); @@ -80,9 +79,11 @@ pub extern "C" fn _getgrnam(name_ptr: c_int, instance: &mut Instance) -> c_int { unsafe { let group = &*libc_getgrnam(name.as_ptr()); - let group_struct_offset = (instance.emscripten_data.malloc)(mem::size_of::() as _, instance); + let group_struct_offset = + (instance.emscripten_data.malloc)(mem::size_of::() as _, instance); - let group_struct_ptr = instance.memory_offset_addr(0, group_struct_offset as _) as *mut GuestGroup; + let group_struct_ptr = + instance.memory_offset_addr(0, group_struct_offset as _) as *mut GuestGroup; (*group_struct_ptr).gr_name = copy_cstr_into_wasm(instance, group.gr_name); (*group_struct_ptr).gr_passwd = copy_cstr_into_wasm(instance, group.gr_passwd); (*group_struct_ptr).gr_gid = group.gr_gid; @@ -92,12 +93,12 @@ pub extern "C" fn _getgrnam(name_ptr: c_int, instance: &mut Instance) -> c_int { } } -pub extern fn _localtime_r() -> u32 { +pub extern "C" fn _localtime_r() -> u32 { debug!("emscripten::_localtime_r"); 0 } -pub extern fn _getpagesize() -> u32 { +pub extern "C" fn _getpagesize() -> u32 { debug!("emscripten::_getpagesize"); 16384 -} \ No newline at end of file +} diff --git a/src/apis/emscripten/errno.rs b/src/apis/emscripten/errno.rs index 9a671af24..02d76b050 100644 --- a/src/apis/emscripten/errno.rs +++ b/src/apis/emscripten/errno.rs @@ -263,4 +263,3 @@ pub extern "C" fn ___seterrno(value: i32) -> i32 { // } // } // } - diff --git a/src/apis/emscripten/lock.rs b/src/apis/emscripten/lock.rs index cf15a7e02..5ac0f83e0 100644 --- a/src/apis/emscripten/lock.rs +++ b/src/apis/emscripten/lock.rs @@ -1,5 +1,5 @@ -use libc::c_int; use crate::webassembly::Instance; +use libc::c_int; // NOTE: Not implemented by Emscripten pub extern "C" fn ___lock(_which: c_int, _varargs: c_int, _instance: &mut Instance) {} diff --git a/src/apis/emscripten/memory.rs b/src/apis/emscripten/memory.rs index eb968c8be..be288f397 100644 --- a/src/apis/emscripten/memory.rs +++ b/src/apis/emscripten/memory.rs @@ -1,6 +1,6 @@ -use libc::{c_void, memcpy, size_t}; -use crate::webassembly::Instance; use super::process::abort_with_message; +use crate::webassembly::Instance; +use libc::{c_void, memcpy, size_t}; /// emscripten: _emscripten_memcpy_big pub extern "C" fn _emscripten_memcpy_big( diff --git a/src/apis/emscripten/mod.rs b/src/apis/emscripten/mod.rs index a0c880247..eff9e5f94 100644 --- a/src/apis/emscripten/mod.rs +++ b/src/apis/emscripten/mod.rs @@ -1,24 +1,24 @@ +use byteorder::{ByteOrder, LittleEndian}; /// NOTE: TODO: These emscripten api implementation only support wasm32 for now because they assume offsets are u32 use crate::webassembly::{ImportObject, ImportValue, LinearMemory}; -use byteorder::{ByteOrder, LittleEndian}; use std::mem; // EMSCRIPTEN APIS mod env; +mod errno; mod io; -mod memory; -mod process; -mod syscalls; mod lock; +mod memory; +mod nullfunc; +mod process; +mod storage; +mod syscalls; +mod time; mod utils; mod varargs; -mod errno; -mod storage; -mod nullfunc; -mod time; -pub use self::utils::is_emscripten_module; pub use self::storage::{align_memory, static_alloc}; +pub use self::utils::is_emscripten_module; // TODO: Magic number - how is this calculated? const TOTAL_STACK: u32 = 5242880; @@ -51,21 +51,17 @@ fn dynamictop_ptr(static_bump: u32) -> u32 { pub fn emscripten_set_up_memory(memory: &mut LinearMemory) { let dynamictop_ptr = dynamictop_ptr(STATIC_BUMP) as usize; - let mem = &mut memory[dynamictop_ptr..dynamictop_ptr+mem::size_of::()]; + let mem = &mut memory[dynamictop_ptr..dynamictop_ptr + mem::size_of::()]; LittleEndian::write_u32(mem, dynamic_base(STATIC_BUMP)); } macro_rules! mock_external { ($import:ident, $name:ident) => {{ - extern fn _mocked_fn() -> i32 { + extern "C" fn _mocked_fn() -> i32 { debug!("emscripten::{} ", stringify!($name)); -1 } - $import.set( - "env", - stringify!($name), - ImportValue::Func(_mocked_fn as _), - ); + $import.set("env", stringify!($name), ImportValue::Func(_mocked_fn as _)); }}; } @@ -103,11 +99,7 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { "DYNAMICTOP_PTR", ImportValue::Global(dynamictop_ptr(STATIC_BUMP) as _), ); - import_object.set( - "env", - "tableBase", - ImportValue::Global(0), - ); + import_object.set("env", "tableBase", ImportValue::Global(0)); // Print functions import_object.set("env", "printf", ImportValue::Func(io::printf as *const u8)); @@ -133,16 +125,8 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { "_getenv", ImportValue::Func(env::_getenv as *const u8), ); - import_object.set( - "env", - "_getpwnam", - ImportValue::Func(env::_getpwnam as _), - ); - import_object.set( - "env", - "_getgrnam", - ImportValue::Func(env::_getgrnam as _), - ); + import_object.set("env", "_getpwnam", ImportValue::Func(env::_getpwnam as _)); + import_object.set("env", "_getgrnam", ImportValue::Func(env::_getgrnam as _)); // Errno import_object.set( "env", @@ -370,16 +354,8 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { "_localtime", ImportValue::Func(time::_localtime as _), ); - import_object.set( - "env", - "_time", - ImportValue::Func(time::_time as _), - ); - import_object.set( - "env", - "_strftime", - ImportValue::Func(time::_strftime as _), - ); + import_object.set("env", "_time", ImportValue::Func(time::_time as _)); + import_object.set("env", "_strftime", ImportValue::Func(time::_strftime as _)); import_object.set( "env", "_localtime_r", diff --git a/src/apis/emscripten/nullfunc.rs b/src/apis/emscripten/nullfunc.rs index b12035152..34d677c7c 100644 --- a/src/apis/emscripten/nullfunc.rs +++ b/src/apis/emscripten/nullfunc.rs @@ -36,4 +36,3 @@ pub extern "C" fn nullfunc_viii(_x: u32, _instance: &Instance) { pub extern "C" fn nullfunc_viiii(_x: u32, _instance: &Instance) { abort_with_message("Invalid function pointer called with signature 'viiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); } - diff --git a/src/apis/emscripten/storage.rs b/src/apis/emscripten/storage.rs index d74a574ef..382bc2e43 100644 --- a/src/apis/emscripten/storage.rs +++ b/src/apis/emscripten/storage.rs @@ -1,4 +1,3 @@ - use crate::webassembly::LinearMemory; pub fn align_memory(ptr: u32) -> u32 { @@ -18,6 +17,9 @@ pub fn static_alloc(size: u32, static_top: &mut u32, memory: &LinearMemory) -> u let total_memory = memory.maximum_size() * LinearMemory::PAGE_SIZE; // NOTE: The `4294967280` is a u32 conversion of -16 as gotten from emscripten. *static_top = (*static_top + size + 15) & 4294967280; - assert!(*static_top < total_memory, "not enough memory for static allocation - increase total_memory!"); + assert!( + *static_top < total_memory, + "not enough memory for static allocation - increase total_memory!" + ); old_static_top } diff --git a/src/apis/emscripten/syscalls.rs b/src/apis/emscripten/syscalls.rs index 31ea74d9f..8848701cf 100644 --- a/src/apis/emscripten/syscalls.rs +++ b/src/apis/emscripten/syscalls.rs @@ -1,34 +1,66 @@ +use super::utils::copy_stat_into_wasm; +use super::varargs::VarArgs; +use crate::webassembly::Instance; /// NOTE: TODO: These syscalls only support wasm_32 for now because they assume offsets are u32 /// Syscall list: https://www.cs.utexas.edu/~bismith/test/syscalls/syscalls32.html use libc::{ - c_int, c_void, utsname, off_t, - ssize_t, write, exit, read, - open, close, - uname, lseek, readv, - iovec, writev, socklen_t, - sockaddr, socket, bind, - connect, listen, accept, - getsockname, getpeername, - sendto, recvfrom, - getsockopt, sendmsg, recvmsg, - msghdr, getpid, pid_t, - gid_t, getgid, fstat, stat, - pread, mkdir, chown, + accept, + bind, + c_int, + c_void, + chown, // fcntl, ioctl, setsockopt, getppid + close, + connect, + exit, + fstat, + getgid, + getpeername, + getpid, + getsockname, + getsockopt, + gid_t, + iovec, + listen, + lseek, + mkdir, + msghdr, + off_t, + open, + pid_t, + pread, + read, + readv, + recvfrom, + recvmsg, + sendmsg, + sendto, + sockaddr, + socket, + socklen_t, + ssize_t, + stat, + uname, + utsname, + write, + writev, }; -use crate::webassembly::Instance; -use super::varargs::VarArgs; -use super::utils::copy_stat_into_wasm; /// sys_exit pub extern "C" fn ___syscall1(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) { debug!("emscripten::___syscall1"); let status: i32 = varargs.get(instance); - unsafe { exit(status); } + unsafe { + exit(status); + } } /// sys_read -pub extern "C" fn ___syscall3(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> ssize_t { +pub extern "C" fn ___syscall3( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> ssize_t { debug!("emscripten::___syscall3"); let fd: i32 = varargs.get(instance); let buf: u32 = varargs.get(instance); @@ -39,7 +71,11 @@ pub extern "C" fn ___syscall3(_which: c_int, mut varargs: VarArgs, instance: &mu } /// sys_write -pub extern "C" fn ___syscall4(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> c_int { +pub extern "C" fn ___syscall4( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { debug!("emscripten::___syscall4"); let fd: i32 = varargs.get(instance); let buf: u32 = varargs.get(instance); @@ -50,7 +86,11 @@ pub extern "C" fn ___syscall4(_which: c_int, mut varargs: VarArgs, instance: &mu } /// sys_open -pub extern "C" fn ___syscall5(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> c_int { +pub extern "C" fn ___syscall5( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { debug!("emscripten::___syscall5"); let pathname: u32 = varargs.get(instance); let flags: i32 = varargs.get(instance); @@ -67,7 +107,11 @@ pub extern "C" fn ___syscall5(_which: c_int, mut varargs: VarArgs, instance: &mu } /// sys_close -pub extern "C" fn ___syscall6(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> c_int { +pub extern "C" fn ___syscall6( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { debug!("emscripten::___syscall6"); let fd: i32 = varargs.get(instance); debug!("fd: {}", fd); @@ -75,7 +119,11 @@ pub extern "C" fn ___syscall6(_which: c_int, mut varargs: VarArgs, instance: &mu } /// sys_ioctl -pub extern "C" fn ___syscall54(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> c_int { +pub extern "C" fn ___syscall54( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { debug!("emscripten::___syscall54"); let _fd: i32 = varargs.get(instance); let _request: u32 = varargs.get(instance); @@ -86,7 +134,11 @@ pub extern "C" fn ___syscall54(_which: c_int, mut varargs: VarArgs, instance: &m /// sys_uname // NOTE: Wondering if we should return custom utsname, like Emscripten. -pub extern "C" fn ___syscall122(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> c_int { +pub extern "C" fn ___syscall122( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { debug!("emscripten::___syscall122"); let buf: u32 = varargs.get(instance); debug!("buf: {}", buf); @@ -95,7 +147,11 @@ pub extern "C" fn ___syscall122(_which: c_int, mut varargs: VarArgs, instance: & } /// sys_lseek -pub extern "C" fn ___syscall140(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> off_t { +pub extern "C" fn ___syscall140( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> off_t { debug!("emscripten::___syscall145"); let fd: i32 = varargs.get(instance); let offset: i64 = varargs.get(instance); @@ -105,7 +161,11 @@ pub extern "C" fn ___syscall140(_which: c_int, mut varargs: VarArgs, instance: & } /// sys_readv -pub extern "C" fn ___syscall145(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> ssize_t { +pub extern "C" fn ___syscall145( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> ssize_t { debug!("emscripten::___syscall145"); let fd: i32 = varargs.get(instance); let iov: u32 = varargs.get(instance); @@ -116,7 +176,11 @@ pub extern "C" fn ___syscall145(_which: c_int, mut varargs: VarArgs, instance: & } // sys_writev -pub extern "C" fn ___syscall146(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> ssize_t { +pub extern "C" fn ___syscall146( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> ssize_t { debug!("emscripten::___syscall145"); let fd: i32 = varargs.get(instance); let iov: u32 = varargs.get(instance); @@ -136,65 +200,80 @@ pub extern "C" fn ___syscall146(_which: c_int, mut varargs: VarArgs, instance: & // } // sys_socketcall -pub extern "C" fn ___syscall102(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> c_int { +pub extern "C" fn ___syscall102( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { debug!("emscripten::___syscall102"); let call: u32 = varargs.get(instance); let mut socket_varargs: VarArgs = varargs.get(instance); match call { - 1 => { // socket (domain: c_int, ty: c_int, protocol: c_int) -> c_int + 1 => { + // socket (domain: c_int, ty: c_int, protocol: c_int) -> c_int let domain: i32 = socket_varargs.get(instance); let ty: i32 = socket_varargs.get(instance); let protocol: i32 = socket_varargs.get(instance); let socket = unsafe { socket(domain, ty, protocol) }; debug!("socket: {}", socket); socket - }, - 2 => { // bind (socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int + } + 2 => { + // bind (socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int // TODO: Emscripten has a different signature. let socket: i32 = socket_varargs.get(instance); let address: u32 = socket_varargs.get(instance); let address_len: u32 = socket_varargs.get(instance); let address = instance.memory_offset_addr(0, address as usize) as *mut sockaddr; unsafe { bind(socket, address, address_len) } - }, - 3 => { // connect (socket: c_int, address: *const sockaddr, len: socklen_t) -> c_int + } + 3 => { + // connect (socket: c_int, address: *const sockaddr, len: socklen_t) -> c_int // TODO: Emscripten has a different signature. let socket: i32 = socket_varargs.get(instance); let address: u32 = socket_varargs.get(instance); let address_len: u32 = socket_varargs.get(instance); let address = instance.memory_offset_addr(0, address as usize) as *mut sockaddr; unsafe { connect(socket, address, address_len) } - }, - 4 => { // listen (socket: c_int, backlog: c_int) -> c_int + } + 4 => { + // listen (socket: c_int, backlog: c_int) -> c_int let socket: i32 = socket_varargs.get(instance); let backlog: i32 = socket_varargs.get(instance); unsafe { listen(socket, backlog) } - }, - 5 => { // accept (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int + } + 5 => { + // accept (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int let socket: i32 = socket_varargs.get(instance); let address: u32 = socket_varargs.get(instance); let address_len: u32 = socket_varargs.get(instance); let address = instance.memory_offset_addr(0, address as usize) as *mut sockaddr; - let address_len_addr = instance.memory_offset_addr(0, address_len as usize) as *mut socklen_t; + let address_len_addr = + instance.memory_offset_addr(0, address_len as usize) as *mut socklen_t; unsafe { accept(socket, address, address_len_addr) } - }, - 6 => { // getsockname (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int + } + 6 => { + // getsockname (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int let socket: i32 = socket_varargs.get(instance); let address: u32 = socket_varargs.get(instance); let address_len: u32 = socket_varargs.get(instance); let address = instance.memory_offset_addr(0, address as usize) as *mut sockaddr; - let address_len_addr = instance.memory_offset_addr(0, address_len as usize) as *mut socklen_t; + let address_len_addr = + instance.memory_offset_addr(0, address_len as usize) as *mut socklen_t; unsafe { getsockname(socket, address, address_len_addr) } - }, - 7 => { // getpeername (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int + } + 7 => { + // getpeername (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int let socket: i32 = socket_varargs.get(instance); let address: u32 = socket_varargs.get(instance); let address_len: u32 = socket_varargs.get(instance); let address = instance.memory_offset_addr(0, address as usize) as *mut sockaddr; - let address_len_addr = instance.memory_offset_addr(0, address_len as usize) as *mut socklen_t; + let address_len_addr = + instance.memory_offset_addr(0, address_len as usize) as *mut socklen_t; unsafe { getpeername(socket, address, address_len_addr) } - }, - 11 => { // sendto (socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t) -> ssize_t + } + 11 => { + // sendto (socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t) -> ssize_t let socket: i32 = socket_varargs.get(instance); let buf: u32 = socket_varargs.get(instance); let flags: usize = socket_varargs.get(instance); @@ -204,8 +283,9 @@ pub extern "C" fn ___syscall102(_which: c_int, mut varargs: VarArgs, instance: & let buf_addr = instance.memory_offset_addr(0, buf as usize) as *mut c_void; let address = instance.memory_offset_addr(0, address as usize) as *mut sockaddr; unsafe { sendto(socket, buf_addr, flags, len, address, address_len) as i32 } - }, - 12 => { // recvfrom (socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t) -> ssize_t + } + 12 => { + // recvfrom (socket: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t) -> ssize_t let socket: i32 = socket_varargs.get(instance); let buf: u32 = socket_varargs.get(instance); let flags: usize = socket_varargs.get(instance); @@ -214,10 +294,12 @@ pub extern "C" fn ___syscall102(_which: c_int, mut varargs: VarArgs, instance: & let address_len: u32 = socket_varargs.get(instance); let buf_addr = instance.memory_offset_addr(0, buf as usize) as *mut c_void; let address = instance.memory_offset_addr(0, address as usize) as *mut sockaddr; - let address_len_addr = instance.memory_offset_addr(0, address_len as usize) as *mut socklen_t; + let address_len_addr = + instance.memory_offset_addr(0, address_len as usize) as *mut socklen_t; unsafe { recvfrom(socket, buf_addr, flags, len, address, address_len_addr) as i32 } - }, - 14 => { // setsockopt (socket: c_int, level: c_int, name: c_int, value: *const c_void, option_len: socklen_t) -> c_int + } + 14 => { + // setsockopt (socket: c_int, level: c_int, name: c_int, value: *const c_void, option_len: socklen_t) -> c_int // let socket: i32 = socket_varargs.get(instance); // debug!("socket: {}", socket); // let level: i32 = socket_varargs.get(instance); @@ -229,7 +311,7 @@ pub extern "C" fn ___syscall102(_which: c_int, mut varargs: VarArgs, instance: & // let option_len: u32 = socket_varargs.get(instance); // debug!("option_len: {}", option_len); // let value_addr = instance.memory_offset_addr(0, value as usize) as *const c_void; - + // let ret = unsafe { setsockopt(socket, level, name, value_addr, option_len) }; // debug!("ret: {}", ret); // if ret != 0 { @@ -237,54 +319,54 @@ pub extern "C" fn ___syscall102(_which: c_int, mut varargs: VarArgs, instance: & // } // ret 0 - }, - 15 => { // getsockopt (sockfd: c_int, level: c_int, optname: c_int, optval: *mut c_void, optlen: *mut socklen_t) -> c_int + } + 15 => { + // getsockopt (sockfd: c_int, level: c_int, optname: c_int, optval: *mut c_void, optlen: *mut socklen_t) -> c_int let socket: i32 = socket_varargs.get(instance); let level: i32 = socket_varargs.get(instance); let name: i32 = socket_varargs.get(instance); let value: u32 = socket_varargs.get(instance); let option_len: u32 = socket_varargs.get(instance); let value_addr = instance.memory_offset_addr(0, value as usize) as *mut c_void; - let option_len_addr = instance.memory_offset_addr(0, option_len as usize) as *mut socklen_t; + let option_len_addr = + instance.memory_offset_addr(0, option_len as usize) as *mut socklen_t; unsafe { getsockopt(socket, level, name, value_addr, option_len_addr) } - }, - 16 => { // sendmsg (fd: c_int, msg: *const msghdr, flags: c_int) -> ssize_t + } + 16 => { + // sendmsg (fd: c_int, msg: *const msghdr, flags: c_int) -> ssize_t let socket: i32 = socket_varargs.get(instance); let msg: u32 = socket_varargs.get(instance); let flags: i32 = socket_varargs.get(instance); let msg_addr = instance.memory_offset_addr(0, msg as usize) as *const msghdr; unsafe { sendmsg(socket, msg_addr, flags) as i32 } - }, - 17 => { // recvmsg (fd: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t + } + 17 => { + // recvmsg (fd: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t let socket: i32 = socket_varargs.get(instance); let msg: u32 = socket_varargs.get(instance); let flags: i32 = socket_varargs.get(instance); let msg_addr = instance.memory_offset_addr(0, msg as usize) as *mut msghdr; unsafe { recvmsg(socket, msg_addr, flags) as i32 } - }, - _ => { // others + } + _ => { + // others -1 - }, + } } } // sys_getpid pub extern "C" fn ___syscall20() -> pid_t { debug!("emscripten::___syscall20"); - unsafe { - getpid() - } + unsafe { getpid() } } // sys_getppid pub extern "C" fn ___syscall64() -> pid_t { debug!("emscripten::___syscall64"); - unsafe { - getpid() - } + unsafe { getpid() } } - // sys_getgid pub extern "C" fn ___syscall201() -> gid_t { debug!("emscripten::___syscall201"); @@ -304,15 +386,22 @@ pub extern "C" fn ___syscall202() -> gid_t { } // sys_prlimit64 -pub extern "C" fn ___syscall340(_which: c_int, mut _varargs: VarArgs, _instance: &mut Instance) -> c_int { +pub extern "C" fn ___syscall340( + _which: c_int, + mut _varargs: VarArgs, + _instance: &mut Instance, +) -> c_int { debug!("emscripten::___syscall340"); // NOTE: Doesn't really matter. Wasm modules cannot exceed WASM_PAGE_SIZE anyway. 0 } - // sys_fstat64 -pub extern "C" fn ___syscall197(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> c_int { +pub extern "C" fn ___syscall197( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { debug!("emscripten::___syscall197"); let fd: c_int = varargs.get(instance); let buf: u32 = varargs.get(instance); @@ -331,7 +420,11 @@ pub extern "C" fn ___syscall197(_which: c_int, mut varargs: VarArgs, instance: & } // sys_pread -pub extern "C" fn ___syscall180(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> c_int { +pub extern "C" fn ___syscall180( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { debug!("emscripten::___syscall180"); let fd: i32 = varargs.get(instance); let buf: u32 = varargs.get(instance); @@ -344,25 +437,29 @@ pub extern "C" fn ___syscall180(_which: c_int, mut varargs: VarArgs, instance: & let buf_ptr = instance.memory_offset_addr(0, buf as _) as _; - unsafe { - pread(fd, buf_ptr, count as _, offset) as _ - } + unsafe { pread(fd, buf_ptr, count as _, offset) as _ } } // sys_mkdir -pub extern "C" fn ___syscall39(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> c_int { +pub extern "C" fn ___syscall39( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { debug!("emscripten::___syscall39"); let pathname: u32 = varargs.get(instance); let mode: u32 = varargs.get(instance); let pathname_addr = instance.memory_offset_addr(0, pathname as usize) as *const i8; - - unsafe { - mkdir(pathname_addr, mode as _) - } + + unsafe { mkdir(pathname_addr, mode as _) } } // sys_stat64 -pub extern "C" fn ___syscall195(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> c_int { +pub extern "C" fn ___syscall195( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { debug!("emscripten::___syscall195"); let pathname: u32 = varargs.get(instance); let buf: u32 = varargs.get(instance); @@ -382,7 +479,11 @@ pub extern "C" fn ___syscall195(_which: c_int, mut varargs: VarArgs, instance: & } // sys_chown -pub extern "C" fn ___syscall212(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> c_int { +pub extern "C" fn ___syscall212( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { debug!("emscripten::___syscall212"); let pathname: u32 = varargs.get(instance); @@ -391,17 +492,19 @@ pub extern "C" fn ___syscall212(_which: c_int, mut varargs: VarArgs, instance: & let pathname_addr = instance.memory_offset_addr(0, pathname as usize) as *const i8; - unsafe { - chown(pathname_addr, owner, group) - } + unsafe { chown(pathname_addr, owner, group) } } // sys_fcntl64 -pub extern "C" fn ___syscall221(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) -> c_int { +pub extern "C" fn ___syscall221( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { let _fd: i32 = varargs.get(instance); let cmd: u32 = varargs.get(instance); match cmd { 2 => 0, _ => -1, } -} \ No newline at end of file +} diff --git a/src/apis/emscripten/time.rs b/src/apis/emscripten/time.rs index c4559fc5b..f36ebc3ba 100644 --- a/src/apis/emscripten/time.rs +++ b/src/apis/emscripten/time.rs @@ -1,29 +1,31 @@ +use super::utils::copy_cstr_into_wasm; use libc::{ c_int, c_long, clock_gettime as libc_clock_gettime, - timespec, // tm, localtime, + time, time_t, - time + timespec, }; -use std::{mem}; +use std::mem; use std::time::SystemTime; -use super::utils::{copy_cstr_into_wasm}; - use crate::webassembly::Instance; /// emscripten: _gettimeofday -pub extern fn _gettimeofday(tp: c_int, tz: c_int, instance: &mut Instance) -> c_int { +pub extern "C" fn _gettimeofday(tp: c_int, tz: c_int, instance: &mut Instance) -> c_int { #[repr(C)] struct GuestTimeVal { tv_sec: i32, tv_usec: i32, } - assert!(tz == 0, "the timezone argument of `_gettimeofday` must be null"); + assert!( + tz == 0, + "the timezone argument of `_gettimeofday` must be null" + ); unsafe { let now = SystemTime::now(); let since_epoch = now.duration_since(SystemTime::UNIX_EPOCH).unwrap(); @@ -35,9 +37,8 @@ pub extern fn _gettimeofday(tp: c_int, tz: c_int, instance: &mut Instance) -> c_ 0 } - /// emscripten: _clock_gettime -pub extern fn _clock_gettime(clk_id: c_int, tp: c_int, instance: &mut Instance) -> c_int { +pub extern "C" fn _clock_gettime(clk_id: c_int, tp: c_int, instance: &mut Instance) -> c_int { #[repr(C)] struct GuestTimeSpec { tv_sec: i32, @@ -85,7 +86,8 @@ pub extern "C" fn _localtime(time_p: u32, instance: &mut Instance) -> c_int { let tm_struct = &*localtime(time_p_addr); // Webassembly allocation - let tm_struct_offset = (instance.emscripten_data.malloc)(mem::size_of::() as _, instance); + let tm_struct_offset = + (instance.emscripten_data.malloc)(mem::size_of::() as _, instance); let tm_struct_ptr = instance.memory_offset_addr(0, tm_struct_offset as _) as *mut GuestTm; // Initializing @@ -116,7 +118,16 @@ pub extern "C" fn _time(time_p: u32, instance: &mut Instance) -> time_t { } /// emscripten: _strftime -pub extern "C" fn _strftime(s_ptr: c_int, maxsize: u32, format_ptr: c_int, tm_ptr: c_int, _instance: &mut Instance) -> time_t { - debug!("emscripten::_strftime {} {} {} {}", s_ptr, maxsize, format_ptr, tm_ptr); +pub extern "C" fn _strftime( + s_ptr: c_int, + maxsize: u32, + format_ptr: c_int, + tm_ptr: c_int, + _instance: &mut Instance, +) -> time_t { + debug!( + "emscripten::_strftime {} {} {} {}", + s_ptr, maxsize, format_ptr, tm_ptr + ); 0 } diff --git a/src/apis/emscripten/utils.rs b/src/apis/emscripten/utils.rs index bde0cd148..0b13aaea3 100644 --- a/src/apis/emscripten/utils.rs +++ b/src/apis/emscripten/utils.rs @@ -1,10 +1,10 @@ +use byteorder::{ByteOrder, LittleEndian}; use crate::webassembly::module::Module; use crate::webassembly::Instance; +use libc::stat; use std::ffi::CStr; use std::os::raw::c_char; use std::slice; -use libc::stat; -use byteorder::{ByteOrder, LittleEndian}; /// We check if a provided module is an Emscripten generated one pub fn is_emscripten_module(module: &Module) -> bool { @@ -28,7 +28,10 @@ pub unsafe fn copy_cstr_into_wasm(instance: &mut Instance, cstr: *const c_char) space_offset } -pub unsafe fn copy_terminated_array_of_cstrs(_instance: &mut Instance, cstrs: *mut *mut c_char) -> u32 { +pub unsafe fn copy_terminated_array_of_cstrs( + _instance: &mut Instance, + cstrs: *mut *mut c_char, +) -> u32 { let total_num = { let mut ptr = cstrs; let mut counter = 0; @@ -38,14 +41,17 @@ pub unsafe fn copy_terminated_array_of_cstrs(_instance: &mut Instance, cstrs: *m } counter }; - debug!("emscripten::copy_terminated_array_of_cstrs::total_num: {}", total_num); + debug!( + "emscripten::copy_terminated_array_of_cstrs::total_num: {}", + total_num + ); 0 } pub unsafe fn copy_stat_into_wasm(instance: &mut Instance, buf: u32, stat: &stat) { let buf_ptr = instance.memory_offset_addr(0, buf as _) as *mut u8; let buf = slice::from_raw_parts_mut(buf_ptr, 76); - + LittleEndian::write_u32(&mut buf[..], stat.st_dev as _); LittleEndian::write_u32(&mut buf[4..], 0); LittleEndian::write_u32(&mut buf[8..], stat.st_ino as _); diff --git a/src/apis/emscripten/varargs.rs b/src/apis/emscripten/varargs.rs index 2809f6d74..d233597fa 100644 --- a/src/apis/emscripten/varargs.rs +++ b/src/apis/emscripten/varargs.rs @@ -12,4 +12,4 @@ impl VarArgs { self.pointer += mem::size_of::() as u32; unsafe { (ptr as *const T).read() } } -} \ No newline at end of file +} diff --git a/src/apis/mod.rs b/src/apis/mod.rs index ca6aa9838..d96282fb8 100644 --- a/src/apis/mod.rs +++ b/src/apis/mod.rs @@ -1,4 +1,4 @@ pub mod emscripten; pub mod host; -pub use self::emscripten::{generate_emscripten_env, is_emscripten_module, align_memory}; +pub use self::emscripten::{align_memory, generate_emscripten_env, is_emscripten_module}; diff --git a/src/main.rs b/src/main.rs index 21cd9e1b3..5b3a19af6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,9 +12,9 @@ extern crate wabt; extern crate wasmparser; #[macro_use] extern crate target_lexicon; +extern crate byteorder; extern crate nix; extern crate rayon; -extern crate byteorder; use std::fs::File; use std::io; diff --git a/src/recovery.rs b/src/recovery.rs index 685dbb1d4..7e515c92e 100644 --- a/src/recovery.rs +++ b/src/recovery.rs @@ -26,39 +26,40 @@ thread_local! { /// the behavior of call_protected is undefined. #[macro_export] macro_rules! call_protected { - ($x:expr) => {unsafe { - use crate::webassembly::ErrorKind; - use crate::recovery::{SETJMP_BUFFER, setjmp}; - use crate::sighandler::install_sighandler; + ($x:expr) => { + unsafe { + use crate::recovery::{setjmp, SETJMP_BUFFER}; + use crate::sighandler::install_sighandler; + use crate::webassembly::ErrorKind; - use nix::sys::signal::{Signal, SIGFPE, SIGILL, SIGSEGV, SIGBUS}; + use nix::sys::signal::{Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV}; - let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get()); - let prev_jmp_buf = *jmp_buf; + let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get()); + let prev_jmp_buf = *jmp_buf; - install_sighandler(); + install_sighandler(); - let signum = setjmp(jmp_buf as *mut ::nix::libc::c_void); - if signum != 0 { - *jmp_buf = prev_jmp_buf; - let signal = match Signal::from_c_int(signum) { - Ok(SIGFPE) => "floating-point exception", - Ok(SIGILL) => "illegal instruction", - Ok(SIGSEGV) => "segmentation violation", - Ok(SIGBUS) => "bus error", - Err(_) => "error while getting the Signal", - _ => "unkown trapped signal", - }; - Err(ErrorKind::RuntimeError(format!("trap - {}", signal))) - } else { - let ret = $x; // TODO: Switch stack? - *jmp_buf = prev_jmp_buf; - Ok(ret) + let signum = setjmp(jmp_buf as *mut ::nix::libc::c_void); + if signum != 0 { + *jmp_buf = prev_jmp_buf; + let signal = match Signal::from_c_int(signum) { + Ok(SIGFPE) => "floating-point exception", + Ok(SIGILL) => "illegal instruction", + Ok(SIGSEGV) => "segmentation violation", + Ok(SIGBUS) => "bus error", + Err(_) => "error while getting the Signal", + _ => "unkown trapped signal", + }; + Err(ErrorKind::RuntimeError(format!("trap - {}", signal))) + } else { + let ret = $x; // TODO: Switch stack? + *jmp_buf = prev_jmp_buf; + Ok(ret) + } } - }} + }; } - /// Unwinds to last protected_call. pub unsafe fn do_unwind(signum: i32) -> ! { // Since do_unwind is only expected to get called from WebAssembly code which doesn't hold any host resources (locks etc.) diff --git a/src/webassembly/instance.rs b/src/webassembly/instance.rs index 61a256ed6..898b37736 100644 --- a/src/webassembly/instance.rs +++ b/src/webassembly/instance.rs @@ -18,8 +18,8 @@ use std::iter::FromIterator; use std::iter::Iterator; use std::mem::size_of; use std::ptr::write_unaligned; -use std::{fmt, slice, mem}; use std::sync::Arc; +use std::{fmt, mem, slice}; use super::super::common::slice::{BoundedSlice, UncheckedSlice}; use super::errors::ErrorKind; @@ -68,8 +68,8 @@ fn get_function_addr( } pub struct EmscriptenData { - pub malloc: extern fn(i32, &mut Instance) -> u32, - pub free: extern fn(i32, &mut Instance), + pub malloc: extern "C" fn(i32, &mut Instance) -> u32, + pub free: extern "C" fn(i32, &mut Instance), } impl fmt::Debug for EmscriptenData { @@ -243,8 +243,7 @@ impl Instance { // let r = *Arc::from_raw(isa_ptr); compile_function(&*options.isa, function_body).unwrap() // unimplemented!() - }) - .collect(); + }).collect(); for compiled_func in compiled_funcs.into_iter() { let CompiledFunction { @@ -495,12 +494,7 @@ impl Instance { tables.iter().map(|table| table[..].into()).collect(); let memories_pointer: Vec> = memories .iter() - .map(|mem| { - BoundedSlice::new( - &mem[..], - mem.current_size(), - ) - }) + .map(|mem| BoundedSlice::new(&mem[..], mem.current_size())) .collect(); let globals_pointer: GlobalsSlice = globals[..].into(); @@ -511,14 +505,16 @@ impl Instance { }; let emscripten_data = unsafe { - let malloc_index = if let Some(Export::Function(index)) = module.info.exports.get("_malloc") { - index - } else { - panic!("Unable to find _malloc export") - }; + let malloc_index = + if let Some(Export::Function(index)) = module.info.exports.get("_malloc") { + index + } else { + panic!("Unable to find _malloc export") + }; let malloc_addr = get_function_addr(&malloc_index, &import_functions, &functions); - let free_index = if let Some(Export::Function(index)) = module.info.exports.get("_free") { + let free_index = if let Some(Export::Function(index)) = module.info.exports.get("_free") + { index } else { panic!("Unable to find _free export") @@ -564,8 +560,7 @@ impl Instance { if let Some(func_index) = self.start_func { let func: fn(&Instance) = get_instance_function!(&self, func_index); call_protected!(func(self)) - } - else { + } else { Ok(()) } } diff --git a/src/webassembly/memory.rs b/src/webassembly/memory.rs index eb67ff1dd..dd094b92e 100644 --- a/src/webassembly/memory.rs +++ b/src/webassembly/memory.rs @@ -3,17 +3,17 @@ //! webassembly::Instance. //! A memory created by Rust or in WebAssembly code will be accessible and //! mutable from both Rust and WebAssembly. -use nix::sys::mman::{mmap, MapFlags, ProtFlags}; use nix::libc::{c_void, mprotect, PROT_READ, PROT_WRITE}; -use std::slice; +use nix::sys::mman::{mmap, MapFlags, ProtFlags}; use std::ops::{Deref, DerefMut}; +use std::slice; /// A linear memory instance. // #[derive(Debug)] pub struct LinearMemory { base: *mut c_void, // The size will always be `LinearMemory::DEFAULT_SIZE` - current: u32, // current number of wasm pages + current: u32, // current number of wasm pages // The maximum size the WebAssembly Memory is allowed to grow // to, in units of WebAssembly pages. When present, the maximum // parameter acts as a hint to the engine to reserve memory up @@ -36,8 +36,8 @@ impl LinearMemory { /// /// `maximum` cannot be set to more than `65536` pages. pub fn new(initial: u32, maximum: Option) -> Self { - assert!(initial <= Self::MAX_PAGES); - assert!(maximum.is_none() || maximum.unwrap() <= Self::MAX_PAGES); + assert!(initial <= Self::MAX_PAGES); + assert!(maximum.is_none() || maximum.unwrap() <= Self::MAX_PAGES); debug!( "Instantiate LinearMemory(initial={:?}, maximum={:?})", initial, maximum @@ -56,13 +56,16 @@ impl LinearMemory { }; if initial > 0 { - assert_eq!(unsafe { - mprotect( - base, - (initial * Self::PAGE_SIZE) as _, - PROT_READ | PROT_WRITE, - ) - }, 0); + assert_eq!( + unsafe { + mprotect( + base, + (initial * Self::PAGE_SIZE) as _, + PROT_READ | PROT_WRITE, + ) + }, + 0 + ); } debug!("LinearMemory instantiated"); @@ -124,11 +127,14 @@ impl LinearMemory { let new_bytes = (new_pages * Self::PAGE_SIZE) as usize; unsafe { - assert_eq!(mprotect( - self.base.add(prev_bytes), - new_bytes - prev_bytes, - PROT_READ | PROT_WRITE, - ), 0); + assert_eq!( + mprotect( + self.base.add(prev_bytes), + new_bytes - prev_bytes, + PROT_READ | PROT_WRITE, + ), + 0 + ); } self.current = new_pages; @@ -156,20 +162,15 @@ impl PartialEq for LinearMemory { } } - impl Deref for LinearMemory { type Target = [u8]; fn deref(&self) -> &[u8] { - unsafe { - slice::from_raw_parts(self.base as _, (self.current * Self::PAGE_SIZE) as _) - } + unsafe { slice::from_raw_parts(self.base as _, (self.current * Self::PAGE_SIZE) as _) } } } impl DerefMut for LinearMemory { fn deref_mut(&mut self) -> &mut [u8] { - unsafe { - slice::from_raw_parts_mut(self.base as _, (self.current * Self::PAGE_SIZE) as _) - } + unsafe { slice::from_raw_parts_mut(self.base as _, (self.current * Self::PAGE_SIZE) as _) } } -} \ No newline at end of file +} diff --git a/src/webassembly/mod.rs b/src/webassembly/mod.rs index 137132ad7..7913b2a59 100644 --- a/src/webassembly/mod.rs +++ b/src/webassembly/mod.rs @@ -7,7 +7,10 @@ pub mod module; pub mod relocation; pub mod utils; -use cranelift_codegen::{isa, settings::{self, Configurable}}; +use cranelift_codegen::{ + isa, + settings::{self, Configurable}, +}; use std::panic; use std::str::FromStr; use target_lexicon; @@ -47,11 +50,9 @@ pub fn instantiate( buffer_source: Vec, import_object: ImportObject<&str, &str>, ) -> Result { - let flags = { let mut builder = settings::builder(); - builder.set("opt_level", "best") - .unwrap(); + builder.set("opt_level", "best").unwrap(); let flags = settings::Flags::new(builder); debug_assert_eq!(flags.opt_level(), settings::OptLevel::Best);