mod host_functions; pub mod objects; use { crate::{ handle::{self, Handle}, interp::{host_functions::host_make_object, objects::TARGETS}, }, alloc::{string::String, vec::Vec}, hashbrown::HashMap, log::trace, spin::{Lazy, Mutex}, wasmi::{Caller, Error, Func, Instance, Linker, Module, Store, TypedFunc}, xml::XMLElement, }; // Seperate use statement use { alloc::{fmt::format, format, vec}, wasmi::Value, }; use self::objects::HandleTarget; #[derive(Debug)] pub struct WasmContext { pub proc_id: Option, pub instance: Instance, pub store: Store, } pub fn wasm() -> Result<(), wasmi::Error> { use wasmi::{Config, Engine}; let mut conf = Config::default(); conf.wasm_bulk_memory(true); // conf., let engine = Engine::new(&conf); // trace!("Engine constructed"); // let wasm = include_bytes!("../../wasm_syscall_test.wasm"); let wasm = include_bytes!("../../../test.wasm"); // trace!("Loading WASM binary"); let module = Module::new(&engine, &wasm[..]).unwrap(); // trace!("Constructing wasm module"); let hs = HostState { handles: vec![] }; let mut store = Store::new(&engine, hs); // trace!("constructing host store"); let read_mem_addr = Func::wrap( &mut store, |caller: Caller<'_, HostState>, param: i32| -> i32 { read_memory_address(caller, param) }, ); let mut linker = >::new(&engine); linker.define( "host", "read_mem_addr", Func::wrap( &mut store, |caller: Caller<'_, HostState>, param: i32| -> i32 { read_memory_address(caller, param) }, ), )?; linker.define( "host", "register_idt_handler", Func::wrap(&mut store, host_functions::host_register_idt_handler), )?; linker.define( "host", "read_object_attribute", Func::wrap(&mut store, host_read_object_attribute), )?; linker.define( "host", "create_object", Func::wrap(&mut store, host_make_object), )?; let instance = linker .instantiate(&mut store, &module)? .ensure_no_start(&mut store)?; let version = instance.get_global(&store, "VERSION"); // trace!("Version: {:?}", version); let hello = instance.get_typed_func::<(), i64>(&store, "start")?; let ret = hello.call(&mut store, ())?; trace!("Called start got return of {:?}", ret); Ok(()) } #[derive(Clone, Debug)] pub struct HostState { handles: Vec>, } impl HostState { pub fn add_handle(&mut self, hand: Handle) -> usize { for (i, h) in self.handles.iter_mut().enumerate() { if let None = h { *h = Some(hand); return i; } } self.handles.push(Some(hand)); return (self.handles.len() - 1); } } pub fn read_memory_address(caller: Caller<'_, HostState>, address: i32) -> i32 { trace!("Address: {}", address); // let obj = host_make_object(caller, 16, 23); 0 } pub fn host_read_object_attribute( mut caller: Caller<'_, HostState>, handle: i64, address_start: i32, length_of_string: i32, ) -> (i32, i32) { let binding = TARGETS; let mut olock = binding.lock(); // olock.get(&handle); let mem = caller.get_export("memory").unwrap().into_memory().unwrap(); let mem_array = mem.data_mut(&mut caller); let mut name = String::new(); for i in address_start..(address_start + length_of_string) { let ch = mem_array[i as usize] as char; name.push(ch); } let Some(Some(a)) = caller.data().handles.get(handle as usize) else { return (0,0); }; let Some(Some(HandleTarget::Object(o))) = olock.get(a.r#ref) else{ return (0,0); }; let Some(r) = o.xml.attributes.iter().find(|a|{ let f = format!("{:?}",a); f.contains(&format!("Attribute{{ name: \"{}",name)) })else{ return (0,0); }; let f = format!("{:?}", r); let p = format!("Attribute{{ name: \"{}\", value: \"", name); let s = format!("\" }}"); let h = f.replace(&p, "").replace(&s, ""); let i = vec![Value::I32(h.len().try_into().unwrap())]; let mut o = vec![Value::I32(0)]; let a = caller .get_export("malloc") .unwrap() .into_func() .unwrap() .call(&mut caller, &i, &mut o); let mem_array = mem.data_mut(&mut caller); let Value::I32(a) = o[0] else{ panic!("invalid malloc"); }; for (s, b) in h.clone().into_bytes().iter().enumerate() { mem_array[(a as usize) + s] = *b; } (a, h.len().try_into().unwrap()) } pub fn build_wasm_context(bytes: Vec) -> Result { use wasmi::{Config, Engine}; let mut conf = Config::default(); conf.wasm_bulk_memory(true); // conf., let engine = Engine::new(&conf); // trace!("Engine constructed"); // let wasm = include_bytes!("../../wasm_syscall_test.wasm"); let wasm = include_bytes!("../../../test.wasm"); // trace!("Loading WASM binary"); let module = Module::new(&engine, &wasm[..]).unwrap(); // trace!("Constructing wasm module"); let hs = HostState { handles: vec![] }; let mut store = Store::new(&engine, hs); // trace!("constructing host store"); let read_mem_addr = Func::wrap( &mut store, |caller: Caller<'_, HostState>, param: i32| -> i32 { read_memory_address(caller, param) }, ); let mut linker = >::new(&engine); linker.define( "host", "read_mem_addr", Func::wrap( &mut store, |caller: Caller<'_, HostState>, param: i32| -> i32 { read_memory_address(caller, param) }, ), )?; linker.define( "host", "read_object_attribute", Func::wrap(&mut store, host_read_object_attribute), )?; linker.define( "host", "create_object", Func::wrap(&mut store, host_make_object), )?; let instance = linker .instantiate(&mut store, &module)? .ensure_no_start(&mut store)?; let wc = WasmContext { instance, store, proc_id: None, }; Ok(wc) } pub type HostFunctionIDT = HashMap; pub struct WCFunction { wc: WasmContext, function: TypedFunc<(), ()>, } pub static HFIDT: Lazy> = Lazy::new(|| { let mut hfidt = HashMap::new(); Mutex::new(hfidt) });