Skip to content

Commit 37fbac4

Browse files
committed
various trace-related fixups
1 parent e607b36 commit 37fbac4

File tree

8 files changed

+111
-63
lines changed

8 files changed

+111
-63
lines changed

src/alloc/isolated_alloc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,15 +318,15 @@ impl IsolatedAlloc {
318318
///
319319
/// SAFETY: Accessing memory after this point will result in a segfault
320320
/// unless it is first unprotected.
321-
pub unsafe fn prepare_ffi(&mut self) -> Result<(), nix::errno::Errno> {
321+
pub unsafe fn start_ffi(&mut self) -> Result<(), nix::errno::Errno> {
322322
let prot = mman::ProtFlags::PROT_NONE;
323323
unsafe { self.mprotect(prot) }
324324
}
325325

326326
/// Deprotects all owned memory by setting it to RW. Erroring here is very
327327
/// likely unrecoverable, so it may panic if applying those permissions
328328
/// fails.
329-
pub fn unprep_ffi(&mut self) {
329+
pub fn end_ffi(&mut self) {
330330
let prot = mman::ProtFlags::PROT_READ | mman::ProtFlags::PROT_WRITE;
331331
unsafe {
332332
self.mprotect(prot).unwrap();

src/bin/miri.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,8 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
227227
} else {
228228
let return_code = miri::eval_entry(tcx, entry_def_id, entry_type, &config, None)
229229
.unwrap_or_else(|| {
230-
//#[cfg(target_os = "linux")]
231-
//miri::native_lib::register_retcode_sv(rustc_driver::EXIT_FAILURE);
230+
#[cfg(target_os = "linux")]
231+
miri::native_lib::register_retcode_sv(rustc_driver::EXIT_FAILURE);
232232
tcx.dcx().abort_if_errors();
233233
rustc_driver::EXIT_FAILURE
234234
});
@@ -804,7 +804,7 @@ fn main() {
804804
// thread in an async-signal-unsafe way such as by accessing shared
805805
// semaphores, etc.; the handler only calls `sleep()` and `exit()`, which
806806
// are async-signal-safe, as is accessing atomics
807-
//let _ = unsafe { miri::native_lib::init_sv() };
807+
let _ = unsafe { miri::native_lib::init_sv() };
808808
}
809809
run_compiler_and_exit(
810810
&rustc_args,

src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,10 @@ pub use rustc_const_eval::interpret::{self, AllocMap, Provenance as _};
100100
use rustc_middle::{bug, span_bug};
101101
use tracing::{info, trace};
102102

103-
//#[cfg(target_os = "linux")]
104-
//pub mod native_lib {
105-
// pub use crate::shims::{init_sv, register_retcode_sv};
106-
//}
103+
#[cfg(target_os = "linux")]
104+
pub mod native_lib {
105+
pub use crate::shims::{init_sv, register_retcode_sv};
106+
}
107107

108108
// Type aliases that set the provenance parameter.
109109
pub type Pointer = interpret::Pointer<Option<machine::Provenance>>;

src/shims/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ pub mod time;
2121
pub mod tls;
2222

2323
pub use self::files::FdTable;
24-
//#[cfg(target_os = "linux")]
25-
//pub use self::native_lib::trace::{init_sv, register_retcode_sv};
24+
#[cfg(target_os = "linux")]
25+
pub use self::native_lib::trace::{init_sv, register_retcode_sv};
2626
pub use self::unix::{DirTable, EpollInterestTable};
2727

2828
/// What needs to be done after emulating an item (a shim or an intrinsic) is done.

src/shims/native_lib/mod.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
//! Implements calling functions from a native library.
22
3-
// FIXME: disabled since it fails to build on many targets.
4-
//#[cfg(target_os = "linux")]
5-
//pub mod trace;
3+
#[cfg(target_os = "linux")]
4+
pub mod trace;
65

76
use std::ops::Deref;
87

@@ -13,13 +12,13 @@ use rustc_middle::mir::interpret::Pointer;
1312
use rustc_middle::ty::{self as ty, IntTy, UintTy};
1413
use rustc_span::Symbol;
1514

16-
//#[cfg(target_os = "linux")]
17-
//use self::trace::Supervisor;
15+
#[cfg(target_os = "linux")]
16+
use self::trace::Supervisor;
1817
use crate::*;
1918

20-
//#[cfg(target_os = "linux")]
21-
//type CallResult<'tcx> = InterpResult<'tcx, (ImmTy<'tcx>, Option<self::trace::messages::MemEvents>)>;
22-
//#[cfg(not(target_os = "linux"))]
19+
#[cfg(target_os = "linux")]
20+
type CallResult<'tcx> = InterpResult<'tcx, (ImmTy<'tcx>, Option<self::trace::messages::MemEvents>)>;
21+
#[cfg(not(target_os = "linux"))]
2322
type CallResult<'tcx> = InterpResult<'tcx, (ImmTy<'tcx>, Option<!>)>;
2423

2524
impl<'tcx> EvalContextExtPriv<'tcx> for crate::MiriInterpCx<'tcx> {}
@@ -33,12 +32,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
3332
libffi_args: Vec<libffi::high::Arg<'a>>,
3433
) -> CallResult<'tcx> {
3534
let this = self.eval_context_mut();
36-
//#[cfg(target_os = "linux")]
37-
//let alloc = this.machine.allocator.as_ref().unwrap();
35+
#[cfg(target_os = "linux")]
36+
let alloc = this.machine.allocator.as_ref().unwrap();
3837

3938
// SAFETY: We don't touch the machine memory past this point.
40-
//#[cfg(target_os = "linux")]
41-
//let (guard, stack_ptr) = unsafe { Supervisor::start_ffi(alloc) };
39+
#[cfg(target_os = "linux")]
40+
let (guard, stack_ptr) = unsafe { Supervisor::start_ffi(alloc) };
4241

4342
// Call the function (`ptr`) with arguments `libffi_args`, and obtain the return value
4443
// as the specified primitive integer type
@@ -112,9 +111,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
112111

113112
// SAFETY: We got the guard and stack pointer from start_ffi, and
114113
// the allocator is the same
115-
//#[cfg(target_os = "linux")]
116-
//let events = unsafe { Supervisor::end_ffi(alloc, guard, stack_ptr) };
117-
//#[cfg(not(target_os = "linux"))]
114+
#[cfg(target_os = "linux")]
115+
let events = unsafe { Supervisor::end_ffi(alloc, guard, stack_ptr) };
116+
#[cfg(not(target_os = "linux"))]
118117
let events = None;
119118

120119
interp_ok((res?, events))
@@ -214,9 +213,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
214213
if !this.machine.native_call_mem_warned.replace(true) {
215214
// Newly set, so first time we get here.
216215
this.emit_diagnostic(NonHaltingDiagnostic::NativeCallSharedMem {
217-
//#[cfg(target_os = "linux")]
218-
//tracing: self::trace::Supervisor::is_enabled(),
219-
//#[cfg(not(target_os = "linux"))]
216+
#[cfg(target_os = "linux")]
217+
tracing: self::trace::Supervisor::is_enabled(),
218+
#[cfg(not(target_os = "linux"))]
220219
tracing: false,
221220
});
222221
}

src/shims/native_lib/trace/child.rs

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ impl Supervisor {
4949
) -> (std::sync::MutexGuard<'static, Option<Supervisor>>, Option<*mut [u8; CALLBACK_STACK_SIZE]>)
5050
{
5151
let mut sv_guard = SUPERVISOR.lock().unwrap();
52-
// If the supervisor is not initialised for whatever reason, fast-fail.
52+
// If the supervisor is not initialised for whatever reason, fast-return.
5353
// This might be desired behaviour, as even on platforms where ptracing
5454
// is not implemented it enables us to enforce that only one FFI call
5555
// happens at a time.
56-
let Some(sv) = sv_guard.take() else {
56+
let Some(sv) = sv_guard.as_mut() else {
5757
return (sv_guard, None);
5858
};
5959

@@ -68,9 +68,9 @@ impl Supervisor {
6868
// SAFETY: We do not access machine memory past this point until the
6969
// supervisor is ready to allow it.
7070
unsafe {
71-
if alloc.borrow_mut().prepare_ffi().is_err() {
71+
if alloc.borrow_mut().start_ffi().is_err() {
7272
// Don't mess up unwinding by maybe leaving the memory partly protected
73-
alloc.borrow_mut().unprep_ffi();
73+
alloc.borrow_mut().end_ffi();
7474
panic!("Cannot protect memory for FFI call!");
7575
}
7676
}
@@ -82,7 +82,6 @@ impl Supervisor {
8282
// enforce an ordering for these events.
8383
sv.message_tx.send(TraceRequest::StartFfi(start_info)).unwrap();
8484
sv.confirm_rx.recv().unwrap();
85-
*sv_guard = Some(sv);
8685
// We need to be stopped for the supervisor to be able to make certain
8786
// modifications to our memory - simply waiting on the recv() doesn't
8887
// count.
@@ -113,20 +112,19 @@ impl Supervisor {
113112
signal::raise(signal::SIGUSR1).unwrap();
114113

115114
// This is safe! It just sets memory to normal expected permissions.
116-
alloc.borrow_mut().unprep_ffi();
115+
alloc.borrow_mut().end_ffi();
117116

118117
// If this is `None`, then `raw_stack_ptr` is None and does not need to
119118
// be deallocated (and there's no need to worry about the guard, since
120119
// it contains nothing).
121-
let sv = sv_guard.take()?;
120+
let sv = sv_guard.as_mut()?;
122121
// SAFETY: Caller upholds that this pointer was allocated as a box with
123122
// this type.
124123
unsafe {
125124
drop(Box::from_raw(raw_stack_ptr.unwrap()));
126125
}
127126
// On the off-chance something really weird happens, don't block forever.
128-
let ret = sv
129-
.event_rx
127+
sv.event_rx
130128
.try_recv_timeout(std::time::Duration::from_secs(5))
131129
.map_err(|e| {
132130
match e {
@@ -135,10 +133,7 @@ impl Supervisor {
135133
eprintln!("Waiting for accesses from supervisor timed out!"),
136134
}
137135
})
138-
.ok();
139-
// Do *not* leave the supervisor empty, or else we might get another fork...
140-
*sv_guard = Some(sv);
141-
ret
136+
.ok()
142137
}
143138
}
144139

@@ -148,11 +143,19 @@ impl Supervisor {
148143
/// receiving back events through `get_events`.
149144
///
150145
/// # Safety
151-
/// The invariants for `fork()` must be upheld by the caller.
146+
/// The invariants for `fork()` must be upheld by the caller, namely either:
147+
/// - Other threads do not exist, or;
148+
/// - If they do exist, either those threads or the resulting child process
149+
/// only ever act in [async-signal-safe](https://www.man7.org/linux/man-pages/man7/signal-safety.7.html) ways.
152150
pub unsafe fn init_sv() -> Result<(), SvInitError> {
153151
// FIXME: Much of this could be reimplemented via the mitosis crate if we upstream the
154152
// relevant missing bits.
155153

154+
// Not on a properly supported architecture!
155+
if cfg!(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))) {
156+
return Err(SvInitError);
157+
}
158+
156159
// On Linux, this will check whether ptrace is fully disabled by the Yama module.
157160
// If Yama isn't running or we're not on Linux, we'll still error later, but
158161
// this saves a very expensive fork call.
@@ -244,8 +247,7 @@ pub unsafe fn init_sv() -> Result<(), SvInitError> {
244247
/// given as a 0 if this is not used.
245248
pub fn register_retcode_sv(code: i32) {
246249
let mut sv_guard = SUPERVISOR.lock().unwrap();
247-
if let Some(sv) = sv_guard.take() {
250+
if let Some(sv) = sv_guard.as_mut() {
248251
sv.message_tx.send(TraceRequest::OverrideRetcode(code)).unwrap();
249-
*sv_guard = Some(sv);
250252
}
251253
}

src/shims/native_lib/trace/messages.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub enum TraceRequest {
4141
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
4242
pub struct StartFfiInfo {
4343
/// A vector of page addresses. These should have been automatically obtained
44-
/// with `IsolatedAlloc::pages` and prepared with `IsolatedAlloc::prepare_ffi`.
44+
/// with `IsolatedAlloc::pages` and prepared with `IsolatedAlloc::start_ffi`.
4545
pub page_ptrs: Vec<usize>,
4646
/// The address of an allocation that can serve as a temporary stack.
4747
/// This should be a leaked `Box<[u8; CALLBACK_STACK_SIZE]>` cast to an int.

0 commit comments

Comments
 (0)