From 7f91a64cf6cc3d962826c7d32b6f4c6a4f86277c Mon Sep 17 00:00:00 2001 From: Steve Akinyemi Date: Thu, 13 Dec 2018 19:28:30 +0100 Subject: [PATCH] Add a bunch of required functions and syscalls --- src/apis/emscripten/exception.rs | 14 +++ src/apis/emscripten/lock.rs | 5 + src/apis/emscripten/math.rs | 19 +++ src/apis/emscripten/memory.rs | 10 +- src/apis/emscripten/mod.rs | 197 +++++++++++++++++++----------- src/apis/emscripten/nullfunc.rs | 10 ++ src/apis/emscripten/process.rs | 21 +++- src/apis/emscripten/syscalls.rs | 201 +++++++++++++++++++++---------- src/apis/emscripten/time.rs | 18 +++ src/apis/emscripten/utils.rs | 2 +- src/emtests/syscalls.rs | 0 11 files changed, 364 insertions(+), 133 deletions(-) create mode 100644 src/apis/emscripten/exception.rs create mode 100644 src/apis/emscripten/math.rs create mode 100644 src/emtests/syscalls.rs diff --git a/src/apis/emscripten/exception.rs b/src/apis/emscripten/exception.rs new file mode 100644 index 000000000..dc45454d5 --- /dev/null +++ b/src/apis/emscripten/exception.rs @@ -0,0 +1,14 @@ +use crate::webassembly::Instance; + +/// emscripten: ___cxa_allocate_exception +pub extern "C" fn ___cxa_allocate_exception(size: u32, instance: &mut Instance) -> u32 { + debug!("emscripten::___cxa_allocate_exception"); + (instance.emscripten_data.as_ref().unwrap().malloc)(size as _, instance) +} + +/// emscripten: ___cxa_throw +/// TODO: We don't have support for exceptions yet +pub extern "C" fn ___cxa_throw(ptr: u32, ty: u32, destructor: u32, instance: &mut Instance) { + debug!("emscripten::___cxa_throw"); + debug!("unimplmeneted yet!"); +} diff --git a/src/apis/emscripten/lock.rs b/src/apis/emscripten/lock.rs index 9067be99e..b3934a183 100644 --- a/src/apis/emscripten/lock.rs +++ b/src/apis/emscripten/lock.rs @@ -10,3 +10,8 @@ pub extern "C" fn ___lock(_which: c_int, _varargs: c_int, _instance: &mut Instan pub extern "C" fn ___unlock(_which: c_int, _varargs: c_int, _instance: &mut Instance) { debug!("emscripten::___unlock"); } + +// NOTE: Not implemented by Emscripten +pub extern "C" fn ___wait(_which: c_int, _varargs: c_int, _instance: &mut Instance) { + debug!("emscripten::___wait"); +} diff --git a/src/apis/emscripten/math.rs b/src/apis/emscripten/math.rs new file mode 100644 index 000000000..9f33e5366 --- /dev/null +++ b/src/apis/emscripten/math.rs @@ -0,0 +1,19 @@ +use crate::webassembly::Instance; + +/// emscripten: _llvm_log10_f64 +pub extern "C" fn _llvm_log10_f64(value: f64) -> f64 { + debug!("emscripten::_llvm_log10_f64"); + value.log10() +} + +/// emscripten: _llvm_log2_f64 +pub extern "C" fn _llvm_log2_f64(value: f64) -> f64 { + debug!("emscripten::_llvm_log2_f64"); + value.log2() +} + +// emscripten: f64-rem +pub extern "C" fn f64_rem(x: f64, y: f64) -> f64 { + debug!("emscripten::f64-rem"); + x % y +} diff --git a/src/apis/emscripten/memory.rs b/src/apis/emscripten/memory.rs index 4caf652bc..ab0304456 100644 --- a/src/apis/emscripten/memory.rs +++ b/src/apis/emscripten/memory.rs @@ -1,6 +1,6 @@ use super::process::abort_with_message; use crate::webassembly::Instance; -use libc::{c_void, memcpy, size_t}; +use libc::{c_void, memcpy, size_t, c_int}; /// emscripten: _emscripten_memcpy_big pub extern "C" fn _emscripten_memcpy_big( @@ -36,3 +36,11 @@ pub extern "C" fn abort_on_cannot_grow_memory() { debug!("emscripten::abort_on_cannot_grow_memory"); abort_with_message("Cannot enlarge memory arrays!"); } + +/// emscripten: ___map_file +pub extern "C" fn ___map_file() -> c_int { + debug!("emscripten::___map_file"); + // NOTE: TODO: Em returns -1 here as well. May need to implement properly + -1 +} + diff --git a/src/apis/emscripten/mod.rs b/src/apis/emscripten/mod.rs index 3ca72a8e8..0c23ae302 100644 --- a/src/apis/emscripten/mod.rs +++ b/src/apis/emscripten/mod.rs @@ -9,6 +9,8 @@ mod errno; mod io; mod lock; mod memory; +mod math; +mod exception; mod nullfunc; mod process; mod signal; @@ -99,6 +101,7 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { // Lock import_object.set("env", "___lock", ImportValue::Func(lock::___lock as _)); import_object.set("env", "___unlock", ImportValue::Func(lock::___unlock as _)); + import_object.set("env", "___wait", ImportValue::Func(lock::___wait as _)); // Env import_object.set("env", "_getenv", ImportValue::Func(env::_getenv as _)); import_object.set("env", "_getpwnam", ImportValue::Func(env::_getpwnam as _)); @@ -136,16 +139,71 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { "___syscall6", ImportValue::Func(syscalls::___syscall6 as _), ); + import_object.set( + "env", + "___syscall12", + ImportValue::Func(syscalls::___syscall12 as _), + ); + import_object.set( + "env", + "___syscall20", + ImportValue::Func(syscalls::___syscall20 as _), + ); + import_object.set( + "env", + "___syscall39", + ImportValue::Func(syscalls::___syscall39 as _), + ); + import_object.set( + "env", + "___syscall40", + ImportValue::Func(syscalls::___syscall40 as _), + ); import_object.set( "env", "___syscall54", ImportValue::Func(syscalls::___syscall54 as _), ); + import_object.set( + "env", + "___syscall57", + ImportValue::Func(syscalls::___syscall57 as _), + ); + import_object.set( + "env", + "___syscall63", + ImportValue::Func(syscalls::___syscall63 as _), + ); + import_object.set( + "env", + "___syscall64", + ImportValue::Func(syscalls::___syscall64 as _), + ); + import_object.set( + "env", + "___syscall102", + ImportValue::Func(syscalls::___syscall102 as _), + ); + import_object.set( + "env", + "___syscall114", + ImportValue::Func(syscalls::___syscall114 as _), + ); + import_object.set( + "env", + "___syscall122", + ImportValue::Func(syscalls::___syscall122 as _), + ); import_object.set( "env", "___syscall140", ImportValue::Func(syscalls::___syscall140 as _), ); + import_object.set( + "env", + "___syscall142", + ImportValue::Func(syscalls::___syscall142 as _), + ); import_object.set( "env", "___syscall145", @@ -158,23 +216,28 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { ); import_object.set( "env", - "___syscall221", - ImportValue::Func(syscalls::___syscall221 as _), + "___syscall180", + ImportValue::Func(syscalls::___syscall180 as _), ); import_object.set( "env", - "___syscall20", - ImportValue::Func(syscalls::___syscall20 as _), + "___syscall181", + ImportValue::Func(syscalls::___syscall181 as _), ); import_object.set( "env", - "___syscall64", - ImportValue::Func(syscalls::___syscall64 as _), + "___syscall192", + ImportValue::Func(syscalls::___syscall192 as _), ); import_object.set( "env", - "___syscall122", - ImportValue::Func(syscalls::___syscall122 as _), + "___syscall195", + ImportValue::Func(syscalls::___syscall195 as _), + ); + import_object.set( + "env", + "___syscall197", + ImportValue::Func(syscalls::___syscall197 as _), ); import_object.set( "env", @@ -186,36 +249,6 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { "___syscall202", ImportValue::Func(syscalls::___syscall202 as _), ); - import_object.set( - "env", - "___syscall340", - ImportValue::Func(syscalls::___syscall340 as _), - ); - import_object.set( - "env", - "___syscall197", - ImportValue::Func(syscalls::___syscall197 as _), - ); - import_object.set( - "env", - "___syscall180", - ImportValue::Func(syscalls::___syscall180 as _), - ); - import_object.set( - "env", - "___syscall181", - ImportValue::Func(syscalls::___syscall181 as _), - ); - import_object.set( - "env", - "___syscall39", - ImportValue::Func(syscalls::___syscall39 as _), - ); - import_object.set( - "env", - "___syscall195", - ImportValue::Func(syscalls::___syscall195 as _), - ); import_object.set( "env", "___syscall212", @@ -228,40 +261,14 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { ); import_object.set( "env", - "___syscall102", - ImportValue::Func(syscalls::___syscall102 as _), + "___syscall330", + ImportValue::Func(syscalls::___syscall330 as _), ); import_object.set( "env", - "___syscall54", - ImportValue::Func(syscalls::___syscall54 as _), + "___syscall340", + ImportValue::Func(syscalls::___syscall340 as _), ); - import_object.set( - "env", - "___syscall12", - ImportValue::Func(syscalls::___syscall12 as _), - ); - import_object.set( - "env", - "___syscall192", - ImportValue::Func(syscalls::___syscall192 as _), - ); - import_object.set( - "env", - "___syscall63", - ImportValue::Func(syscalls::___syscall63 as _), - ); - import_object.set( - "env", - "___syscall142", - ImportValue::Func(syscalls::___syscall142 as _), - ); - import_object.set( - "env", - "___syscall57", - ImportValue::Func(syscalls::___syscall57 as _), - ); - // Process import_object.set("env", "abort", ImportValue::Func(process::em_abort as _)); import_object.set("env", "_abort", ImportValue::Func(process::_abort as _)); @@ -270,9 +277,15 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { "abortStackOverflow", ImportValue::Func(process::abort_stack_overflow as _), ); + import_object.set( + "env", + "_llvm_trap", + ImportValue::Func(process::_llvm_trap as _), + ); import_object.set("env", "_fork", ImportValue::Func(process::_fork as _)); import_object.set("env", "_exit", ImportValue::Func(process::_exit as _)); - + import_object.set("env", "_system", ImportValue::Func(process::_system as _)); + import_object.set("env", "_popen", ImportValue::Func(process::_popen as _)); // Signal import_object.set( "env", @@ -320,6 +333,22 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { "getTotalMemory", ImportValue::Func(memory::get_total_memory as _), ); + import_object.set( + "env", + "___map_file", + ImportValue::Func(memory::___map_file as _), + ); + // Exception + import_object.set( + "env", + "___cxa_allocate_exception", + ImportValue::Func(exception::___cxa_allocate_exception as _), + ); + import_object.set( + "env", + "___cxa_allocate_exception", + ImportValue::Func(exception::___cxa_throw as _), + ); // NullFuncs import_object.set( "env", @@ -366,6 +395,16 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { "nullFunc_viiii", ImportValue::Func(nullfunc::nullfunc_viiii as _), ); + import_object.set( + "env", + "nullFunc_viiiii", + ImportValue::Func(nullfunc::nullfunc_viiiii as _), + ); + import_object.set( + "env", + "nullFunc_viiiiii", + ImportValue::Func(nullfunc::nullfunc_viiiiii as _), + ); // Time import_object.set( "env", @@ -377,6 +416,21 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { "_clock_gettime", ImportValue::Func(time::_clock_gettime as _), ); + import_object.set( + "env", + "___clock_gettime", + ImportValue::Func(time::___clock_gettime as _), + ); + import_object.set( + "env", + "_clock", + ImportValue::Func(time::_clock as _), + ); + import_object.set( + "env", + "_difftime", + ImportValue::Func(time::_difftime as _), + ); import_object.set( "env", "_asctime", @@ -409,6 +463,11 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { "_sysconf", ImportValue::Func(env::_sysconf as _), ); + // Math + import_object.set("env", "_llvm_log10_f64", ImportValue::Func(math::_llvm_log10_f64 as _)); + import_object.set("env", "_llvm_log2_f64", ImportValue::Func(math::_llvm_log2_f64 as _)); + import_object.set("asm2wasm", "f64-rem", ImportValue::Func(math::f64_rem as _)); + mock_external!(import_object, _waitpid); mock_external!(import_object, _utimes); diff --git a/src/apis/emscripten/nullfunc.rs b/src/apis/emscripten/nullfunc.rs index 40351560b..6974b6dc1 100644 --- a/src/apis/emscripten/nullfunc.rs +++ b/src/apis/emscripten/nullfunc.rs @@ -45,3 +45,13 @@ pub extern "C" fn nullfunc_viiii(_x: u32, _instance: &Instance) { debug!("emscripten::nullfunc_viiii"); 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)"); } + +pub extern "C" fn nullfunc_viiiii(_x: u32, _instance: &Instance) { + debug!("emscripten::nullfunc_viiiii"); + abort_with_message("Invalid function pointer called with signature 'viiiii'. 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)"); +} + +pub extern "C" fn nullfunc_viiiiii(_x: u32, _instance: &Instance) { + debug!("emscripten::nullfunc_viiiiii"); + abort_with_message("Invalid function pointer called with signature 'viiiiii'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this)"); +} diff --git a/src/apis/emscripten/process.rs b/src/apis/emscripten/process.rs index 09eeb4053..1bd1774c4 100644 --- a/src/apis/emscripten/process.rs +++ b/src/apis/emscripten/process.rs @@ -1,4 +1,4 @@ -use libc::{abort, c_char, pid_t, c_int, exit}; +use libc::{abort, c_char, pid_t, c_int, exit, EAGAIN}; use crate::webassembly::Instance; use std::ffi::CStr; @@ -48,3 +48,22 @@ pub extern "C" fn abort_stack_overflow() { // TODO: Message incomplete. Need to finish em runtime data first abort_with_message("Stack overflow! Attempted to allocate some bytes on the stack"); } + +pub extern "C" fn _llvm_trap() { + debug!("emscripten::_llvm_trap"); + abort_with_message("abort!"); +} + +pub extern "C" fn _system() -> c_int { + debug!("emscripten::_system"); + // TODO: May need to change this Em impl to a working version + eprintln!("Can't call external programs"); + return EAGAIN; +} + +pub extern "C" fn _popen() -> c_int { + debug!("emscripten::_popen"); + // TODO: May need to change this Em impl to a working version + eprintln!("Missing function: popen"); + unsafe { abort(); } +} diff --git a/src/apis/emscripten/syscalls.rs b/src/apis/emscripten/syscalls.rs index eb379eb77..0661a48c8 100644 --- a/src/apis/emscripten/syscalls.rs +++ b/src/apis/emscripten/syscalls.rs @@ -63,9 +63,21 @@ use libc::{ SOL_SOCKET, TIOCGWINSZ, // ENOTTY, - c_char + c_char, + rusage, + rmdir, + EINVAL, + fcntl, + F_SETFD, + F_GETFD, }; -// use std::sys::fd::FileDesc; + +// Linking to functions that are provided by rust libc +#[cfg(target_os = "macos")] +#[link(name = "c")] +extern { + pub fn wait4(pid: pid_t, status: *mut c_int, options: c_int, rusage: *mut rusage) -> pid_t; +} // Another conditional constant for name resolution: Macos et iOS use // SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket. @@ -181,15 +193,19 @@ pub extern "C" fn ___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 _) }; - 0 + unsafe { mkdir(pathname_addr, mode as _) } } -// getppid -pub extern "C" fn ___syscall64() -> pid_t { - debug!("emscripten::___syscall64 (getppid)"); - unsafe { getpid() } +// rmdir +pub extern "C" fn ___syscall40( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { + debug!("emscripten::___syscall40 (rmdir)"); + let pathname: u32 = varargs.get(instance); + let pathname_addr = instance.memory_offset_addr(0, pathname as usize) as *const i8; + unsafe { rmdir(pathname_addr) } } /// ioctl @@ -234,6 +250,40 @@ pub extern "C" fn ___syscall54( } } +// setpgid +pub extern "C" fn ___syscall57( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { + debug!("emscripten::___syscall57 (setpgid)"); + let pid: i32 = varargs.get(instance); + let pgid: i32 = varargs.get(instance); + unsafe { + setpgid(pid, pgid) + } +} + +// dup2 +pub extern "C" fn ___syscall63( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { + debug!("emscripten::___syscall63 (dup2)"); + + let src: i32 = varargs.get(instance); + let dst: i32 = varargs.get(instance); + + unsafe { dup2(src, dst) } +} + +// getppid +pub extern "C" fn ___syscall64() -> pid_t { + debug!("emscripten::___syscall64 (getppid)"); + unsafe { getpid() } +} + // socketcall pub extern "C" fn ___syscall102( _which: c_int, @@ -365,7 +415,7 @@ pub extern "C" fn ___syscall102( let fd = unsafe { accept(socket, address, address_len_addr) }; - unsafe { + unsafe { let address_linux = instance.memory_offset_addr(0, address_addr as usize) as *mut LinuxSockAddr; (*address_linux).sa_family = (*address).sa_family as u16; (*address_linux).sa_data = (*address).sa_data; @@ -503,6 +553,27 @@ pub extern "C" fn ___syscall102( } } +/// wait4 +pub extern "C" fn ___syscall114( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> pid_t { + debug!("emscripten::___syscall114 (wait4)"); + let pid: pid_t = varargs.get(instance); + let status: u32 = varargs.get(instance); + let options: c_int = varargs.get(instance); + let rusage: u32 = varargs.get(instance); + let status_addr = instance.memory_offset_addr(0, status as usize) as *mut c_int; + let rusage_addr = instance.memory_offset_addr(0, rusage as usize) as *mut rusage; + let res = unsafe { wait4(pid, status_addr, options, rusage_addr) }; + debug!( + "=> pid: {}, status: {:?}, options: {}, rusage: {:?} = pid: {}", + pid, status_addr, options, rusage_addr, res + ); + res +} + /// uname // NOTE: Wondering if we should return custom utsname, like Emscripten. pub extern "C" fn ___syscall122( @@ -517,6 +588,29 @@ pub extern "C" fn ___syscall122( unsafe { uname(buf_addr) } } +// select +pub extern "C" fn ___syscall142( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> c_int { + debug!("emscripten::___syscall142 (newselect)"); + + let nfds: i32 = varargs.get(instance); + let readfds: u32 = varargs.get(instance); + let writefds: u32 = varargs.get(instance); + let exceptfds: u32 = varargs.get(instance); + let _timeout: i32 = varargs.get(instance); + + assert!(nfds <= 64, "`nfds` must be less than or equal to 64"); + assert!(exceptfds == 0, "`exceptfds` is not supporrted"); + + let readfds_ptr = instance.memory_offset_addr(0, readfds as _) as _; + let writefds_ptr = instance.memory_offset_addr(0, writefds as _) as _; + + unsafe { select(nfds, readfds_ptr, writefds_ptr, 0 as _, 0 as _) } +} + // mmap2 pub extern "C" fn ___syscall192( _which: c_int, @@ -798,6 +892,42 @@ pub extern "C" fn ___syscall221( } } +/// dup3 +pub extern "C" fn ___syscall330( + _which: c_int, + mut varargs: VarArgs, + instance: &mut Instance, +) -> pid_t { + // Implementation based on description at https://linux.die.net/man/2/dup3 + debug!("emscripten::___syscall330 (dup3)"); + let oldfd: c_int = varargs.get(instance); + let newfd: c_int = varargs.get(instance); + let flags: c_int = varargs.get(instance); + + if oldfd == newfd { + return EINVAL; + } + + let res = unsafe { dup2(oldfd, newfd) }; + + // Set flags on newfd (https://www.gnu.org/software/libc/manual/html_node/Descriptor-Flags.html) + let mut old_flags = unsafe { fcntl (newfd, F_GETFD, 0) }; + + if old_flags > 0 { + old_flags |= flags; + } else if old_flags == 0 { + old_flags &= !flags; + } + + unsafe { fcntl (newfd, F_SETFD, old_flags); } + + debug!( + "=> oldfd: {}, newfd: {}, flags: {} = pid: {}", + oldfd, newfd, flags, res + ); + res +} + // prlimit64 pub extern "C" fn ___syscall340( _which: c_int, @@ -824,54 +954,3 @@ pub extern "C" fn ___syscall340( 0 } - -// dup2 -pub extern "C" fn ___syscall63( - _which: c_int, - mut varargs: VarArgs, - instance: &mut Instance, -) -> c_int { - debug!("emscripten::___syscall63 (dup2)"); - - let src: i32 = varargs.get(instance); - let dst: i32 = varargs.get(instance); - - unsafe { dup2(src, dst) } -} - -// select -pub extern "C" fn ___syscall142( - _which: c_int, - mut varargs: VarArgs, - instance: &mut Instance, -) -> c_int { - debug!("emscripten::___syscall142 (newselect)"); - - let nfds: i32 = varargs.get(instance); - let readfds: u32 = varargs.get(instance); - let writefds: u32 = varargs.get(instance); - let exceptfds: u32 = varargs.get(instance); - let _timeout: i32 = varargs.get(instance); - - assert!(nfds <= 64, "`nfds` must be less than or equal to 64"); - assert!(exceptfds == 0, "`exceptfds` is not supporrted"); - - let readfds_ptr = instance.memory_offset_addr(0, readfds as _) as _; - let writefds_ptr = instance.memory_offset_addr(0, writefds as _) as _; - - unsafe { select(nfds, readfds_ptr, writefds_ptr, 0 as _, 0 as _) } -} - -// setpgid -pub extern "C" fn ___syscall57( - _which: c_int, - mut varargs: VarArgs, - instance: &mut Instance, -) -> c_int { - debug!("emscripten::___syscall57 (setpgid)"); - let pid: i32 = varargs.get(instance); - let pgid: i32 = varargs.get(instance); - unsafe { - setpgid(pid, pgid) - } -} diff --git a/src/apis/emscripten/time.rs b/src/apis/emscripten/time.rs index 0395646a5..2b4ca5a46 100644 --- a/src/apis/emscripten/time.rs +++ b/src/apis/emscripten/time.rs @@ -66,6 +66,24 @@ pub extern "C" fn _clock_gettime(clk_id: c_int, tp: c_int, instance: &mut Instan 0 } +/// emscripten: ___clock_gettime +pub extern "C" fn ___clock_gettime(clk_id: c_int, tp: c_int, instance: &mut Instance) -> c_int { + debug!("emscripten::___clock_gettime {} {}", clk_id, tp); + _clock_gettime(clk_id, tp, instance) +} + +/// emscripten: _clock +pub extern "C" fn _clock() -> c_int { + debug!("emscripten::_clock"); + 0 // TODO: unimplemented +} + +/// emscripten: _difftime +pub extern "C" fn _difftime(t0: u32, t1: u32) -> c_int { + debug!("emscripten::_difftime"); + (t0 - t1) as _ +} + #[repr(C)] struct guest_tm { pub tm_sec: c_int, // 0 diff --git a/src/apis/emscripten/utils.rs b/src/apis/emscripten/utils.rs index 1a748cc6b..fd03b05f2 100644 --- a/src/apis/emscripten/utils.rs +++ b/src/apis/emscripten/utils.rs @@ -17,7 +17,7 @@ pub fn is_emscripten_module(module: &Module) -> bool { false } -pub unsafe fn write_to_buf(string: *const c_char, buf: u32, max: u32, instance: &Instance) -> u32 { +pub fn write_to_buf(string: *const c_char, buf: u32, max: u32, instance: &Instance) -> u32 { let buf_addr = instance.memory_offset_addr(0, buf as _) as *mut c_char; unsafe { diff --git a/src/emtests/syscalls.rs b/src/emtests/syscalls.rs new file mode 100644 index 000000000..e69de29bb