diff --git a/src/module.rs b/src/module.rs index bc0b14bca9..22e974eea7 100644 --- a/src/module.rs +++ b/src/module.rs @@ -489,7 +489,7 @@ impl ModuleInstance { } if let Some(memory_ref) = module_ref.memory_by_index(DEFAULT_MEMORY_INDEX) { - tracer.push_init_memory(memory_ref) + tracer.push_init_memory(current_module_id, memory_ref) } } } diff --git a/src/runner.rs b/src/runner.rs index ab59d694ba..3898ff4a6f 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -496,7 +496,7 @@ impl Interpreter { let raw_address = <_>::from_value_internal(*self.value_stack.top()); let address = effective_address(offset, raw_address).map_or(None, |addr| Some(addr)); - let mmid = tracer.lookup_memory_instance( + let origin_mmid = tracer.lookup_memory_instance_origin( &function_context .memory .clone() @@ -509,7 +509,7 @@ impl Interpreter { effective_address: address, vtype: parity_wasm::elements::ValueType::I32, load_size, - mmid: mmid as u64, + origin_mmid, }) } isa::Instruction::I64Load(offset) | isa::Instruction::I64Load8U(offset) => { @@ -521,7 +521,7 @@ impl Interpreter { let raw_address = <_>::from_value_internal(*self.value_stack.top()); let address = effective_address(offset, raw_address).map_or(None, |addr| Some(addr)); - let mmid = tracer.lookup_memory_instance( + let origin_mmid = tracer.lookup_memory_instance_origin( &function_context .memory .clone() @@ -534,7 +534,7 @@ impl Interpreter { effective_address: address, vtype: parity_wasm::elements::ValueType::I64, load_size, - mmid: mmid as u64, + origin_mmid, }) } isa::Instruction::I32Store(offset) | isa::Instruction::I32Store8(offset) => { @@ -548,7 +548,8 @@ impl Interpreter { let raw_address = <_>::from_value_internal(*self.value_stack.pick(2)); let address = effective_address(offset, raw_address).map_or(None, |addr| Some(addr)); - let mmid = tracer.lookup_memory_instance(&function_context.memory.clone().unwrap()); + let origin_mmid = + tracer.lookup_memory_instance_origin(&function_context.memory.clone().unwrap()); let pre_block_value = address.map(|address| { let mut buf = [0u8; 8]; @@ -568,7 +569,7 @@ impl Interpreter { value: value as u64, vtype: parity_wasm::elements::ValueType::I32, store_size, - mmid: mmid as u64, + origin_mmid, pre_block_value, }) } @@ -583,7 +584,8 @@ impl Interpreter { let raw_address = <_>::from_value_internal(*self.value_stack.pick(2)); let address = effective_address(offset, raw_address).map_or(None, |addr| Some(addr)); - let mmid = tracer.lookup_memory_instance(&function_context.memory.clone().unwrap()); + let origin_mmid = + tracer.lookup_memory_instance_origin(&function_context.memory.clone().unwrap()); let pre_block_value = address.map(|address| { let mut buf = [0u8; 8]; @@ -603,7 +605,7 @@ impl Interpreter { value, vtype: parity_wasm::elements::ValueType::I64, store_size, - mmid: mmid as u64, + origin_mmid, pre_block_value, }) } @@ -720,7 +722,7 @@ impl Interpreter { value: from_value_internal_to_u64_with_typ(vtype.into(), *self.value_stack.top()), vtype: vtype.into(), }, - isa::Instruction::GetGlobal(idx) => { + isa::Instruction::GetGlobal(idx) | isa::Instruction::SetGlobal(idx) => { let tracer = self.tracer.as_ref().unwrap().borrow(); let global_ref = context.module().global_by_index(idx).unwrap(); @@ -733,49 +735,25 @@ impl Interpreter { let (origin_module, origin_idx) = tracer.lookup_global_instance(&global_ref).unwrap(); - let moid = tracer.lookup_module_instance(&context.module); - /* - * TODO: imported global is not support yet. - */ - assert_eq!(origin_module, moid); - assert_eq!(origin_idx, idx as u16); - - StepInfo::GetGlobal { - idx, - origin_module: moid, - origin_idx: idx as u16, - vtype, - is_mutable, - value, - } - } - isa::Instruction::SetGlobal(idx) => { - let tracer = self.tracer.as_ref().unwrap().borrow(); - let global_ref = context.module().global_by_index(idx).unwrap(); - let is_mutable = global_ref.is_mutable(); - let vtype: VarType = global_ref.value_type().into_elements().into(); - let value = from_value_internal_to_u64_with_typ( - vtype.into(), - ValueInternal::from(global_ref.get()), - ); - - let (origin_module, origin_idx) = - tracer.lookup_global_instance(&global_ref).unwrap(); - let moid = tracer.lookup_module_instance(&context.module); - /* - * TODO: imported global is not support yet. - */ - assert_eq!(origin_module, moid); - assert_eq!(origin_idx, idx as u16); - - StepInfo::SetGlobal { - idx, - origin_module: moid, - origin_idx: idx as u16, - vtype, - is_mutable, - value, + match *instructions { + isa::Instruction::GetGlobal(_) => StepInfo::GetGlobal { + idx, + origin_module, + origin_idx, + vtype, + is_mutable, + value, + }, + isa::Instruction::SetGlobal(_) => StepInfo::SetGlobal { + idx, + origin_module, + origin_idx, + vtype, + is_mutable, + value, + }, + _ => unreachable!(), } } @@ -935,7 +913,7 @@ impl Interpreter { effective_address, vtype, load_size, - mmid, + origin_mmid, } = pre_status.unwrap() { let block_value = { @@ -960,7 +938,7 @@ impl Interpreter { *self.value_stack.top(), ), block_value, - mmid, + origin_mmid, } } else { unreachable!() @@ -977,7 +955,7 @@ impl Interpreter { value, vtype, store_size, - mmid, + origin_mmid, pre_block_value, } = pre_status.unwrap() { @@ -999,7 +977,7 @@ impl Interpreter { raw_address, effective_address: effective_address.unwrap(), value: value as u64, - mmid, + origin_mmid, pre_block_value: pre_block_value.unwrap(), updated_block_value, } diff --git a/src/tracer/etable.rs b/src/tracer/etable.rs index 93bf2461bc..6e6691e6e6 100644 --- a/src/tracer/etable.rs +++ b/src/tracer/etable.rs @@ -38,7 +38,7 @@ pub enum RunInstructionTracePre { effective_address: Option, // use option in case of memory out of bound vtype: ValueType, load_size: MemoryReadSize, - mmid: u64, + origin_mmid: u16, }, Store { offset: u32, @@ -47,7 +47,7 @@ pub enum RunInstructionTracePre { value: u64, vtype: ValueType, store_size: MemoryStoreSize, - mmid: u64, + origin_mmid: u16, pre_block_value: Option, }, diff --git a/src/tracer/imtable.rs b/src/tracer/imtable.rs deleted file mode 100644 index 87e6b5d5ef..0000000000 --- a/src/tracer/imtable.rs +++ /dev/null @@ -1,55 +0,0 @@ -use specs::{ - imtable::InitMemoryTableEntry, - mtable::{LocationType, VarType}, -}; - -#[derive(Debug, Clone)] -pub struct IMEntry { - pub is_global: bool, - pub is_mutable: bool, - pub module_instance_index: u16, - pub offset: u32, - pub vtype: VarType, - pub value: u64, -} - -impl Into for IMEntry { - fn into(self) -> InitMemoryTableEntry { - InitMemoryTableEntry { - is_mutable: self.is_mutable, - ltype: if self.is_global { - LocationType::Global - } else { - LocationType::Heap - }, - mmid: self.module_instance_index as u64, - offset: self.offset as u64, - vtype: self.vtype, - value: self.value, - } - } -} - -#[derive(Debug, Default)] -pub struct IMTable(pub Vec); - -impl IMTable { - pub(crate) fn push( - &mut self, - is_global: bool, - is_mutable: bool, - module_instance_index: u16, - offset: u32, - vtype: VarType, - value: u64, - ) { - self.0.push(IMEntry { - is_mutable, - is_global, - module_instance_index, - offset, - vtype, - value, - }) - } -} diff --git a/src/tracer/itable.rs b/src/tracer/itable.rs index 4a25807bdb..b404c3d4b3 100644 --- a/src/tracer/itable.rs +++ b/src/tracer/itable.rs @@ -14,7 +14,7 @@ impl Into for IEntry { fn into(self) -> InstructionTableEntry { InstructionTableEntry { moid: self.module_instance_index, - mmid: self.module_instance_index, + // mmid: self.module_instance_index, fid: self.func_index, iid: self.pc, opcode: self.opcode, diff --git a/src/tracer/mod.rs b/src/tracer/mod.rs index f6ee1c1a59..14b01438d3 100644 --- a/src/tracer/mod.rs +++ b/src/tracer/mod.rs @@ -1,6 +1,11 @@ use std::collections::HashMap; -use specs::{host_function::HostFunctionDesc, mtable::VarType, types::FunctionType}; +use specs::{ + host_function::HostFunctionDesc, + imtable::{ImportMemoryEntry, InitMemoryEntry, InitMemoryTable, InitMemoryTableEntry}, + mtable::{LocationType, VarType}, + types::FunctionType, +}; use crate::{ runner::{from_value_internal_to_u64_with_typ, ValueInternal}, @@ -14,13 +19,11 @@ use crate::{ use self::{ etable::ETable, - imtable::IMTable, itable::{IEntry, ITable}, jtable::JTable, }; pub mod etable; -pub mod imtable; pub mod itable; pub mod jtable; @@ -34,11 +37,12 @@ pub struct FuncDesc { #[derive(Debug)] pub struct Tracer { pub itable: ITable, - pub imtable: IMTable, + pub imtable: InitMemoryTable, pub etable: ETable, pub jtable: JTable, module_instance_lookup: Vec<(ModuleRef, u16)>, memory_instance_lookup: Vec<(MemoryRef, u16)>, + memory_instance_origin_mmid: Vec<(MemoryRef, u16)>, global_instance_lookup: Vec<(GlobalRef, (u16, u16))>, function_lookup: Vec<(FuncRef, u16)>, last_jump_eid: Vec, @@ -52,12 +56,13 @@ impl Tracer { pub fn new(host_plugin_lookup: HashMap) -> Self { Tracer { itable: ITable::default(), - imtable: IMTable::default(), + imtable: InitMemoryTable::default(), etable: ETable::default(), last_jump_eid: vec![0], jtable: JTable::default(), module_instance_lookup: vec![], memory_instance_lookup: vec![], + memory_instance_origin_mmid: vec![], global_instance_lookup: vec![], function_lookup: vec![], function_index_allocator: 1, @@ -105,44 +110,83 @@ impl Tracer { } impl Tracer { - pub(crate) fn push_init_memory(&mut self, memref: MemoryRef) { - let pages = (*memref).limits().initial(); - // one page contains 64KB*1024/8=8192 u64 entries - for i in 0..(pages * 8192) { - let mut buf = [0u8; 8]; - (*memref).get_into(i * 8, &mut buf).unwrap(); - self.imtable.push( - false, - true, - self.next_memory_id(), - i, - VarType::I64, - u64::from_le_bytes(buf), - ); + fn try_get_memory_ref_origin_mmid(&self, memref: &MemoryRef) -> Option { + for (m_ref, mmid) in &self.memory_instance_origin_mmid { + if memref == m_ref { + return Some(*mmid); + } } - self.memory_instance_lookup - .push((memref, self.next_memory_id())); + None + } + + pub(crate) fn push_init_memory(&mut self, moid: u16, memref: MemoryRef) { + if let Some(origin_moid) = self.try_get_memory_ref_origin_mmid(&memref) { + self.imtable + .push(InitMemoryTableEntry::Import(ImportMemoryEntry { + ltype: LocationType::Heap, + origin_moid: origin_moid, + origin_idx: 0, // Currently wasm only supports one memory instance per module. + moid: moid, + idx: 0, + })) + } else { + let pages = (*memref).limits().initial(); + + // one page contains 64KB*1024/8=8192 u64 entries + for i in 0..(pages * 8192) { + let mut buf = [0u8; 8]; + (*memref).get_into(i * 8, &mut buf).unwrap(); + + let entry = InitMemoryTableEntry::Init(InitMemoryEntry { + ltype: LocationType::Heap, + is_mutable: true, + mmid: moid as u64, + offset: i as u64, + vtype: VarType::I64, + value: u64::from_le_bytes(buf), + }); + + self.imtable.push(entry); + } + + self.memory_instance_origin_mmid + .push((memref.clone(), moid)); + } + + self.memory_instance_lookup.push((memref, moid)); } pub(crate) fn push_global(&mut self, moid: u16, globalidx: u32, globalref: &GlobalRef) { let vtype = globalref.elements_value_type().into(); - if let Some((_origin_moid, _origin_idx)) = self.lookup_global_instance(globalref) { - // Import global does not support yet. - todo!() + if let Some((origin_moid, origin_idx)) = self.lookup_global_instance(globalref) { + let entry = InitMemoryTableEntry::Import(ImportMemoryEntry { + ltype: LocationType::Global, + origin_moid, + origin_idx, + moid, + idx: globalidx as u16, + }); + + self.imtable.push(entry) } else { self.global_instance_lookup .push((globalref.clone(), (moid, globalidx as u16))); - self.imtable.push( - true, - globalref.is_mutable(), - moid, - globalidx, + let entry = InitMemoryTableEntry::Init(InitMemoryEntry { + ltype: LocationType::Global, + is_mutable: globalref.is_mutable(), + mmid: moid as u64, + offset: globalidx as u64, vtype, - from_value_internal_to_u64_with_typ(vtype, ValueInternal::from(globalref.get())), - ) + value: from_value_internal_to_u64_with_typ( + vtype, + ValueInternal::from(globalref.get()), + ), + }); + + self.imtable.push(entry) } } @@ -283,6 +327,16 @@ impl Tracer { unreachable!() } + pub fn lookup_memory_instance_origin(&self, module_instance: &MemoryRef) -> u16 { + for m in &self.memory_instance_origin_mmid { + if &m.0 == module_instance { + return m.1; + } + } + + unreachable!() + } + pub fn lookup_global_instance(&self, global_instance: &GlobalRef) -> Option<(u16, u16)> { for m in &self.global_instance_lookup { if &m.0 == global_instance {