use alloc::{collections::BTreeMap, sync::Arc, vec::Vec};
use lock_api::RawMutex;
use crate::{KprobeAuxiliaryOps, KprobeOps, ProbePoint, UniProbe};
#[derive(Debug)]
pub struct ProbeManager<L: RawMutex + 'static, F: KprobeAuxiliaryOps> {
break_list: BTreeMap<usize, Vec<UniProbe<L, F>>>,
debug_list: BTreeMap<usize, Vec<UniProbe<L, F>>>,
}
impl<L: RawMutex + 'static, F: KprobeAuxiliaryOps> Default for ProbeManager<L, F> {
fn default() -> Self {
Self::new()
}
}
impl<L: RawMutex + 'static, F: KprobeAuxiliaryOps> ProbeManager<L, F> {
pub const fn new() -> Self {
ProbeManager {
break_list: BTreeMap::new(),
debug_list: BTreeMap::new(),
}
}
pub fn insert_probe(&mut self, probe: UniProbe<L, F>) {
let probe_point = probe.probe_point().clone();
self.insert_break_point(probe_point.break_address(), probe.clone());
self.insert_debug_point(probe_point.debug_address(), probe);
}
fn insert_break_point(&mut self, address: usize, probe: UniProbe<L, F>) {
let list = self.break_list.entry(address).or_default();
list.push(probe);
}
fn insert_debug_point(&mut self, address: usize, probe: UniProbe<L, F>) {
let list = self.debug_list.entry(address).or_default();
list.push(probe);
}
pub fn get_break_list(&self, address: usize) -> Option<&Vec<UniProbe<L, F>>> {
self.break_list.get(&address)
}
pub fn get_debug_list(&self, address: usize) -> Option<&Vec<UniProbe<L, F>>> {
self.debug_list.get(&address)
}
pub fn kprobe_num(&self, address: usize) -> usize {
self.break_list_len(address)
}
pub(crate) fn replace_debug_list_with_new_address(
&mut self,
old_address: usize,
new_address: usize,
) {
if let Some(list) = self.debug_list.remove(&old_address) {
self.debug_list.insert(new_address, list);
}
}
#[inline]
fn break_list_len(&self, address: usize) -> usize {
self.break_list
.get(&address)
.map(|list| list.len())
.unwrap_or(0)
}
#[inline]
fn debug_list_len(&self, address: usize) -> usize {
self.debug_list
.get(&address)
.map(|list| list.len())
.unwrap_or(0)
}
pub fn remove_probe(&mut self, probe: UniProbe<L, F>) {
let probe_point = probe.probe_point().clone();
self.remove_one_break(probe_point.break_address(), &probe);
self.remove_one_debug(probe_point.debug_address(), &probe);
}
fn remove_one_break(&mut self, address: usize, probe: &UniProbe<L, F>) {
if let Some(list) = self.break_list.get_mut(&address) {
list.retain(|x| match x {
UniProbe::Kprobe(kprobe) => match probe {
UniProbe::Kprobe(kprobe2) => !Arc::ptr_eq(kprobe, kprobe2),
UniProbe::Uprobe(_) | UniProbe::Uretprobe(_) | UniProbe::Kretprobe(_) => true,
},
UniProbe::Kretprobe(kretprobe) => match probe {
UniProbe::Kprobe(_) | UniProbe::Uprobe(_) | UniProbe::Uretprobe(_) => true,
UniProbe::Kretprobe(kretprobe2) => !Arc::ptr_eq(kretprobe, kretprobe2),
},
UniProbe::Uprobe(uprobe) => match probe {
UniProbe::Uprobe(uprobe2) => !Arc::ptr_eq(uprobe, uprobe2),
UniProbe::Uretprobe(_) | UniProbe::Kprobe(_) | UniProbe::Kretprobe(_) => true,
},
UniProbe::Uretprobe(uretprobe) => match probe {
UniProbe::Uprobe(_) | UniProbe::Kprobe(_) | UniProbe::Kretprobe(_) => true,
UniProbe::Uretprobe(uretprobe2) => !Arc::ptr_eq(uretprobe, uretprobe2),
},
});
}
if self.break_list_len(address) == 0 {
self.break_list.remove(&address);
}
}
fn remove_one_debug(&mut self, address: usize, probe: &UniProbe<L, F>) {
if let Some(list) = self.debug_list.get_mut(&address) {
list.retain(|x| match x {
UniProbe::Kprobe(kprobe) => match &probe {
UniProbe::Kprobe(kprobe2) => !Arc::ptr_eq(kprobe, kprobe2),
UniProbe::Kretprobe(_) | UniProbe::Uprobe(_) | UniProbe::Uretprobe(_) => true,
},
UniProbe::Kretprobe(kretprobe) => match &probe {
UniProbe::Kprobe(_) | UniProbe::Uprobe(_) | UniProbe::Uretprobe(_) => true,
UniProbe::Kretprobe(kretprobe2) => !Arc::ptr_eq(kretprobe, kretprobe2),
},
UniProbe::Uprobe(uprobe) => match &probe {
UniProbe::Uprobe(uprobe2) => !Arc::ptr_eq(uprobe, uprobe2),
UniProbe::Uretprobe(_) | UniProbe::Kprobe(_) | UniProbe::Kretprobe(_) => true,
},
UniProbe::Uretprobe(uretprobe) => match &probe {
UniProbe::Uprobe(_) | UniProbe::Kprobe(_) | UniProbe::Kretprobe(_) => true,
UniProbe::Uretprobe(uretprobe2) => !Arc::ptr_eq(uretprobe, uretprobe2),
},
});
}
if self.debug_list_len(address) == 0 {
self.debug_list.remove(&address);
}
}
}
pub type ProbePointList<F> = BTreeMap<usize, Arc<ProbePoint<F>>>;