use deepsize2::DeepSizeOf;
use serde::{Deserialize, Serialize};
pub const NUM_LOCAL_MEMORY_ENTRIES_PER_ROW_EXEC: usize = 1;
pub const NUM_LOCAL_PAGE_PROT_ENTRIES_PER_ROW_EXEC: usize = 1;
pub const NUM_PAGE_PROT_ENTRIES_PER_ROW_EXEC: usize = 4;
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize, PartialEq, Eq, DeepSizeOf)]
#[repr(C)]
pub struct MemoryRecord {
pub timestamp: u64,
pub value: u64,
}
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
pub struct MemoryEntry {
pub external_flag: bool,
pub timestamp: u64,
pub value: u64,
}
impl MemoryEntry {
#[must_use]
pub fn init(value: u64) -> Self {
Self { external_flag: false, timestamp: 0, value }
}
}
impl From<MemoryEntry> for MemoryRecord {
fn from(value: MemoryEntry) -> Self {
let MemoryEntry { timestamp, value, .. } = value;
Self { timestamp, value }
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum MemoryAccessPosition {
UntrustedInstruction = 0,
Memory = 1,
C = 2,
B = 3,
A = 4,
}
#[allow(clippy::manual_non_exhaustive)]
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize, PartialEq, Eq, DeepSizeOf)]
#[repr(C)]
pub struct MemoryReadRecord {
pub value: u64,
pub timestamp: u64,
pub prev_timestamp: u64,
pub prev_page_prot_record: Option<PageProtRecord>,
}
#[allow(clippy::manual_non_exhaustive)]
#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize, PartialEq, Eq, DeepSizeOf)]
#[repr(C)]
pub struct MemoryWriteRecord {
pub prev_timestamp: u64,
pub prev_page_prot_record: Option<PageProtRecord>,
pub prev_value: u64,
pub timestamp: u64,
pub value: u64,
}
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, DeepSizeOf)]
pub enum MemoryRecordEnum {
Read(MemoryReadRecord),
Write(MemoryWriteRecord),
}
impl MemoryRecordEnum {
#[must_use]
pub fn current_record(&self) -> MemoryRecord {
match self {
MemoryRecordEnum::Read(record) => {
MemoryRecord { timestamp: record.timestamp, value: record.value }
}
MemoryRecordEnum::Write(record) => {
MemoryRecord { timestamp: record.timestamp, value: record.value }
}
}
}
#[must_use]
pub fn previous_record(&self) -> MemoryRecord {
match self {
MemoryRecordEnum::Read(record) => {
MemoryRecord { timestamp: record.prev_timestamp, value: record.value }
}
MemoryRecordEnum::Write(record) => {
MemoryRecord { timestamp: record.prev_timestamp, value: record.prev_value }
}
}
}
#[must_use]
pub fn previous_page_prot_record(&self) -> Option<PageProtRecord> {
match self {
MemoryRecordEnum::Read(record) => record.prev_page_prot_record,
MemoryRecordEnum::Write(record) => record.prev_page_prot_record,
}
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, DeepSizeOf)]
#[repr(C)]
pub struct MemoryInitializeFinalizeEvent {
pub addr: u64,
pub value: u64,
pub timestamp: u64,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, DeepSizeOf)]
#[repr(C)]
pub struct PageProtInitializeFinalizeEvent {
pub page_idx: u64,
pub page_prot: u8,
pub timestamp: u64,
}
impl PageProtInitializeFinalizeEvent {
#[must_use]
pub const fn initialize(page_idx: u64, page_prot: u8) -> Self {
Self { page_idx, page_prot, timestamp: 0 }
}
#[must_use]
pub const fn finalize_from_record(page_idx: u64, record: &PageProtRecord) -> Self {
Self { page_idx, page_prot: record.page_prot, timestamp: record.timestamp }
}
}
impl MemoryReadRecord {
#[must_use]
#[inline]
pub const fn new(
entry: &MemoryEntry,
prev_entry: &MemoryEntry,
prev_page_prot_record: Option<PageProtRecord>,
) -> Self {
let MemoryEntry { timestamp, value, .. } = *entry;
let MemoryEntry { timestamp: prev_timestamp, value: _, .. } = *prev_entry;
debug_assert!(timestamp > prev_timestamp);
Self { value, timestamp, prev_timestamp, prev_page_prot_record }
}
}
impl From<MemoryRecordEnum> for MemoryReadRecord {
fn from(record: MemoryRecordEnum) -> Self {
match record {
MemoryRecordEnum::Read(record) => record,
MemoryRecordEnum::Write(_) => panic!("Cannot convert a write record to a read record"),
}
}
}
impl MemoryWriteRecord {
#[must_use]
#[inline]
pub const fn new(
entry: &MemoryEntry,
prev_entry: &MemoryEntry,
prev_page_prot_record: Option<PageProtRecord>,
) -> Self {
let MemoryEntry { timestamp, value, .. } = *entry;
let MemoryEntry { timestamp: prev_timestamp, value: prev_value, .. } = *prev_entry;
debug_assert!(timestamp > prev_timestamp);
Self { prev_timestamp, prev_page_prot_record, prev_value, timestamp, value }
}
}
impl MemoryRecordEnum {
#[must_use]
pub const fn value(&self) -> u64 {
match self {
MemoryRecordEnum::Read(record) => record.value,
MemoryRecordEnum::Write(record) => record.value,
}
}
#[must_use]
pub const fn prev_value(&self) -> u64 {
match self {
MemoryRecordEnum::Read(record) => record.value,
MemoryRecordEnum::Write(record) => record.prev_value,
}
}
}
impl MemoryInitializeFinalizeEvent {
#[must_use]
pub const fn initialize(addr: u64, value: u64) -> Self {
Self { addr, value, timestamp: 0 }
}
#[must_use]
pub const fn finalize_from_record(addr: u64, record: &MemoryEntry) -> Self {
Self { addr, value: record.value, timestamp: record.timestamp }
}
#[must_use]
pub const fn finalize(addr: u64, value: u64, timestamp: u64) -> Self {
Self { addr, value, timestamp }
}
}
impl From<MemoryReadRecord> for MemoryRecordEnum {
fn from(read_record: MemoryReadRecord) -> Self {
MemoryRecordEnum::Read(read_record)
}
}
impl From<MemoryWriteRecord> for MemoryRecordEnum {
fn from(write_record: MemoryWriteRecord) -> Self {
MemoryRecordEnum::Write(write_record)
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, DeepSizeOf)]
#[repr(C)]
pub struct MemoryLocalEvent {
pub addr: u64,
pub initial_mem_access: MemoryRecord,
pub final_mem_access: MemoryRecord,
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, DeepSizeOf, PartialEq, Eq)]
#[repr(C)]
pub struct PageProtRecord {
pub external_flag: bool,
pub timestamp: u64,
pub page_prot: u8,
}
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq, DeepSizeOf)]
#[repr(C)]
pub struct PageProtLocalEvent {
pub page_idx: u64,
pub initial_page_prot_access: PageProtRecord,
pub final_page_prot_access: PageProtRecord,
}
pub trait IntoMemoryRecord {
fn previous_record(&self) -> MemoryRecord;
fn current_record(&self) -> MemoryRecord;
}
impl IntoMemoryRecord for MemoryReadRecord {
fn previous_record(&self) -> MemoryRecord {
MemoryRecord { timestamp: self.prev_timestamp, value: self.value }
}
fn current_record(&self) -> MemoryRecord {
MemoryRecord { timestamp: self.timestamp, value: self.value }
}
}
impl IntoMemoryRecord for MemoryWriteRecord {
fn previous_record(&self) -> MemoryRecord {
MemoryRecord { timestamp: self.prev_timestamp, value: self.prev_value }
}
fn current_record(&self) -> MemoryRecord {
MemoryRecord { timestamp: self.timestamp, value: self.value }
}
}