Skip to content

Commit 6794b61

Browse files
committed
add separate allocator for MiriMachine
1 parent ac636db commit 6794b61

File tree

7 files changed

+432
-20
lines changed

7 files changed

+432
-20
lines changed

src/alloc_bytes.rs renamed to src/alloc/alloc_bytes.rs

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,16 @@ use std::{alloc, slice};
55
use rustc_abi::{Align, Size};
66
use rustc_middle::mir::interpret::AllocBytes;
77

8+
#[cfg(target_os = "linux")]
9+
use crate::alloc::isolated_alloc::IsolatedAlloc;
810
use crate::helpers::ToU64 as _;
911

12+
#[derive(Clone, Copy, Debug)]
13+
pub enum MiriAllocParams {
14+
Global,
15+
Isolated,
16+
}
17+
1018
/// Allocation bytes that explicitly handle the layout of the data they're storing.
1119
/// This is necessary to interface with native code that accesses the program store in Miri.
1220
#[derive(Debug)]
@@ -18,13 +26,16 @@ pub struct MiriAllocBytes {
1826
/// * If `self.layout.size() == 0`, then `self.ptr` was allocated with the equivalent layout with size 1.
1927
/// * Otherwise, `self.ptr` points to memory allocated with `self.layout`.
2028
ptr: *mut u8,
29+
/// Whether this instance of `MiriAllocBytes` had its allocation created by calling `alloc::alloc()`
30+
/// (`Global`) or the discrete allocator (`Isolated`)
31+
params: MiriAllocParams,
2132
}
2233

2334
impl Clone for MiriAllocBytes {
2435
fn clone(&self) -> Self {
2536
let bytes: Cow<'_, [u8]> = Cow::Borrowed(self);
2637
let align = Align::from_bytes(self.layout.align().to_u64()).unwrap();
27-
MiriAllocBytes::from_bytes(bytes, align, ())
38+
MiriAllocBytes::from_bytes(bytes, align, self.params)
2839
}
2940
}
3041

@@ -37,8 +48,23 @@ impl Drop for MiriAllocBytes {
3748
} else {
3849
self.layout
3950
};
51+
4052
// SAFETY: Invariant, `self.ptr` points to memory allocated with `self.layout`.
41-
unsafe { alloc::dealloc(self.ptr, alloc_layout) }
53+
unsafe {
54+
match self.params {
55+
MiriAllocParams::Global => alloc::dealloc(self.ptr, alloc_layout),
56+
MiriAllocParams::Isolated => {
57+
#[cfg(target_os = "linux")]
58+
{
59+
IsolatedAlloc::dealloc(self.ptr, alloc_layout)
60+
}
61+
#[cfg(not(target_os = "linux"))]
62+
{
63+
unreachable!()
64+
}
65+
}
66+
}
67+
}
4268
}
4369
}
4470

@@ -67,6 +93,7 @@ impl MiriAllocBytes {
6793
fn alloc_with(
6894
size: u64,
6995
align: u64,
96+
params: MiriAllocParams,
7097
alloc_fn: impl FnOnce(Layout) -> *mut u8,
7198
) -> Result<MiriAllocBytes, ()> {
7299
let size = usize::try_from(size).map_err(|_| ())?;
@@ -80,22 +107,39 @@ impl MiriAllocBytes {
80107
Err(())
81108
} else {
82109
// SAFETY: All `MiriAllocBytes` invariants are fulfilled.
83-
Ok(Self { ptr, layout })
110+
Ok(Self { ptr, layout, params })
84111
}
85112
}
86113
}
87114

88115
impl AllocBytes for MiriAllocBytes {
89-
/// Placeholder!
90-
type AllocParams = ();
116+
type AllocParams = MiriAllocParams;
91117

92-
fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, align: Align, _params: ()) -> Self {
118+
fn from_bytes<'a>(
119+
slice: impl Into<Cow<'a, [u8]>>,
120+
align: Align,
121+
params: MiriAllocParams,
122+
) -> Self {
93123
let slice = slice.into();
94124
let size = slice.len();
95125
let align = align.bytes();
96126
// SAFETY: `alloc_fn` will only be used with `size != 0`.
97-
let alloc_fn = |layout| unsafe { alloc::alloc(layout) };
98-
let alloc_bytes = MiriAllocBytes::alloc_with(size.to_u64(), align, alloc_fn)
127+
let alloc_fn = |layout| unsafe {
128+
match params {
129+
MiriAllocParams::Global => alloc::alloc(layout),
130+
MiriAllocParams::Isolated => {
131+
#[cfg(target_os = "linux")]
132+
{
133+
IsolatedAlloc::alloc(layout)
134+
}
135+
#[cfg(not(target_os = "linux"))]
136+
{
137+
unreachable!()
138+
}
139+
}
140+
}
141+
};
142+
let alloc_bytes = MiriAllocBytes::alloc_with(size.to_u64(), align, params, alloc_fn)
99143
.unwrap_or_else(|()| {
100144
panic!("Miri ran out of memory: cannot create allocation of {size} bytes")
101145
});
@@ -105,12 +149,26 @@ impl AllocBytes for MiriAllocBytes {
105149
alloc_bytes
106150
}
107151

108-
fn zeroed(size: Size, align: Align, _params: ()) -> Option<Self> {
152+
fn zeroed(size: Size, align: Align, params: MiriAllocParams) -> Option<Self> {
109153
let size = size.bytes();
110154
let align = align.bytes();
111155
// SAFETY: `alloc_fn` will only be used with `size != 0`.
112-
let alloc_fn = |layout| unsafe { alloc::alloc_zeroed(layout) };
113-
MiriAllocBytes::alloc_with(size, align, alloc_fn).ok()
156+
let alloc_fn = |layout| unsafe {
157+
match params {
158+
MiriAllocParams::Global => alloc::alloc_zeroed(layout),
159+
MiriAllocParams::Isolated => {
160+
#[cfg(target_os = "linux")]
161+
{
162+
IsolatedAlloc::alloc_zeroed(layout)
163+
}
164+
#[cfg(not(target_os = "linux"))]
165+
{
166+
unreachable!()
167+
}
168+
}
169+
}
170+
};
171+
MiriAllocBytes::alloc_with(size, align, params, alloc_fn).ok()
114172
}
115173

116174
fn as_mut_ptr(&mut self) -> *mut u8 {

0 commit comments

Comments
 (0)