miri/shims/native_lib/trace/
messages.rs

1//! Houses the types that are directly sent across the IPC channels.
2//!
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.
6//!
7//! After initialisation is done, the overall structure of a traced FFI call from
8//! the child process's POV is as follows:
9//! ```
10//! message_tx.send(TraceRequest::StartFfi);
11//! confirm_rx.recv(); // receives a `Confirmation`
12//! raise(SIGSTOP);
13//! /* do ffi call */
14//! raise(SIGUSR1); // morally equivalent to some kind of "TraceRequest::EndFfi"
15//! let events = event_rx.recv(); // receives a `MemEvents`
16//! ```
17//! `TraceRequest::OverrideRetcode` can be sent at any point in the above, including
18//! before or after all of them. `confirm_rx.recv()` is to be called after, to ensure
19//! that the child does not exit before the supervisor has registered the return code.
20//!
21//! NB: sending these events out of order, skipping steps, etc. will result in
22//! unspecified behaviour from the supervisor process, so use the abstractions
23//! in `super::child` (namely `do_ffi()`) to handle this. It is
24//! trivially easy to cause a deadlock or crash by messing this up!
25
26/// An IPC request sent by the child process to the parent.
27///
28/// The sender for this channel should live on the child process.
29#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
30pub enum TraceRequest {
31    /// Requests that tracing begins. Following this being sent, the child must
32    /// wait to receive a `Confirmation` on the respective channel and then
33    /// `raise(SIGSTOP)`.
34    ///
35    /// To avoid possible issues while allocating memory for IPC channels, ending
36    /// the tracing is instead done via `raise(SIGUSR1)`.
37    StartFfi(StartFfiInfo),
38    /// Manually overrides the code that the supervisor will return upon exiting.
39    /// Once set, it is permanent. This can be called again to change the value.
40    ///
41    /// After sending this, the child must wait to receive a `Confirmation`.
42    OverrideRetcode(i32),
43}
44
45/// Information needed to begin tracing.
46#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
47pub struct StartFfiInfo {
48    /// A vector of page addresses that store the miri heap which is accessible from C.
49    pub page_ptrs: Vec<usize>,
50    /// The address of an allocation that can serve as a temporary stack.
51    /// This should be a leaked `Box<[u8; CALLBACK_STACK_SIZE]>` cast to an int.
52    pub stack_ptr: usize,
53}
54
55/// A marker type confirming that the supervisor has received the request to begin
56/// tracing and is now waiting for a `SIGSTOP`.
57///
58/// The sender for this channel should live on the parent process.
59#[derive(serde::Serialize, serde::Deserialize, Debug)]
60pub struct Confirmation;