Improved formatting

This commit is contained in:
Syrus Akbary 2018-11-26 20:29:26 -08:00
parent 50f6ea3bd4
commit c2ede37a72
17 changed files with 337 additions and 242 deletions

View File

@ -1,15 +1,12 @@
use super::super::host; use super::super::host;
/// NOTE: These syscalls only support wasm_32 for now because they take u32 offset /// NOTE: These syscalls only support wasm_32 for now because they take u32 offset
use libc::{ use libc::{c_int, getgrnam as libc_getgrnam, getpwnam as libc_getpwnam};
c_int, getpwnam as libc_getpwnam,
getgrnam as libc_getgrnam,
};
use std::ffi::CStr; use std::ffi::CStr;
use std::os::raw::c_char;
use std::mem; 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 super::utils::{copy_cstr_into_wasm, copy_terminated_array_of_cstrs};
use crate::webassembly::Instance;
/// emscripten: _getenv /// emscripten: _getenv
pub extern "C" fn _getenv(name_ptr: c_int, instance: &mut Instance) -> c_int { 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 { unsafe {
let passwd = &*libc_getpwnam(name.as_ptr()); let passwd = &*libc_getpwnam(name.as_ptr());
let passwd_struct_offset = (instance.emscripten_data.malloc)(mem::size_of::<GuestPasswd>() as _, instance); let passwd_struct_offset =
(instance.emscripten_data.malloc)(mem::size_of::<GuestPasswd>() 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_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_passwd = copy_cstr_into_wasm(instance, passwd.pw_passwd);
(*passwd_struct_ptr).pw_gecos = copy_cstr_into_wasm(instance, passwd.pw_gecos); (*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 { unsafe {
let group = &*libc_getgrnam(name.as_ptr()); let group = &*libc_getgrnam(name.as_ptr());
let group_struct_offset = (instance.emscripten_data.malloc)(mem::size_of::<GuestGroup>() as _, instance); let group_struct_offset =
(instance.emscripten_data.malloc)(mem::size_of::<GuestGroup>() 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_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_passwd = copy_cstr_into_wasm(instance, group.gr_passwd);
(*group_struct_ptr).gr_gid = group.gr_gid; (*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"); debug!("emscripten::_localtime_r");
0 0
} }
pub extern fn _getpagesize() -> u32 { pub extern "C" fn _getpagesize() -> u32 {
debug!("emscripten::_getpagesize"); debug!("emscripten::_getpagesize");
16384 16384
} }

View File

@ -263,4 +263,3 @@ pub extern "C" fn ___seterrno(value: i32) -> i32 {
// } // }
// } // }
// } // }

View File

@ -1,5 +1,5 @@
use libc::c_int;
use crate::webassembly::Instance; use crate::webassembly::Instance;
use libc::c_int;
// NOTE: Not implemented by Emscripten // NOTE: Not implemented by Emscripten
pub extern "C" fn ___lock(_which: c_int, _varargs: c_int, _instance: &mut Instance) {} pub extern "C" fn ___lock(_which: c_int, _varargs: c_int, _instance: &mut Instance) {}

View File

@ -1,6 +1,6 @@
use libc::{c_void, memcpy, size_t};
use crate::webassembly::Instance;
use super::process::abort_with_message; use super::process::abort_with_message;
use crate::webassembly::Instance;
use libc::{c_void, memcpy, size_t};
/// emscripten: _emscripten_memcpy_big /// emscripten: _emscripten_memcpy_big
pub extern "C" fn _emscripten_memcpy_big( pub extern "C" fn _emscripten_memcpy_big(

View File

@ -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 /// NOTE: TODO: These emscripten api implementation only support wasm32 for now because they assume offsets are u32
use crate::webassembly::{ImportObject, ImportValue, LinearMemory}; use crate::webassembly::{ImportObject, ImportValue, LinearMemory};
use byteorder::{ByteOrder, LittleEndian};
use std::mem; use std::mem;
// EMSCRIPTEN APIS // EMSCRIPTEN APIS
mod env; mod env;
mod errno;
mod io; mod io;
mod memory;
mod process;
mod syscalls;
mod lock; mod lock;
mod memory;
mod nullfunc;
mod process;
mod storage;
mod syscalls;
mod time;
mod utils; mod utils;
mod varargs; 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::storage::{align_memory, static_alloc};
pub use self::utils::is_emscripten_module;
// TODO: Magic number - how is this calculated? // TODO: Magic number - how is this calculated?
const TOTAL_STACK: u32 = 5242880; 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) { pub fn emscripten_set_up_memory(memory: &mut LinearMemory) {
let dynamictop_ptr = dynamictop_ptr(STATIC_BUMP) as usize; let dynamictop_ptr = dynamictop_ptr(STATIC_BUMP) as usize;
let mem = &mut memory[dynamictop_ptr..dynamictop_ptr+mem::size_of::<u32>()]; let mem = &mut memory[dynamictop_ptr..dynamictop_ptr + mem::size_of::<u32>()];
LittleEndian::write_u32(mem, dynamic_base(STATIC_BUMP)); LittleEndian::write_u32(mem, dynamic_base(STATIC_BUMP));
} }
macro_rules! mock_external { macro_rules! mock_external {
($import:ident, $name:ident) => {{ ($import:ident, $name:ident) => {{
extern fn _mocked_fn() -> i32 { extern "C" fn _mocked_fn() -> i32 {
debug!("emscripten::{} <mock>", stringify!($name)); debug!("emscripten::{} <mock>", stringify!($name));
-1 -1
} }
$import.set( $import.set("env", stringify!($name), ImportValue::Func(_mocked_fn as _));
"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", "DYNAMICTOP_PTR",
ImportValue::Global(dynamictop_ptr(STATIC_BUMP) as _), ImportValue::Global(dynamictop_ptr(STATIC_BUMP) as _),
); );
import_object.set( import_object.set("env", "tableBase", ImportValue::Global(0));
"env",
"tableBase",
ImportValue::Global(0),
);
// Print functions // Print functions
import_object.set("env", "printf", ImportValue::Func(io::printf as *const u8)); 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", "_getenv",
ImportValue::Func(env::_getenv as *const u8), ImportValue::Func(env::_getenv as *const u8),
); );
import_object.set( import_object.set("env", "_getpwnam", ImportValue::Func(env::_getpwnam as _));
"env", import_object.set("env", "_getgrnam", ImportValue::Func(env::_getgrnam as _));
"_getpwnam",
ImportValue::Func(env::_getpwnam as _),
);
import_object.set(
"env",
"_getgrnam",
ImportValue::Func(env::_getgrnam as _),
);
// Errno // Errno
import_object.set( import_object.set(
"env", "env",
@ -370,16 +354,8 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
"_localtime", "_localtime",
ImportValue::Func(time::_localtime as _), ImportValue::Func(time::_localtime as _),
); );
import_object.set( import_object.set("env", "_time", ImportValue::Func(time::_time as _));
"env", import_object.set("env", "_strftime", ImportValue::Func(time::_strftime as _));
"_time",
ImportValue::Func(time::_time as _),
);
import_object.set(
"env",
"_strftime",
ImportValue::Func(time::_strftime as _),
);
import_object.set( import_object.set(
"env", "env",
"_localtime_r", "_localtime_r",

View File

@ -36,4 +36,3 @@ pub extern "C" fn nullfunc_viii(_x: u32, _instance: &Instance) {
pub extern "C" fn nullfunc_viiii(_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)"); 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)");
} }

View File

@ -1,4 +1,3 @@
use crate::webassembly::LinearMemory; use crate::webassembly::LinearMemory;
pub fn align_memory(ptr: u32) -> u32 { 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; let total_memory = memory.maximum_size() * LinearMemory::PAGE_SIZE;
// NOTE: The `4294967280` is a u32 conversion of -16 as gotten from emscripten. // NOTE: The `4294967280` is a u32 conversion of -16 as gotten from emscripten.
*static_top = (*static_top + size + 15) & 4294967280; *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 old_static_top
} }

View File

@ -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 /// 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 /// Syscall list: https://www.cs.utexas.edu/~bismith/test/syscalls/syscalls32.html
use libc::{ use libc::{
c_int, c_void, utsname, off_t, accept,
ssize_t, write, exit, read, bind,
open, close, c_int,
uname, lseek, readv, c_void,
iovec, writev, socklen_t, chown,
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,
// fcntl, ioctl, setsockopt, getppid // 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 /// sys_exit
pub extern "C" fn ___syscall1(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) { pub extern "C" fn ___syscall1(_which: c_int, mut varargs: VarArgs, instance: &mut Instance) {
debug!("emscripten::___syscall1"); debug!("emscripten::___syscall1");
let status: i32 = varargs.get(instance); let status: i32 = varargs.get(instance);
unsafe { exit(status); } unsafe {
exit(status);
}
} }
/// sys_read /// 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"); debug!("emscripten::___syscall3");
let fd: i32 = varargs.get(instance); let fd: i32 = varargs.get(instance);
let buf: u32 = 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 /// 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"); debug!("emscripten::___syscall4");
let fd: i32 = varargs.get(instance); let fd: i32 = varargs.get(instance);
let buf: u32 = 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 /// 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"); debug!("emscripten::___syscall5");
let pathname: u32 = varargs.get(instance); let pathname: u32 = varargs.get(instance);
let flags: i32 = 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 /// 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"); debug!("emscripten::___syscall6");
let fd: i32 = varargs.get(instance); let fd: i32 = varargs.get(instance);
debug!("fd: {}", fd); debug!("fd: {}", fd);
@ -75,7 +119,11 @@ pub extern "C" fn ___syscall6(_which: c_int, mut varargs: VarArgs, instance: &mu
} }
/// sys_ioctl /// 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"); debug!("emscripten::___syscall54");
let _fd: i32 = varargs.get(instance); let _fd: i32 = varargs.get(instance);
let _request: u32 = 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 /// sys_uname
// NOTE: Wondering if we should return custom utsname, like Emscripten. // 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"); debug!("emscripten::___syscall122");
let buf: u32 = varargs.get(instance); let buf: u32 = varargs.get(instance);
debug!("buf: {}", buf); debug!("buf: {}", buf);
@ -95,7 +147,11 @@ pub extern "C" fn ___syscall122(_which: c_int, mut varargs: VarArgs, instance: &
} }
/// sys_lseek /// 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"); debug!("emscripten::___syscall145");
let fd: i32 = varargs.get(instance); let fd: i32 = varargs.get(instance);
let offset: i64 = 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 /// 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"); debug!("emscripten::___syscall145");
let fd: i32 = varargs.get(instance); let fd: i32 = varargs.get(instance);
let iov: u32 = 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 // 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"); debug!("emscripten::___syscall145");
let fd: i32 = varargs.get(instance); let fd: i32 = varargs.get(instance);
let iov: u32 = 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 // 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"); debug!("emscripten::___syscall102");
let call: u32 = varargs.get(instance); let call: u32 = varargs.get(instance);
let mut socket_varargs: VarArgs = varargs.get(instance); let mut socket_varargs: VarArgs = varargs.get(instance);
match call { 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 domain: i32 = socket_varargs.get(instance);
let ty: i32 = socket_varargs.get(instance); let ty: i32 = socket_varargs.get(instance);
let protocol: i32 = socket_varargs.get(instance); let protocol: i32 = socket_varargs.get(instance);
let socket = unsafe { socket(domain, ty, protocol) }; let socket = unsafe { socket(domain, ty, protocol) };
debug!("socket: {}", socket); debug!("socket: {}", 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. // TODO: Emscripten has a different signature.
let socket: i32 = socket_varargs.get(instance); let socket: i32 = socket_varargs.get(instance);
let address: u32 = socket_varargs.get(instance); let address: u32 = socket_varargs.get(instance);
let address_len: 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 = instance.memory_offset_addr(0, address as usize) as *mut sockaddr;
unsafe { bind(socket, address, address_len) } 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. // TODO: Emscripten has a different signature.
let socket: i32 = socket_varargs.get(instance); let socket: i32 = socket_varargs.get(instance);
let address: u32 = socket_varargs.get(instance); let address: u32 = socket_varargs.get(instance);
let address_len: 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 = instance.memory_offset_addr(0, address as usize) as *mut sockaddr;
unsafe { connect(socket, address, address_len) } 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 socket: i32 = socket_varargs.get(instance);
let backlog: i32 = socket_varargs.get(instance); let backlog: i32 = socket_varargs.get(instance);
unsafe { listen(socket, backlog) } 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 socket: i32 = socket_varargs.get(instance);
let address: u32 = socket_varargs.get(instance); let address: u32 = socket_varargs.get(instance);
let address_len: 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 = 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) } 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 socket: i32 = socket_varargs.get(instance);
let address: u32 = socket_varargs.get(instance); let address: u32 = socket_varargs.get(instance);
let address_len: 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 = 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) } 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 socket: i32 = socket_varargs.get(instance);
let address: u32 = socket_varargs.get(instance); let address: u32 = socket_varargs.get(instance);
let address_len: 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 = 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) } 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 socket: i32 = socket_varargs.get(instance);
let buf: u32 = socket_varargs.get(instance); let buf: u32 = socket_varargs.get(instance);
let flags: usize = 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 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 = instance.memory_offset_addr(0, address as usize) as *mut sockaddr;
unsafe { sendto(socket, buf_addr, flags, len, address, address_len) as i32 } 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 socket: i32 = socket_varargs.get(instance);
let buf: u32 = socket_varargs.get(instance); let buf: u32 = socket_varargs.get(instance);
let flags: usize = 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 address_len: u32 = socket_varargs.get(instance);
let buf_addr = instance.memory_offset_addr(0, buf as usize) as *mut c_void; 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 = 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 } 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); // let socket: i32 = socket_varargs.get(instance);
// debug!("socket: {}", socket); // debug!("socket: {}", socket);
// let level: i32 = socket_varargs.get(instance); // 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); // let option_len: u32 = socket_varargs.get(instance);
// debug!("option_len: {}", option_len); // debug!("option_len: {}", option_len);
// let value_addr = instance.memory_offset_addr(0, value as usize) as *const c_void; // 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) }; // let ret = unsafe { setsockopt(socket, level, name, value_addr, option_len) };
// debug!("ret: {}", ret); // debug!("ret: {}", ret);
// if ret != 0 { // if ret != 0 {
@ -237,54 +319,54 @@ pub extern "C" fn ___syscall102(_which: c_int, mut varargs: VarArgs, instance: &
// } // }
// ret // ret
0 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 socket: i32 = socket_varargs.get(instance);
let level: i32 = socket_varargs.get(instance); let level: i32 = socket_varargs.get(instance);
let name: i32 = socket_varargs.get(instance); let name: i32 = socket_varargs.get(instance);
let value: u32 = socket_varargs.get(instance); let value: u32 = socket_varargs.get(instance);
let option_len: 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 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) } 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 socket: i32 = socket_varargs.get(instance);
let msg: u32 = socket_varargs.get(instance); let msg: u32 = socket_varargs.get(instance);
let flags: i32 = 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; let msg_addr = instance.memory_offset_addr(0, msg as usize) as *const msghdr;
unsafe { sendmsg(socket, msg_addr, flags) as i32 } 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 socket: i32 = socket_varargs.get(instance);
let msg: u32 = socket_varargs.get(instance); let msg: u32 = socket_varargs.get(instance);
let flags: i32 = 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; let msg_addr = instance.memory_offset_addr(0, msg as usize) as *mut msghdr;
unsafe { recvmsg(socket, msg_addr, flags) as i32 } unsafe { recvmsg(socket, msg_addr, flags) as i32 }
}, }
_ => { // others _ => {
// others
-1 -1
}, }
} }
} }
// sys_getpid // sys_getpid
pub extern "C" fn ___syscall20() -> pid_t { pub extern "C" fn ___syscall20() -> pid_t {
debug!("emscripten::___syscall20"); debug!("emscripten::___syscall20");
unsafe { unsafe { getpid() }
getpid()
}
} }
// sys_getppid // sys_getppid
pub extern "C" fn ___syscall64() -> pid_t { pub extern "C" fn ___syscall64() -> pid_t {
debug!("emscripten::___syscall64"); debug!("emscripten::___syscall64");
unsafe { unsafe { getpid() }
getpid()
}
} }
// sys_getgid // sys_getgid
pub extern "C" fn ___syscall201() -> gid_t { pub extern "C" fn ___syscall201() -> gid_t {
debug!("emscripten::___syscall201"); debug!("emscripten::___syscall201");
@ -304,15 +386,22 @@ pub extern "C" fn ___syscall202() -> gid_t {
} }
// sys_prlimit64 // 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"); debug!("emscripten::___syscall340");
// NOTE: Doesn't really matter. Wasm modules cannot exceed WASM_PAGE_SIZE anyway. // NOTE: Doesn't really matter. Wasm modules cannot exceed WASM_PAGE_SIZE anyway.
0 0
} }
// sys_fstat64 // 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"); debug!("emscripten::___syscall197");
let fd: c_int = varargs.get(instance); let fd: c_int = varargs.get(instance);
let buf: u32 = 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 // 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"); debug!("emscripten::___syscall180");
let fd: i32 = varargs.get(instance); let fd: i32 = varargs.get(instance);
let buf: u32 = 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 _; let buf_ptr = instance.memory_offset_addr(0, buf as _) as _;
unsafe { unsafe { pread(fd, buf_ptr, count as _, offset) as _ }
pread(fd, buf_ptr, count as _, offset) as _
}
} }
// sys_mkdir // 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"); debug!("emscripten::___syscall39");
let pathname: u32 = varargs.get(instance); let pathname: u32 = varargs.get(instance);
let mode: u32 = varargs.get(instance); let mode: u32 = varargs.get(instance);
let pathname_addr = instance.memory_offset_addr(0, pathname as usize) as *const i8; let pathname_addr = instance.memory_offset_addr(0, pathname as usize) as *const i8;
unsafe { unsafe { mkdir(pathname_addr, mode as _) }
mkdir(pathname_addr, mode as _)
}
} }
// sys_stat64 // 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"); debug!("emscripten::___syscall195");
let pathname: u32 = varargs.get(instance); let pathname: u32 = varargs.get(instance);
let buf: 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 // 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"); debug!("emscripten::___syscall212");
let pathname: u32 = varargs.get(instance); 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; let pathname_addr = instance.memory_offset_addr(0, pathname as usize) as *const i8;
unsafe { unsafe { chown(pathname_addr, owner, group) }
chown(pathname_addr, owner, group)
}
} }
// sys_fcntl64 // 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 _fd: i32 = varargs.get(instance);
let cmd: u32 = varargs.get(instance); let cmd: u32 = varargs.get(instance);
match cmd { match cmd {
2 => 0, 2 => 0,
_ => -1, _ => -1,
} }
} }

