mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 06:15:33 +00:00
Fix localtime implementation
This commit is contained in:
parent
bbb2f080cc
commit
181837d7cc
@ -97,11 +97,6 @@ pub extern "C" fn _getgrnam(name_ptr: c_int, instance: &mut Instance) -> c_int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub extern "C" fn _localtime_r() -> u32 {
|
|
||||||
debug!("emscripten::_localtime_r");
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub extern "C" fn _getpagesize() -> u32 {
|
pub extern "C" fn _getpagesize() -> u32 {
|
||||||
debug!("emscripten::_getpagesize");
|
debug!("emscripten::_getpagesize");
|
||||||
16384
|
16384
|
||||||
|
@ -18,7 +18,7 @@ mod time;
|
|||||||
mod utils;
|
mod utils;
|
||||||
mod varargs;
|
mod varargs;
|
||||||
|
|
||||||
pub use self::storage::{align_memory, static_alloc};
|
pub use self::storage::{align_memory};
|
||||||
pub use self::utils::{is_emscripten_module, allocate_on_stack, allocate_cstr_on_stack};
|
pub use self::utils::{is_emscripten_module, allocate_on_stack, allocate_cstr_on_stack};
|
||||||
|
|
||||||
// TODO: Magic number - how is this calculated?
|
// TODO: Magic number - how is this calculated?
|
||||||
@ -27,6 +27,8 @@ const TOTAL_STACK: u32 = 5242880;
|
|||||||
const DYNAMICTOP_PTR_DIFF: u32 = 1088;
|
const DYNAMICTOP_PTR_DIFF: u32 = 1088;
|
||||||
// TODO: make this variable
|
// TODO: make this variable
|
||||||
const STATIC_BUMP: u32 = 215536;
|
const STATIC_BUMP: u32 = 215536;
|
||||||
|
// TODO: make this variable
|
||||||
|
const GLOBAL_BASE: u32 = 1024;
|
||||||
|
|
||||||
fn stacktop(static_bump: u32) -> u32 {
|
fn stacktop(static_bump: u32) -> u32 {
|
||||||
align_memory(dynamictop_ptr(static_bump) + 4)
|
align_memory(dynamictop_ptr(static_bump) + 4)
|
||||||
@ -44,11 +46,10 @@ fn dynamictop_ptr(static_bump: u32) -> u32 {
|
|||||||
static_bump + DYNAMICTOP_PTR_DIFF
|
static_bump + DYNAMICTOP_PTR_DIFF
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn static_alloc(size: usize, static_top: &mut size) -> usize {
|
|
||||||
// let ret = *static_top;
|
pub fn statictop(static_bump: u32) -> u32 {
|
||||||
// *static_top = (*static_top + size + 15) & (-16 as usize);
|
GLOBAL_BASE + 5520
|
||||||
// ret
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn emscripten_set_up_memory(memory: &mut LinearMemory) {
|
pub fn emscripten_set_up_memory(memory: &mut LinearMemory) {
|
||||||
let dynamictop_ptr = dynamictop_ptr(STATIC_BUMP) as usize;
|
let dynamictop_ptr = dynamictop_ptr(STATIC_BUMP) as usize;
|
||||||
@ -383,6 +384,11 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
|
|||||||
"_clock_gettime",
|
"_clock_gettime",
|
||||||
ImportValue::Func(time::_clock_gettime as _),
|
ImportValue::Func(time::_clock_gettime as _),
|
||||||
);
|
);
|
||||||
|
import_object.set(
|
||||||
|
"env",
|
||||||
|
"_asctime",
|
||||||
|
ImportValue::Func(time::_asctime as _),
|
||||||
|
);
|
||||||
import_object.set(
|
import_object.set(
|
||||||
"env",
|
"env",
|
||||||
"_localtime",
|
"_localtime",
|
||||||
@ -393,7 +399,7 @@ pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> {
|
|||||||
import_object.set(
|
import_object.set(
|
||||||
"env",
|
"env",
|
||||||
"_localtime_r",
|
"_localtime_r",
|
||||||
ImportValue::Func(env::_localtime_r as _),
|
ImportValue::Func(time::_localtime_r as _),
|
||||||
);
|
);
|
||||||
import_object.set(
|
import_object.set(
|
||||||
"env",
|
"env",
|
||||||
|
@ -4,22 +4,15 @@ pub fn align_memory(ptr: u32) -> u32 {
|
|||||||
(ptr + 15) & !15
|
(ptr + 15) & !15
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn static_alloc(size: u32, instance: &mut Instance) -> u32 {
|
|
||||||
// let static_top = instance.emscripten_data.static_top;
|
|
||||||
// let total_memory = instance.memories[0].maximum.unwrap_or(LinearMemory::DEFAULT_HEAP_SIZE as u32);
|
|
||||||
// instance.emscripten_data.static_top = (static_top + size + 15) & 4294967280;
|
|
||||||
// assert!(static_top < total_memory, "not enough memory for static allocation - increase total_memory!");
|
|
||||||
// static_top
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn static_alloc(size: u32, static_top: &mut u32, memory: &LinearMemory) -> u32 {
|
// pub fn static_alloc(size: u32, static_top: &mut u32, memory: &LinearMemory) -> u32 {
|
||||||
let old_static_top = *static_top;
|
// let old_static_top = *static_top;
|
||||||
let total_memory = memory.maximum_size() * LinearMemory::PAGE_SIZE;
|
// let total_memory = memory.maximum_size() * LinearMemory::PAGE_SIZE;
|
||||||
// NOTE: The `4294967280` is a u32 conversion of -16 as gotten from emscripten.
|
// // NOTE: The `4294967280` is a u32 conversion of -16 as gotten from emscripten.
|
||||||
*static_top = (*static_top + size + 15) & 4294967280;
|
// *static_top = (*static_top + size + 15) & 4294967280;
|
||||||
assert!(
|
// assert!(
|
||||||
*static_top < total_memory,
|
// *static_top < total_memory,
|
||||||
"not enough memory for static allocation - increase total_memory!"
|
// "not enough memory for static allocation - increase total_memory!"
|
||||||
);
|
// );
|
||||||
old_static_top
|
// old_static_top
|
||||||
}
|
// }
|
||||||
|
@ -3,11 +3,13 @@ use libc::{
|
|||||||
c_int,
|
c_int,
|
||||||
c_long,
|
c_long,
|
||||||
clock_gettime as libc_clock_gettime,
|
clock_gettime as libc_clock_gettime,
|
||||||
// tm,
|
|
||||||
localtime,
|
localtime,
|
||||||
|
localtime_r,
|
||||||
|
tm,
|
||||||
time,
|
time,
|
||||||
time_t,
|
time_t,
|
||||||
timespec,
|
timespec,
|
||||||
|
c_char,
|
||||||
};
|
};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
@ -64,37 +66,101 @@ pub extern "C" fn _clock_gettime(clk_id: c_int, tp: c_int, instance: &mut Instan
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct guest_tm {
|
||||||
|
pub tm_sec: c_int, // 4 - 0
|
||||||
|
pub tm_min: c_int, // 4 - 4
|
||||||
|
pub tm_hour: c_int, // 4 - 8
|
||||||
|
pub tm_mday: c_int, // 4 - 12
|
||||||
|
pub tm_mon: c_int, // 4 - 16
|
||||||
|
pub tm_year: c_int, // 4 - 20
|
||||||
|
pub tm_wday: c_int, // 4 - 24
|
||||||
|
pub tm_yday: c_int, // 4 - 28
|
||||||
|
pub tm_isdst: c_int, // 4 - 32
|
||||||
|
pub tm_gmtoff: c_int, // 4 - 36
|
||||||
|
pub tm_zone: c_int, // 4 - 40
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[repr(C)]
|
||||||
|
// struct asctime_tm {
|
||||||
|
// pub tm_sec: c_int, // 4 - 0
|
||||||
|
// pub tm_min: c_int, // 4 - 4
|
||||||
|
// pub tm_hour: c_int, // 4 - 8
|
||||||
|
// pub tm_mday: c_int, // 4 - 12
|
||||||
|
// pub tm_mon: c_int, // 4 - 16
|
||||||
|
// pub tm_year: c_int, // 4 - 20
|
||||||
|
// pub tm_wday: c_int, // 4 - 24
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// emscripten: _asctime
|
||||||
|
pub extern "C" fn _asctime(time: u32, instance: &mut Instance) -> u32 {
|
||||||
|
debug!("emscripten::_asctime {}", time);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let date = &*(instance.memory_offset_addr(0, time as _) as *mut guest_tm);
|
||||||
|
|
||||||
|
let days = vec!["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
||||||
|
let months = vec!["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
||||||
|
|
||||||
|
let day = if date.tm_mday < 10 {" "} else {" "};
|
||||||
|
let hour = if date.tm_hour < 10 {" 0"} else {" "};
|
||||||
|
let min = if date.tm_min < 10 {":0"} else {":"};
|
||||||
|
let sec = if date.tm_sec < 10 {":0"} else {":"};
|
||||||
|
let year = 1900 + date.tm_year;
|
||||||
|
|
||||||
|
let mut time_str = format!(
|
||||||
|
// "{} {}{}{}{}{}{}{}{}{} {}\0 \0\0",
|
||||||
|
"{} {}{}{}{}{}{}{}{}{} {}\0",
|
||||||
|
days[date.tm_wday as usize],
|
||||||
|
months[date.tm_mon as usize],
|
||||||
|
day, date.tm_mday,
|
||||||
|
hour, date.tm_hour,
|
||||||
|
min, date.tm_min,
|
||||||
|
sec, date.tm_sec,
|
||||||
|
year
|
||||||
|
);
|
||||||
|
|
||||||
|
let time_str_ptr = time_str.as_ptr() as _;
|
||||||
|
|
||||||
|
// TODO: asctime_r is specced to behave in an undefined manner if the algorithm would attempt
|
||||||
|
// to write out more than 26 bytes (including the null terminator).
|
||||||
|
// See http://pubs.opengroup.org/onlinepubs/9699919799/functions/asctime.html
|
||||||
|
// Our undefined behavior is to truncate the write to at most 26 bytes, including null terminator.
|
||||||
|
let time_str_offset = copy_cstr_into_wasm(instance, time_str_ptr);
|
||||||
|
|
||||||
|
let c_str = instance.memory_offset_addr(0, time_str_offset as _) as *mut i8;
|
||||||
|
use std::ffi::CStr;
|
||||||
|
debug!("########## cstr = {:?}", CStr::from_ptr(c_str));
|
||||||
|
println!("Kaboom!");
|
||||||
|
|
||||||
|
// std::mem::forget(time_str);
|
||||||
|
time_str_offset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// emscripten: _tvset
|
||||||
|
pub extern "C" fn _tvset() {
|
||||||
|
debug!("emscripten::_tvset UNIMPLEMENTED");
|
||||||
|
}
|
||||||
|
|
||||||
/// emscripten: _localtime
|
/// emscripten: _localtime
|
||||||
pub extern "C" fn _localtime(time_p: u32, instance: &mut Instance) -> c_int {
|
pub extern "C" fn _localtime(time_p: u32, instance: &mut Instance) -> c_int {
|
||||||
debug!("emscripten::_localtime {}", time_p);
|
debug!("emscripten::_localtime {}", time_p);
|
||||||
|
// NOTE: emscripten seems to want tzset() called in this function
|
||||||
#[repr(C)]
|
// https://stackoverflow.com/questions/19170721/real-time-awareness-of-timezone-change-in-localtime-vs-localtime-r
|
||||||
struct GuestTm {
|
|
||||||
tm_sec: i32,
|
|
||||||
tm_min: i32,
|
|
||||||
tm_hour: i32,
|
|
||||||
tm_mday: i32,
|
|
||||||
tm_mon: i32,
|
|
||||||
tm_year: i32,
|
|
||||||
tm_wday: i32,
|
|
||||||
tm_yday: i32,
|
|
||||||
tm_isdst: i32,
|
|
||||||
tm_gmtoff: c_long,
|
|
||||||
tm_zone: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let time_p_addr = instance.memory_offset_addr(0, time_p as _) as *mut i64;
|
let time_p_addr = instance.memory_offset_addr(0, time_p as _) as *mut i64;
|
||||||
|
|
||||||
let tm_struct = &*localtime(time_p_addr);
|
let tm_struct = &*localtime(time_p_addr);
|
||||||
|
|
||||||
// Webassembly allocation
|
|
||||||
let tm_struct_offset = (instance.emscripten_data.as_ref().unwrap().malloc)(
|
let tm_struct_offset = (instance.emscripten_data.as_ref().unwrap().malloc)(
|
||||||
mem::size_of::<GuestTm>() as _,
|
mem::size_of::<guest_tm>() as _,
|
||||||
instance,
|
instance,
|
||||||
);
|
);
|
||||||
let tm_struct_ptr = instance.memory_offset_addr(0, tm_struct_offset as _) as *mut GuestTm;
|
|
||||||
|
|
||||||
// Initializing
|
let tm_struct_ptr = instance.memory_offset_addr(0, tm_struct_offset as _) as *mut guest_tm;
|
||||||
|
|
||||||
(*tm_struct_ptr).tm_sec = tm_struct.tm_sec;
|
(*tm_struct_ptr).tm_sec = tm_struct.tm_sec;
|
||||||
(*tm_struct_ptr).tm_min = tm_struct.tm_min;
|
(*tm_struct_ptr).tm_min = tm_struct.tm_min;
|
||||||
(*tm_struct_ptr).tm_hour = tm_struct.tm_hour;
|
(*tm_struct_ptr).tm_hour = tm_struct.tm_hour;
|
||||||
@ -104,8 +170,56 @@ pub extern "C" fn _localtime(time_p: u32, instance: &mut Instance) -> c_int {
|
|||||||
(*tm_struct_ptr).tm_wday = tm_struct.tm_wday;
|
(*tm_struct_ptr).tm_wday = tm_struct.tm_wday;
|
||||||
(*tm_struct_ptr).tm_yday = tm_struct.tm_yday;
|
(*tm_struct_ptr).tm_yday = tm_struct.tm_yday;
|
||||||
(*tm_struct_ptr).tm_isdst = tm_struct.tm_isdst;
|
(*tm_struct_ptr).tm_isdst = tm_struct.tm_isdst;
|
||||||
(*tm_struct_ptr).tm_gmtoff = tm_struct.tm_gmtoff;
|
(*tm_struct_ptr).tm_gmtoff = tm_struct.tm_gmtoff as i32;
|
||||||
(*tm_struct_ptr).tm_zone = copy_cstr_into_wasm(instance, tm_struct.tm_zone);
|
(*tm_struct_ptr).tm_zone = copy_cstr_into_wasm(instance, tm_struct.tm_zone) as i32;
|
||||||
|
|
||||||
|
tm_struct_offset as c_int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// emscripten: _localtime_r
|
||||||
|
pub extern "C" fn _localtime_r(time_p: u32, result: u32, instance: &mut Instance) -> c_int {
|
||||||
|
debug!("emscripten::_localtime_r {}", time_p);
|
||||||
|
|
||||||
|
// NOTE: emscripten seems to want tzset() called in this function
|
||||||
|
// https://stackoverflow.com/questions/19170721/real-time-awareness-of-timezone-change-in-localtime-vs-localtime-r
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let time_p_addr = instance.memory_offset_addr(0, time_p as _) as *mut i64;
|
||||||
|
let result_addr = instance.memory_offset_addr(0, result as _) as *mut guest_tm;
|
||||||
|
let mut result_tm = tm {
|
||||||
|
tm_sec: (*result_addr).tm_sec,
|
||||||
|
tm_min: (*result_addr).tm_min,
|
||||||
|
tm_hour: (*result_addr).tm_hour,
|
||||||
|
tm_mday: (*result_addr).tm_mday,
|
||||||
|
tm_mon: (*result_addr).tm_mon,
|
||||||
|
tm_year: (*result_addr).tm_year,
|
||||||
|
tm_wday: (*result_addr).tm_wday,
|
||||||
|
tm_yday: (*result_addr).tm_yday,
|
||||||
|
tm_isdst: (*result_addr).tm_isdst,
|
||||||
|
tm_gmtoff: (*result_addr).tm_gmtoff as _,
|
||||||
|
tm_zone: instance.memory_offset_addr(0, (*result_addr).tm_zone as _) as _,
|
||||||
|
};
|
||||||
|
|
||||||
|
let tm_struct = &*localtime_r(time_p_addr, &mut result_tm);
|
||||||
|
|
||||||
|
let tm_struct_offset = (instance.emscripten_data.as_ref().unwrap().malloc)(
|
||||||
|
mem::size_of::<guest_tm>() as _,
|
||||||
|
instance,
|
||||||
|
);
|
||||||
|
|
||||||
|
let tm_struct_ptr = instance.memory_offset_addr(0, tm_struct_offset as _) as *mut guest_tm;
|
||||||
|
|
||||||
|
(*tm_struct_ptr).tm_sec = tm_struct.tm_sec;
|
||||||
|
(*tm_struct_ptr).tm_min = tm_struct.tm_min;
|
||||||
|
(*tm_struct_ptr).tm_hour = tm_struct.tm_hour;
|
||||||
|
(*tm_struct_ptr).tm_mday = tm_struct.tm_mday;
|
||||||
|
(*tm_struct_ptr).tm_mon = tm_struct.tm_mon;
|
||||||
|
(*tm_struct_ptr).tm_year = tm_struct.tm_year;
|
||||||
|
(*tm_struct_ptr).tm_wday = tm_struct.tm_wday;
|
||||||
|
(*tm_struct_ptr).tm_yday = tm_struct.tm_yday;
|
||||||
|
(*tm_struct_ptr).tm_isdst = tm_struct.tm_isdst;
|
||||||
|
(*tm_struct_ptr).tm_gmtoff = tm_struct.tm_gmtoff as i32;
|
||||||
|
(*tm_struct_ptr).tm_zone = copy_cstr_into_wasm(instance, tm_struct.tm_zone) as i32;
|
||||||
|
|
||||||
tm_struct_offset as c_int
|
tm_struct_offset as c_int
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,8 @@ pub unsafe fn copy_cstr_into_wasm(instance: &mut Instance, cstr: *const c_char)
|
|||||||
*loc = byte;
|
*loc = byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Appending null byte won't work, because there is CStr::from_ptr(cstr)
|
||||||
|
// at the top that crashes when there is no null byte
|
||||||
*raw_memory.add(cstr_len) = 0;
|
*raw_memory.add(cstr_len) = 0;
|
||||||
|
|
||||||
space_offset
|
space_offset
|
||||||
|
@ -92,7 +92,8 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
|
|||||||
get_instance_function!(instance, func_index);
|
get_instance_function!(instance, func_index);
|
||||||
|
|
||||||
let (argc, argv) = store_module_arguments(options, &mut instance);
|
let (argc, argv) = store_module_arguments(options, &mut instance);
|
||||||
|
|
||||||
|
// TODO: This assumes argc and argv are always passed.
|
||||||
return call_protected!(main(argc, argv, &instance)).map_err(|err| format!("{}", err));
|
return call_protected!(main(argc, argv, &instance)).map_err(|err| format!("{}", err));
|
||||||
// TODO: We should implement emscripten __ATEXIT__
|
// TODO: We should implement emscripten __ATEXIT__
|
||||||
} else {
|
} else {
|
||||||
@ -144,37 +145,3 @@ fn store_module_arguments(options: &Run, instance: &mut webassembly::Instance) -
|
|||||||
|
|
||||||
(argc as u32, argv_offset)
|
(argc as u32, argv_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn get_module_arguments(options: &Run, instance: &mut webassembly::Instance) -> (u32, u32) {
|
|
||||||
// // Application Arguments
|
|
||||||
// let mut arg_values: Vec<String> = Vec::new();
|
|
||||||
// let mut arg_addrs: Vec<*const u8> = Vec::new();
|
|
||||||
// let arg_length = options.args.len() + 1;
|
|
||||||
|
|
||||||
// arg_values.reserve_exact(arg_length);
|
|
||||||
// arg_addrs.reserve_exact(arg_length);
|
|
||||||
|
|
||||||
// // Push name of wasm file
|
|
||||||
// arg_values.push(format!("{}\0", options.path.to_str().unwrap()));
|
|
||||||
// arg_addrs.push(arg_values[0].as_ptr());
|
|
||||||
|
|
||||||
// // Push additional arguments
|
|
||||||
// for (i, arg) in options.args.iter().enumerate() {
|
|
||||||
// arg_values.push(format!("{}\0", arg));
|
|
||||||
// arg_addrs.push(arg_values[i + 1].as_ptr());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Get argument count and pointer to addresses
|
|
||||||
// let argv = arg_addrs.as_ptr() as *mut *mut i8;
|
|
||||||
// let argc = arg_length as u32;
|
|
||||||
|
|
||||||
// // Copy the the arguments into the wasm memory and get offset
|
|
||||||
// let argv_offset = unsafe {
|
|
||||||
// copy_cstr_array_into_wasm(argc, argv, instance)
|
|
||||||
// };
|
|
||||||
|
|
||||||
// debug!("argc = {:?}", argc);
|
|
||||||
// debug!("argv = {:?}", arg_addrs);
|
|
||||||
|
|
||||||
// (argc, argv_offset)
|
|
||||||
// }
|
|
||||||
|
Loading…
Reference in New Issue
Block a user