diff --git a/src/apis/emscripten/env.rs b/src/apis/emscripten/env.rs index 623de1191..22bd32e79 100644 --- a/src/apis/emscripten/env.rs +++ b/src/apis/emscripten/env.rs @@ -1,11 +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 { @@ -22,33 +28,6 @@ pub extern "C" fn _getenv(name_ptr: c_int, instance: &mut Instance) -> c_int { } } -unsafe fn copy_cstr_into_wasm(instance: &mut Instance, cstr: *const c_char) -> u32 { - let s = CStr::from_ptr(cstr).to_str().unwrap(); - let space_offset = (instance.emscripten_data.malloc)(s.len() as _, instance); - let raw_memory = instance.memory_offset_addr(0, space_offset as _) as *mut u8; - let mut slice = slice::from_raw_parts_mut(raw_memory, s.len()); - - for (byte, loc) in s.bytes().zip(slice.iter_mut()) { - *loc = byte; - } - - space_offset -} - -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; - while !(*ptr).is_null() { - counter += 1; - ptr = ptr.add(1); - } - counter - }; - println!("total_num: {}", total_num); - 0 -} - pub extern "C" fn _getpwnam(name_ptr: c_int, instance: &mut Instance) -> c_int { #[repr(C)] struct GuestPasswd { @@ -111,4 +90,16 @@ pub extern "C" fn _getgrnam(name_ptr: c_int, instance: &mut Instance) -> c_int { group_struct_offset as c_int } -} \ No newline at end of file +} + +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 062edbf51..a5b5df2b1 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 { debug!("emscripten::{} ", stringify!($name)); - // return 0 + -1 } $import.set( "env", @@ -133,6 +133,16 @@ 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 _), + ); // Errno import_object.set( "env", @@ -288,18 +298,7 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { "nullFunc_viiii", ImportValue::Func(nullfunc::nullfunc_viiii as *const u8), ); - - // named syscalls - import_object.set( - "env", - "_getpwnam", - ImportValue::Func(env::_getpwnam as _), - ); - import_object.set( - "env", - "_getgrnam", - ImportValue::Func(env::_getgrnam as _), - ); + // Time import_object.set( "env", "_gettimeofday", @@ -310,11 +309,31 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { "_clock_gettime", ImportValue::Func(time::_clock_gettime as _), ); + import_object.set( + "env", + "_localtime", + ImportValue::Func(time::_localtime as _), + ); + import_object.set( + "env", + "_time", + ImportValue::Func(time::_time 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); - mock_external!(import_object, _time); + // mock_external!(import_object, _time); mock_external!(import_object, _sysconf); mock_external!(import_object, _strftime); mock_external!(import_object, _sigsuspend); @@ -331,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_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); diff --git a/src/apis/emscripten/time.rs b/src/apis/emscripten/time.rs index 85c9d7519..ebb089fd9 100644 --- a/src/apis/emscripten/time.rs +++ b/src/apis/emscripten/time.rs @@ -1,5 +1,19 @@ -use libc::{gettimeofday, timeval, c_int, clock_gettime, clockid_t, timespec}; -use std::ptr; +use libc::{ + gettimeofday, + timeval, + c_int, + clock_gettime, + clock_gettime as libc_clock_gettime, + clockid_t, + timespec, + tm, + localtime, + time_t, + time +}; +use std::{ptr, slice, mem}; +use std::time::SystemTime; + use crate::webassembly::Instance; @@ -18,6 +32,25 @@ pub extern "C" fn _gettimeofday(timeval_ptr_offset: c_int, tz_offset: c_int, ins 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 { @@ -30,3 +63,47 @@ pub extern "C" fn _clock_gettime(clk_id: clockid_t, tp_offset: c_int, instance: 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 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 _; +// } +// 0 +// } + +/// emscripten: _localtime +pub extern "C" fn _localtime(time_p: u32, instance: &mut Instance) -> *mut tm { + debug!("emscripten::_localtime {}", time_p); + + unsafe { + let time_p_addr = instance.memory_offset_addr(0, time_p as _) as *mut i64; + localtime(time_p_addr) + } +} + +/// emscripten: _time +pub extern "C" fn _time(time_p: u32, instance: &mut Instance) -> time_t { + debug!("emscripten::_time {}", time_p); + + unsafe { + let time_p_addr = instance.memory_offset_addr(0, time_p as _) as *mut i64; + time(time_p_addr) + } +} diff --git a/src/apis/emscripten/utils.rs b/src/apis/emscripten/utils.rs index bbc659a0c..3c2d66153 100644 --- a/src/apis/emscripten/utils.rs +++ b/src/apis/emscripten/utils.rs @@ -1,4 +1,8 @@ use crate::webassembly::module::Module; +use crate::webassembly::Instance; +use std::ffi::CStr; +use std::os::raw::c_char; +use std::{slice, mem}; /// We check if a provided module is an Emscripten generated one pub fn is_emscripten_module(module: &Module) -> bool { @@ -10,6 +14,32 @@ pub fn is_emscripten_module(module: &Module) -> bool { return false; } +pub unsafe fn copy_cstr_into_wasm(instance: &mut Instance, cstr: *const c_char) -> u32 { + let s = CStr::from_ptr(cstr).to_str().unwrap(); + let space_offset = (instance.emscripten_data.malloc)(s.len() as _, instance); + let raw_memory = instance.memory_offset_addr(0, space_offset as _) as *mut u8; + let mut slice = slice::from_raw_parts_mut(raw_memory, s.len()); + + for (byte, loc) in s.bytes().zip(slice.iter_mut()) { + *loc = byte; + } + space_offset +} + +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; + while !(*ptr).is_null() { + counter += 1; + ptr = ptr.add(1); + } + counter + }; + println!("total_num: {}", total_num); + 0 +} + #[cfg(test)] mod tests { use super::super::generate_emscripten_env;