View File

@ -1,29 +1,31 @@
use super::utils::copy_cstr_into_wasm;
use libc::{ use libc::{
c_int, c_int,
c_long, c_long,
clock_gettime as libc_clock_gettime, clock_gettime as libc_clock_gettime,
timespec,
// tm, // tm,
localtime, localtime,
time,
time_t, time_t,
time timespec,
}; };
use std::{mem}; use std::mem;
use std::time::SystemTime; use std::time::SystemTime;
use super::utils::{copy_cstr_into_wasm};
use crate::webassembly::Instance; use crate::webassembly::Instance;
/// emscripten: _gettimeofday /// 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)] #[repr(C)]
struct GuestTimeVal { struct GuestTimeVal {
tv_sec: i32, tv_sec: i32,
tv_usec: 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 { unsafe {
let now = SystemTime::now(); let now = SystemTime::now();
let since_epoch = now.duration_since(SystemTime::UNIX_EPOCH).unwrap(); 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 0
} }
/// emscripten: _clock_gettime /// 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)] #[repr(C)]
struct GuestTimeSpec { struct GuestTimeSpec {
tv_sec: i32, 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); let tm_struct = &*localtime(time_p_addr);
// Webassembly allocation // Webassembly allocation
let tm_struct_offset = (instance.emscripten_data.malloc)(mem::size_of::<GuestTm>() as _, instance); let tm_struct_offset =
(instance.emscripten_data.malloc)(mem::size_of::<GuestTm>() as _, instance);
let tm_struct_ptr = instance.memory_offset_addr(0, tm_struct_offset as _) as *mut GuestTm; let tm_struct_ptr = instance.memory_offset_addr(0, tm_struct_offset as _) as *mut GuestTm;
// Initializing // Initializing
@ -116,7 +118,16 @@ pub extern "C" fn _time(time_p: u32, instance: &mut Instance) -> time_t {
} }
/// emscripten: _strftime /// 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 { pub extern "C" fn _strftime(
debug!("emscripten::_strftime {} {} {} {}", s_ptr, maxsize, format_ptr, tm_ptr); 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 0
} }

