Skip to content

Commit d2ed49d

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

File tree

13 files changed

+94
-102
lines changed

13 files changed

+94
-102
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ default = ["stack-cache"]
6767
genmc = []
6868
stack-cache = []
6969
stack-cache-consistency-check = ["stack-cache"]
70+
trace = []
7071

7172
[lints.rust.unexpected_cfgs]
7273
level = "warn"

build.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
fn main() {
2+
if cfg!(all(
3+
target_os = "linux",
4+
target_env = "gnu",
5+
any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64")
6+
)) {
7+
println!("cargo::rustc-cfg=feature=\"trace\"");
8+
}
9+
}

src/alloc/alloc_bytes.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
use std::alloc::Layout;
22
use std::borrow::Cow;
33
use std::{alloc, slice};
4-
#[cfg(target_os = "linux")]
4+
#[cfg(feature = "trace")]
55
use std::{cell::RefCell, rc::Rc};
66

77
use rustc_abi::{Align, Size};
88
use rustc_middle::mir::interpret::AllocBytes;
99

10-
#[cfg(target_os = "linux")]
10+
#[cfg(feature = "trace")]
1111
use crate::alloc::isolated_alloc::IsolatedAlloc;
1212
use crate::helpers::ToU64 as _;
1313

1414
#[derive(Clone, Debug)]
1515
pub enum MiriAllocParams {
1616
Global,
17-
#[cfg(target_os = "linux")]
17+
#[cfg(feature = "trace")]
1818
Isolated(Rc<RefCell<IsolatedAlloc>>),
1919
}
2020

@@ -56,7 +56,7 @@ impl Drop for MiriAllocBytes {
5656
unsafe {
5757
match self.params.clone() {
5858
MiriAllocParams::Global => alloc::dealloc(self.ptr, alloc_layout),
59-
#[cfg(target_os = "linux")]
59+
#[cfg(feature = "trace")]
6060
MiriAllocParams::Isolated(alloc) =>
6161
alloc.borrow_mut().dealloc(self.ptr, alloc_layout),
6262
}
@@ -123,7 +123,7 @@ impl AllocBytes for MiriAllocBytes {
123123
let alloc_fn = |layout, params: &MiriAllocParams| unsafe {
124124
match params {
125125
MiriAllocParams::Global => alloc::alloc(layout),
126-
#[cfg(target_os = "linux")]
126+
#[cfg(feature = "trace")]
127127
MiriAllocParams::Isolated(alloc) => alloc.borrow_mut().alloc(layout),
128128
}
129129
};
@@ -144,7 +144,7 @@ impl AllocBytes for MiriAllocBytes {
144144
let alloc_fn = |layout, params: &MiriAllocParams| unsafe {
145145
match params {
146146
MiriAllocParams::Global => alloc::alloc_zeroed(layout),
147-
#[cfg(target_os = "linux")]
147+
#[cfg(feature = "trace")]
148148
MiriAllocParams::Isolated(alloc) => alloc.borrow_mut().alloc_zeroed(layout),
149149
}
150150
};

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/alloc/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
mod alloc_bytes;
2-
#[cfg(target_os = "linux")]
2+
#[cfg(feature = "trace")]
33
pub mod isolated_alloc;
44

55
pub use self::alloc_bytes::{MiriAllocBytes, MiriAllocParams};

src/bin/miri.rs

Lines changed: 4 additions & 4 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(feature = "trace")]
231+
miri::native_lib::register_retcode_sv(rustc_driver::EXIT_FAILURE);
232232
tcx.dcx().abort_if_errors();
233233
rustc_driver::EXIT_FAILURE
234234
});
@@ -796,15 +796,15 @@ fn main() {
796796

797797
debug!("rustc arguments: {:?}", rustc_args);
798798
debug!("crate arguments: {:?}", miri_config.args);
799-
#[cfg(target_os = "linux")]
799+
#[cfg(feature = "trace")]
800800
if !miri_config.native_lib.is_empty() && miri_config.native_lib_enable_tracing {
801801
// FIXME: This should display a diagnostic / warning on error
802802
// SAFETY: If any other threads exist at this point (namely for the ctrlc
803803
// handler), they will not interact with anything on the main rustc/Miri
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(feature = "trace")]
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/machine.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ pub struct MiriMachine<'tcx> {
530530
pub(crate) rng: RefCell<StdRng>,
531531

532532
/// The allocator used for the machine's `AllocBytes` in native-libs mode.
533-
#[cfg(target_os = "linux")]
533+
#[cfg(feature = "trace")]
534534
pub(crate) allocator: Option<Rc<RefCell<crate::alloc::isolated_alloc::IsolatedAlloc>>>,
535535

536536
/// The allocation IDs to report when they are being allocated
@@ -718,7 +718,7 @@ impl<'tcx> MiriMachine<'tcx> {
718718
local_crates,
719719
extern_statics: FxHashMap::default(),
720720
rng: RefCell::new(rng),
721-
#[cfg(target_os = "linux")]
721+
#[cfg(feature = "trace")]
722722
allocator: if !config.native_lib.is_empty() {
723723
Some(Rc::new(RefCell::new(crate::alloc::isolated_alloc::IsolatedAlloc::new())))
724724
} else { None },
@@ -924,7 +924,7 @@ impl VisitProvenance for MiriMachine<'_> {
924924
backtrace_style: _,
925925
local_crates: _,
926926
rng: _,
927-
#[cfg(target_os = "linux")]
927+
#[cfg(feature = "trace")]
928928
allocator: _,
929929
tracked_alloc_ids: _,
930930
track_alloc_accesses: _,
@@ -1817,12 +1817,12 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
18171817
fn get_default_alloc_params(&self) -> <Self::Bytes as AllocBytes>::AllocParams {
18181818
use crate::alloc::MiriAllocParams;
18191819

1820-
#[cfg(target_os = "linux")]
1820+
#[cfg(feature = "trace")]
18211821
match &self.allocator {
18221822
Some(alloc) => MiriAllocParams::Isolated(alloc.clone()),
18231823
None => MiriAllocParams::Global,
18241824
}
1825-
#[cfg(not(target_os = "linux"))]
1825+
#[cfg(not(feature = "trace"))]
18261826
MiriAllocParams::Global
18271827
}
18281828
}

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(feature = "trace")]
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(feature = "trace")]
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(feature = "trace")]
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(feature = "trace")]
20+
type CallResult<'tcx> = InterpResult<'tcx, (ImmTy<'tcx>, Option<self::trace::messages::MemEvents>)>;
21+
#[cfg(not(feature = "trace"))]
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(feature = "trace")]
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(feature = "trace")]
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(feature = "trace")]
115+
let events = unsafe { Supervisor::end_ffi(alloc, guard, stack_ptr) };
116+
#[cfg(not(feature = "trace"))]
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(feature = "trace")]
217+
tracing: self::trace::Supervisor::is_enabled(),
218+
#[cfg(not(feature = "trace"))]
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)