Merge branch 'master' into command/dash

This commit is contained in:
Jesús Leganés-Combarro 'piranna 2019-07-08 19:16:33 +02:00
commit 9b501e4c3f
14 changed files with 438 additions and 238 deletions

View File

@ -105,8 +105,8 @@ lint:
precommit: lint test
build:
cargo build --release --features debug
debug:
cargo build --release --features backend:singlepass,debug,trace
install:
cargo install --path .
@ -118,7 +118,7 @@ release:
release-fast:
# If you are in OS-X, you will need mingw-w64 for cross compiling to windows
# brew install mingw-w64
cargo build --release
cargo build --release --features backend:singlepass
bench:
cargo bench --all

View File

@ -68,159 +68,6 @@ pub fn _dladdr(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
debug!("emscripten::_dladdr");
0
}
pub fn _pthread_attr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_attr_destroy");
0
}
pub fn _pthread_attr_getstack(
_ctx: &mut Ctx,
_stackaddr: i32,
_stacksize: i32,
_other: i32,
) -> i32 {
debug!(
"emscripten::_pthread_attr_getstack({}, {}, {})",
_stackaddr, _stacksize, _other
);
// TODO: Translate from Emscripten
// HEAP32[stackaddr >> 2] = STACK_BASE;
// HEAP32[stacksize >> 2] = TOTAL_STACK;
0
}
pub fn _pthread_attr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_attr_init({})", _a);
0
}
pub fn _pthread_attr_setstacksize(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_attr_setstacksize");
0
}
pub fn _pthread_cleanup_pop(_ctx: &mut Ctx, _a: i32) -> () {
trace!("emscripten::_pthread_cleanup_pop");
}
pub fn _pthread_cleanup_push(_ctx: &mut Ctx, _a: i32, _b: i32) -> () {
trace!("emscripten::_pthread_cleanup_push");
}
pub fn _pthread_cond_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_cond_destroy");
0
}
pub fn _pthread_cond_init(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_cond_init");
0
}
pub fn _pthread_cond_signal(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_cond_signal");
0
}
pub fn _pthread_cond_timedwait(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32) -> i32 {
trace!("emscripten::_pthread_cond_timedwait");
0
}
pub fn _pthread_cond_wait(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_cond_wait");
0
}
pub fn _pthread_condattr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_condattr_destroy");
0
}
pub fn _pthread_condattr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_condattr_init");
0
}
pub fn _pthread_condattr_setclock(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_condattr_setclock");
0
}
pub fn _pthread_create(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32, _d: i32) -> i32 {
trace!("emscripten::_pthread_create");
// 11 seems to mean "no"
11
}
pub fn _pthread_detach(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_detach");
0
}
pub fn _pthread_equal(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_equal");
0
}
pub fn _pthread_exit(_ctx: &mut Ctx, _a: i32) -> () {
trace!("emscripten::_pthread_exit");
}
pub fn _pthread_getattr_np(_ctx: &mut Ctx, _thread: i32, _attr: i32) -> i32 {
trace!("emscripten::_pthread_getattr_np({}, {})", _thread, _attr);
0
}
pub fn _pthread_getspecific(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_getspecific");
0
}
pub fn _pthread_join(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_join");
0
}
pub fn _pthread_key_create(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_key_create");
0
}
pub fn _pthread_mutex_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_mutex_destroy");
0
}
pub fn _pthread_mutex_init(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_mutex_init");
0
}
pub fn _pthread_mutexattr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_mutexattr_destroy");
0
}
pub fn _pthread_mutexattr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_mutexattr_init");
0
}
pub fn _pthread_mutexattr_settype(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_mutexattr_settype");
0
}
pub fn _pthread_once(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_once");
0
}
pub fn _pthread_rwlock_destroy(_ctx: &mut Ctx, _rwlock: i32) -> i32 {
trace!("emscripten::_pthread_rwlock_destroy({})", _rwlock);
0
}
pub fn _pthread_rwlock_init(_ctx: &mut Ctx, _rwlock: i32, _attr: i32) -> i32 {
trace!("emscripten::_pthread_rwlock_init({}, {})", _rwlock, _attr);
0
}
pub fn _pthread_rwlock_rdlock(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_rwlock_rdlock");
0
}
pub fn _pthread_rwlock_unlock(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_rwlock_unlock");
0
}
pub fn _pthread_rwlock_wrlock(_ctx: &mut Ctx, _rwlock: i32) -> i32 {
trace!("emscripten::_pthread_rwlock_wrlock({})", _rwlock);
0
}
pub fn _pthread_setcancelstate(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_setcancelstate");
0
}
pub fn _pthread_setspecific(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_setspecific");
0
}
pub fn _pthread_sigmask(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32) -> i32 {
trace!("emscripten::_pthread_sigmask");
0
}
pub fn ___gxx_personality_v0(
_ctx: &mut Ctx,
_a: i32,

View File

@ -22,11 +22,16 @@ use wasmer_runtime_core::{
};
pub fn call_malloc(ctx: &mut Ctx, size: u32) -> u32 {
get_emscripten_data(ctx).malloc.call(size).unwrap()
get_emscripten_data(ctx)
.malloc
.as_ref()
.unwrap()
.call(size)
.unwrap()
}
pub fn call_malloc_with_cast<T: Copy, Ty>(ctx: &mut Ctx, size: u32) -> WasmPtr<T, Ty> {
WasmPtr::new(get_emscripten_data(ctx).malloc.call(size).unwrap())
WasmPtr::new(call_malloc(ctx, size))
}
pub fn call_memalign(ctx: &mut Ctx, alignment: u32, size: u32) -> u32 {
@ -40,6 +45,8 @@ pub fn call_memalign(ctx: &mut Ctx, alignment: u32, size: u32) -> u32 {
pub fn call_memset(ctx: &mut Ctx, pointer: u32, value: u32, size: u32) -> u32 {
get_emscripten_data(ctx)
.memset
.as_ref()
.unwrap()
.call(pointer, value, size)
.unwrap()
}

View File

@ -51,6 +51,7 @@ mod lock;
mod math;
mod memory;
mod process;
mod pthread;
mod signal;
mod storage;
mod syscalls;
@ -84,11 +85,13 @@ const GLOBAL_BASE: u32 = 1024;
const STATIC_BASE: u32 = GLOBAL_BASE;
pub struct EmscriptenData<'a> {
pub malloc: Func<'a, u32, u32>,
pub free: Func<'a, u32>,
pub globals: &'a EmscriptenGlobalsData,
pub malloc: Option<Func<'a, u32, u32>>,
pub free: Option<Func<'a, u32>>,
pub memalign: Option<Func<'a, (u32, u32), u32>>,
pub memset: Func<'a, (u32, u32, u32), u32>,
pub stack_alloc: Func<'a, u32, u32>,
pub memset: Option<Func<'a, (u32, u32, u32), u32>>,
pub stack_alloc: Option<Func<'a, u32, u32>>,
pub jumps: Vec<UnsafeCell<[u32; 27]>>,
pub opened_dirs: HashMap<i32, Box<*mut libcDIR>>,
@ -162,13 +165,17 @@ pub struct EmscriptenData<'a> {
impl<'a> EmscriptenData<'a> {
pub fn new(
instance: &'a mut Instance,
globals: &'a EmscriptenGlobalsData,
mapped_dirs: HashMap<String, PathBuf>,
) -> EmscriptenData<'a> {
let malloc = instance.func("_malloc").unwrap();
let free = instance.func("_free").unwrap();
let memalign = instance.func("_memalign").ok();
let memset = instance.func("_memset").unwrap();
let stack_alloc = instance.func("stackAlloc").unwrap();
let malloc = instance.func("_malloc").or(instance.func("malloc")).ok();
let free = instance.func("_free").or(instance.func("free")).ok();
let memalign = instance
.func("_memalign")
.or(instance.func("memalign"))
.ok();
let memset = instance.func("_memset").or(instance.func("memset")).ok();
let stack_alloc = instance.func("stackAlloc").ok();
let dyn_call_i = instance.func("dynCall_i").ok();
let dyn_call_ii = instance.func("dynCall_ii").ok();
@ -227,9 +234,14 @@ impl<'a> EmscriptenData<'a> {
let stack_save = instance.func("stackSave").ok();
let stack_restore = instance.func("stackRestore").ok();
let set_threw = instance.func("_setThrew").ok();
let set_threw = instance
.func("_setThrew")
.or(instance.func("setThrew"))
.ok();
EmscriptenData {
globals,
malloc,
free,
memalign,
@ -305,12 +317,13 @@ impl<'a> EmscriptenData<'a> {
pub fn run_emscripten_instance(
_module: &Module,
instance: &mut Instance,
globals: &mut EmscriptenGlobals,
path: &str,
args: Vec<&str>,
entrypoint: Option<String>,
mapped_dirs: Vec<(String, PathBuf)>,
) -> CallResult<()> {
let mut data = EmscriptenData::new(instance, mapped_dirs.into_iter().collect());
let mut data = EmscriptenData::new(instance, &globals.data, mapped_dirs.into_iter().collect());
let data_ptr = &mut data as *mut _ as *mut c_void;
instance.context_mut().data = data_ptr;
@ -332,17 +345,26 @@ pub fn run_emscripten_instance(
//let (argc, argv) = store_module_arguments(instance.context_mut(), args);
instance.call(&ep, &[Value::I32(arg as i32)])?;
} else {
let main_func = instance.dyn_func("_main")?;
let (func_name, main_func) = match instance.dyn_func("_main") {
Ok(func) => Ok(("_main", func)),
Err(_e) => match instance.dyn_func("main") {
Ok(func) => Ok(("main", func)),
Err(e) => Err(e),
},
}?;
let num_params = main_func.signature().params().len();
let _result = match num_params {
2 => {
let mut new_args = vec![path];
new_args.extend(args);
let (argc, argv) = store_module_arguments(instance.context_mut(), new_args);
instance.call("_main", &[Value::I32(argc as i32), Value::I32(argv as i32)])?;
instance.call(
func_name,
&[Value::I32(argc as i32), Value::I32(argv as i32)],
)?;
}
0 => {
instance.call("_main", &[])?;
instance.call(func_name, &[])?;
}
_ => panic!(
"The emscripten main function has received an incorrect number of params {}",
@ -430,13 +452,13 @@ impl EmscriptenGlobals {
}
let (table_min, table_max) = get_emscripten_table_size(&module);
let (memory_min, memory_max) = get_emscripten_memory_size(&module);
let (memory_min, memory_max, shared) = get_emscripten_memory_size(&module);
// Memory initialization
let memory_type = MemoryDescriptor {
minimum: memory_min,
maximum: memory_max,
shared: false,
shared: shared,
};
let memory = Memory::new(memory_type).unwrap();
@ -750,6 +772,7 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
"alignfault" => func!(crate::memory::alignfault),
"ftfault" => func!(crate::memory::ftfault),
"getTotalMemory" => func!(crate::memory::get_total_memory),
"_sbrk" => func!(crate::memory::sbrk),
"___map_file" => func!(crate::memory::___map_file),
// Exception
@ -781,6 +804,8 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
"_strftime_l" => func!(crate::time::_strftime_l),
"_localtime_r" => func!(crate::time::_localtime_r),
"_gmtime_r" => func!(crate::time::_gmtime_r),
"_ctime" => func!(crate::time::_ctime),
"_ctime_r" => func!(crate::time::_ctime_r),
"_mktime" => func!(crate::time::_mktime),
"_gmtime" => func!(crate::time::_gmtime),
@ -856,42 +881,43 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
"___cxa_free_exception" => func!(crate::emscripten_target::___cxa_free_exception),
"___resumeException" => func!(crate::emscripten_target::___resumeException),
"_dladdr" => func!(crate::emscripten_target::_dladdr),
"_pthread_attr_destroy" => func!(crate::emscripten_target::_pthread_attr_destroy),
"_pthread_attr_getstack" => func!(crate::emscripten_target::_pthread_attr_getstack),
"_pthread_attr_init" => func!(crate::emscripten_target::_pthread_attr_init),
"_pthread_attr_setstacksize" => func!(crate::emscripten_target::_pthread_attr_setstacksize),
"_pthread_cleanup_pop" => func!(crate::emscripten_target::_pthread_cleanup_pop),
"_pthread_cleanup_push" => func!(crate::emscripten_target::_pthread_cleanup_push),
"_pthread_cond_destroy" => func!(crate::emscripten_target::_pthread_cond_destroy),
"_pthread_cond_init" => func!(crate::emscripten_target::_pthread_cond_init),
"_pthread_cond_signal" => func!(crate::emscripten_target::_pthread_cond_signal),
"_pthread_cond_timedwait" => func!(crate::emscripten_target::_pthread_cond_timedwait),
"_pthread_cond_wait" => func!(crate::emscripten_target::_pthread_cond_wait),
"_pthread_condattr_destroy" => func!(crate::emscripten_target::_pthread_condattr_destroy),
"_pthread_condattr_init" => func!(crate::emscripten_target::_pthread_condattr_init),
"_pthread_condattr_setclock" => func!(crate::emscripten_target::_pthread_condattr_setclock),
"_pthread_create" => func!(crate::emscripten_target::_pthread_create),
"_pthread_detach" => func!(crate::emscripten_target::_pthread_detach),
"_pthread_equal" => func!(crate::emscripten_target::_pthread_equal),
"_pthread_exit" => func!(crate::emscripten_target::_pthread_exit),
"_pthread_getattr_np" => func!(crate::emscripten_target::_pthread_getattr_np),
"_pthread_getspecific" => func!(crate::emscripten_target::_pthread_getspecific),
"_pthread_join" => func!(crate::emscripten_target::_pthread_join),
"_pthread_key_create" => func!(crate::emscripten_target::_pthread_key_create),
"_pthread_mutex_destroy" => func!(crate::emscripten_target::_pthread_mutex_destroy),
"_pthread_mutex_init" => func!(crate::emscripten_target::_pthread_mutex_init),
"_pthread_mutexattr_destroy" => func!(crate::emscripten_target::_pthread_mutexattr_destroy),
"_pthread_mutexattr_init" => func!(crate::emscripten_target::_pthread_mutexattr_init),
"_pthread_mutexattr_settype" => func!(crate::emscripten_target::_pthread_mutexattr_settype),
"_pthread_once" => func!(crate::emscripten_target::_pthread_once),
"_pthread_rwlock_destroy" => func!(crate::emscripten_target::_pthread_rwlock_destroy),
"_pthread_rwlock_init" => func!(crate::emscripten_target::_pthread_rwlock_init),
"_pthread_rwlock_rdlock" => func!(crate::emscripten_target::_pthread_rwlock_rdlock),
"_pthread_rwlock_unlock" => func!(crate::emscripten_target::_pthread_rwlock_unlock),
"_pthread_rwlock_wrlock" => func!(crate::emscripten_target::_pthread_rwlock_wrlock),
"_pthread_setcancelstate" => func!(crate::emscripten_target::_pthread_setcancelstate),
"_pthread_setspecific" => func!(crate::emscripten_target::_pthread_setspecific),
"_pthread_sigmask" => func!(crate::emscripten_target::_pthread_sigmask),
"_pthread_attr_destroy" => func!(crate::pthread::_pthread_attr_destroy),
"_pthread_attr_getstack" => func!(crate::pthread::_pthread_attr_getstack),
"_pthread_attr_init" => func!(crate::pthread::_pthread_attr_init),
"_pthread_attr_setstacksize" => func!(crate::pthread::_pthread_attr_setstacksize),
"_pthread_cleanup_pop" => func!(crate::pthread::_pthread_cleanup_pop),
"_pthread_cleanup_push" => func!(crate::pthread::_pthread_cleanup_push),
"_pthread_cond_destroy" => func!(crate::pthread::_pthread_cond_destroy),
"_pthread_cond_init" => func!(crate::pthread::_pthread_cond_init),
"_pthread_cond_signal" => func!(crate::pthread::_pthread_cond_signal),
"_pthread_cond_timedwait" => func!(crate::pthread::_pthread_cond_timedwait),
"_pthread_cond_wait" => func!(crate::pthread::_pthread_cond_wait),
"_pthread_condattr_destroy" => func!(crate::pthread::_pthread_condattr_destroy),
"_pthread_condattr_init" => func!(crate::pthread::_pthread_condattr_init),
"_pthread_condattr_setclock" => func!(crate::pthread::_pthread_condattr_setclock),
"_pthread_create" => func!(crate::pthread::_pthread_create),
"_pthread_detach" => func!(crate::pthread::_pthread_detach),
"_pthread_equal" => func!(crate::pthread::_pthread_equal),
"_pthread_exit" => func!(crate::pthread::_pthread_exit),
"_pthread_self" => func!(crate::pthread::_pthread_self),
"_pthread_getattr_np" => func!(crate::pthread::_pthread_getattr_np),
"_pthread_getspecific" => func!(crate::pthread::_pthread_getspecific),
"_pthread_join" => func!(crate::pthread::_pthread_join),
"_pthread_key_create" => func!(crate::pthread::_pthread_key_create),
"_pthread_mutex_destroy" => func!(crate::pthread::_pthread_mutex_destroy),
"_pthread_mutex_init" => func!(crate::pthread::_pthread_mutex_init),
"_pthread_mutexattr_destroy" => func!(crate::pthread::_pthread_mutexattr_destroy),
"_pthread_mutexattr_init" => func!(crate::pthread::_pthread_mutexattr_init),
"_pthread_mutexattr_settype" => func!(crate::pthread::_pthread_mutexattr_settype),
"_pthread_once" => func!(crate::pthread::_pthread_once),
"_pthread_rwlock_destroy" => func!(crate::pthread::_pthread_rwlock_destroy),
"_pthread_rwlock_init" => func!(crate::pthread::_pthread_rwlock_init),
"_pthread_rwlock_rdlock" => func!(crate::pthread::_pthread_rwlock_rdlock),
"_pthread_rwlock_unlock" => func!(crate::pthread::_pthread_rwlock_unlock),
"_pthread_rwlock_wrlock" => func!(crate::pthread::_pthread_rwlock_wrlock),
"_pthread_setcancelstate" => func!(crate::pthread::_pthread_setcancelstate),
"_pthread_setspecific" => func!(crate::pthread::_pthread_setspecific),
"_pthread_sigmask" => func!(crate::pthread::_pthread_sigmask),
"___gxx_personality_v0" => func!(crate::emscripten_target::___gxx_personality_v0),
"_gai_strerror" => func!(crate::env::_gai_strerror),
"_getdtablesize" => func!(crate::emscripten_target::_getdtablesize),
@ -952,6 +978,17 @@ pub fn generate_emscripten_env(globals: &mut EmscriptenGlobals) -> ImportObject
"_confstr" => func!(crate::unistd::confstr),
};
// Compatibility with newer versions of Emscripten
use crate::wasmer_runtime_core::import::LikeNamespace;
for (k, v) in env_ns.get_exports() {
if k.starts_with("_") {
let k = &k[1..];
if !env_ns.contains_key(k) {
env_ns.insert(k, v.to_export());
}
}
}
for null_func_name in globals.null_func_names.iter() {
env_ns.insert(null_func_name.as_str(), Func::new(nullfunc).to_export());
}

View File

@ -1,3 +1,4 @@
use super::env::get_emscripten_data;
use super::process::abort_with_message;
use libc::{c_int, c_void, memcpy, size_t};
use wasmer_runtime_core::{
@ -65,6 +66,34 @@ pub fn _emscripten_resize_heap(ctx: &mut Ctx, requested_size: u32) -> u32 {
}
}
/// emscripten: sbrk
pub fn sbrk(ctx: &mut Ctx, increment: i32) -> i32 {
debug!("emscripten::sbrk");
// let old_dynamic_top = 0;
// let new_dynamic_top = 0;
let mut globals = get_emscripten_data(ctx).globals;
let dynamictop_ptr = (globals.dynamictop_ptr) as usize;
let old_dynamic_top = ctx.memory(0).view::<u32>()[dynamictop_ptr].get() as i32;
let new_dynamic_top: i32 = old_dynamic_top + increment;
let total_memory = _emscripten_get_heap_size(ctx) as i32;
debug!(
" => PTR {}, old: {}, new: {}, increment: {}, total: {}",
dynamictop_ptr, old_dynamic_top, new_dynamic_top, increment, total_memory
);
if increment > 0 && new_dynamic_top < old_dynamic_top || new_dynamic_top < 0 {
abort_on_cannot_grow_memory_old(ctx);
return -1;
}
if new_dynamic_top > total_memory {
let resized = _emscripten_resize_heap(ctx, new_dynamic_top as u32);
if resized == 0 {
return -1;
}
}
ctx.memory(0).view::<u32>()[dynamictop_ptr].set(new_dynamic_top as u32);
return old_dynamic_top as _;
}
/// emscripten: getTotalMemory
pub fn get_total_memory(_ctx: &mut Ctx) -> u32 {
debug!("emscripten::get_total_memory");

View File

@ -0,0 +1,197 @@
use wasmer_runtime_core::vm::Ctx;
pub fn _pthread_attr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_attr_destroy");
0
}
pub fn _pthread_attr_getstack(
_ctx: &mut Ctx,
_stackaddr: i32,
_stacksize: i32,
_other: i32,
) -> i32 {
trace!(
"emscripten::_pthread_attr_getstack({}, {}, {})",
_stackaddr,
_stacksize,
_other
);
// TODO: Translate from Emscripten
// HEAP32[stackaddr >> 2] = STACK_BASE;
// HEAP32[stacksize >> 2] = TOTAL_STACK;
0
}
pub fn _pthread_attr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_attr_init({})", _a);
0
}
pub fn _pthread_attr_setstacksize(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_attr_setstacksize");
0
}
pub fn _pthread_cleanup_pop(_ctx: &mut Ctx, _a: i32) -> () {
trace!("emscripten::_pthread_cleanup_pop");
}
pub fn _pthread_cleanup_push(_ctx: &mut Ctx, _a: i32, _b: i32) -> () {
trace!("emscripten::_pthread_cleanup_push");
}
pub fn _pthread_cond_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_cond_destroy");
0
}
pub fn _pthread_cond_init(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_cond_init");
0
}
pub fn _pthread_cond_signal(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_cond_signal");
0
}
pub fn _pthread_cond_timedwait(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32) -> i32 {
trace!("emscripten::_pthread_cond_timedwait");
0
}
pub fn _pthread_cond_wait(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_cond_wait");
0
}
pub fn _pthread_condattr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_condattr_destroy");
0
}
pub fn _pthread_condattr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_condattr_init");
0
}
pub fn _pthread_condattr_setclock(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_condattr_setclock");
0
}
pub fn _pthread_create(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32, _d: i32) -> i32 {
trace!("emscripten::_pthread_create");
// 11 seems to mean "no"
11
}
pub fn _pthread_detach(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_detach");
0
}
pub fn _pthread_equal(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_equal");
0
}
pub fn _pthread_exit(_ctx: &mut Ctx, _a: i32) -> () {
trace!("emscripten::_pthread_exit");
}
pub fn _pthread_getattr_np(_ctx: &mut Ctx, _thread: i32, _attr: i32) -> i32 {
trace!("emscripten::_pthread_getattr_np({}, {})", _thread, _attr);
0
}
pub fn _pthread_getspecific(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_getspecific");
0
}
pub fn _pthread_join(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_join");
0
}
pub fn _pthread_self(_ctx: &mut Ctx) -> i32 {
trace!("emscripten::_pthread_self");
0
}
pub fn _pthread_key_create(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_key_create");
0
}
pub fn _pthread_mutex_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_mutex_destroy");
0
}
pub fn _pthread_mutex_init(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_mutex_init");
0
}
pub fn _pthread_mutexattr_destroy(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_mutexattr_destroy");
0
}
pub fn _pthread_mutexattr_init(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_mutexattr_init");
0
}
pub fn _pthread_mutexattr_settype(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_mutexattr_settype");
0
}
pub fn _pthread_once(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_once");
0
}
pub fn _pthread_rwlock_destroy(_ctx: &mut Ctx, _rwlock: i32) -> i32 {
trace!("emscripten::_pthread_rwlock_destroy({})", _rwlock);
0
}
pub fn _pthread_rwlock_init(_ctx: &mut Ctx, _rwlock: i32, _attr: i32) -> i32 {
trace!("emscripten::_pthread_rwlock_init({}, {})", _rwlock, _attr);
0
}
pub fn _pthread_rwlock_rdlock(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_rwlock_rdlock");
0
}
pub fn _pthread_rwlock_unlock(_ctx: &mut Ctx, _a: i32) -> i32 {
trace!("emscripten::_pthread_rwlock_unlock");
0
}
pub fn _pthread_rwlock_wrlock(_ctx: &mut Ctx, _rwlock: i32) -> i32 {
trace!("emscripten::_pthread_rwlock_wrlock({})", _rwlock);
0
}
pub fn _pthread_setcancelstate(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_setcancelstate");
0
}
pub fn _pthread_setspecific(_ctx: &mut Ctx, _a: i32, _b: i32) -> i32 {
trace!("emscripten::_pthread_setspecific");
0
}
pub fn _pthread_sigmask(_ctx: &mut Ctx, _a: i32, _b: i32, _c: i32) -> i32 {
trace!("emscripten::_pthread_sigmask");
0
}

View File

@ -32,7 +32,6 @@ use libc::{
// iovec,
loff_t,
lseek,
off_t,
// open,
pid_t,
read,
@ -427,8 +426,8 @@ pub fn ___syscall140(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
let offset_low: u32 = varargs.get(ctx);
let result_ptr_value: WasmPtr<loff_t> = varargs.get(ctx);
let whence: i32 = varargs.get(ctx);
let offset = offset_low as off_t;
let ret = unsafe { lseek(fd, offset, whence) as i64 };
let offset = offset_low;
let ret = unsafe { lseek(fd, offset as _, whence) as i64 };
let result_ptr = result_ptr_value.deref(ctx.memory(0)).unwrap();
result_ptr.set(ret);

View File

@ -25,6 +25,7 @@ use libc::{
getgid,
getgroups,
getpeername,
getpgid,
getrusage,
getsockname,
getsockopt,
@ -76,22 +77,36 @@ use libc::{
SOL_SOCKET,
TIOCGWINSZ,
TIOCSPGRP,
// TCGETS,
// TCSETSW,
};
// They are not exposed in in Rust libc in macOS
const TCGETS: u64 = 0x5401;
const TCSETSW: u64 = 0x5403;
// `libc` constants as provided by `emscripten`. Maybe move to own file?
const WASM_FIONBIO: u32 = 0x5421;
const WASM_FIOCLEX: u32 = 0x5451;
const WASM_TIOCSPGRP: u32 = 0x5410;
const WASM_TIOCGWINSZ: u32 = 0x5413;
const WASM_TCGETS: u32 = 0x5401;
const WASM_TCSETSW: u32 = 0x5403;
// Based on @syrusakbary sugerence at
// https://github.com/wasmerio/wasmer/pull/532#discussion_r300837800
fn translate_ioctl(wasm_ioctl: u32) -> c_ulong {
match wasm_ioctl {
WASM_FIOCLEX => FIOCLEX,
WASM_FIONBIO => FIONBIO,
WASM_TIOCGWINSZ => TIOCGWINSZ,
WASM_TIOCSPGRP => TIOCSPGRP,
WASM_TCGETS => TCGETS,
WASM_TCSETSW => TCSETSW,
otherwise => otherwise as c_ulong,
_otherwise => {
unimplemented!("The ioctl {} is not yet implemented", wasm_ioctl);
}
}
}
@ -444,33 +459,27 @@ pub fn ___syscall54(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int
debug!("=> fd: {}, op: {}", fd, request);
// Got the equivalents here: https://code.woboq.org/linux/linux/include/uapi/asm-generic/ioctls.h.html
let argp: u32 = varargs.get(ctx);
let argp_ptr = emscripten_memory_pointer!(ctx.memory(0), argp) as *mut c_void;
// let ret = unsafe { ioctl(fd, translate_ioctl(request) as _, argp_ptr) };
// debug!("=> {}", ret);
// ret
match request {
WASM_FIOCLEX | WASM_FIONBIO | WASM_TIOCGWINSZ | WASM_TIOCSPGRP | WASM_TCGETS
| WASM_TCSETSW => {
let argp: u32 = varargs.get(ctx);
let argp_ptr = emscripten_memory_pointer!(ctx.memory(0), argp) as *mut c_void;
let translated_request = translate_ioctl(request);
let ret = unsafe { ioctl(fd, translated_request, argp_ptr) };
debug!(
" => request: {}, translated: {}, return: {}",
request, translated_request, ret
);
match request as _ {
TIOCGWINSZ => {
let ret = unsafe { ioctl(fd, translate_ioctl(request) as _, argp_ptr) };
debug!("ret(TIOCGWINSZ): {} (harcoded to 0)", ret);
// ret
// TODO: We hardcode the value to have emscripten tests pass, as for some reason
// when the capturer is active, ioctl returns -1 instead of 0
if ret == -1 {
0
} else {
ret
if request == WASM_TIOCGWINSZ && ret == -1 {
return 0;
}
}
TIOCSPGRP => {
debug!("ret(TIOCSPGRP): (noop)");
0
ret
}
_ => {
let ret = unsafe { ioctl(fd, translate_ioctl(request) as _, argp_ptr) };
debug!("ret({}): {}", request, ret);
ret
unimplemented!("not implemented case {}", request);
}
}
}
@ -794,6 +803,20 @@ fn translate_socket_name_flag(name: i32) -> i32 {
}
}
/// getpgid
pub fn ___syscall132(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall132 (getpgid)");
let pid: pid_t = varargs.get(ctx);
let ret = unsafe { getpgid(pid) };
debug!("=> pid: {} = {}", pid, ret);
if ret == -1 {
debug!("=> last os error: {}", Error::last_os_error(),);
}
ret
}
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct EmPollFd {
@ -1051,6 +1074,24 @@ pub fn ___syscall220(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
pos as i32
}
// fcntl64
pub fn ___syscall221(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall221 (fcntl64) {}", _which);
let fd: i32 = varargs.get(ctx);
let cmd: i32 = varargs.get(ctx);
let arg: i32 = varargs.get(ctx);
// (FAPPEND - 0x08
// |FASYNC - 0x40
// |FFSYNC - 0x80
// |FNONBLOCK - 0x04
let ret = unsafe { fcntl(fd, cmd, arg) };
debug!("=> fd: {}, cmd: {} = {}", fd, cmd, ret);
if ret == -1 {
debug!("=> last os error: {}", Error::last_os_error(),);
}
ret
}
/// fallocate
pub fn ___syscall324(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall324 (fallocate) {}", _which);

View File

@ -134,6 +134,12 @@ pub fn ___syscall85(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
-1
}
/// getpgid
pub fn ___syscall132(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall132 (getpgid)");
-1
}
/// lchown
pub fn ___syscall198(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall198 (lchown) {}", _which);
@ -288,6 +294,12 @@ pub fn ___syscall220(_ctx: &mut Ctx, _one: i32, _two: i32) -> i32 {
-1
}
// fcntl64
pub fn ___syscall221(_ctx: &mut Ctx, _which: c_int, mut _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall221 (fcntl64) {}", _which);
-1
}
/// fchown
pub fn ___syscall207(_ctx: &mut Ctx, _which: c_int, _varargs: VarArgs) -> c_int {
debug!("emscripten::___syscall207 (fchown) {}", _which);

View File

@ -1,4 +1,5 @@
use super::utils::{copy_cstr_into_wasm, write_to_buf};
use crate::allocate_on_stack;
use libc::{c_char, c_int};
// use libc::{c_char, c_int, clock_getres, clock_settime};
use std::mem;
@ -313,6 +314,23 @@ pub fn _time(ctx: &mut Ctx, time_p: u32) -> i32 {
}
}
pub fn _ctime_r(ctx: &mut Ctx, time_p: u32, buf: u32) -> u32 {
debug!("emscripten::_ctime_r {} {}", time_p, buf);
// var stack = stackSave();
let (result_offset, _result_slice): (u32, &mut [u8]) = unsafe { allocate_on_stack(ctx, 44) };
let time = _localtime_r(ctx, time_p, result_offset) as u32;
let rv = _asctime_r(ctx, time, buf);
// stackRestore(stack);
rv
}
pub fn _ctime(ctx: &mut Ctx, time_p: u32) -> u32 {
debug!("emscripten::_ctime {}", time_p);
let tm_current = 2414544;
_ctime_r(ctx, time_p, tm_current)
}
/// emscripten: _timegm
#[cfg(not(target_os = "windows"))]
#[allow(clippy::cast_ptr_alignment)]

View File

@ -24,7 +24,9 @@ pub fn is_emscripten_module(module: &Module) -> bool {
.namespace_table
.get(import_name.namespace_index);
let field = module.info().name_table.get(import_name.name_index);
if field == "_emscripten_memcpy_big" && namespace == "env" {
if (field == "_emscripten_memcpy_big" || field == "emscripten_memcpy_big")
&& namespace == "env"
{
return true;
}
}
@ -36,9 +38,9 @@ pub fn get_emscripten_table_size(module: &Module) -> (u32, Option<u32>) {
(table.minimum, table.maximum)
}
pub fn get_emscripten_memory_size(module: &Module) -> (Pages, Option<Pages>) {
pub fn get_emscripten_memory_size(module: &Module) -> (Pages, Option<Pages>, bool) {
let (_, memory) = &module.info().imported_memories[ImportedMemoryIndex::new(0)];
(memory.minimum, memory.maximum)
(memory.minimum, memory.maximum, memory.shared)
}
/// Reads values written by `-s EMIT_EMSCRIPTEN_METADATA=1`
@ -110,6 +112,8 @@ pub unsafe fn copy_cstr_into_wasm(ctx: &mut Ctx, cstr: *const c_char) -> u32 {
pub unsafe fn allocate_on_stack<'a, T: Copy>(ctx: &'a mut Ctx, count: u32) -> (u32, &'a mut [T]) {
let offset = get_emscripten_data(ctx)
.stack_alloc
.as_ref()
.unwrap()
.call(count * (size_of::<T>() as u32))
.unwrap();
let addr = emscripten_memory_pointer!(ctx.memory(0), offset) as *mut T;

View File

@ -53,6 +53,7 @@ macro_rules! assert_emscripten_output {
wasmer_emscripten::run_emscripten_instance(
&module,
&mut instance,
&mut emscripten_globals,
$name,
$args,
None,

View File

@ -189,6 +189,13 @@ impl Namespace {
{
self.map.insert(name.into(), Box::new(export))
}
pub fn contains_key<S>(&mut self, key: S) -> bool
where
S: Into<String>,
{
self.map.contains_key(&key.into())
}
}
impl LikeNamespace for Namespace {

View File

@ -474,6 +474,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
wasmer_emscripten::run_emscripten_instance(
&module,
&mut instance,
&mut emscripten_globals,
if let Some(cn) = &options.command_name {
cn
} else {