From b7c5f27b3724944e0ed4dd300d00280a514cb1d0 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Fri, 22 Mar 2019 15:35:38 -0700 Subject: [PATCH] this commit makes the whole thing work --- lib/emscripten/src/syscalls/unix/host_fs.rs | 14 +- lib/emscripten/src/syscalls/unix/mod.rs | 2 +- lib/emscripten/src/syscalls/unix/select.rs | 154 +++++++++++++++----- lib/emscripten/src/syscalls/unix/vfs.rs | 56 ++++--- 4 files changed, 167 insertions(+), 59 deletions(-) diff --git a/lib/emscripten/src/syscalls/unix/host_fs.rs b/lib/emscripten/src/syscalls/unix/host_fs.rs index 002be7c50..e9960e748 100644 --- a/lib/emscripten/src/syscalls/unix/host_fs.rs +++ b/lib/emscripten/src/syscalls/unix/host_fs.rs @@ -343,9 +343,14 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut sockaddr; let address_len_addr = emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut socklen_t; - unsafe { + let recv_result = unsafe { libc::recvfrom(socket, buf_addr, flags, len, address, address_len_addr) as i32 - } + }; + debug!( + "recvfrom: socket: {}, flags: {}, len: {}, result: {}", + socket, flags, len, recv_result + ); + recv_result } 14 => { debug!("socket: setsockopt"); @@ -458,7 +463,10 @@ pub fn ___syscall142(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in } set_file_descriptors.push(virtual_fd); } - debug!("set read descriptors AFTER select: {:?}", set_file_descriptors); + debug!( + "set read descriptors AFTER select: {:?}", + set_file_descriptors + ); debug!("select returns {}", result); result diff --git a/lib/emscripten/src/syscalls/unix/mod.rs b/lib/emscripten/src/syscalls/unix/mod.rs index a4ca25ba9..b4a71331c 100644 --- a/lib/emscripten/src/syscalls/unix/mod.rs +++ b/lib/emscripten/src/syscalls/unix/mod.rs @@ -30,9 +30,9 @@ extern "C" { pub fn wait4(pid: pid_t, status: *mut c_int, options: c_int, rusage: *mut rusage) -> pid_t; } +use crate::utils::read_string_from_wasm; #[cfg(not(target_os = "macos"))] use libc::wait4; -use crate::utils::read_string_from_wasm; /// wait4 #[allow(clippy::cast_ptr_alignment)] diff --git a/lib/emscripten/src/syscalls/unix/select.rs b/lib/emscripten/src/syscalls/unix/select.rs index 1971634b5..6f77708e8 100644 --- a/lib/emscripten/src/syscalls/unix/select.rs +++ b/lib/emscripten/src/syscalls/unix/select.rs @@ -1,10 +1,10 @@ -use wasmer_runtime_core::vm::Ctx; +use crate::macros::emscripten_memory_ptr; +use crate::syscalls::emscripten_vfs::{FileHandle, VirtualFd}; use crate::varargs::VarArgs; use std::collections::HashMap; -use std::slice; -use crate::syscalls::emscripten_vfs::{FileHandle, VirtualFd}; use std::ffi::c_void; -use crate::macros::emscripten_memory_ptr; +use std::slice; +use wasmer_runtime_core::vm::Ctx; #[cfg(feature = "vfs")] #[derive(Debug)] @@ -14,8 +14,12 @@ struct FdPair { } #[cfg(feature = "vfs")] -fn translate_to_host_file_descriptors(ctx: &mut Ctx, mut varargs: &mut VarArgs, nfds: i32, fds_set_offset: u32) -> (i32, HashMap, Vec) { - +fn translate_to_host_file_descriptors( + ctx: &mut Ctx, + mut varargs: &mut VarArgs, + nfds: i32, + fds_set_offset: u32, +) -> (i32, HashMap, Vec) { let set_ptr = emscripten_memory_ptr(ctx.memory(0), fds_set_offset) as *mut _; // e.g. libc::unix::bsd::fd_set let set_u8_ptr = set_ptr as *mut u8; @@ -23,12 +27,12 @@ fn translate_to_host_file_descriptors(ctx: &mut Ctx, mut varargs: &mut VarArgs, let end_offset = fds_set_offset as usize + bit_array_size; let set_view = &ctx.memory(0).view::()[(fds_set_offset as usize)..end_offset]; use bit_field::BitArray; -// let check = set_ptr.get_bit(1); + // let check = set_ptr.get_bit(1); let fds_slice = unsafe { slice::from_raw_parts(set_u8_ptr, bit_array_size) }; -// (0usize..nfds as usize).filter_map(|x| fds_slice.get_bit(x)); -// let ofds = (0..nfds).filter_map(|v| fd_slice.v) + // (0usize..nfds as usize).filter_map(|x| fds_slice.get_bit(x)); + // let ofds = (0..nfds).filter_map(|v| fd_slice.v) let original_fds: Vec = (0..nfds) .filter_map(|virtual_fd| { if fds_slice.get_bit(virtual_fd as usize) { @@ -36,18 +40,22 @@ fn translate_to_host_file_descriptors(ctx: &mut Ctx, mut varargs: &mut VarArgs, } else { None } - }).collect::>(); + }) + .collect::>(); let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); // virtual read and write file descriptors - let file_descriptor_pairs = original_fds.iter() + let file_descriptor_pairs = original_fds + .iter() .filter(|vfd| { if let FileHandle::VirtualFile(handle) = vfs.fd_map.get(&VirtualFd(**vfd)).unwrap() { - debug!("skipping virtual fd {} (vbox handle {}) because is a virtual file", *vfd, *handle); + debug!( + "skipping virtual fd {} (vbox handle {}) because is a virtual file", + *vfd, *handle + ); false - } - else { + } else { true } }) @@ -56,7 +64,7 @@ fn translate_to_host_file_descriptors(ctx: &mut Ctx, mut varargs: &mut VarArgs, let file_handle = vfs.fd_map.get(&vfd).unwrap(); let host_fd = match file_handle { FileHandle::Socket(host_fd) => host_fd, -// FileHandle::VirtualFile(handle) => handle, + // FileHandle::VirtualFile(handle) => handle, _ => panic!(), }; let pair = FdPair { @@ -77,8 +85,10 @@ fn translate_to_host_file_descriptors(ctx: &mut Ctx, mut varargs: &mut VarArgs, // helper look up tables let mut lookup = HashMap::new(); for pair in file_descriptor_pairs.iter() { -// if pair.virtual_fd > sz { sz = pair.host_fd } - if pair.host_fd > sz { sz = pair.host_fd } + // if pair.virtual_fd > sz { sz = pair.host_fd } + if pair.host_fd > sz { + sz = pair.host_fd + } lookup.insert(pair.host_fd, pair.virtual_fd); } @@ -86,9 +96,13 @@ fn translate_to_host_file_descriptors(ctx: &mut Ctx, mut varargs: &mut VarArgs, (max_file_descriptor, lookup, file_descriptor_pairs) } - #[cfg(feature = "vfs")] -fn translate_to_virtual_file_descriptors(ctx: &mut Ctx, nfds: i32, fds_set_offset: u32, lookup: HashMap) -> Vec { +fn translate_to_virtual_file_descriptors( + ctx: &mut Ctx, + nfds: i32, + fds_set_offset: u32, + lookup: HashMap, +) -> Vec { let set_ptr = emscripten_memory_pointer!(ctx.memory(0), fds_set_offset) as *mut _; let set_u8_ptr = set_ptr as *mut u8; let fds_slice = unsafe { slice::from_raw_parts_mut(set_u8_ptr, nfds as usize) }; @@ -101,20 +115,28 @@ fn translate_to_virtual_file_descriptors(ctx: &mut Ctx, nfds: i32, fds_set_offse } else { None } - }).collect::>(); + }) + .collect::>(); // swap descriptors back - let pairs = fds.iter() + let pairs = fds + .iter() .filter_map(|host_fd| { - lookup.get(&host_fd).map(|virtual_fd| (*virtual_fd, host_fd)) + lookup + .get(&host_fd) + .map(|virtual_fd| (*virtual_fd, host_fd)) }) .map(|(virtual_fd, host_fd)| { unsafe { libc::FD_CLR(*host_fd, set_ptr); libc::FD_SET(virtual_fd, set_ptr); } - FdPair { virtual_fd, host_fd: *host_fd } - }).collect::>(); + FdPair { + virtual_fd, + host_fd: *host_fd, + } + }) + .collect::>(); pairs } @@ -132,35 +154,93 @@ pub fn ___syscall142(ctx: &mut Ctx, _which: libc::c_int, mut varargs: VarArgs) - let readfds_set_ptr = emscripten_memory_pointer!(ctx.memory(0), readfds) as *mut _; let writefds_set_ptr = emscripten_memory_pointer!(ctx.memory(0), writefds) as *mut _; -// debug!(" select read descriptors: {:?}", read_fds); -// -// debug!("select write descriptors: {:?}", write_fds); + // debug!(" select read descriptors: {:?}", read_fds); + // + // debug!("select write descriptors: {:?}", write_fds); - let (read_max, read_lookup, read_pairs) - = translate_to_host_file_descriptors(ctx, &mut varargs, nfds, readfds); - let (write_max, write_lookup, write_pairs) - = translate_to_host_file_descriptors(ctx, &mut varargs, nfds, writefds); + let (read_max, read_lookup, read_pairs) = + translate_to_host_file_descriptors(ctx, &mut varargs, nfds, readfds); + let (write_max, write_lookup, write_pairs) = + translate_to_host_file_descriptors(ctx, &mut varargs, nfds, writefds); - let max = if read_max > write_max { read_max } else { write_max }; + let max = if read_max > write_max { + read_max + } else { + write_max + }; + debug!("max host fd for select: {}", max); let mut sz = max; - debug!("set read descriptors BEFORE select: {:?}", read_pairs); - debug!("set write descriptors BEFORE select: {:?}", write_pairs); + debug!( + "set read descriptors BEFORE select: {:?}", + read_pairs // .iter() + // .map(|pair| pair.virtual_fd) + // .collect::>() + ); + debug!( + "set write descriptors BEFORE select: {:?}", + write_pairs // .iter() + // .map(|pair| pair.virtual_fd) + // .collect::>() + ); // call `select` sz = sz + 1; + debug!( + "readfds_set_ptr: {:?}", + read_pairs + .iter() + .map(|pair| pair.host_fd) + .collect::>() + ); + let fds_slice = unsafe { slice::from_raw_parts(readfds_set_ptr as *const u8, 4) } as &[u8]; + debug!("host read set before: {:?}", fds_slice); let mut result = unsafe { libc::select(sz, readfds_set_ptr, writefds_set_ptr, 0 as _, 0 as _) }; + debug!("host read set after: {:?}", fds_slice); + + unsafe { + use libc::FD_ISSET; + let s = 3; + let x = [ + FD_ISSET(s, readfds_set_ptr), + FD_ISSET(s + 1, readfds_set_ptr), + FD_ISSET(s + 2, readfds_set_ptr), + FD_ISSET(s + 3, readfds_set_ptr), + FD_ISSET(s + 4, readfds_set_ptr), + FD_ISSET(s + 5, readfds_set_ptr), + FD_ISSET(s + 6, readfds_set_ptr), + FD_ISSET(s + 7, readfds_set_ptr), + FD_ISSET(s + 8, readfds_set_ptr), + FD_ISSET(s + 9, readfds_set_ptr), + FD_ISSET(s + 10, readfds_set_ptr), + FD_ISSET(s + 11, readfds_set_ptr), + ]; + debug!("sets (start with fd #{}: {:?}", s, x); + } if result == -1 { - panic!("result returned from select was -1. The errno code: {}", errno::errno()); + panic!( + "result returned from select was -1. The errno code: {}", + errno::errno() + ); } let read_pairs = translate_to_virtual_file_descriptors(ctx, sz, readfds, read_lookup); - debug!("select read descriptors after select completes: {:?}", read_pairs); + debug!( + "select read descriptors after select completes: {:?}", + read_pairs // .iter() + // .map(|pair| pair.virtual_fd) + // .collect::>() + ); let write_pairs = translate_to_virtual_file_descriptors(ctx, sz, writefds, write_lookup); - debug!("select write descriptors after select completes: {:?}", write_pairs); + debug!( + "select write descriptors after select completes: {:?}", + write_pairs // .iter() + // .map(|pair| pair.virtual_fd) + // .collect::>() + ); debug!("select returns {}", result); result diff --git a/lib/emscripten/src/syscalls/unix/vfs.rs b/lib/emscripten/src/syscalls/unix/vfs.rs index af52be5d7..9f1bf729c 100644 --- a/lib/emscripten/src/syscalls/unix/vfs.rs +++ b/lib/emscripten/src/syscalls/unix/vfs.rs @@ -1,15 +1,15 @@ +use crate::macros::emscripten_memory_ptr; use crate::syscalls::emscripten_vfs::FileHandle::{Socket, VirtualFile}; use crate::syscalls::emscripten_vfs::{FileHandle, VirtualFd}; use crate::utils::{copy_stat_into_wasm, read_string_from_wasm}; use crate::varargs::VarArgs; +use bit_field::BitArray; use libc::stat; use std::collections::HashMap; use std::ffi::c_void; use std::os::raw::c_int; use std::slice; use wasmer_runtime_core::vm::Ctx; -use bit_field::BitArray; -use crate::macros::emscripten_memory_ptr; /// read pub fn ___syscall3(ctx: &mut Ctx, _: i32, mut varargs: VarArgs) -> i32 { @@ -42,22 +42,25 @@ pub fn ___syscall4(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int let buf_slice = unsafe { slice::from_raw_parts_mut(buf_addr, count as _) }; let vfd = VirtualFd(fd); let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap(); - let count: usize = match vfs.fd_map.get(&vfd) { + let (host_fd, count) = match vfs.fd_map.get(&vfd) { Some(FileHandle::VirtualFile(handle)) => { vfs.vfs .write_file(*handle as _, buf_slice, count as _, 0) .unwrap(); - count as usize + (*handle, count as usize) } Some(FileHandle::Socket(host_fd)) => unsafe { - libc::write(*host_fd, buf_addr as _, count as _) as usize + ( + *host_fd, + libc::write(*host_fd, buf_addr as _, count as _) as usize, + ) }, None => panic!(), }; debug!("wrote: {}", read_string_from_wasm(ctx.memory(0), buf)); debug!( "=> fd: {} (host {}), buf: {}, count: {}\n", - vfd.0, fd, buf, count + vfd.0, host_fd, buf, count ); count as c_int } @@ -76,8 +79,14 @@ pub fn ___syscall5(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int !vfs.fd_map.contains_key(&next_lowest_virtual_fd), "Emscripten vfs should not contain file descriptor." ); - vfs.fd_map.insert(next_lowest_virtual_fd.clone(), virtual_file_handle); - debug!("=> opening `{}` with new virtual fd: {} (zbox handle {})", path_str, next_lowest_virtual_fd.clone(), fd); + vfs.fd_map + .insert(next_lowest_virtual_fd.clone(), virtual_file_handle); + debug!( + "=> opening `{}` with new virtual fd: {} (zbox handle {})", + path_str, + next_lowest_virtual_fd.clone(), + fd + ); debug!("{}", path_str); return next_lowest_virtual_fd.0 as _; } @@ -525,7 +534,7 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in let vfd = VirtualFd(socket); let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); - let rcv_result = unsafe { + let recv_result = unsafe { libc::recvfrom( host_socket_fd, buf_addr, @@ -535,8 +544,11 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in address_len_addr, ) as i32 }; - rcv_result - + debug!( + "recvfrom: socket: {}, flags: {}, len: {}, result: {}", + socket, flags, len, recv_result + ); + recv_result } 14 => { debug!("socket: setsockopt"); @@ -574,7 +586,10 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in use libc::socklen_t; let socket = socket_varargs.get(ctx); let level: i32 = socket_varargs.get(ctx); + let correct_level = if level == 1 { libc::SOL_SOCKET } else { level }; let name: i32 = socket_varargs.get(ctx); + let correct_name = if name == 3 { libc::SO_TYPE } else { name }; + let value: u32 = socket_varargs.get(ctx); let option_len: u32 = socket_varargs.get(ctx); let value_addr = emscripten_memory_pointer!(ctx.memory(0), value) as _; @@ -586,7 +601,7 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap(); let result = unsafe { - libc::getsockopt(host_socket_fd, level, name, value_addr, option_len_addr) + libc::getsockopt(host_socket_fd, correct_level, correct_name, value_addr, option_len_addr) }; if result == -1 { @@ -647,17 +662,20 @@ pub fn ___syscall146(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { } let iov_array_offset = iov_array_offset as u32; - let count = (0..iovcnt as u32).fold(0,|acc, iov_array_index| { + let count = (0..iovcnt as u32).fold(0, |acc, iov_array_index| { unsafe { let iov_offset = iov_array_offset + iov_array_index * 8; // get the offset to the iov let (iov_buf_slice, iov_buf_ptr, count) = { let emscripten_memory = ctx.memory(0); - let guest_iov_ptr = emscripten_memory_ptr(emscripten_memory, iov_offset) as *mut GuestIovec; + let guest_iov_ptr = + emscripten_memory_ptr(emscripten_memory, iov_offset) as *mut GuestIovec; let iov_base_offset = (*guest_iov_ptr).iov_base as u32; - let iov_buf_ptr = emscripten_memory_ptr(emscripten_memory, iov_base_offset) as *const c_void; + let iov_buf_ptr = + emscripten_memory_ptr(emscripten_memory, iov_base_offset) as *const c_void; let iov_len = (*guest_iov_ptr).iov_len as usize; - let iov_buf_slice = unsafe { slice::from_raw_parts(iov_buf_ptr as *const u8, iov_len) }; + let iov_buf_slice = + unsafe { slice::from_raw_parts(iov_buf_ptr as *const u8, iov_len) }; (iov_buf_slice, iov_buf_ptr, iov_len) }; @@ -684,11 +702,13 @@ pub fn ___syscall146(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 { } }); - debug!("=> fd: {}, iov: {}, iovcnt = {}, returning {}", fd, iov_array_offset, iovcnt, count); + debug!( + "=> fd: {}, iov: {}, iovcnt = {}, returning {}", + fd, iov_array_offset, iovcnt, count + ); count as _ } - /// pread pub fn ___syscall180(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int { debug!("emscripten::___syscall180 (pread) {}", _which);