xref: /DragonOS/kernel/src/debug/kprobe/mod.rs (revision fae6e9ade46a52976ad5d099643d51cc20876448)
1*fae6e9adSlinfeng use crate::debug::kprobe::args::KprobeInfo;
2*fae6e9adSlinfeng use crate::libs::rwlock::RwLock;
3*fae6e9adSlinfeng use crate::libs::spinlock::SpinLock;
4*fae6e9adSlinfeng use alloc::collections::BTreeMap;
5*fae6e9adSlinfeng use alloc::sync::Arc;
6*fae6e9adSlinfeng use alloc::vec::Vec;
7*fae6e9adSlinfeng use kprobe::{Kprobe, KprobeBuilder, KprobeOps, KprobePoint};
8*fae6e9adSlinfeng use system_error::SystemError;
9*fae6e9adSlinfeng 
10*fae6e9adSlinfeng pub mod args;
11*fae6e9adSlinfeng #[cfg(feature = "kprobe_test")]
12*fae6e9adSlinfeng mod test;
13*fae6e9adSlinfeng 
14*fae6e9adSlinfeng pub type LockKprobe = Arc<RwLock<Kprobe>>;
15*fae6e9adSlinfeng pub static KPROBE_MANAGER: SpinLock<KprobeManager> = SpinLock::new(KprobeManager::new());
16*fae6e9adSlinfeng static KPROBE_POINT_LIST: SpinLock<BTreeMap<usize, Arc<KprobePoint>>> =
17*fae6e9adSlinfeng     SpinLock::new(BTreeMap::new());
18*fae6e9adSlinfeng 
19*fae6e9adSlinfeng /// 管理所有的kprobe探测点
20*fae6e9adSlinfeng #[derive(Debug, Default)]
21*fae6e9adSlinfeng pub struct KprobeManager {
22*fae6e9adSlinfeng     break_list: BTreeMap<usize, Vec<LockKprobe>>,
23*fae6e9adSlinfeng     debug_list: BTreeMap<usize, Vec<LockKprobe>>,
24*fae6e9adSlinfeng }
25*fae6e9adSlinfeng 
26*fae6e9adSlinfeng impl KprobeManager {
new() -> Self27*fae6e9adSlinfeng     pub const fn new() -> Self {
28*fae6e9adSlinfeng         KprobeManager {
29*fae6e9adSlinfeng             break_list: BTreeMap::new(),
30*fae6e9adSlinfeng             debug_list: BTreeMap::new(),
31*fae6e9adSlinfeng         }
32*fae6e9adSlinfeng     }
33*fae6e9adSlinfeng     /// # 插入一个kprobe
34*fae6e9adSlinfeng     ///
35*fae6e9adSlinfeng     /// ## 参数
36*fae6e9adSlinfeng     /// - `kprobe`: kprobe的实例
insert_kprobe(&mut self, kprobe: LockKprobe)37*fae6e9adSlinfeng     pub fn insert_kprobe(&mut self, kprobe: LockKprobe) {
38*fae6e9adSlinfeng         let probe_point = kprobe.read().probe_point().clone();
39*fae6e9adSlinfeng         self.insert_break_point(probe_point.break_address(), kprobe.clone());
40*fae6e9adSlinfeng         self.insert_debug_point(probe_point.debug_address(), kprobe);
41*fae6e9adSlinfeng     }
42*fae6e9adSlinfeng 
43*fae6e9adSlinfeng     /// # 向break_list中插入一个kprobe
44*fae6e9adSlinfeng     ///
45*fae6e9adSlinfeng     /// ## 参数
46*fae6e9adSlinfeng     /// - `address`: kprobe的地址, 由`KprobePoint::break_address()`或者`KprobeBuilder::probe_addr()`返回
47*fae6e9adSlinfeng     /// - `kprobe`: kprobe的实例
insert_break_point(&mut self, address: usize, kprobe: LockKprobe)48*fae6e9adSlinfeng     fn insert_break_point(&mut self, address: usize, kprobe: LockKprobe) {
49*fae6e9adSlinfeng         let list = self.break_list.entry(address).or_default();
50*fae6e9adSlinfeng         list.push(kprobe);
51*fae6e9adSlinfeng     }
52*fae6e9adSlinfeng 
53*fae6e9adSlinfeng     /// # 向debug_list中插入一个kprobe
54*fae6e9adSlinfeng     ///
55*fae6e9adSlinfeng     /// ## 参数
56*fae6e9adSlinfeng     /// - `address`: kprobe的单步执行地址,由`KprobePoint::debug_address()`返回
57*fae6e9adSlinfeng     /// - `kprobe`: kprobe的实例
insert_debug_point(&mut self, address: usize, kprobe: LockKprobe)58*fae6e9adSlinfeng     fn insert_debug_point(&mut self, address: usize, kprobe: LockKprobe) {
59*fae6e9adSlinfeng         let list = self.debug_list.entry(address).or_default();
60*fae6e9adSlinfeng         list.push(kprobe);
61*fae6e9adSlinfeng     }
62*fae6e9adSlinfeng 
get_break_list(&self, address: usize) -> Option<&Vec<LockKprobe>>63*fae6e9adSlinfeng     pub fn get_break_list(&self, address: usize) -> Option<&Vec<LockKprobe>> {
64*fae6e9adSlinfeng         self.break_list.get(&address)
65*fae6e9adSlinfeng     }
66*fae6e9adSlinfeng 
get_debug_list(&self, address: usize) -> Option<&Vec<LockKprobe>>67*fae6e9adSlinfeng     pub fn get_debug_list(&self, address: usize) -> Option<&Vec<LockKprobe>> {
68*fae6e9adSlinfeng         self.debug_list.get(&address)
69*fae6e9adSlinfeng     }
70*fae6e9adSlinfeng 
71*fae6e9adSlinfeng     /// # 返回一个地址上注册的kprobe数量
72*fae6e9adSlinfeng     ///
73*fae6e9adSlinfeng     /// ## 参数
74*fae6e9adSlinfeng     /// - `address`: kprobe的地址, 由`KprobePoint::break_address()`或者`KprobeBuilder::probe_addr()`返回
kprobe_num(&self, address: usize) -> usize75*fae6e9adSlinfeng     pub fn kprobe_num(&self, address: usize) -> usize {
76*fae6e9adSlinfeng         self.break_list_len(address)
77*fae6e9adSlinfeng     }
78*fae6e9adSlinfeng 
79*fae6e9adSlinfeng     #[inline]
break_list_len(&self, address: usize) -> usize80*fae6e9adSlinfeng     fn break_list_len(&self, address: usize) -> usize {
81*fae6e9adSlinfeng         self.break_list
82*fae6e9adSlinfeng             .get(&address)
83*fae6e9adSlinfeng             .map(|list| list.len())
84*fae6e9adSlinfeng             .unwrap_or(0)
85*fae6e9adSlinfeng     }
86*fae6e9adSlinfeng     #[inline]
debug_list_len(&self, address: usize) -> usize87*fae6e9adSlinfeng     fn debug_list_len(&self, address: usize) -> usize {
88*fae6e9adSlinfeng         self.debug_list
89*fae6e9adSlinfeng             .get(&address)
90*fae6e9adSlinfeng             .map(|list| list.len())
91*fae6e9adSlinfeng             .unwrap_or(0)
92*fae6e9adSlinfeng     }
93*fae6e9adSlinfeng 
94*fae6e9adSlinfeng     /// # 移除一个kprobe
95*fae6e9adSlinfeng     ///
96*fae6e9adSlinfeng     /// ## 参数
97*fae6e9adSlinfeng     /// - `kprobe`: kprobe的实例
remove_kprobe(&mut self, kprobe: &LockKprobe)98*fae6e9adSlinfeng     pub fn remove_kprobe(&mut self, kprobe: &LockKprobe) {
99*fae6e9adSlinfeng         let probe_point = kprobe.read().probe_point().clone();
100*fae6e9adSlinfeng         self.remove_one_break(probe_point.break_address(), kprobe);
101*fae6e9adSlinfeng         self.remove_one_debug(probe_point.debug_address(), kprobe);
102*fae6e9adSlinfeng     }
103*fae6e9adSlinfeng 
104*fae6e9adSlinfeng     /// # 从break_list中移除一个kprobe
105*fae6e9adSlinfeng     ///
106*fae6e9adSlinfeng     /// 如果没有其他kprobe注册在这个地址上,则删除列表
107*fae6e9adSlinfeng     ///
108*fae6e9adSlinfeng     /// ## 参数
109*fae6e9adSlinfeng     /// - `address`: kprobe的地址, 由`KprobePoint::break_address()`或者`KprobeBuilder::probe_addr()`返回
110*fae6e9adSlinfeng     /// - `kprobe`: kprobe的实例
remove_one_break(&mut self, address: usize, kprobe: &LockKprobe)111*fae6e9adSlinfeng     fn remove_one_break(&mut self, address: usize, kprobe: &LockKprobe) {
112*fae6e9adSlinfeng         if let Some(list) = self.break_list.get_mut(&address) {
113*fae6e9adSlinfeng             list.retain(|x| !Arc::ptr_eq(x, kprobe));
114*fae6e9adSlinfeng         }
115*fae6e9adSlinfeng         if self.break_list_len(address) == 0 {
116*fae6e9adSlinfeng             self.break_list.remove(&address);
117*fae6e9adSlinfeng         }
118*fae6e9adSlinfeng     }
119*fae6e9adSlinfeng 
120*fae6e9adSlinfeng     /// # 从debug_list中移除一个kprobe
121*fae6e9adSlinfeng     ///
122*fae6e9adSlinfeng     /// 如果没有其他kprobe注册在这个地址上,则删除列表
123*fae6e9adSlinfeng     ///
124*fae6e9adSlinfeng     /// ## 参数
125*fae6e9adSlinfeng     /// - `address`: kprobe的单步执行地址,由`KprobePoint::debug_address()`返回
126*fae6e9adSlinfeng     /// - `kprobe`: kprobe的实例
remove_one_debug(&mut self, address: usize, kprobe: &LockKprobe)127*fae6e9adSlinfeng     fn remove_one_debug(&mut self, address: usize, kprobe: &LockKprobe) {
128*fae6e9adSlinfeng         if let Some(list) = self.debug_list.get_mut(&address) {
129*fae6e9adSlinfeng             list.retain(|x| !Arc::ptr_eq(x, kprobe));
130*fae6e9adSlinfeng         }
131*fae6e9adSlinfeng         if self.debug_list_len(address) == 0 {
132*fae6e9adSlinfeng             self.debug_list.remove(&address);
133*fae6e9adSlinfeng         }
134*fae6e9adSlinfeng     }
135*fae6e9adSlinfeng }
136*fae6e9adSlinfeng 
137*fae6e9adSlinfeng #[cfg(feature = "kprobe_test")]
138*fae6e9adSlinfeng #[allow(unused)]
139*fae6e9adSlinfeng /// This function is only used for testing kprobe
kprobe_test()140*fae6e9adSlinfeng pub fn kprobe_test() {
141*fae6e9adSlinfeng     test::kprobe_test();
142*fae6e9adSlinfeng }
143*fae6e9adSlinfeng 
144*fae6e9adSlinfeng /// # 注册一个kprobe
145*fae6e9adSlinfeng ///
146*fae6e9adSlinfeng /// 该函数会根据`symbol`查找对应的函数地址,如果找不到则返回错误。
147*fae6e9adSlinfeng ///
148*fae6e9adSlinfeng /// ## 参数
149*fae6e9adSlinfeng /// - `kprobe_info`: kprobe的信息
register_kprobe(kprobe_info: KprobeInfo) -> Result<LockKprobe, SystemError>150*fae6e9adSlinfeng pub fn register_kprobe(kprobe_info: KprobeInfo) -> Result<LockKprobe, SystemError> {
151*fae6e9adSlinfeng     let kprobe_builder = KprobeBuilder::try_from(kprobe_info)?;
152*fae6e9adSlinfeng     let address = kprobe_builder.probe_addr();
153*fae6e9adSlinfeng     let existed_point = KPROBE_POINT_LIST.lock().get(&address).map(Clone::clone);
154*fae6e9adSlinfeng     let kprobe = match existed_point {
155*fae6e9adSlinfeng         Some(existed_point) => {
156*fae6e9adSlinfeng             kprobe_builder
157*fae6e9adSlinfeng                 .with_probe_point(existed_point.clone())
158*fae6e9adSlinfeng                 .install()
159*fae6e9adSlinfeng                 .0
160*fae6e9adSlinfeng         }
161*fae6e9adSlinfeng         None => {
162*fae6e9adSlinfeng             let (kprobe, probe_point) = kprobe_builder.install();
163*fae6e9adSlinfeng             KPROBE_POINT_LIST.lock().insert(address, probe_point);
164*fae6e9adSlinfeng             kprobe
165*fae6e9adSlinfeng         }
166*fae6e9adSlinfeng     };
167*fae6e9adSlinfeng     let kprobe = Arc::new(RwLock::new(kprobe));
168*fae6e9adSlinfeng     KPROBE_MANAGER.lock().insert_kprobe(kprobe.clone());
169*fae6e9adSlinfeng     Ok(kprobe)
170*fae6e9adSlinfeng }
171*fae6e9adSlinfeng 
172*fae6e9adSlinfeng /// # 注销一个kprobe
173*fae6e9adSlinfeng ///
174*fae6e9adSlinfeng /// ## 参数
175*fae6e9adSlinfeng /// - `kprobe`: 已安装的kprobe
unregister_kprobe(kprobe: LockKprobe)176*fae6e9adSlinfeng pub fn unregister_kprobe(kprobe: LockKprobe) {
177*fae6e9adSlinfeng     let kprobe_addr = kprobe.read().probe_point().break_address();
178*fae6e9adSlinfeng     KPROBE_MANAGER.lock().remove_kprobe(&kprobe);
179*fae6e9adSlinfeng     // 如果没有其他kprobe注册在这个地址上,则删除探测点
180*fae6e9adSlinfeng     if KPROBE_MANAGER.lock().kprobe_num(kprobe_addr) == 0 {
181*fae6e9adSlinfeng         KPROBE_POINT_LIST.lock().remove(&kprobe_addr);
182*fae6e9adSlinfeng     }
183*fae6e9adSlinfeng }
184