xref: /DragonOS/kernel/crates/kprobe/src/arch/mod.rs (revision 7b0ef10895108a0de5ff5ef3d2f93f40cf2e33a5)
1 use alloc::boxed::Box;
2 use alloc::string::String;
3 use alloc::sync::Arc;
4 use core::{any::Any, fmt::Debug};
5 
6 #[cfg(target_arch = "loongarch64")]
7 mod loongarch64;
8 #[cfg(target_arch = "riscv64")]
9 mod rv64;
10 #[cfg(target_arch = "x86_64")]
11 mod x86;
12 
13 #[cfg(target_arch = "loongarch64")]
14 pub use loongarch64::*;
15 #[cfg(target_arch = "riscv64")]
16 pub use rv64::*;
17 #[cfg(target_arch = "x86_64")]
18 pub use x86::*;
19 
20 #[cfg(target_arch = "x86_64")]
21 pub type KprobePoint = X86KprobePoint;
22 #[cfg(target_arch = "riscv64")]
23 pub type KprobePoint = Rv64KprobePoint;
24 #[cfg(target_arch = "loongarch64")]
25 pub type KprobePoint = LA64KprobePoint;
26 
27 pub trait ProbeArgs: Send {
28     /// 用于使用者转换到特定架构下的TrapFrame
29     fn as_any(&self) -> &dyn Any;
30     /// 返回导致break异常的地址
31     fn break_address(&self) -> usize;
32     /// 返回导致单步执行异常的地址
33     fn debug_address(&self) -> usize;
34 }
35 
36 pub trait KprobeOps: Send {
37     /// # 返回探测点的下一条指令地址
38     ///
39     /// 执行流需要回到正常的路径中,在执行完探测点的指令后,需要返回到下一条指令
40     fn return_address(&self) -> usize;
41     /// # 返回单步执行的指令地址
42     ///
43     /// 通常探测点的处的原指令被保存在一个数组当中。根据架构的不同, 在保存的指令后面,可能会填充必要的指令。
44     /// 例如x86架构下支持单步执行的特性, 而其它架构下通常没有,因此我们使用break异常来进行模拟,所以会填充
45     /// 一条断点指令。
46     fn single_step_address(&self) -> usize;
47     /// # 返回单步执行指令触发异常的地址
48     ///
49     /// 其值等于`single_step_address`的值加上探测点指令的长度
50     fn debug_address(&self) -> usize;
51     /// # 返回设置break断点的地址
52     ///
53     /// 其值与探测点地址相等
54     fn break_address(&self) -> usize;
55 }
56 
57 struct ProbeHandler {
58     func: fn(&dyn ProbeArgs),
59 }
60 
61 impl ProbeHandler {
62     pub fn new(func: fn(&dyn ProbeArgs)) -> Self {
63         ProbeHandler { func }
64     }
65     /// 调用探测点处理函数
66     pub fn call(&self, trap_frame: &dyn ProbeArgs) {
67         (self.func)(trap_frame);
68     }
69 }
70 
71 pub struct KprobeBuilder {
72     symbol: Option<String>,
73     symbol_addr: usize,
74     offset: usize,
75     pre_handler: ProbeHandler,
76     post_handler: ProbeHandler,
77     fault_handler: Option<ProbeHandler>,
78     event_callback: Option<Box<dyn CallBackFunc>>,
79     probe_point: Option<Arc<KprobePoint>>,
80     enable: bool,
81 }
82 
83 pub trait EventCallback: Send {
84     fn call(&self, trap_frame: &dyn ProbeArgs);
85 }
86 
87 impl KprobeBuilder {
88     pub fn new(
89         symbol: Option<String>,
90         symbol_addr: usize,
91         offset: usize,
92         pre_handler: fn(&dyn ProbeArgs),
93         post_handler: fn(&dyn ProbeArgs),
94         enable: bool,
95     ) -> Self {
96         KprobeBuilder {
97             symbol,
98             symbol_addr,
99             offset,
100             pre_handler: ProbeHandler::new(pre_handler),
101             post_handler: ProbeHandler::new(post_handler),
102             event_callback: None,
103             fault_handler: None,
104             probe_point: None,
105             enable,
106         }
107     }
108 
109     pub fn with_fault_handler(mut self, func: fn(&dyn ProbeArgs)) -> Self {
110         self.fault_handler = Some(ProbeHandler::new(func));
111         self
112     }
113 
114     pub fn with_probe_point(mut self, point: Arc<KprobePoint>) -> Self {
115         self.probe_point = Some(point);
116         self
117     }
118 
119     pub fn with_event_callback(mut self, event_callback: Box<dyn CallBackFunc>) -> Self {
120         self.event_callback = Some(event_callback);
121         self
122     }
123 
124     /// 获取探测点的地址
125     ///
126     /// 探测点的地址 == break指令的地址
127     pub fn probe_addr(&self) -> usize {
128         self.symbol_addr + self.offset
129     }
130 }
131 
132 pub struct KprobeBasic {
133     symbol: Option<String>,
134     symbol_addr: usize,
135     offset: usize,
136     pre_handler: ProbeHandler,
137     post_handler: ProbeHandler,
138     fault_handler: ProbeHandler,
139     event_callback: Option<Box<dyn CallBackFunc>>,
140     enable: bool,
141 }
142 
143 pub trait CallBackFunc: Send + Sync {
144     fn call(&self, trap_frame: &dyn ProbeArgs);
145 }
146 
147 impl Debug for KprobeBasic {
148     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
149         f.debug_struct("Kprobe")
150             .field("symbol", &self.symbol)
151             .field("symbol_addr", &self.symbol_addr)
152             .field("offset", &self.offset)
153             .finish()
154     }
155 }
156 
157 impl KprobeBasic {
158     pub fn call_pre_handler(&self, trap_frame: &dyn ProbeArgs) {
159         self.pre_handler.call(trap_frame);
160     }
161 
162     pub fn call_post_handler(&self, trap_frame: &dyn ProbeArgs) {
163         self.post_handler.call(trap_frame);
164     }
165 
166     pub fn call_fault_handler(&self, trap_frame: &dyn ProbeArgs) {
167         self.fault_handler.call(trap_frame);
168     }
169 
170     pub fn call_event_callback(&self, trap_frame: &dyn ProbeArgs) {
171         if let Some(ref call_back) = self.event_callback {
172             call_back.call(trap_frame);
173         }
174     }
175 
176     pub fn update_event_callback(&mut self, callback: Box<dyn CallBackFunc>) {
177         self.event_callback = Some(callback);
178     }
179 
180     pub fn disable(&mut self) {
181         self.enable = false;
182     }
183 
184     pub fn enable(&mut self) {
185         self.enable = true;
186     }
187 
188     pub fn is_enabled(&self) -> bool {
189         self.enable
190     }
191     /// 返回探测点的函数名称
192     pub fn symbol(&self) -> Option<&str> {
193         self.symbol.as_deref()
194     }
195 }
196 
197 impl From<KprobeBuilder> for KprobeBasic {
198     fn from(value: KprobeBuilder) -> Self {
199         let fault_handler = value.fault_handler.unwrap_or(ProbeHandler::new(|_| {}));
200         KprobeBasic {
201             symbol: value.symbol,
202             symbol_addr: value.symbol_addr,
203             offset: value.offset,
204             pre_handler: value.pre_handler,
205             post_handler: value.post_handler,
206             event_callback: value.event_callback,
207             fault_handler,
208             enable: value.enable,
209         }
210     }
211 }
212