2019-05-03 23:07:07 -07:00
|
|
|
pub mod service;
|
|
|
|
|
|
|
|
use wasmer_runtime_core::{
|
|
|
|
loader::{self, Loader, Instance},
|
|
|
|
backend::RunnableModule,
|
2019-05-04 09:56:52 -07:00
|
|
|
vm::{Ctx, LocalGlobal, SigId, Anyfunc},
|
2019-05-03 23:07:07 -07:00
|
|
|
module::ModuleInfo,
|
2019-05-06 08:28:12 -07:00
|
|
|
types::{Value, LocalMemoryIndex, LocalTableIndex, ImportedMemoryIndex, ImportedTableIndex, FuncIndex},
|
2019-05-03 23:07:07 -07:00
|
|
|
structures::TypedIndex,
|
|
|
|
};
|
2019-05-06 08:28:12 -07:00
|
|
|
use service::{ServiceContext, LoadProfile, RunProfile, TableEntryRequest, ImportInfo};
|
2019-05-03 23:07:07 -07:00
|
|
|
|
|
|
|
pub struct KernelLoader;
|
|
|
|
|
|
|
|
impl Loader for KernelLoader {
|
|
|
|
type Instance = KernelInstance;
|
|
|
|
type Error = String;
|
|
|
|
|
2019-05-04 09:56:52 -07:00
|
|
|
fn load(&self, rm: &dyn RunnableModule, module: &ModuleInfo, full_ctx: &Ctx) -> Result<Self::Instance, Self::Error> {
|
|
|
|
let ctx = &full_ctx.internal;
|
2019-05-03 23:07:07 -07:00
|
|
|
let code = rm.get_code().unwrap();
|
|
|
|
let memory = if let Some(_) = module.memories.get(LocalMemoryIndex::new(0)) {
|
|
|
|
Some(unsafe {
|
|
|
|
::std::slice::from_raw_parts((**ctx.memories).base, (**ctx.memories).bound)
|
2019-05-05 05:03:07 -07:00
|
|
|
})
|
2019-05-03 23:07:07 -07:00
|
|
|
} else if let Some(_) = module.imported_memories.get(ImportedMemoryIndex::new(0)) {
|
|
|
|
return Err("imported memory is not supported".into());
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2019-05-04 09:56:52 -07:00
|
|
|
let table: Option<Vec<TableEntryRequest>> = if let Some(_) = module.tables.get(LocalTableIndex::new(0)) {
|
|
|
|
Some(unsafe {
|
|
|
|
let table = &**ctx.tables;
|
|
|
|
let elements: &[Anyfunc] = ::std::slice::from_raw_parts(table.base as *const Anyfunc, table.count);
|
|
|
|
let base_addr = code.as_ptr() as usize;
|
|
|
|
let end_addr = base_addr + code.len();
|
|
|
|
elements.iter().map(|x| {
|
|
|
|
let func_addr = x.func as usize;
|
|
|
|
TableEntryRequest {
|
|
|
|
offset: if x.func.is_null() || func_addr < base_addr || func_addr >= end_addr {
|
|
|
|
::std::usize::MAX
|
|
|
|
} else {
|
|
|
|
x.func as usize - base_addr
|
|
|
|
},
|
|
|
|
sig_id: x.sig_id.0,
|
|
|
|
}
|
|
|
|
}).collect()
|
|
|
|
})
|
|
|
|
} else if let Some(_) = module.imported_tables.get(ImportedTableIndex::new(0)) {
|
|
|
|
return Err("imported table is not supported".into());
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2019-05-03 23:07:07 -07:00
|
|
|
if module.imported_globals.len() > 0 {
|
|
|
|
return Err("imported globals are not supported".into());
|
|
|
|
}
|
|
|
|
let globals: Vec<u64> = unsafe {
|
|
|
|
let globals: &[*mut LocalGlobal] = ::std::slice::from_raw_parts(ctx.globals, module.globals.len());
|
|
|
|
globals.iter().map(|x| (**x).data).collect()
|
|
|
|
};
|
2019-05-06 08:28:12 -07:00
|
|
|
let mut import_names: Vec<ImportInfo> = vec![];
|
|
|
|
for (idx, import) in &module.imported_functions {
|
2019-05-04 08:28:13 -07:00
|
|
|
let name = format!("{}##{}", module.namespace_table.get(import.namespace_index), module.name_table.get(import.name_index));
|
2019-05-06 08:28:12 -07:00
|
|
|
let sig = module.signatures.get(
|
|
|
|
*module.func_assoc.get(FuncIndex::new(idx.index())).unwrap()
|
|
|
|
).unwrap();
|
|
|
|
import_names.push(ImportInfo {
|
|
|
|
name: name,
|
|
|
|
param_count: sig.params().len(),
|
|
|
|
});
|
2019-05-04 08:28:13 -07:00
|
|
|
}
|
2019-05-05 05:03:07 -07:00
|
|
|
let dynamic_sigindices: &[u32] = unsafe {
|
|
|
|
::std::mem::transmute::<&[SigId], &[u32]>(
|
|
|
|
::std::slice::from_raw_parts(ctx.dynamic_sigindices, full_ctx.dynamic_sigindice_count())
|
|
|
|
)
|
|
|
|
};
|
|
|
|
let profile = LoadProfile {
|
|
|
|
code: code,
|
2019-05-03 23:07:07 -07:00
|
|
|
memory: memory,
|
2019-05-05 05:03:07 -07:00
|
|
|
memory_max: 0,
|
|
|
|
globals: &globals,
|
|
|
|
imports: &import_names,
|
|
|
|
dynamic_sigindices: dynamic_sigindices,
|
|
|
|
table: table.as_ref().map(|x| x.as_slice()),
|
|
|
|
};
|
|
|
|
let sc = ServiceContext::new(profile).map_err(|x| format!("{:?}", x))?;
|
|
|
|
Ok(KernelInstance {
|
|
|
|
context: sc,
|
2019-05-03 23:07:07 -07:00
|
|
|
offsets: rm.get_offsets().unwrap(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct KernelInstance {
|
|
|
|
context: ServiceContext,
|
|
|
|
offsets: Vec<usize>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Instance for KernelInstance {
|
|
|
|
type Error = String;
|
|
|
|
fn call(&mut self, id: usize, args: &[Value]) -> Result<u64, String> {
|
|
|
|
let args: Vec<u64> = args.iter().map(|x| x.to_u64()).collect();
|
|
|
|
|
|
|
|
let ret = self.context.run_code(RunProfile {
|
|
|
|
entry_offset: self.offsets[id] as u32,
|
2019-05-05 05:03:07 -07:00
|
|
|
params: &args,
|
2019-05-03 23:07:07 -07:00
|
|
|
}).map_err(|x| format!("{:?}", x))?;
|
2019-05-05 09:32:35 -07:00
|
|
|
Ok(ret)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_memory(&mut self, offset: u32, len: u32) -> Result<Vec<u8>, String> {
|
|
|
|
self.context.read_memory(offset, len).map_err(|x| format!("{:?}", x))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn write_memory(&mut self, offset: u32, len: u32, buf: &[u8]) -> Result<(), String> {
|
|
|
|
self.context.write_memory(offset, len, buf).map_err(|x| format!("{:?}", x))
|
2019-05-03 23:07:07 -07:00
|
|
|
}
|
|
|
|
}
|