1 #![doc(hidden)] 2 3 use crate::runtime::vm::instance::Instance; 4 use crate::runtime::vm::vmcontext::VMContext; 5 use wasmtime_environ::{EntityRef, MemoryIndex}; 6 use wasmtime_versioned_export_macros::versioned_export; 7 8 static mut VMCTX_AND_MEMORY: (*mut VMContext, usize) = (std::ptr::null_mut(), 0); 9 10 #[versioned_export] 11 pub unsafe extern "C" fn resolve_vmctx_memory(ptr: usize) -> *const u8 { 12 Instance::from_vmctx(VMCTX_AND_MEMORY.0, |handle| { 13 assert!( 14 VMCTX_AND_MEMORY.1 < handle.env_module().memory_plans.len(), 15 "memory index for debugger is out of bounds" 16 ); 17 let index = MemoryIndex::new(VMCTX_AND_MEMORY.1); 18 let mem = handle.get_memory(index); 19 mem.base.add(ptr) 20 }) 21 } 22 23 #[versioned_export] 24 pub unsafe extern "C" fn resolve_vmctx_memory_ptr(p: *const u32) -> *const u8 { 25 let ptr = std::ptr::read(p); 26 assert!( 27 !VMCTX_AND_MEMORY.0.is_null(), 28 "must call `__vmctx->set()` before resolving Wasm pointers" 29 ); 30 Instance::from_vmctx(VMCTX_AND_MEMORY.0, |handle| { 31 assert!( 32 VMCTX_AND_MEMORY.1 < handle.env_module().memory_plans.len(), 33 "memory index for debugger is out of bounds" 34 ); 35 let index = MemoryIndex::new(VMCTX_AND_MEMORY.1); 36 let mem = handle.get_memory(index); 37 mem.base.add(ptr as usize) 38 }) 39 } 40 41 #[versioned_export] 42 pub unsafe extern "C" fn set_vmctx_memory(vmctx_ptr: *mut VMContext) { 43 // TODO multi-memory 44 VMCTX_AND_MEMORY = (vmctx_ptr, 0); 45 } 46 47 // Ensures that set_vmctx_memory and resolve_vmctx_memory_ptr are linked and 48 // exported as symbols. It is a workaround: the executable normally ignores 49 // `pub extern "C"`, see rust-lang/rust#25057. 50 pub fn ensure_exported() { 51 if cfg!(miri) { 52 return; 53 } 54 unsafe { 55 std::ptr::read_volatile(resolve_vmctx_memory_ptr as *const u8); 56 std::ptr::read_volatile(set_vmctx_memory as *const u8); 57 std::ptr::read_volatile(resolve_vmctx_memory as *const u8); 58 } 59 } 60