blob: bef6cc1b2f3e4b25776adbcfad5c49b9de14ad36 [file] [log] [blame]
//! Houses the types that are directly sent across the IPC channels.
//!
//! When forking to initialise the supervisor during `init_sv`, the child raises
//! a `SIGSTOP`; if the parent successfully ptraces the child, it will allow it
//! to resume. Else, the child will be killed by the parent.
//!
//! After initialisation is done, the overall structure of a traced FFI call from
//! the child process's POV is as follows:
//! ```
//! message_tx.send(TraceRequest::StartFfi);
//! confirm_rx.recv(); // receives a `Confirmation`
//! raise(SIGSTOP);
//! /* do ffi call */
//! raise(SIGUSR1); // morally equivalent to some kind of "TraceRequest::EndFfi"
//! let events = event_rx.recv(); // receives a `MemEvents`
//! ```
//! `TraceRequest::OverrideRetcode` can be sent at any point in the above, including
//! before or after all of them. `confirm_rx.recv()` is to be called after, to ensure
//! that the child does not exit before the supervisor has registered the return code.
//!
//! NB: sending these events out of order, skipping steps, etc. will result in
//! unspecified behaviour from the supervisor process, so use the abstractions
//! in `super::child` (namely `do_ffi()`) to handle this. It is
//! trivially easy to cause a deadlock or crash by messing this up!
/// An IPC request sent by the child process to the parent.
///
/// The sender for this channel should live on the child process.
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub enum TraceRequest {
/// Requests that tracing begins. Following this being sent, the child must
/// wait to receive a `Confirmation` on the respective channel and then
/// `raise(SIGSTOP)`.
///
/// To avoid possible issues while allocating memory for IPC channels, ending
/// the tracing is instead done via `raise(SIGUSR1)`.
StartFfi(StartFfiInfo),
/// Manually overrides the code that the supervisor will return upon exiting.
/// Once set, it is permanent. This can be called again to change the value.
///
/// After sending this, the child must wait to receive a `Confirmation`.
OverrideRetcode(i32),
}
/// Information needed to begin tracing.
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
pub struct StartFfiInfo {
/// A vector of page addresses that store the miri heap which is accessible from C.
pub page_ptrs: Vec<usize>,
/// The address of an allocation that can serve as a temporary stack.
/// This should be a leaked `Box<[u8; CALLBACK_STACK_SIZE]>` cast to an int.
pub stack_ptr: usize,
}
/// A marker type confirming that the supervisor has received the request to begin
/// tracing and is now waiting for a `SIGSTOP`.
///
/// The sender for this channel should live on the parent process.
#[derive(serde::Serialize, serde::Deserialize, Debug)]
pub struct Confirmation;