1
0
mirror of https://github.com/fluencelabs/wasmer synced 2025-03-16 16:20:49 +00:00

remove unix-specific code from code windows sees

This commit is contained in:
Mark McCaskey 2019-07-01 11:42:50 -07:00
parent 4fcb3c4c83
commit d825fe9eb2
5 changed files with 252 additions and 237 deletions
lib/emscripten/src

@ -1,13 +1,9 @@
#![allow(non_snake_case)]
use crate::env::{call_malloc_with_cast, get_emscripten_data};
use libc::c_char;
use crate::env::get_emscripten_data;
#[cfg(target_os = "linux")]
use libc::getdtablesize;
use wasmer_runtime_core::{
memory::ptr::{Array, WasmPtr},
vm::Ctx,
};
use wasmer_runtime_core::vm::Ctx;
pub fn asm_const_i(_ctx: &mut Ctx, _val: i32) -> i32 {
debug!("emscripten::asm_const_i: {}", _val);
@ -237,26 +233,6 @@ pub fn ___gxx_personality_v0(
0
}
// this may be a memory leak, probably not though because emscripten does the same thing
pub fn _gai_strerror(ctx: &mut Ctx, ecode: i32) -> i32 {
debug!("emscripten::_gai_strerror({})", ecode);
let cstr = unsafe { std::ffi::CStr::from_ptr(libc::gai_strerror(ecode)) };
let bytes = cstr.to_bytes_with_nul();
let string_on_guest: WasmPtr<c_char, Array> = call_malloc_with_cast(ctx, bytes.len() as _);
let writer = unsafe {
string_on_guest
.deref_mut(ctx.memory(0), 0, bytes.len() as _)
.unwrap()
};
for (i, byte) in bytes.iter().enumerate() {
writer[i].set(*byte as i8);
}
string_on_guest.offset() as _
}
#[cfg(target_os = "linux")]
pub fn _getdtablesize(_ctx: &mut Ctx) -> i32 {
debug!("emscripten::getdtablesize");

@ -14,7 +14,6 @@ use libc::c_char;
use crate::{allocate_on_stack, EmscriptenData};
use std::cell::Cell;
use std::os::raw::c_int;
use wasmer_runtime_core::{
memory::ptr::{Array, WasmPtr},
@ -22,211 +21,6 @@ use wasmer_runtime_core::{
vm::Ctx,
};
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct EmAddrInfo {
// int
ai_flags: i32,
// int
ai_family: i32,
// int
ai_socktype: i32,
// int
ai_protocol: i32,
// socklen_t
ai_addrlen: u32,
// struct sockaddr*
ai_addr: WasmPtr<EmSockAddr>,
// char*
ai_canonname: WasmPtr<c_char, Array>,
// struct addrinfo*
ai_next: WasmPtr<EmAddrInfo>,
}
unsafe impl ValueType for EmAddrInfo {}
// NOTE: from looking at emscripten JS, this should be a union
// TODO: review this, highly likely to have bugs
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct EmSockAddr {
sa_family: i16,
sa_data: [c_char; 14],
}
unsafe impl ValueType for EmSockAddr {}
pub fn _getaddrinfo(
ctx: &mut Ctx,
node_ptr: WasmPtr<c_char>,
service_str_ptr: WasmPtr<c_char>,
hints_ptr: WasmPtr<EmAddrInfo>,
res_val_ptr: WasmPtr<WasmPtr<EmAddrInfo>>,
) -> i32 {
use libc::{addrinfo, freeaddrinfo};
debug!("emscripten::_getaddrinfo");
let memory = ctx.memory(0);
debug!(" => node = {}", unsafe {
node_ptr
.deref(memory)
.map(|np| {
std::ffi::CStr::from_ptr(np as *const Cell<c_char> as *const c_char)
.to_string_lossy()
})
.unwrap_or(std::borrow::Cow::Borrowed("null"))
});
debug!(" => server_str = {}", unsafe {
service_str_ptr
.deref(memory)
.map(|np| {
std::ffi::CStr::from_ptr(np as *const Cell<c_char> as *const c_char)
.to_string_lossy()
})
.unwrap_or(std::borrow::Cow::Borrowed("null"))
});
let hints = hints_ptr.deref(memory).map(|hints_memory| {
let hints_guest = dbg!(hints_memory.get());
unsafe {
let mut hints_native: addrinfo = std::mem::uninitialized();
hints_native.ai_flags = hints_guest.ai_flags;
hints_native.ai_family = hints_guest.ai_family;
hints_native.ai_socktype = hints_guest.ai_socktype;
hints_native.ai_protocol = hints_guest.ai_protocol;
hints_native.ai_addrlen = 0;
hints_native.ai_addr = std::ptr::null_mut();
hints_native.ai_canonname = std::ptr::null_mut();
hints_native.ai_next = std::ptr::null_mut();
hints_native
}
});
let mut out_ptr: *mut addrinfo = std::ptr::null_mut();
// allocate equivalent memory for res_val_ptr
let result = unsafe {
libc::getaddrinfo(
(node_ptr
.deref(memory)
.map(|m| m as *const Cell<c_char> as *const c_char))
.unwrap_or(std::ptr::null()),
(service_str_ptr
.deref(memory)
.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)
.unwrap_or(std::ptr::null()),
&mut out_ptr as *mut *mut addrinfo,
)
};
if dbg!(result) != 0 {
return result;
}
// walk linked list and copy over, freeing them from the kernel
let head_of_list = unsafe {
let mut current_host_node = out_ptr;
let mut head_of_list = None;
let mut previous_guest_node: Option<WasmPtr<EmAddrInfo>> = None;
while !current_host_node.is_null() {
let current_guest_node_ptr: WasmPtr<EmAddrInfo> =
call_malloc_with_cast(ctx, std::mem::size_of::<EmAddrInfo>() as _);
if head_of_list.is_none() {
dbg!("Setting head of list");
head_of_list = Some(current_guest_node_ptr);
}
// connect list
if let Some(prev_guest) = previous_guest_node {
let mut pg = prev_guest.deref_mut(ctx.memory(0)).unwrap().get_mut();
pg.ai_next = current_guest_node_ptr;
dbg!("list connected");
}
// update values
let host_addrlen = (*current_host_node).ai_addrlen;
// allocate addr and copy data
let guest_sockaddr_ptr = {
let host_sockaddr_ptr = (*current_host_node).ai_addr;
let guest_sockaddr_ptr: WasmPtr<EmSockAddr> =
call_malloc_with_cast(ctx, host_addrlen as _);
let guest_sockaddr = guest_sockaddr_ptr
.deref_mut(ctx.memory(0))
.unwrap()
.get_mut();
guest_sockaddr.sa_family = (*host_sockaddr_ptr).sa_family as i16;
guest_sockaddr.sa_data = (*host_sockaddr_ptr).sa_data.clone();
guest_sockaddr_ptr
};
dbg!("Socketaddr allocated");
// allocate canon name on guest and copy data over
let guest_canonname_ptr = {
let str_ptr = (*current_host_node).ai_canonname;
if !str_ptr.is_null() {
let canonname_cstr = dbg!(std::ffi::CStr::from_ptr(str_ptr));
let canonname_bytes = canonname_cstr.to_bytes_with_nul();
let str_size = dbg!(canonname_bytes.len());
let guest_canonname: WasmPtr<c_char, Array> =
call_malloc_with_cast(ctx, str_size as _);
let guest_canonname_writer = guest_canonname
.deref(ctx.memory(0), 0, str_size as _)
.unwrap();
for (i, b) in canonname_bytes.into_iter().enumerate() {
guest_canonname_writer[i].set(*b as i8)
}
guest_canonname
} else {
WasmPtr::new(0)
}
};
dbg!("canonname allocated");
let mut current_guest_node = current_guest_node_ptr
.deref_mut(ctx.memory(0))
.unwrap()
.get_mut();
// TODO order these
current_guest_node.ai_flags = (*current_host_node).ai_flags;
current_guest_node.ai_family = (*current_host_node).ai_family;
current_guest_node.ai_socktype = (*current_host_node).ai_socktype;
current_guest_node.ai_protocol = (*current_host_node).ai_protocol;
current_guest_node.ai_addrlen = host_addrlen;
current_guest_node.ai_addr = guest_sockaddr_ptr;
current_guest_node.ai_canonname = guest_canonname_ptr;
current_guest_node.ai_next = WasmPtr::new(0);
dbg!("Guest node updated");
previous_guest_node = Some(current_guest_node_ptr);
current_host_node = (*current_host_node).ai_next;
dbg!("End of loop bookkeeping finished");
}
dbg!("freeing memory");
// this frees all connected nodes on the linked list
freeaddrinfo(out_ptr);
head_of_list.unwrap_or(WasmPtr::new(0))
};
res_val_ptr
.deref(ctx.memory(0))
.unwrap()
.set(dbg!(head_of_list));
0
}
pub fn call_malloc(ctx: &mut Ctx, size: u32) -> u32 {
get_emscripten_data(ctx).malloc.call(size).unwrap()
}
@ -362,3 +156,37 @@ pub fn _fpathconf(_ctx: &mut Ctx, _fildes: c_int, name: c_int) -> c_int {
}
}
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct EmAddrInfo {
// int
pub ai_flags: i32,
// int
pub ai_family: i32,
// int
pub ai_socktype: i32,
// int
pub ai_protocol: i32,
// socklen_t
pub ai_addrlen: u32,
// struct sockaddr*
pub ai_addr: WasmPtr<EmSockAddr>,
// char*
pub ai_canonname: WasmPtr<c_char, Array>,
// struct addrinfo*
pub ai_next: WasmPtr<EmAddrInfo>,
}
unsafe impl ValueType for EmAddrInfo {}
// NOTE: from looking at emscripten JS, this should be a union
// TODO: review this, highly likely to have bugs
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct EmSockAddr {
pub sa_family: i16,
pub sa_data: [c_char; 14],
}
unsafe impl ValueType for EmSockAddr {}

@ -3,13 +3,17 @@ use libc::{
c_int, getenv, getgrnam as libc_getgrnam, getpwnam as libc_getpwnam, putenv, setenv, sysconf,
unsetenv,
};
use std::cell::Cell;
use std::ffi::CStr;
use std::mem;
use std::os::raw::c_char;
use crate::env::call_malloc;
use crate::env::{call_malloc, call_malloc_with_cast, EmAddrInfo, EmSockAddr};
use crate::utils::{copy_cstr_into_wasm, copy_terminated_array_of_cstrs};
use wasmer_runtime_core::vm::Ctx;
use wasmer_runtime_core::{
memory::ptr::{Array, WasmPtr},
vm::Ctx,
};
// #[no_mangle]
/// emscripten: _getenv // (name: *const char) -> *const c_char;
@ -140,3 +144,194 @@ pub fn _sysconf(_ctx: &mut Ctx, name: c_int) -> i32 {
// TODO: Implement like emscripten expects regarding memory/page size
unsafe { sysconf(name) as i32 } // TODO review i64
}
// this may be a memory leak, probably not though because emscripten does the same thing
pub fn _gai_strerror(ctx: &mut Ctx, ecode: i32) -> i32 {
debug!("emscripten::_gai_strerror({})", ecode);
let cstr = unsafe { std::ffi::CStr::from_ptr(libc::gai_strerror(ecode)) };
let bytes = cstr.to_bytes_with_nul();
let string_on_guest: WasmPtr<c_char, Array> = call_malloc_with_cast(ctx, bytes.len() as _);
let writer = unsafe {
string_on_guest
.deref_mut(ctx.memory(0), 0, bytes.len() as _)
.unwrap()
};
for (i, byte) in bytes.iter().enumerate() {
writer[i].set(*byte as i8);
}
string_on_guest.offset() as _
}
pub fn _getaddrinfo(
ctx: &mut Ctx,
node_ptr: WasmPtr<c_char>,
service_str_ptr: WasmPtr<c_char>,
hints_ptr: WasmPtr<EmAddrInfo>,
res_val_ptr: WasmPtr<WasmPtr<EmAddrInfo>>,
) -> i32 {
use libc::{addrinfo, freeaddrinfo};
debug!("emscripten::_getaddrinfo");
let memory = ctx.memory(0);
debug!(" => node = {}", unsafe {
node_ptr
.deref(memory)
.map(|np| {
std::ffi::CStr::from_ptr(np as *const Cell<c_char> as *const c_char)
.to_string_lossy()
})
.unwrap_or(std::borrow::Cow::Borrowed("null"))
});
debug!(" => server_str = {}", unsafe {
service_str_ptr
.deref(memory)
.map(|np| {
std::ffi::CStr::from_ptr(np as *const Cell<c_char> as *const c_char)
.to_string_lossy()
})
.unwrap_or(std::borrow::Cow::Borrowed("null"))
});
let hints = hints_ptr.deref(memory).map(|hints_memory| {
let hints_guest = dbg!(hints_memory.get());
unsafe {
let mut hints_native: addrinfo = std::mem::uninitialized();
hints_native.ai_flags = hints_guest.ai_flags;
hints_native.ai_family = hints_guest.ai_family;
hints_native.ai_socktype = hints_guest.ai_socktype;
hints_native.ai_protocol = hints_guest.ai_protocol;
hints_native.ai_addrlen = 0;
hints_native.ai_addr = std::ptr::null_mut();
hints_native.ai_canonname = std::ptr::null_mut();
hints_native.ai_next = std::ptr::null_mut();
hints_native
}
});
let mut out_ptr: *mut addrinfo = std::ptr::null_mut();
// allocate equivalent memory for res_val_ptr
let result = unsafe {
libc::getaddrinfo(
(node_ptr
.deref(memory)
.map(|m| m as *const Cell<c_char> as *const c_char))
.unwrap_or(std::ptr::null()),
(service_str_ptr
.deref(memory)
.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)
.unwrap_or(std::ptr::null()),
&mut out_ptr as *mut *mut addrinfo,
)
};
if dbg!(result) != 0 {
return result;
}
// walk linked list and copy over, freeing them from the kernel
let head_of_list = unsafe {
let mut current_host_node = out_ptr;
let mut head_of_list = None;
let mut previous_guest_node: Option<WasmPtr<EmAddrInfo>> = None;
while !current_host_node.is_null() {
let current_guest_node_ptr: WasmPtr<EmAddrInfo> =
call_malloc_with_cast(ctx, std::mem::size_of::<EmAddrInfo>() as _);
if head_of_list.is_none() {
dbg!("Setting head of list");
head_of_list = Some(current_guest_node_ptr);
}
// connect list
if let Some(prev_guest) = previous_guest_node {
let mut pg = prev_guest.deref_mut(ctx.memory(0)).unwrap().get_mut();
pg.ai_next = current_guest_node_ptr;
dbg!("list connected");
}
// update values
let host_addrlen = (*current_host_node).ai_addrlen;
// allocate addr and copy data
let guest_sockaddr_ptr = {
let host_sockaddr_ptr = (*current_host_node).ai_addr;
let guest_sockaddr_ptr: WasmPtr<EmSockAddr> =
call_malloc_with_cast(ctx, host_addrlen as _);
let guest_sockaddr = guest_sockaddr_ptr
.deref_mut(ctx.memory(0))
.unwrap()
.get_mut();
guest_sockaddr.sa_family = (*host_sockaddr_ptr).sa_family as i16;
guest_sockaddr.sa_data = (*host_sockaddr_ptr).sa_data.clone();
guest_sockaddr_ptr
};
dbg!("Socketaddr allocated");
// allocate canon name on guest and copy data over
let guest_canonname_ptr = {
let str_ptr = (*current_host_node).ai_canonname;
if !str_ptr.is_null() {
let canonname_cstr = dbg!(std::ffi::CStr::from_ptr(str_ptr));
let canonname_bytes = canonname_cstr.to_bytes_with_nul();
let str_size = dbg!(canonname_bytes.len());
let guest_canonname: WasmPtr<c_char, Array> =
call_malloc_with_cast(ctx, str_size as _);
let guest_canonname_writer = guest_canonname
.deref(ctx.memory(0), 0, str_size as _)
.unwrap();
for (i, b) in canonname_bytes.into_iter().enumerate() {
guest_canonname_writer[i].set(*b as i8)
}
guest_canonname
} else {
WasmPtr::new(0)
}
};
dbg!("canonname allocated");
let mut current_guest_node = current_guest_node_ptr
.deref_mut(ctx.memory(0))
.unwrap()
.get_mut();
// TODO order these
current_guest_node.ai_flags = (*current_host_node).ai_flags;
current_guest_node.ai_family = (*current_host_node).ai_family;
current_guest_node.ai_socktype = (*current_host_node).ai_socktype;
current_guest_node.ai_protocol = (*current_host_node).ai_protocol;
current_guest_node.ai_addrlen = host_addrlen;
current_guest_node.ai_addr = guest_sockaddr_ptr;
current_guest_node.ai_canonname = guest_canonname_ptr;
current_guest_node.ai_next = WasmPtr::new(0);
dbg!("Guest node updated");
previous_guest_node = Some(current_guest_node_ptr);
current_host_node = (*current_host_node).ai_next;
dbg!("End of loop bookkeeping finished");
}
dbg!("freeing memory");
// this frees all connected nodes on the linked list
freeaddrinfo(out_ptr);
head_of_list.unwrap_or(WasmPtr::new(0))
};
res_val_ptr
.deref(ctx.memory(0))
.unwrap()
.set(dbg!(head_of_list));
0
}

@ -5,9 +5,9 @@ use std::ffi::CString;
use std::mem;
use std::os::raw::c_char;
use crate::env::call_malloc;
use crate::env::{call_malloc, EmAddrInfo};
use crate::utils::{copy_cstr_into_wasm, read_string_from_wasm};
use wasmer_runtime_core::vm::Ctx;
use wasmer_runtime_core::{memory::ptr::WasmPtr, vm::Ctx};
extern "C" {
#[link_name = "_putenv"]
@ -131,3 +131,19 @@ pub fn _sysconf(_ctx: &mut Ctx, name: c_int) -> c_long {
// stub because sysconf is not valid on windows
0
}
pub fn _gai_strerror(_ctx: &mut Ctx, _ecode: i32) -> i32 {
debug!("emscripten::_gai_strerror({}) - stub", _ecode);
-1
}
pub fn _getaddrinfo(
ctx: &mut Ctx,
node_ptr: WasmPtr<c_char>,
service_str_ptr: WasmPtr<c_char>,
hints_ptr: WasmPtr<EmAddrInfo>,
res_val_ptr: WasmPtr<WasmPtr<EmAddrInfo>>,
) -> i32 {
debug!("emscripten::_getaddrinfo -- stub");
-1
}

@ -887,7 +887,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
"_pthread_setspecific" => func!(crate::emscripten_target::_pthread_setspecific),
"_pthread_sigmask" => func!(crate::emscripten_target::_pthread_sigmask),
"___gxx_personality_v0" => func!(crate::emscripten_target::___gxx_personality_v0),
"_gai_strerror" => func!(crate::emscripten_target::_gai_strerror),
"_gai_strerror" => func!(crate::env::_gai_strerror),
"_getdtablesize" => func!(crate::emscripten_target::_getdtablesize),
"_gethostbyaddr" => func!(crate::emscripten_target::_gethostbyaddr),
"_gethostbyname" => func!(crate::emscripten_target::_gethostbyname),