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;
/// 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::<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_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::<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_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
}
}

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 libc::c_int;
// NOTE: Not implemented by Emscripten
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 crate::webassembly::Instance;
use libc::{c_void, memcpy, size_t};
/// emscripten: _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
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::<u32>()];
let mem = &mut memory[dynamictop_ptr..dynamictop_ptr + mem::size_of::<u32>()];
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::{} <mock>", 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",

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) {
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;
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
}

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
/// 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,
}
}
}

View File

@ -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::<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;
// 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
}

View File

@ -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 _);

View File

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

View File

@ -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};

View File

@ -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;

View File

@ -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.)

View File

@ -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<BoundedSlice<u8>> = 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(())
}
}

View File

@ -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<u32>) -> 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 _) }
}
}
}

View File

@ -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<u8>,
import_object: ImportObject<&str, &str>,
) -> Result<ResultObject, ErrorKind> {
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);