Merge branch 'master' into update-cranelift

This commit is contained in:
nlewycky 2019-07-02 10:07:22 -07:00 committed by GitHub
commit edb674d84b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 183 additions and 90 deletions

View File

@ -135,7 +135,8 @@ pub fn _pthread_condattr_setclock(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
}
pub fn _pthread_create(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32, _d: i32) -> i32 {
trace!("emscripten::_pthread_create");
0
// 11 seems to mean "no"
11
}
pub fn _pthread_detach(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_detach");

View File

@ -220,10 +220,10 @@ pub fn _getaddrinfo(
.deref(memory)
.map(|m| m as *const Cell<c_char> as *const c_char))
.unwrap_or(std::ptr::null()),
(service_str_ptr
service_str_ptr
.deref(memory)
.map(|m| m as *const Cell<c_char> as *const c_char))
.unwrap_or(std::ptr::null()),
.map(|m| m as *const Cell<c_char> as *const c_char)
.unwrap_or(std::ptr::null()),
hints
.as_ref()
.map(|h| h as *const addrinfo)

View File

@ -21,9 +21,9 @@ pub fn _emscripten_memcpy_big(ctx: &mut Ctx, dest: u32, src: u32, len: u32) -> u
/// emscripten: _emscripten_get_heap_size
pub fn _emscripten_get_heap_size(ctx: &mut Ctx) -> u32 {
debug!("emscripten::_emscripten_get_heap_size");
trace!("emscripten::_emscripten_get_heap_size");
let result = ctx.memory(0).size().bytes().0 as u32;
debug!("=> {}", result);
trace!("=> {}", result);
result
}

View File

@ -276,34 +276,6 @@ pub fn ___syscall75(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
-1
}
// readlink
pub fn ___syscall85(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
debug!("emscripten::___syscall85 (readlink)");
let _path = varargs.get_str(ctx);
let buf = varargs.get_str(ctx);
// let buf_addr: i32 = varargs.get(ctx);
let buf_size: i32 = varargs.get(ctx);
let fd = 3;
let ret = unsafe { read(fd, buf as _, buf_size as _) as i32 };
debug!(
"=> buf: {}, buf_size: {}, return: {} ",
unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() },
buf_size,
ret
);
// let ret = unsafe {
// readlink(path, buf as _, buf_size as _) as i32
// };
// debug!("=> path: {}, buf: {}, buf_size: {}, return: {} ",
// unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() },
// unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() },
// // std::ffi::CStr::from_ptr(buf).to_str().unwrap(),
// // buf,
// buf_size,
// ret);
ret
}
pub fn ___syscall91(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
debug!("emscripten::___syscall91 - stub");
0
@ -531,11 +503,6 @@ pub fn ___syscall146(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
}
}
pub fn ___syscall168(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
debug!("emscripten::___syscall168 - stub");
-1
}
pub fn ___syscall191(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
let _resource: i32 = varargs.get(ctx);
debug!(

View File

@ -7,7 +7,6 @@ use libc::{
accept,
access,
bind,
c_char,
c_int,
c_void,
chown,
@ -72,15 +71,15 @@ use libc::{
F_GETFD,
F_SETFD,
SOL_SOCKET,
SO_REUSEADDR,
TIOCGWINSZ,
};
#[allow(unused_imports)]
use std::ffi::CStr;
use wasmer_runtime_core::vm::Ctx;
use wasmer_runtime_core::{memory::ptr::WasmPtr, vm::Ctx};
use crate::utils;
use crate::env::EmSockAddr;
use crate::utils::{self, get_cstr_path};
#[allow(unused_imports)]
use std::io::Error;
use std::mem;
@ -92,7 +91,7 @@ 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;
pub fn fdatasync(fd: c_int) -> c_int;
pub fn lstat64(path: *const c_char, buf: *mut c_void) -> c_int;
pub fn lstat64(path: *const libc::c_char, buf: *mut c_void) -> c_int;
}
#[cfg(not(target_os = "macos"))]
@ -101,9 +100,9 @@ use libc::{fallocate, fdatasync, ftruncate64, lstat, madvise, wait4};
// Another conditional constant for name resolution: Macos et iOS use
// SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket.
// Other platforms do otherwise.
#[cfg(target_os = "darwin")]
#[cfg(target_os = "macos")]
use libc::SO_NOSIGPIPE;
#[cfg(not(target_os = "darwin"))]
#[cfg(not(target_os = "macos"))]
const SO_NOSIGPIPE: c_int = 0;
/// open
@ -187,6 +186,35 @@ pub fn ___syscall83(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
result
}
/// readlink
pub fn ___syscall85(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> i32 {
debug!("emscripten::___syscall85 (readlink)");
let pathname_addr = varargs.get_str(ctx);
let buf = varargs.get_str(ctx);
// let buf_addr: i32 = varargs.get(ctx);
let buf_size: i32 = varargs.get(ctx);
let real_path_owned = get_cstr_path(ctx, pathname_addr);
let real_path = if let Some(ref rp) = real_path_owned {
rp.as_c_str().as_ptr()
} else {
pathname_addr
};
let ret = unsafe { libc::readlink(real_path, buf as _, buf_size as _) as i32 };
if ret == -1 {
debug!("readlink failed");
return ret;
}
debug!(
"=> path: {}, buf: {}, buf_size: {}, return: {} ",
unsafe { std::ffi::CStr::from_ptr(real_path).to_str().unwrap() },
unsafe { std::ffi::CStr::from_ptr(buf as _).to_str().unwrap() },
buf_size,
ret
);
ret
}
/// ftruncate64
pub fn ___syscall194(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall194 (ftruncate64) {}", _which);
@ -444,6 +472,7 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
let call: u32 = varargs.get(ctx);
let mut socket_varargs: VarArgs = varargs.get(ctx);
// migrating to EmSockAddr, port being separate here is nice, should update that too
#[repr(C)]
pub struct GuestSockaddrIn {
pub sin_family: sa_family_t, // u16
@ -458,13 +487,6 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
pub s_addr: in_addr_t, // u32
}
// debug!("GuestSockaddrIn = {}", size_of::<GuestSockaddrIn>());
pub struct LinuxSockAddr {
pub sa_family: u16,
pub sa_data: [c_char; 14],
}
match call {
1 => {
debug!("socket: socket");
@ -487,6 +509,7 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
unimplemented!("non blocking sockets");
}
// why is this here?
type T = u32;
let payload = 1 as *const T as _;
unsafe {
@ -500,7 +523,7 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
};
debug!(
"=> domain: {} (AF_INET/2), type: {} (SOCK_STREAM/1), protocol: {} = fd: {}",
"=> domain: {}, type: {}, protocol: {} = fd: {}",
domain, ty, protocol, fd
);
fd as _
@ -555,47 +578,75 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
5 => {
debug!("socket: accept");
// accept (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int
let socket = socket_varargs.get(ctx);
let address_addr: u32 = socket_varargs.get(ctx);
let address_len: u32 = socket_varargs.get(ctx);
let address = emscripten_memory_pointer!(ctx.memory(0), address_addr) as *mut sockaddr;
let socket: i32 = socket_varargs.get(ctx);
let address: WasmPtr<EmSockAddr> = socket_varargs.get(ctx);
let address_len: WasmPtr<u32> = socket_varargs.get(ctx);
debug!(
"=> socket: {}, address: {:?}, address_len: {}",
socket, address, address_len
socket,
address.deref(ctx.memory(0)).unwrap().get(),
address_len.deref(ctx.memory(0)).unwrap().get()
);
let address_len_addr =
emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut socklen_t;
unsafe { address_len.deref_mut(ctx.memory(0)).unwrap().get_mut() };
// let mut address_len_addr: socklen_t = 0;
let fd = unsafe { accept(socket, address, address_len_addr) };
let (fd, host_address) = unsafe {
let mut host_address: sockaddr = std::mem::uninitialized();
let fd = accept(socket, &mut host_address, address_len_addr);
unsafe {
let address_linux =
emscripten_memory_pointer!(ctx.memory(0), address_addr) as *mut LinuxSockAddr;
(*address_linux).sa_family = (*address).sa_family as u16;
(*address_linux).sa_data = (*address).sa_data;
(fd, host_address)
};
let address_addr = unsafe { address.deref_mut(ctx.memory(0)).unwrap().get_mut() };
address_addr.sa_family = host_address.sa_family as _;
address_addr.sa_data = host_address.sa_data.clone();
// why is this here?
// set_cloexec
unsafe {
ioctl(fd, FIOCLEX);
};
debug!("fd: {}", fd);
debug!(
"address: {:?}, len: {}, result fd = {}",
address_addr, address_len_addr, fd
);
fd as _
}
6 => {
debug!("socket: getsockname");
// getsockname (socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int
let socket = socket_varargs.get(ctx);
let address: u32 = socket_varargs.get(ctx);
let address_len: u32 = socket_varargs.get(ctx);
let address = emscripten_memory_pointer!(ctx.memory(0), address) as *mut sockaddr;
let socket: i32 = socket_varargs.get(ctx);
let address: WasmPtr<EmSockAddr> = socket_varargs.get(ctx);
let address_len: WasmPtr<u32> = socket_varargs.get(ctx);
let address_len_addr =
emscripten_memory_pointer!(ctx.memory(0), address_len) as *mut socklen_t;
unsafe { getsockname(socket, address, address_len_addr) }
unsafe { address_len.deref_mut(ctx.memory(0)).unwrap().get_mut() };
let (ret, sock_addr_host) = unsafe {
// read host data into new var
let mut address: sockaddr = std::mem::uninitialized();
let ret = getsockname(
socket,
&mut address as *mut sockaddr,
address_len_addr as *mut u32,
);
(ret, address)
};
// translate from host data into emscripten data
let mut address_mut = unsafe { address.deref_mut(ctx.memory(0)).unwrap().get_mut() };
address_mut.sa_family = sock_addr_host.sa_family as _;
address_mut.sa_data = sock_addr_host.sa_data.clone();
debug!(
"=> socket: {}, address, {:?}, address_len: {}, result = {}",
socket, address_mut, address_len_addr, ret
);
ret
}
7 => {
debug!("socket: getpeername");
@ -647,25 +698,23 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
}
14 => {
debug!("socket: setsockopt");
// NOTE: Emscripten seems to be passing the wrong values to this syscall
// level: Em passes 1 as SOL_SOCKET; SOL_SOCKET is 0xffff in BSD
// name: Em passes SO_ACCEPTCONN, but Nginx complains about REUSEADDR
// OSX and BSD have completely different values, be very careful here
// https://github.com/openbsd/src/blob/master/sys/sys/socket.h#L156
// setsockopt (socket: c_int, level: c_int, name: c_int, value: *const c_void, option_len: socklen_t) -> c_int
let socket = socket_varargs.get(ctx);
let level: i32 = socket_varargs.get(ctx);
// SOL_SOCKET = 0xffff (BSD, OSX)
let level = if level == 1 { SOL_SOCKET } else { level };
let name: i32 = socket_varargs.get(ctx);
// SO_REUSEADDR = 0x4 (BSD, OSX)
let name = if name == 2 { SO_REUSEADDR } else { name };
let untranslated_name: i32 = socket_varargs.get(ctx);
let value: u32 = socket_varargs.get(ctx);
let option_len = socket_varargs.get(ctx);
let value_addr = emscripten_memory_pointer!(ctx.memory(0), value) as _; // Endian problem
let option_len: u32 = socket_varargs.get(ctx);
let value_addr =
emscripten_memory_pointer!(ctx.memory(0), value) as *const libc::c_void;
let name: i32 = translate_socket_name_flag(untranslated_name);
let ret = unsafe { setsockopt(socket, level, name, value_addr, option_len) };
debug!("=> socketfd: {}, level: {}, name: {}, value_addr: {:?}, option_len: {} = status: {}", socket, level, name, value_addr, option_len, ret);
debug!("=> socketfd: {}, level: {}, name: {}, value_addr: {:?}, option_len: {} = status: {}", socket, level, untranslated_name, value_addr, option_len, ret);
ret
}
15 => {
@ -673,7 +722,9 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
// getsockopt (sockfd: c_int, level: c_int, optname: c_int, optval: *mut c_void, optlen: *mut socklen_t) -> c_int
let socket = socket_varargs.get(ctx);
let level: i32 = socket_varargs.get(ctx);
let name: i32 = socket_varargs.get(ctx);
let level = if level == 1 { SOL_SOCKET } else { level };
let untranslated_name: i32 = socket_varargs.get(ctx);
let name: i32 = translate_socket_name_flag(untranslated_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 _;
@ -706,6 +757,60 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
}
}
/// OSX and BSD have completely different values, we must translate from emscripten's Linuxy
/// value into one that we can pass to native syscalls
fn translate_socket_name_flag(name: i32) -> i32 {
match name {
2 => libc::SO_REUSEADDR,
3 => libc::SO_TYPE,
4 => libc::SO_ERROR,
5 => libc::SO_DONTROUTE,
6 => libc::SO_BROADCAST,
7 => libc::SO_SNDBUF,
8 => libc::SO_RCVBUF,
9 => libc::SO_KEEPALIVE,
10 => libc::SO_OOBINLINE,
13 => libc::SO_LINGER,
18 => libc::SO_RCVLOWAT,
19 => libc::SO_SNDLOWAT,
20 => libc::SO_RCVTIMEO,
21 => libc::SO_SNDTIMEO,
// SO_DEBUG missing
30 => libc::SO_ACCEPTCONN,
otherwise => otherwise,
}
}
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct EmPollFd {
pub fd: i32,
pub events: i16,
pub revents: i16,
}
unsafe impl wasmer_runtime_core::types::ValueType for EmPollFd {}
/// poll
pub fn ___syscall168(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
debug!("emscripten::___syscall168(poll)");
let fds: WasmPtr<EmPollFd> = varargs.get(ctx);
let nfds: u32 = varargs.get(ctx);
let timeout: i32 = varargs.get(ctx);
let fds_mut = unsafe { fds.deref_mut(ctx.memory(0)).unwrap().get_mut() };
let ret = unsafe {
libc::poll(
fds_mut as *mut EmPollFd as *mut libc::pollfd,
nfds as _,
timeout,
)
};
ret
}
// pread
pub fn ___syscall180(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall180 (pread) {}", _which);
@ -885,11 +990,11 @@ pub fn ___syscall220(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
let dirp = emscripten_memory_pointer!(ctx.memory(0), dirp_addr) as *mut u8;
let mut opened_dirs = &mut get_emscripten_data(ctx).opened_dirs;
let opened_dirs = &mut get_emscripten_data(ctx).opened_dirs;
// need to persist stream across calls?
// let dir: *mut libc::DIR = unsafe { libc::fdopendir(fd) };
let mut dir = &*opened_dirs
let dir = &*opened_dirs
.entry(fd)
.or_insert_with(|| unsafe { Box::new(libc::fdopendir(fd)) });

View File

@ -128,6 +128,12 @@ pub fn ___syscall83(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
unimplemented!()
}
/// readlink
pub fn ___syscall85(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall85 (readlink) {}", _which);
-1
}
/// lchown
pub fn ___syscall198(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall198 (lchown) {}", _which);
@ -255,6 +261,12 @@ pub fn ___syscall122(_ctx: &mut Ctx, which: c_int, mut _varargs: VarArgs) -> c_i
-1
}
/// poll
pub fn ___syscall168(_ctx: &mut Ctx, _which: i32, _varargs: VarArgs) -> i32 {
debug!("emscripten::___syscall168(poll) - stub");
-1
}
/// lstat64
pub fn ___syscall196(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
debug!("emscripten::___syscall196 (lstat64) - stub");

View File

@ -46,7 +46,9 @@ fn align_pointer(ptr: usize, align: usize) -> usize {
impl<T: Copy + ValueType> WasmPtr<T, Item> {
#[inline]
pub fn deref<'a>(self, memory: &'a Memory) -> Option<&'a Cell<T>> {
if (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0 {
if self.offset == 0
|| (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0
{
return None;
}
unsafe {
@ -60,7 +62,9 @@ impl<T: Copy + ValueType> WasmPtr<T, Item> {
#[inline]
pub unsafe fn deref_mut<'a>(self, memory: &'a Memory) -> Option<&'a mut Cell<T>> {
if (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0 {
if self.offset == 0
|| (self.offset as usize) + mem::size_of::<T>() >= memory.size().bytes().0
{
return None;
}
let cell_ptr = align_pointer(
@ -79,7 +83,9 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
let item_size = mem::size_of::<T>() + (mem::size_of::<T>() % mem::align_of::<T>());
let slice_full_len = index as usize + length as usize;
if (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0 {
if self.offset == 0
|| (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0
{
return None;
}
@ -106,7 +112,9 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
let item_size = mem::size_of::<T>() + (mem::size_of::<T>() % mem::align_of::<T>());
let slice_full_len = index as usize + length as usize;
if (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0 {
if self.offset == 0
|| (self.offset as usize) + (item_size * slice_full_len) >= memory.size().bytes().0
{
return None;
}