1 use super::cvt;
2 use crate::prelude::*;
3 use crate::runtime::vm::sys::{capi, vm::MemoryImageSource};
4 use crate::runtime::vm::{HostAlignedByteCount, SendSyncPtr};
5 use core::ops::Range;
6 use core::ptr::{self, NonNull};
7 #[cfg(feature = "std")]
8 use std::{fs::File, path::Path};
9 
10 #[cfg(feature = "std")]
open_file_for_mmap(_path: &Path) -> Result<File>11 pub fn open_file_for_mmap(_path: &Path) -> Result<File> {
12     crate::bail!("not supported on this platform");
13 }
14 
15 #[derive(Debug)]
16 pub struct Mmap {
17     memory: SendSyncPtr<[u8]>,
18 }
19 
20 impl Mmap {
new_empty() -> Mmap21     pub fn new_empty() -> Mmap {
22         Mmap {
23             memory: crate::vm::sys::empty_mmap(),
24         }
25     }
26 
new(size: HostAlignedByteCount) -> Result<Self>27     pub fn new(size: HostAlignedByteCount) -> Result<Self> {
28         let mut ptr = ptr::null_mut();
29         cvt(unsafe {
30             capi::wasmtime_mmap_new(
31                 size.byte_count(),
32                 capi::PROT_READ | capi::PROT_WRITE,
33                 &mut ptr,
34             )
35         })?;
36         let memory = ptr::slice_from_raw_parts_mut(ptr.cast(), size.byte_count());
37         let memory = SendSyncPtr::new(NonNull::new(memory).unwrap());
38         Ok(Mmap { memory })
39     }
40 
reserve(size: HostAlignedByteCount) -> Result<Self>41     pub fn reserve(size: HostAlignedByteCount) -> Result<Self> {
42         let mut ptr = ptr::null_mut();
43         cvt(unsafe { capi::wasmtime_mmap_new(size.byte_count(), 0, &mut ptr) })?;
44         let memory = ptr::slice_from_raw_parts_mut(ptr.cast(), size.byte_count());
45         let memory = SendSyncPtr::new(NonNull::new(memory).unwrap());
46         Ok(Mmap { memory })
47     }
48 
49     #[cfg(feature = "std")]
from_file(_file: &File) -> Result<Self>50     pub fn from_file(_file: &File) -> Result<Self> {
51         crate::bail!("not supported on this platform");
52     }
53 
make_accessible( &self, start: HostAlignedByteCount, len: HostAlignedByteCount, ) -> Result<()>54     pub unsafe fn make_accessible(
55         &self,
56         start: HostAlignedByteCount,
57         len: HostAlignedByteCount,
58     ) -> Result<()> {
59         let ptr = self.memory.as_ptr();
60         unsafe {
61             cvt(capi::wasmtime_mprotect(
62                 ptr.byte_add(start.byte_count()).cast(),
63                 len.byte_count(),
64                 capi::PROT_READ | capi::PROT_WRITE,
65             ))?;
66         }
67 
68         Ok(())
69     }
70 
71     #[inline]
as_send_sync_ptr(&self) -> SendSyncPtr<u8>72     pub fn as_send_sync_ptr(&self) -> SendSyncPtr<u8> {
73         self.memory.cast()
74     }
75 
76     #[inline]
len(&self) -> usize77     pub fn len(&self) -> usize {
78         self.memory.as_ptr().len()
79     }
80 
make_executable( &self, range: Range<usize>, enable_branch_protection: bool, ) -> Result<()>81     pub unsafe fn make_executable(
82         &self,
83         range: Range<usize>,
84         enable_branch_protection: bool,
85     ) -> Result<()> {
86         unsafe {
87             let base = self.memory.as_ptr().byte_add(range.start).cast();
88             let len = range.end - range.start;
89 
90             // not mapped into the C API at this time.
91             let _ = enable_branch_protection;
92 
93             cvt(capi::wasmtime_mprotect(
94                 base,
95                 len,
96                 capi::PROT_READ | capi::PROT_EXEC,
97             ))?;
98         }
99         Ok(())
100     }
101 
make_readonly(&self, range: Range<usize>) -> Result<()>102     pub unsafe fn make_readonly(&self, range: Range<usize>) -> Result<()> {
103         unsafe {
104             let base = self.memory.as_ptr().byte_add(range.start).cast();
105             let len = range.end - range.start;
106 
107             cvt(capi::wasmtime_mprotect(base, len, capi::PROT_READ))?;
108         }
109         Ok(())
110     }
111 
make_readwrite(&self, range: Range<usize>) -> Result<()>112     pub unsafe fn make_readwrite(&self, range: Range<usize>) -> Result<()> {
113         unsafe {
114             let base = self.memory.as_ptr().byte_add(range.start).cast();
115             let len = range.end - range.start;
116 
117             cvt(capi::wasmtime_mprotect(
118                 base,
119                 len,
120                 capi::PROT_READ | capi::PROT_WRITE,
121             ))?;
122         }
123         Ok(())
124     }
125 
map_image_at( &self, image_source: &MemoryImageSource, source_offset: u64, memory_offset: HostAlignedByteCount, memory_len: HostAlignedByteCount, ) -> Result<()>126     pub unsafe fn map_image_at(
127         &self,
128         image_source: &MemoryImageSource,
129         source_offset: u64,
130         memory_offset: HostAlignedByteCount,
131         memory_len: HostAlignedByteCount,
132     ) -> Result<()> {
133         assert_eq!(source_offset, 0);
134         unsafe {
135             let base = self
136                 .memory
137                 .as_ptr()
138                 .byte_add(memory_offset.byte_count())
139                 .cast();
140             cvt(capi::wasmtime_memory_image_map_at(
141                 image_source.image_ptr().as_ptr(),
142                 base,
143                 memory_len.byte_count(),
144             ))
145         }
146     }
147 }
148 
149 impl Drop for Mmap {
drop(&mut self)150     fn drop(&mut self) {
151         unsafe {
152             let ptr = self.memory.as_ptr().cast();
153             let len = self.memory.as_ptr().len();
154             if len == 0 {
155                 return;
156             }
157             cvt(capi::wasmtime_munmap(ptr, len)).unwrap();
158         }
159     }
160 }
161