use crate::target::Arch;
use crate::target::Target;
use crate::target::TargetResult;
#[cfg(feature = "alloc")]
use alloc::borrow::ToOwned;
use managed::ManagedSlice;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Tracepoint(pub usize);
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct StateVariable(usize);
#[derive(Debug, Clone)]
pub struct NewTracepoint<U> {
pub number: Tracepoint,
pub enabled: bool,
pub addr: U,
pub step_count: u64,
pub pass_count: u64,
}
#[derive(Debug)]
pub enum TracepointAction<'a, U> {
Registers {
mask: ManagedSlice<'a, u8>,
},
Memory {
basereg: Option<u64>,
offset: U,
length: u64,
},
Expression {
expr: ManagedSlice<'a, u8>,
},
}
#[derive(Debug, Clone, Copy)]
pub enum TracepointSourceType {
At,
Cond,
Cmd,
}
#[derive(Debug)]
pub struct SourceTracepoint<'a, U> {
pub number: Tracepoint,
pub addr: U,
pub kind: TracepointSourceType,
pub start: u32,
pub slen: u32,
pub bytes: ManagedSlice<'a, u8>,
}
#[cfg(feature = "alloc")]
impl<U: Copy> SourceTracepoint<'_, U> {
pub fn get_owned<'b>(&self) -> SourceTracepoint<'b, U> {
SourceTracepoint {
number: self.number,
addr: self.addr,
kind: self.kind,
start: self.start,
slen: self.slen,
bytes: ManagedSlice::Owned(self.bytes.to_owned()),
}
}
}
#[cfg(feature = "alloc")]
impl<U: Copy> TracepointAction<'_, U> {
pub fn get_owned<'b>(&self) -> TracepointAction<'b, U> {
use core::ops::Deref;
match self {
TracepointAction::Registers { mask } => TracepointAction::Registers {
mask: ManagedSlice::Owned(mask.deref().into()),
},
TracepointAction::Memory {
basereg,
offset,
length,
} => TracepointAction::Memory {
basereg: *basereg,
offset: *offset,
length: *length,
},
TracepointAction::Expression { expr } => TracepointAction::Expression {
expr: ManagedSlice::Owned(expr.deref().into()),
},
}
}
}
#[derive(Debug)]
pub enum ExperimentStatus<'a> {
Running,
NotRunning,
NotRun,
Stop(Option<&'a [u8]>),
Full,
Disconnected,
PassCount(Tracepoint),
Error(&'a [u8], Tracepoint),
Unknown,
}
#[derive(Debug)]
pub enum ExperimentExplanation<'a> {
Frames(usize),
Created(usize),
Size(usize),
Free(usize),
Circular(bool),
DisconnectedTracing(bool),
Other(&'a str),
}
#[derive(Debug)]
pub enum BufferShape {
Circular,
Linear,
}
#[derive(Debug)]
pub enum TraceBufferConfig {
Shape(BufferShape),
Size(Option<u64>),
}
#[derive(Debug)]
pub enum FrameRequest<U> {
Select(u64),
AtPC(U),
Hit(Tracepoint),
Between(U, U),
Outside(U, U),
}
#[derive(Debug)]
pub enum FrameDescription {
FrameNumber(u64),
Hit(Tracepoint),
}
#[derive(Debug)]
pub struct TracepointStatus {
pub hit_count: u64,
pub bytes_used: u64,
}
#[derive(Debug)]
pub(crate) enum TracepointEnumerateCursor<U> {
New { tp: Tracepoint, addr: U },
Action { tp: Tracepoint, addr: U, step: u64 },
Source { tp: Tracepoint, addr: U, step: u64 },
}
#[derive(Debug, Default)]
pub struct TracepointEnumerateState<U> {
pub(crate) cursor: Option<TracepointEnumerateCursor<U>>,
}
#[derive(Debug)]
pub enum TracepointEnumerateStep<U> {
Action,
Source,
Next {
tp: Tracepoint,
addr: U,
},
Done,
}
pub trait Tracepoints: Target {
fn tracepoints_init(&mut self) -> TargetResult<(), Self>;
fn tracepoint_create_begin(
&mut self,
tdp: NewTracepoint<<Self::Arch as Arch>::Usize>,
) -> TargetResult<(), Self>;
fn tracepoint_create_continue(
&mut self,
tp: Tracepoint,
action: &TracepointAction<'_, <Self::Arch as Arch>::Usize>,
) -> TargetResult<(), Self>;
fn tracepoint_create_complete(&mut self, tp: Tracepoint) -> TargetResult<(), Self>;
fn tracepoint_status(
&self,
tp: Tracepoint,
addr: <Self::Arch as Arch>::Usize,
) -> TargetResult<TracepointStatus, Self>;
fn tracepoint_enumerate_state(
&mut self,
) -> &mut TracepointEnumerateState<<Self::Arch as Arch>::Usize>;
fn tracepoint_enumerate_start(
&mut self,
tp: Option<Tracepoint>,
f: &mut dyn FnMut(&NewTracepoint<<Self::Arch as Arch>::Usize>),
) -> TargetResult<TracepointEnumerateStep<<Self::Arch as Arch>::Usize>, Self>;
fn tracepoint_enumerate_action(
&mut self,
tp: Tracepoint,
step: u64,
f: &mut dyn FnMut(&TracepointAction<'_, <Self::Arch as Arch>::Usize>),
) -> TargetResult<TracepointEnumerateStep<<Self::Arch as Arch>::Usize>, Self>;
fn trace_buffer_configure(&mut self, config: TraceBufferConfig) -> TargetResult<(), Self>;
fn trace_buffer_request(
&mut self,
offset: u64,
len: usize,
f: &mut dyn FnMut(&mut [u8]),
) -> TargetResult<(), Self>;
fn trace_experiment_status(
&self,
report: &mut dyn FnMut(ExperimentStatus<'_>),
) -> TargetResult<(), Self>;
fn trace_experiment_info(
&self,
report: &mut dyn FnMut(ExperimentExplanation<'_>),
) -> TargetResult<(), Self>;
fn trace_experiment_start(&mut self) -> TargetResult<(), Self>;
fn trace_experiment_stop(&mut self) -> TargetResult<(), Self>;
fn select_frame(
&mut self,
frame: FrameRequest<<Self::Arch as Arch>::Usize>,
report: &mut dyn FnMut(FrameDescription),
) -> TargetResult<(), Self>;
#[inline(always)]
fn support_tracepoint_source(&mut self) -> Option<TracepointSourceOps<'_, Self>> {
None
}
}
pub trait TracepointSource: Tracepoints {
fn tracepoint_attach_source(
&mut self,
src: SourceTracepoint<'_, <Self::Arch as Arch>::Usize>,
) -> TargetResult<(), Self>;
fn tracepoint_enumerate_source(
&mut self,
tp: Tracepoint,
step: u64,
f: &mut dyn FnMut(&SourceTracepoint<'_, <Self::Arch as Arch>::Usize>),
) -> TargetResult<TracepointEnumerateStep<<Self::Arch as Arch>::Usize>, Self>;
}
define_ext!(TracepointsOps, Tracepoints);
define_ext!(TracepointSourceOps, TracepointSource);