From 42b122d639739b7127a76a8bc3647688beefc534 Mon Sep 17 00:00:00 2001 From: Mark McCaskey Date: Wed, 20 Mar 2019 15:13:00 -0700 Subject: [PATCH] add many emscripten functions for PHP --- lib/emscripten/src/emscripten_target.rs | 28 +++++ lib/emscripten/src/lib.rs | 20 ++++ lib/emscripten/src/math.rs | 10 ++ lib/emscripten/src/syscalls/unix.rs | 142 +++++++++++++++++++++++- 4 files changed, 199 insertions(+), 1 deletion(-) diff --git a/lib/emscripten/src/emscripten_target.rs b/lib/emscripten/src/emscripten_target.rs index 4508f4f54..656a5d7f8 100644 --- a/lib/emscripten/src/emscripten_target.rs +++ b/lib/emscripten/src/emscripten_target.rs @@ -287,6 +287,26 @@ pub fn invoke_iiiiii( panic!("dyn_call_iiiiii is set to None"); } } +pub fn invoke_iiiiiii( + ctx: &mut Ctx, + index: i32, + a1: i32, + a2: i32, + a3: i32, + a4: i32, + a5: i32, + a6: i32, +) -> i32 { + debug!("emscripten::invoke_iiiiiii"); + if let Some(dyn_call_iiiiiii) = &get_emscripten_data(ctx).dyn_call_iiiiiii { + dyn_call_iiiiiii + .call(index, a1, a2, a3, a4, a5, a6) + .unwrap() + } else { + panic!("dyn_call_iiiiiii is set to None"); + } +} + pub fn invoke_vd(ctx: &mut Ctx, index: i32, a1: f64) { debug!("emscripten::invoke_vd"); if let Some(dyn_call_vd) = &get_emscripten_data(ctx).dyn_call_vd { @@ -573,3 +593,11 @@ pub fn invoke_vijj(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: i32, a4: i32 panic!("dyn_call_vijj is set to None"); } } +pub fn invoke_viidii(ctx: &mut Ctx, index: i32, a1: i32, a2: i32, a3: f64, a4: i32, a5: i32) { + debug!("emscripten::invoke_viidii"); + if let Some(dyn_call_viidii) = &get_emscripten_data(ctx).dyn_call_viidii { + dyn_call_viidii.call(index, a1, a2, a3, a4, a5).unwrap(); + } else { + panic!("dyn_call_viidii is set to None"); + } +} diff --git a/lib/emscripten/src/lib.rs b/lib/emscripten/src/lib.rs index 1cde93620..98093ef09 100644 --- a/lib/emscripten/src/lib.rs +++ b/lib/emscripten/src/lib.rs @@ -94,6 +94,7 @@ pub struct EmscriptenData<'a> { pub dyn_call_diiii: Option>, pub dyn_call_iiiii: Option>, pub dyn_call_iiiiii: Option>, + pub dyn_call_iiiiiii: Option>, pub dyn_call_vd: Option>, pub dyn_call_viiiii: Option>, pub dyn_call_viiiiii: Option>, @@ -117,6 +118,7 @@ pub struct EmscriptenData<'a> { pub dyn_call_viji: Option>, pub dyn_call_vijiii: Option>, pub dyn_call_vijj: Option>, + pub dyn_call_viidii: Option>, } impl<'a> EmscriptenData<'a> { @@ -146,6 +148,7 @@ impl<'a> EmscriptenData<'a> { let dyn_call_diiii = instance.func("dynCall_diiii").ok(); let dyn_call_iiiii = instance.func("dynCall_iiiii").ok(); let dyn_call_iiiiii = instance.func("dynCall_iiiiii").ok(); + let dyn_call_iiiiiii = instance.func("dynCall_iiiiiii").ok(); let dyn_call_vd = instance.func("dynCall_vd").ok(); let dyn_call_viiiii = instance.func("dynCall_viiiii").ok(); let dyn_call_viiiiii = instance.func("dynCall_viiiiii").ok(); @@ -168,6 +171,7 @@ impl<'a> EmscriptenData<'a> { let dyn_call_viji = instance.func("dynCall_viji").ok(); let dyn_call_vijiii = instance.func("dynCall_vijiii").ok(); let dyn_call_vijj = instance.func("dynCall_vijj").ok(); + let dyn_call_viidii = instance.func("dynCall_viidii").ok(); EmscriptenData { malloc, @@ -191,6 +195,7 @@ impl<'a> EmscriptenData<'a> { dyn_call_diiii, dyn_call_iiiii, dyn_call_iiiiii, + dyn_call_iiiiiii, dyn_call_vd, dyn_call_viiiii, dyn_call_viiiiii, @@ -213,6 +218,7 @@ impl<'a> EmscriptenData<'a> { dyn_call_viji, dyn_call_vijiii, dyn_call_vijj, + dyn_call_viidii, } } } @@ -457,13 +463,17 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "___syscall4" => func!(crate::syscalls::___syscall4), "___syscall5" => func!(crate::syscalls::___syscall5), "___syscall6" => func!(crate::syscalls::___syscall6), + "___syscall9" => func!(crate::syscalls::___syscall9), "___syscall10" => func!(crate::syscalls::___syscall10), "___syscall12" => func!(crate::syscalls::___syscall12), "___syscall15" => func!(crate::syscalls::___syscall15), "___syscall20" => func!(crate::syscalls::___syscall20), + "___syscall33" => func!(crate::syscalls::___syscall33), + "___syscall34" => func!(crate::syscalls::___syscall34), "___syscall39" => func!(crate::syscalls::___syscall39), "___syscall38" => func!(crate::syscalls::___syscall38), "___syscall40" => func!(crate::syscalls::___syscall40), + "___syscall41" => func!(crate::syscalls::___syscall41), "___syscall42" => func!(crate::syscalls::___syscall42), "___syscall54" => func!(crate::syscalls::___syscall54), "___syscall57" => func!(crate::syscalls::___syscall57), @@ -472,6 +482,8 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "___syscall64" => func!(crate::syscalls::___syscall64), "___syscall66" => func!(crate::syscalls::___syscall66), "___syscall75" => func!(crate::syscalls::___syscall75), + "___syscall77" => func!(crate::syscalls::___syscall77), + "___syscall83" => func!(crate::syscalls::___syscall83), "___syscall85" => func!(crate::syscalls::___syscall85), "___syscall91" => func!(crate::syscalls::___syscall191), "___syscall97" => func!(crate::syscalls::___syscall97), @@ -493,10 +505,14 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "___syscall195" => func!(crate::syscalls::___syscall195), "___syscall196" => func!(crate::syscalls::___syscall196), "___syscall197" => func!(crate::syscalls::___syscall197), + "___syscall198" => func!(crate::syscalls::___syscall198), "___syscall199" => func!(crate::syscalls::___syscall199), + "___syscall200" => func!(crate::syscalls::___syscall200), "___syscall201" => func!(crate::syscalls::___syscall201), "___syscall202" => func!(crate::syscalls::___syscall202), + "___syscall205" => func!(crate::syscalls::___syscall205), "___syscall212" => func!(crate::syscalls::___syscall212), + "___syscall219" => func!(crate::syscalls::___syscall219), "___syscall220" => func!(crate::syscalls::___syscall220), "___syscall221" => func!(crate::syscalls::___syscall221), "___syscall268" => func!(crate::syscalls::___syscall268), @@ -652,6 +668,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "invoke_diiii" => func!(crate::emscripten_target::invoke_diiii), "invoke_iiiii" => func!(crate::emscripten_target::invoke_iiiii), "invoke_iiiiii" => func!(crate::emscripten_target::invoke_iiiiii), + "invoke_iiiiiii" => func!(crate::emscripten_target::invoke_iiiiiii), "invoke_vd" => func!(crate::emscripten_target::invoke_vd), "invoke_viiiii" => func!(crate::emscripten_target::invoke_viiiii), "invoke_viiiiii" => func!(crate::emscripten_target::invoke_viiiiii), @@ -674,6 +691,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject "invoke_viji" => func!(crate::emscripten_target::invoke_viji), "invoke_vijiii" => func!(crate::emscripten_target::invoke_vijiii), "invoke_vijj" => func!(crate::emscripten_target::invoke_vijj), + "invoke_viidii" => func!(crate::emscripten_target::invoke_viidii), }, "global" => { "NaN" => Global::new(Value::F64(f64::NAN)), @@ -681,6 +699,8 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject }, "global.Math" => { "pow" => func!(crate::math::pow), + "exp" => func!(crate::math::exp), + "log" => func!(crate::math::log), }, "asm2wasm" => { "f64-rem" => func!(crate::math::f64_rem), diff --git a/lib/emscripten/src/math.rs b/lib/emscripten/src/math.rs index a60966a1c..63eee79b4 100644 --- a/lib/emscripten/src/math.rs +++ b/lib/emscripten/src/math.rs @@ -37,3 +37,13 @@ pub fn f64_rem(_ctx: &mut Ctx, x: f64, y: f64) -> f64 { pub fn pow(_ctx: &mut Ctx, x: f64, y: f64) -> f64 { x.powf(y) } + +// emscripten: global.Math exp +pub fn exp(_ctx: &mut Ctx, value: f64) -> f64 { + value.exp() +} + +// emscripten: global.Math log +pub fn log(_ctx: &mut Ctx, value: f64) -> f64 { + value.ln() +} diff --git a/lib/emscripten/src/syscalls/unix.rs b/lib/emscripten/src/syscalls/unix.rs index ac332571d..5ff8d840b 100644 --- a/lib/emscripten/src/syscalls/unix.rs +++ b/lib/emscripten/src/syscalls/unix.rs @@ -3,6 +3,7 @@ use crate::varargs::VarArgs; /// Syscall list: https://www.cs.utexas.edu/~bismith/test/syscalls/syscalls32.html use libc::{ accept, + access, bind, // ENOTTY, c_char, @@ -11,19 +12,27 @@ use libc::{ chown, // fcntl, setsockopt, getppid connect, + dup, dup2, fcntl, getgid, + getgroups, getpeername, + getrusage, getsockname, getsockopt, + gid_t, in_addr_t, in_port_t, ioctl, + kill, + lchown, + link, // iovec, listen, mkdir, msghdr, + nice, open, pid_t, pread, @@ -40,9 +49,12 @@ use libc::{ sendto, setpgid, setsockopt, + size_t, sockaddr, socket, socklen_t, + symlink, + uid_t, uname, utsname, EINVAL, @@ -64,10 +76,11 @@ use std::mem; #[link(name = "c")] extern "C" { pub fn wait4(pid: pid_t, status: *mut c_int, options: c_int, rusage: *mut rusage) -> pid_t; + pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int; } #[cfg(not(target_os = "macos"))] -use libc::wait4; +use libc::{madvise, wait4}; // Another conditional constant for name resolution: Macos et iOS use // SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket. @@ -93,6 +106,85 @@ pub fn ___syscall5(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int fd } +/// link +pub fn ___syscall9(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall9 (link) {}", _which); + + let oldname: c_int = varargs.get(ctx); + let newname: c_int = varargs.get(ctx); + let oldname_ptr = emscripten_memory_pointer!(ctx.memory(0), oldname) as *const i8; + let newname_ptr = emscripten_memory_pointer!(ctx.memory(0), newname) as *const i8; + let result = unsafe { link(oldname_ptr, newname_ptr) }; + debug!( + "=> oldname: {}, newname: {}, result: {}", + unsafe { std::ffi::CStr::from_ptr(oldname_ptr).to_str().unwrap() }, + unsafe { std::ffi::CStr::from_ptr(newname_ptr).to_str().unwrap() }, + result, + ); + result +} + +/// getrusage +pub fn ___syscall77(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall77 (getrusage) {}", _which); + + let resource: c_int = varargs.get(ctx); + let rusage_ptr: c_int = varargs.get(ctx); + let rusage = emscripten_memory_pointer!(ctx.memory(0), rusage_ptr) as *mut rusage; + unsafe { getrusage(resource, rusage) } +} + +/// link +pub fn ___syscall83(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall83 (symlink) {}", _which); + + let path1_ptr: c_int = varargs.get(ctx); + let path2_ptr: c_int = varargs.get(ctx); + let path1 = emscripten_memory_pointer!(ctx.memory(0), path1_ptr) as *mut i8; + let path2 = emscripten_memory_pointer!(ctx.memory(0), path2_ptr) as *mut i8; + let result = unsafe { symlink(path1, path2) }; + debug!( + "=> path1: {}, path2: {}, result: {}", + unsafe { std::ffi::CStr::from_ptr(path1).to_str().unwrap() }, + unsafe { std::ffi::CStr::from_ptr(path2).to_str().unwrap() }, + result, + ); + result +} + +/// lchown +pub fn ___syscall198(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall198 (lchown) {}", _which); + let path: c_int = varargs.get(ctx); + let uid: uid_t = varargs.get(ctx); + let gid: gid_t = varargs.get(ctx); + let path_ptr = emscripten_memory_pointer!(ctx.memory(0), path) as *const i8; + let result = unsafe { lchown(path_ptr, uid, gid) }; + debug!( + "=> path: {}, uid: {}, gid: {}, result: {}", + unsafe { std::ffi::CStr::from_ptr(path_ptr).to_str().unwrap() }, + uid, + gid, + result, + ); + result +} + +/// getgroups +pub fn ___syscall205(ctx: &mut Ctx, ngroups_max: c_int, groups: c_int) -> c_int { + debug!( + "emscripten::___syscall205 (getgroups) {} {}", + ngroups_max, groups + ); + let gid_ptr = emscripten_memory_pointer!(ctx.memory(0), groups) as *mut gid_t; + let result = unsafe { getgroups(ngroups_max, gid_ptr) }; + debug!( + "=> ngroups_max: {}, gid_ptr: {:?}, result: {}", + ngroups_max, gid_ptr, result, + ); + result +} + // chown pub fn ___syscall212(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall212 (chown) {}", _which); @@ -106,6 +198,41 @@ pub fn ___syscall212(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in unsafe { chown(pathname_addr, owner, group) } } +/// madvise +pub fn ___syscall219(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall212 (chown) {}", _which); + + let addr_ptr: c_int = varargs.get(ctx); + let len: usize = varargs.get(ctx); + let advice: c_int = varargs.get(ctx); + + let addr = emscripten_memory_pointer!(ctx.memory(0), addr_ptr) as *mut c_void; + + unsafe { madvise(addr, len, advice) } +} + +/// access +pub fn ___syscall33(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall33 (access) {}", _which); + let path_ptr: c_int = varargs.get(ctx); + let amode: c_int = varargs.get(ctx); + let path = emscripten_memory_pointer!(ctx.memory(0), path_ptr) as *const i8; + let result = unsafe { access(path, amode) }; + debug!( + "=> path: {}, result: {}", + unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() }, + result + ); + result +} + +/// nice +pub fn ___syscall34(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall34 (nice) {}", _which); + let inc_r: c_int = varargs.get(ctx); + unsafe { nice(inc_r) } +} + // mkdir pub fn ___syscall39(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall39 (mkdir) {}", _which); @@ -115,6 +242,19 @@ pub fn ___syscall39(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int unsafe { mkdir(pathname_addr, mode as _) } } +/// dup +pub fn ___syscall41(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { + debug!("emscripten::___syscall41 (dup) {}", _which); + let fd: c_int = varargs.get(ctx); + unsafe { dup(fd) } +} + +// tkill? REVIEW: double check this, truncate on OSX? +pub fn ___syscall200(_ctx: &mut Ctx, pid: pid_t, sig: c_int) -> i32 { + debug!("emscripten::___syscall200 (tkill)"); + unsafe { kill(pid, sig) } +} + // getgid pub fn ___syscall201(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 { debug!("emscripten::___syscall201 (getgid)");