panda/api/
rr.rs

1use std::ffi::CString;
2use std::ptr;
3
4use crate::{Error, RrError};
5
6/// RR point-in-time: get current count of instructions replayed
7pub fn rr_get_guest_instr_count() -> u64 {
8    unsafe { panda_sys::rr_get_guest_instr_count_external() as _ }
9}
10
11/// Stop and quit, wraps QMP functions.
12pub fn vm_quit() {
13    let rr_ctrl_ret = unsafe { panda_sys::panda_vm_quit() };
14    // Non-fallible: https://sourcegraph.com/github.com/panda-re/panda/-/blob/panda/src/callbacks.c#L755:5
15    // Defensive assert in case C-side ever becomes fallible
16    assert_eq!(rr_ctrl_ret, panda_sys::RRCTRL_ret_RRCTRL_OK);
17}
18
19/// Start recording.
20/// If `snapshot.is_some()` restore the named snapshot prior to recording.
21pub fn record_begin(name: &str, snapshot: Option<&str>) -> Result<(), Error> {
22    match CString::new(name) {
23        Ok(c_name) => match snapshot {
24            Some(snap_name) => match CString::new(snap_name) {
25                Ok(c_snap_name) => {
26                    let rr_ctrl_ret = unsafe {
27                        panda_sys::panda_record_begin(c_name.as_ptr(), c_snap_name.as_ptr())
28                    };
29                    RrError::translate_err_code(rr_ctrl_ret)
30                }
31                Err(e) => Err(Error::InvalidString(e)),
32            },
33            None => {
34                let rr_ctrl_ret =
35                    unsafe { panda_sys::panda_record_begin(c_name.as_ptr(), ptr::null()) };
36                RrError::translate_err_code(rr_ctrl_ret)
37            }
38        },
39        Err(e) => Err(Error::InvalidString(e)),
40    }
41}
42
43/// End currently recording.
44pub fn record_end() -> Result<(), Error> {
45    let rr_ctrl_ret = unsafe { panda_sys::panda_record_end() };
46    RrError::translate_err_code(rr_ctrl_ret)
47}
48
49/// Start replay.
50pub fn replay_begin(name: &str) -> Result<(), Error> {
51    match CString::new(name) {
52        Ok(c_name) => {
53            let rr_ctrl_ret = unsafe { panda_sys::panda_replay_begin(c_name.as_ptr()) };
54            RrError::translate_err_code(rr_ctrl_ret)
55        }
56        Err(e) => Err(Error::InvalidString(e)),
57    }
58}
59
60/// End currently running replay.
61pub fn replay_end() -> Result<(), Error> {
62    let rr_ctrl_ret = unsafe { panda_sys::panda_replay_end() };
63    RrError::translate_err_code(rr_ctrl_ret)
64}
65