Skip to content

Commit 9e54dab

Browse files
committed
review 3
1 parent 7d6685d commit 9e54dab

File tree

6 files changed

+41
-26
lines changed

6 files changed

+41
-26
lines changed

src/shims/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub mod time;
2121
pub mod tls;
2222

2323
pub use self::files::FdTable;
24+
#[cfg(target_os = "linux")]
2425
pub use self::native_lib::trace::{init_sv, register_retcode_sv};
2526
pub use self::unix::{DirTable, EpollInterestTable};
2627

src/shims/native_lib/mod.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,10 @@ use rustc_span::Symbol;
1515
target_env = "gnu",
1616
any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")
1717
)),
18-
path = "trace_stub.rs"
18+
path = "trace/stub.rs"
1919
)]
2020
pub mod trace;
2121

22-
use self::trace::Supervisor;
2322
use crate::*;
2423

2524
impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
@@ -35,14 +34,13 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
3534
let this = self.eval_context_mut();
3635
#[cfg(target_os = "linux")]
3736
let alloc = this.machine.allocator.as_ref().unwrap();
38-
39-
// SAFETY: We don't touch the machine memory past this point.
40-
#[cfg(target_os = "linux")]
41-
let guard = unsafe { Supervisor::start_ffi(alloc) };
37+
#[cfg(not(target_os = "linux"))]
38+
// Placeholder value.
39+
let alloc = ();
4240

4341
// Call the function (`ptr`) with arguments `libffi_args`, and obtain the return value
4442
// as the specified primitive integer type
45-
let res = 'res: {
43+
let ffi_fn = || {
4644
let scalar = match dest.layout.ty.kind() {
4745
// ints
4846
ty::Int(IntTy::I8) => {
@@ -93,15 +91,15 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
9391
// have the output_type `Tuple([])`.
9492
ty::Tuple(t_list) if (*t_list).deref().is_empty() => {
9593
unsafe { ffi::call::<()>(ptr, libffi_args.as_slice()) };
96-
break 'res interp_ok(ImmTy::uninit(dest.layout));
94+
return interp_ok(ImmTy::uninit(dest.layout));
9795
}
9896
ty::RawPtr(..) => {
9997
let x = unsafe { ffi::call::<*const ()>(ptr, libffi_args.as_slice()) };
10098
let ptr = Pointer::new(Provenance::Wildcard, Size::from_bytes(x.addr()));
10199
Scalar::from_pointer(ptr, this)
102100
}
103101
_ =>
104-
break 'res Err(err_unsup_format!(
102+
return Err(err_unsup_format!(
105103
"unsupported return type for native call: {:?}",
106104
link_name
107105
))
@@ -110,11 +108,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
110108
interp_ok(ImmTy::from_scalar(scalar, dest.layout))
111109
};
112110

113-
// SAFETY: We got the guard and stack pointer from start_ffi, and
114-
// the allocator is the same
115-
let events = unsafe { Supervisor::end_ffi(guard) };
116-
117-
interp_ok((res?, events))
111+
trace::do_ffi(alloc, ffi_fn)
118112
}
119113

120114
/// Get the pointer to the function of the specified name in the shared object file,

src/shims/native_lib/trace/child.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ use crate::alloc::isolated_alloc::IsolatedAlloc;
1515
/// need to ensure that either (a) only one `MiriMachine` is performing an FFI call
1616
/// at any given time, or (b) there are distinct supervisor and child processes for
1717
/// each machine. The former was chosen here.
18+
///
19+
/// This should only contain a `None` if the supervisor has not (yet) been initialised;
20+
/// otherwise, if `init_sv` was called and did not error, this will always be nonempty.
1821
static SUPERVISOR: std::sync::Mutex<Option<Supervisor>> = std::sync::Mutex::new(None);
1922

2023
/// The main means of communication between the child and parent process,
@@ -162,10 +165,6 @@ impl Supervisor {
162165
/// supervisor process could not be created successfully; else, the caller
163166
/// is now the child process and can communicate via `start_ffi`/`end_ffi`,
164167
/// receiving back events through `get_events`.
165-
///
166-
/// When forking to initialise the supervisor, the child raises a `SIGSTOP`; if
167-
/// the parent successfully ptraces the child, it will allow it to resume. Else,
168-
/// the child will be killed by the parent.
169168
///
170169
/// # Safety
171170
/// The invariants for `fork()` must be upheld by the caller, namely either:

src/shims/native_lib/trace/messages.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
//! Houses the types that are directly sent across the IPC channels.
22
//!
3+
//! When forking to initialise the supervisor during `init_sv`, the child raises
4+
//! a `SIGSTOP`; if the parent successfully ptraces the child, it will allow it
5+
//! to resume. Else, the child will be killed by the parent.
36
//!
47
//! After initialisation is done, the overall structure of a traced FFI call from
58
//! the child process's POV is as follows:

src/shims/native_lib/trace/mod.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,34 @@ mod child;
22
pub mod messages;
33
mod parent;
44

5+
use std::{cell::RefCell, rc::Rc};
6+
7+
use rustc_const_eval::interpret::InterpResult;
8+
9+
use crate::alloc::isolated_alloc::IsolatedAlloc;
10+
511
pub use self::child::{Supervisor, init_sv, register_retcode_sv};
612

713
/// The size of the temporary stack we use for callbacks that the server executes in the client.
814
/// This should be big enough that `mempr_on` and `mempr_off` can safely be jumped into with the
915
/// stack pointer pointing to a "stack" of this size without overflowing it.
1016
const CALLBACK_STACK_SIZE: usize = 1024;
1117

12-
pub(super) type CallResult<'tcx> = rustc_const_eval::interpret::InterpResult<
18+
/// Wrapper type for what we get back from an FFI call; the former is its actual
19+
/// return value, and the latter is the list of memory accesses that occurred during
20+
/// this call.
21+
pub type CallResult<'tcx> = InterpResult<
1322
'tcx,
1423
(crate::ImmTy<'tcx>, Option<messages::MemEvents>),
1524
>;
25+
26+
/// Performs an arbitrary FFI call, enabling tracing from the supervisor.
27+
pub fn do_ffi<'tcx>(alloc: &Rc<RefCell<IsolatedAlloc>>, f: impl FnOnce() -> InterpResult<'tcx, crate::ImmTy<'tcx>>) -> CallResult<'tcx> {
28+
// SAFETY: We don't touch the machine memory past this point.
29+
let guard = unsafe { Supervisor::start_ffi(alloc) };
30+
31+
f().map(|v| {
32+
let memevents = unsafe { Supervisor::end_ffi(guard) };
33+
(v, memevents)
34+
})
35+
}

src/shims/native_lib/trace_stub.rs renamed to src/shims/native_lib/trace/stub.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@ impl Supervisor {
88
pub fn is_enabled() -> bool {
99
false
1010
}
11+
}
1112

12-
#[inline(always)]
13-
pub unsafe fn start_ffi<T>(_: T) {}
14-
15-
#[inline(always)]
16-
pub unsafe fn end_ffi<T>(_: T) -> Option<!> {
17-
None
18-
}
13+
pub fn do_ffi<'tcx, T>(_: T, f: impl FnOnce() -> InterpResult<'tcx, crate::ImmTy<'tcx>>) -> CallResult<'tcx> {
14+
f().map(|v| {
15+
(v, None)
16+
})
1917
}
2018

2119
#[expect(clippy::missing_safety_doc)]

0 commit comments

Comments
 (0)