View File

@ -1,10 +1,10 @@
use byteorder::{ByteOrder, LittleEndian};
use crate::webassembly::module::Module; use crate::webassembly::module::Module;
use crate::webassembly::Instance; use crate::webassembly::Instance;
use libc::stat;
use std::ffi::CStr; use std::ffi::CStr;
use std::os::raw::c_char; use std::os::raw::c_char;
use std::slice; use std::slice;
use libc::stat;
use byteorder::{ByteOrder, LittleEndian};
/// We check if a provided module is an Emscripten generated one /// We check if a provided module is an Emscripten generated one
pub fn is_emscripten_module(module: &Module) -> bool { 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 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 total_num = {
let mut ptr = cstrs; let mut ptr = cstrs;
let mut counter = 0; let mut counter = 0;
@ -38,14 +41,17 @@ pub unsafe fn copy_terminated_array_of_cstrs(_instance: &mut Instance, cstrs: *m
} }
counter counter
}; };
debug!("emscripten::copy_terminated_array_of_cstrs::total_num: {}", total_num); debug!(
"emscripten::copy_terminated_array_of_cstrs::total_num: {}",
total_num
);
0 0
} }
pub unsafe fn copy_stat_into_wasm(instance: &mut Instance, buf: u32, stat: &stat) { 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_ptr = instance.memory_offset_addr(0, buf as _) as *mut u8;
let buf = slice::from_raw_parts_mut(buf_ptr, 76); let buf = slice::from_raw_parts_mut(buf_ptr, 76);
LittleEndian::write_u32(&mut buf[..], stat.st_dev as _); LittleEndian::write_u32(&mut buf[..], stat.st_dev as _);
LittleEndian::write_u32(&mut buf[4..], 0); LittleEndian::write_u32(&mut buf[4..], 0);
LittleEndian::write_u32(&mut buf[8..], stat.st_ino as _); LittleEndian::write_u32(&mut buf[8..], stat.st_ino as _);

View File

@ -12,4 +12,4 @@ impl VarArgs {
self.pointer += mem::size_of::<T>() as u32; self.pointer += mem::size_of::<T>() as u32;
unsafe { (ptr as *const T).read() } unsafe { (ptr as *const T).read() }
} }
} }

