cranelift_jit/memory/
mod.rs1use cranelift_module::{ModuleError, ModuleResult};
2use std::io;
3
4mod arena;
5mod system;
6
7pub use arena::ArenaMemoryProvider;
8pub use system::SystemMemoryProvider;
9
10#[derive(Clone, Copy, Debug, PartialEq)]
12pub enum BranchProtection {
13 None,
15 BTI,
17}
18
19pub trait JITMemoryProvider {
21 fn allocate_readexec(&mut self, size: usize, align: u64) -> io::Result<*mut u8>;
23 fn allocate_readwrite(&mut self, size: usize, align: u64) -> io::Result<*mut u8>;
25 fn allocate_readonly(&mut self, size: usize, align: u64) -> io::Result<*mut u8>;
27
28 unsafe fn free_memory(&mut self);
30 fn finalize(&mut self, branch_protection: BranchProtection) -> ModuleResult<()>;
32}
33
34pub(crate) fn set_readable_and_executable(
41 ptr: *mut u8,
42 len: usize,
43 branch_protection: BranchProtection,
44) -> ModuleResult<()> {
45 unsafe {
50 wasmtime_jit_icache_coherence::clear_cache(ptr as *const libc::c_void, len)
51 .expect("Failed cache clear")
52 };
53
54 unsafe {
55 region::protect(ptr, len, region::Protection::READ_EXECUTE).map_err(|e| {
56 ModuleError::Backend(
57 anyhow::Error::new(e).context("unable to make memory readable+executable"),
58 )
59 })?;
60 }
61
62 if branch_protection == BranchProtection::BTI {
64 #[cfg(all(target_arch = "aarch64", target_os = "linux"))]
65 if std::arch::is_aarch64_feature_detected!("bti") {
66 let prot = libc::PROT_EXEC | libc::PROT_READ | 0x10;
67
68 unsafe {
69 if libc::mprotect(ptr as *mut libc::c_void, len, prot) < 0 {
70 return Err(ModuleError::Backend(
71 anyhow::Error::new(io::Error::last_os_error())
72 .context("unable to make memory readable+executable"),
73 ));
74 }
75 }
76 }
77 }
78
79 Ok(())
80}