diff --git a/src/apis/emscripten/env.rs b/src/apis/emscripten/env.rs index 97f91c2b6..e68bb9b65 100644 --- a/src/apis/emscripten/env.rs +++ b/src/apis/emscripten/env.rs @@ -1,12 +1,17 @@ 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, passwd, getgrnam as libc_getgrnam, group}; +use libc::{ + c_int, getpwnam as libc_getpwnam, passwd, + getgrnam as libc_getgrnam, group, clock_gettime as libc_clock_gettime, timespec, + // uname as libc_uname, utsname, +}; use std::ffi::CStr; use std::os::raw::c_char; use std::{slice, mem}; use crate::webassembly::Instance; use super::utils::{copy_cstr_into_wasm, copy_terminated_array_of_cstrs}; +use crate::webassembly::LinearMemory; /// emscripten: _getenv pub extern "C" fn _getenv(name_ptr: c_int, instance: &mut Instance) -> c_int { @@ -86,3 +91,26 @@ pub extern "C" fn _getgrnam(name_ptr: c_int, instance: &mut Instance) -> c_int { group_struct_offset as c_int } } + +pub extern fn _getpid(_instance: &mut Instance) -> c_int { + 0 +} +pub extern fn _getppid(_instance: &mut Instance) -> c_int { + 0 +} + +pub extern fn _uname(_buf: c_int, _instance: &mut Instance) -> c_int { + 0 +} + +pub extern fn _localtime_r() -> u32 { + 0 +} + +pub extern fn _getpagesize() -> u32 { + LinearMemory::PAGE_SIZE +} + +pub extern fn _prlimit(pid: c_int, resource: c_int, new_limit: c_int, old_limit: c_int, instance: &mut Instance) -> c_int { + 0 +} diff --git a/src/apis/emscripten/memory.rs b/src/apis/emscripten/memory.rs index cbaa7e6bf..241fe462e 100644 --- a/src/apis/emscripten/memory.rs +++ b/src/apis/emscripten/memory.rs @@ -21,7 +21,8 @@ pub extern "C" fn _emscripten_memcpy_big( /// emscripten: getTotalMemory pub extern "C" fn get_total_memory(instance: &mut Instance) -> u32 { debug!("emscripten::get_total_memory"); - instance.memories[0].current_pages() + // instance.memories[0].current_pages() + 16777216 } /// emscripten: enlargeMemory diff --git a/src/apis/emscripten/mod.rs b/src/apis/emscripten/mod.rs index c45df0896..1ed832c9c 100644 --- a/src/apis/emscripten/mod.rs +++ b/src/apis/emscripten/mod.rs @@ -57,9 +57,9 @@ pub fn emscripten_set_up_memory(memory: &mut LinearMemory) { macro_rules! mock_external { ($import:ident, $name:ident) => {{ - fn _mocked_fn() { + extern fn _mocked_fn() -> i32 { println!("emscripten::{} ", stringify!($name)); - // return 0 + -1 } $import.set( "env", @@ -304,6 +304,32 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { "_time", ImportValue::Func(time::_time as _), ); + import_object.set( + "env", + "___syscall20", + ImportValue::Func(env::_getpid as _), + ); + import_object.set( + "env", + "___syscall64", + ImportValue::Func(env::_getppid as _), + ); + import_object.set( + "env", + "___syscall122", + ImportValue::Func(env::_uname as _), + ); + import_object.set( + "env", + "_localtime_r", + ImportValue::Func(env::_localtime_r as _), + ); + import_object.set( + "env", + "_getpagesize", + ImportValue::Func(env::_getpagesize as _), + ); + mock_external!(import_object, _waitpid); mock_external!(import_object, _utimes); mock_external!(import_object, _usleep); @@ -324,14 +350,14 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { mock_external!(import_object, _sched_yield); mock_external!(import_object, _raise); mock_external!(import_object, _mktime); - mock_external!(import_object, _localtime_r); - // mock_external!(import_object, _localtime); + // mock_external!(import_object, _localtime_r); + mock_external!(import_object, _localtime); mock_external!(import_object, _llvm_stacksave); mock_external!(import_object, _llvm_stackrestore); mock_external!(import_object, _kill); mock_external!(import_object, _gmtime_r); // mock_external!(import_object, _gettimeofday); - mock_external!(import_object, _getpagesize); + // mock_external!(import_object, _getpagesize); mock_external!(import_object, _getgrent); mock_external!(import_object, _getaddrinfo); mock_external!(import_object, _fork); @@ -344,7 +370,7 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { mock_external!(import_object, ___syscall85); mock_external!(import_object, ___syscall75); mock_external!(import_object, ___syscall66); - mock_external!(import_object, ___syscall64); + // mock_external!(import_object, ___syscall64); mock_external!(import_object, ___syscall63); mock_external!(import_object, ___syscall60); mock_external!(import_object, ___syscall54); @@ -373,9 +399,9 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { // mock_external!(import_object, ___syscall145); mock_external!(import_object, ___syscall142); mock_external!(import_object, ___syscall140); - mock_external!(import_object, ___syscall122); + // mock_external!(import_object, ___syscall122); mock_external!(import_object, ___syscall102); - mock_external!(import_object, ___syscall20); + // mock_external!(import_object, ___syscall20); mock_external!(import_object, ___syscall15); mock_external!(import_object, ___syscall10); diff --git a/src/apis/emscripten/time.rs b/src/apis/emscripten/time.rs index 4c4d67ab7..b28a3e6dc 100644 --- a/src/apis/emscripten/time.rs +++ b/src/apis/emscripten/time.rs @@ -2,7 +2,7 @@ use libc::{ gettimeofday, timeval, c_int, - clock_gettime, + clock_gettime as libc_clock_gettime, clockid_t, timespec, tm, @@ -15,30 +15,72 @@ use std::{ptr, slice, mem}; use crate::webassembly::Instance; /// emscripten: _gettimeofday -pub extern "C" fn _gettimeofday(timeval_ptr_offset: c_int, tz_offset: c_int, instance: &mut Instance) -> c_int { - debug!("emscripten::_gettimeofday {}", timeval_ptr_offset); +// pub extern "C" fn _gettimeofday(timeval_ptr_offset: c_int, tz_offset: c_int, instance: &mut Instance) -> c_int { +// debug!("emscripten::_gettimeofday {}", timeval_ptr_offset); - unsafe { - let mut timeval_value = *(instance.memory_offset_addr(0, timeval_ptr_offset as _) as *mut timeval); - // We skip the timezone for now - let mut tz = ptr::null_mut(); - debug!("emscripten::_gettimeofday(initial) {} {}", (timeval_value).tv_sec, (timeval_value).tv_usec); +// unsafe { +// let mut timeval_value = *(instance.memory_offset_addr(0, timeval_ptr_offset as _) as *mut timeval); +// // We skip the timezone for now +// let mut tz = ptr::null_mut(); +// debug!("emscripten::_gettimeofday(initial) {} {}", (timeval_value).tv_sec, (timeval_value).tv_usec); - let returned = gettimeofday(&mut timeval_value, tz); - debug!("emscripten::_gettimeofday(filled) {} {}", (timeval_value).tv_sec, (timeval_value).tv_usec); - returned +// let returned = gettimeofday(&mut timeval_value, tz); +// debug!("emscripten::_gettimeofday(filled) {} {}", (timeval_value).tv_sec, (timeval_value).tv_usec); +// returned +// } +// } +pub extern 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"); + unsafe { + let now = SystemTime::now(); + let since_epoch = now.duration_since(SystemTime::UNIX_EPOCH).unwrap(); + let timeval_struct_ptr = instance.memory_offset_addr(0, tp as _) as *mut GuestTimeVal; + + (*timeval_struct_ptr).tv_sec = since_epoch.as_secs() as _; + (*timeval_struct_ptr).tv_usec = since_epoch.subsec_nanos() as _; + } + 0 } + /// emscripten: _clock_gettime -pub extern "C" fn _clock_gettime(clk_id: clockid_t, tp_offset: c_int, instance: &mut Instance) -> c_int { - debug!("emscripten::_clock_gettime {} {}", clk_id, tp_offset); +// pub extern "C" fn _clock_gettime(clk_id: clockid_t, tp_offset: c_int, instance: &mut Instance) -> c_int { +// debug!("emscripten::_clock_gettime {} {}", clk_id, tp_offset); + +// unsafe { +// let mut tp = instance.memory_offset_addr(0, tp_offset as _) as *mut timespec; +// let returned = clock_gettime(clk_id, tp); +// debug!("emscripten::clock_gettime(filled) {} {}", (*tp).tv_sec, (*tp).tv_nsec); +// returned +// } +// } + +pub extern fn _clock_gettime(clk_id: c_int, tp: c_int, instance: &mut Instance) -> c_int { + #[repr(C)] + struct GuestTimeSpec { + tv_sec: i32, + tv_nsec: i32, + } unsafe { - let mut tp = instance.memory_offset_addr(0, tp_offset as _) as *mut timespec; - let returned = clock_gettime(clk_id, tp); - debug!("emscripten::clock_gettime(filled) {} {}", (*tp).tv_sec, (*tp).tv_nsec); - returned + let mut timespec = timespec { + tv_sec: 0, + tv_nsec: 0, + }; + let ret = libc_clock_gettime(clk_id as _, &mut timespec); + if ret != 0 { + return ret; + } + + let timespec_struct_ptr = instance.memory_offset_addr(0, tp as _) as *mut GuestTimeSpec; + (*timespec_struct_ptr).tv_sec = timespec.tv_sec as _; + (*timespec_struct_ptr).tv_nsec = timespec.tv_nsec as _; } } diff --git a/src/apis/emscripten/utils.rs b/src/apis/emscripten/utils.rs index 4c2198160..3c2d66153 100644 --- a/src/apis/emscripten/utils.rs +++ b/src/apis/emscripten/utils.rs @@ -1,10 +1,9 @@ use crate::webassembly::module::Module; +use crate::webassembly::Instance; use std::ffi::CStr; use std::os::raw::c_char; use std::{slice, mem}; -use crate::webassembly::Instance; - /// We check if a provided module is an Emscripten generated one pub fn is_emscripten_module(module: &Module) -> bool { for (module, _field) in &module.info.imported_funcs { @@ -24,7 +23,6 @@ pub unsafe fn copy_cstr_into_wasm(instance: &mut Instance, cstr: *const c_char) for (byte, loc) in s.bytes().zip(slice.iter_mut()) { *loc = byte; } - space_offset }