View File

@ -1,4 +1,4 @@
pub mod emscripten; pub mod emscripten;
pub mod host; 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};

View File

@ -12,9 +12,9 @@ extern crate wabt;
extern crate wasmparser; extern crate wasmparser;
#[macro_use] #[macro_use]
extern crate target_lexicon; extern crate target_lexicon;
extern crate byteorder;
extern crate nix; extern crate nix;
extern crate rayon; extern crate rayon;
extern crate byteorder;
use std::fs::File; use std::fs::File;
use std::io; use std::io;

View File

@ -26,39 +26,40 @@ thread_local! {
/// the behavior of call_protected is undefined. /// the behavior of call_protected is undefined.
#[macro_export] #[macro_export]
macro_rules! call_protected { macro_rules! call_protected {
($x:expr) => {unsafe { ($x:expr) => {
use crate::webassembly::ErrorKind; unsafe {
use crate::recovery::{SETJMP_BUFFER, setjmp}; use crate::recovery::{setjmp, SETJMP_BUFFER};
use crate::sighandler::install_sighandler; 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 jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
let prev_jmp_buf = *jmp_buf; let prev_jmp_buf = *jmp_buf;
install_sighandler(); install_sighandler();
let signum = setjmp(jmp_buf as *mut ::nix::libc::c_void); let signum = setjmp(jmp_buf as *mut ::nix::libc::c_void);
if signum != 0 { if signum != 0 {
*jmp_buf = prev_jmp_buf; *jmp_buf = prev_jmp_buf;
let signal = match Signal::from_c_int(signum) { let signal = match Signal::from_c_int(signum) {
Ok(SIGFPE) => "floating-point exception", Ok(SIGFPE) => "floating-point exception",
Ok(SIGILL) => "illegal instruction", Ok(SIGILL) => "illegal instruction",
Ok(SIGSEGV) => "segmentation violation", Ok(SIGSEGV) => "segmentation violation",
Ok(SIGBUS) => "bus error", Ok(SIGBUS) => "bus error",
Err(_) => "error while getting the Signal", Err(_) => "error while getting the Signal",
_ => "unkown trapped signal", _ => "unkown trapped signal",
}; };
Err(ErrorKind::RuntimeError(format!("trap - {}", signal))) Err(ErrorKind::RuntimeError(format!("trap - {}", signal)))
} else { } else {
let ret = $x; // TODO: Switch stack? let ret = $x; // TODO: Switch stack?
*jmp_buf = prev_jmp_buf; *jmp_buf = prev_jmp_buf;
Ok(ret) Ok(ret)
}
} }
}} };
} }
/// Unwinds to last protected_call. /// Unwinds to last protected_call.
pub unsafe fn do_unwind(signum: i32) -> ! { 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.) // Since do_unwind is only expected to get called from WebAssembly code which doesn't hold any host resources (locks etc.)

View File

@ -18,8 +18,8 @@ use std::iter::FromIterator;
use std::iter::Iterator; use std::iter::Iterator;
use std::mem::size_of; use std::mem::size_of;
use std::ptr::write_unaligned; use std::ptr::write_unaligned;
use std::{fmt, slice, mem};
use std::sync::Arc; use std::sync::Arc;
use std::{fmt, mem, slice};
use super::super::common::slice::{BoundedSlice, UncheckedSlice}; use super::super::common::slice::{BoundedSlice, UncheckedSlice};
use super::errors::ErrorKind; use super::errors::ErrorKind;
@ -68,8 +68,8 @@ fn get_function_addr(
} }
pub struct EmscriptenData { pub struct EmscriptenData {
pub malloc: extern fn(i32, &mut Instance) -> u32, pub malloc: extern "C" fn(i32, &mut Instance) -> u32,
pub free: extern fn(i32, &mut Instance), pub free: extern "C" fn(i32, &mut Instance),
} }
impl fmt::Debug for EmscriptenData { impl fmt::Debug for EmscriptenData {
@ -243,8 +243,7 @@ impl Instance {
// let r = *Arc::from_raw(isa_ptr); // let r = *Arc::from_raw(isa_ptr);
compile_function(&*options.isa, function_body).unwrap() compile_function(&*options.isa, function_body).unwrap()
// unimplemented!() // unimplemented!()
}) }).collect();
.collect();
for compiled_func in compiled_funcs.into_iter() { for compiled_func in compiled_funcs.into_iter() {
let CompiledFunction { let CompiledFunction {
@ -495,12 +494,7 @@ impl Instance {
tables.iter().map(|table| table[..].into()).collect(); tables.iter().map(|table| table[..].into()).collect();
let memories_pointer: Vec<BoundedSlice<u8>> = memories let memories_pointer: Vec<BoundedSlice<u8>> = memories
.iter() .iter()
.map(|mem| { .map(|mem| BoundedSlice::new(&mem[..], mem.current_size()))
BoundedSlice::new(
&mem[..],
mem.current_size(),
)
})
.collect(); .collect();
let globals_pointer: GlobalsSlice = globals[..].into(); let globals_pointer: GlobalsSlice = globals[..].into();
@ -511,14 +505,16 @@ impl Instance {
}; };
let emscripten_data = unsafe { let emscripten_data = unsafe {
let malloc_index = if let Some(Export::Function(index)) = module.info.exports.get("_malloc") { let malloc_index =
index if let Some(Export::Function(index)) = module.info.exports.get("_malloc") {
} else { index
panic!("Unable to find _malloc export") } else {
}; panic!("Unable to find _malloc export")
};
let malloc_addr = get_function_addr(&malloc_index, &import_functions, &functions); 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 index
} else { } else {
panic!("Unable to find _free export") panic!("Unable to find _free export")
@ -564,8 +560,7 @@ impl Instance {
if let Some(func_index) = self.start_func { if let Some(func_index) = self.start_func {
let func: fn(&Instance) = get_instance_function!(&self, func_index); let func: fn(&Instance) = get_instance_function!(&self, func_index);
call_protected!(func(self)) call_protected!(func(self))
} } else {
else {
Ok(()) Ok(())
} }
} }

View File

@ -3,17 +3,17 @@
//! webassembly::Instance. //! webassembly::Instance.
//! A memory created by Rust or in WebAssembly code will be accessible and //! A memory created by Rust or in WebAssembly code will be accessible and
//! mutable from both Rust and WebAssembly. //! mutable from both Rust and WebAssembly.
use nix::sys::mman::{mmap, MapFlags, ProtFlags};
use nix::libc::{c_void, mprotect, PROT_READ, PROT_WRITE}; 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::ops::{Deref, DerefMut};
use std::slice;
/// A linear memory instance. /// A linear memory instance.
// //
#[derive(Debug)] #[derive(Debug)]
pub struct LinearMemory { pub struct LinearMemory {
base: *mut c_void, // The size will always be `LinearMemory::DEFAULT_SIZE` 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 // The maximum size the WebAssembly Memory is allowed to grow
// to, in units of WebAssembly pages. When present, the maximum // to, in units of WebAssembly pages. When present, the maximum
// parameter acts as a hint to the engine to reserve memory up // 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. /// `maximum` cannot be set to more than `65536` pages.
pub fn new(initial: u32, maximum: Option<u32>) -> Self { pub fn new(initial: u32, maximum: Option<u32>) -> Self {
assert!(initial <= Self::MAX_PAGES); assert!(initial <= Self::MAX_PAGES);
assert!(maximum.is_none() || maximum.unwrap() <= Self::MAX_PAGES); assert!(maximum.is_none() || maximum.unwrap() <= Self::MAX_PAGES);
debug!( debug!(
"Instantiate LinearMemory(initial={:?}, maximum={:?})", "Instantiate LinearMemory(initial={:?}, maximum={:?})",
initial, maximum initial, maximum
@ -56,13 +56,16 @@ impl LinearMemory {
}; };
if initial > 0 { if initial > 0 {
assert_eq!(unsafe { assert_eq!(
mprotect( unsafe {
base, mprotect(
(initial * Self::PAGE_SIZE) as _, base,
PROT_READ | PROT_WRITE, (initial * Self::PAGE_SIZE) as _,
) PROT_READ | PROT_WRITE,
}, 0); )
},
0
);
} }
debug!("LinearMemory instantiated"); debug!("LinearMemory instantiated");
@ -124,11 +127,14 @@ impl LinearMemory {
let new_bytes = (new_pages * Self::PAGE_SIZE) as usize; let new_bytes = (new_pages * Self::PAGE_SIZE) as usize;
unsafe { unsafe {
assert_eq!(mprotect( assert_eq!(
self.base.add(prev_bytes), mprotect(
new_bytes - prev_bytes, self.base.add(prev_bytes),
PROT_READ | PROT_WRITE, new_bytes - prev_bytes,
), 0); PROT_READ | PROT_WRITE,
),
0
);
} }
self.current = new_pages; self.current = new_pages;
@ -156,20 +162,15 @@ impl PartialEq for LinearMemory {
} }
} }
impl Deref for LinearMemory { impl Deref for LinearMemory {
type Target = [u8]; type Target = [u8];
fn deref(&self) -> &[u8] { fn deref(&self) -> &[u8] {
unsafe { unsafe { slice::from_raw_parts(self.base as _, (self.current * Self::PAGE_SIZE) as _) }
slice::from_raw_parts(self.base as _, (self.current * Self::PAGE_SIZE) as _)
}
} }
} }
impl DerefMut for LinearMemory { impl DerefMut for LinearMemory {
fn deref_mut(&mut self) -> &mut [u8] { fn deref_mut(&mut self) -> &mut [u8] {
unsafe { unsafe { slice::from_raw_parts_mut(self.base as _, (self.current * Self::PAGE_SIZE) as _) }
slice::from_raw_parts_mut(self.base as _, (self.current * Self::PAGE_SIZE) as _)
}
} }
} }

View File

@ -7,7 +7,10 @@ pub mod module;
pub mod relocation; pub mod relocation;
pub mod utils; pub mod utils;
use cranelift_codegen::{isa, settings::{self, Configurable}}; use cranelift_codegen::{
isa,
settings::{self, Configurable},
};
use std::panic; use std::panic;
use std::str::FromStr; use std::str::FromStr;
use target_lexicon; use target_lexicon;
@ -47,11 +50,9 @@ pub fn instantiate(
buffer_source: Vec<u8>, buffer_source: Vec<u8>,
import_object: ImportObject<&str, &str>, import_object: ImportObject<&str, &str>,
) -> Result<ResultObject, ErrorKind> { ) -> Result<ResultObject, ErrorKind> {
let flags = { let flags = {
let mut builder = settings::builder(); let mut builder = settings::builder();
builder.set("opt_level", "best") builder.set("opt_level", "best").unwrap();
.unwrap();
let flags = settings::Flags::new(builder); let flags = settings::Flags::new(builder);
debug_assert_eq!(flags.opt_level(), settings::OptLevel::Best); debug_assert_eq!(flags.opt_level(), settings::OptLevel::Best);