Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/jit/src/memory/mod.rs
1692 views
1
use cranelift_module::{ModuleError, ModuleResult};
2
use std::io;
3
4
mod arena;
5
mod system;
6
7
pub use arena::ArenaMemoryProvider;
8
pub use system::SystemMemoryProvider;
9
10
/// Type of branch protection to apply to executable memory.
11
#[derive(Clone, Copy, Debug, PartialEq)]
12
pub enum BranchProtection {
13
/// No protection.
14
None,
15
/// Use the Branch Target Identification extension of the Arm architecture.
16
BTI,
17
}
18
19
/// A provider of memory for the JIT.
20
pub trait JITMemoryProvider {
21
/// Allocate memory that will be executable once finalized.
22
fn allocate_readexec(&mut self, size: usize, align: u64) -> io::Result<*mut u8>;
23
/// Allocate writable memory.
24
fn allocate_readwrite(&mut self, size: usize, align: u64) -> io::Result<*mut u8>;
25
/// Allocate memory that will be read-only once finalized.
26
fn allocate_readonly(&mut self, size: usize, align: u64) -> io::Result<*mut u8>;
27
28
/// Free the memory region.
29
unsafe fn free_memory(&mut self);
30
/// Finalize the memory region and apply memory protections.
31
fn finalize(&mut self, branch_protection: BranchProtection) -> ModuleResult<()>;
32
}
33
34
/// Marks the memory region as readable and executable.
35
///
36
/// This function deals with applies branch protection and clears the icache,
37
/// but *doesn't* flush the pipeline. Callers have to ensure that
38
/// [`wasmtime_jit_icache_coherence::pipeline_flush_mt`] is called before the
39
/// mappings are used.
40
pub(crate) fn set_readable_and_executable(
41
ptr: *mut u8,
42
len: usize,
43
branch_protection: BranchProtection,
44
) -> ModuleResult<()> {
45
// Clear all the newly allocated code from cache if the processor requires it
46
//
47
// Do this before marking the memory as R+X, technically we should be able to do it after
48
// but there are some CPU's that have had errata about doing this with read only memory.
49
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 BTI is requested, and the architecture supports it, use mprotect to set the PROT_BTI flag.
63
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 | /* PROT_BTI */ 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
}
81
82