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 as_any(&self) -> &dyn Any29 fn as_any(&self) -> &dyn Any; 30 /// 返回导致break异常的地址 break_address(&self) -> usize31 fn break_address(&self) -> usize; 32 /// 返回导致单步执行异常的地址 debug_address(&self) -> usize33 fn debug_address(&self) -> usize; 34 } 35 36 pub trait KprobeOps: Send { 37 /// # 返回探测点的下一条指令地址 38 /// 39 /// 执行流需要回到正常的路径中,在执行完探测点的指令后,需要返回到下一条指令 return_address(&self) -> usize40 fn return_address(&self) -> usize; 41 /// # 返回单步执行的指令地址 42 /// 43 /// 通常探测点的处的原指令被保存在一个数组当中。根据架构的不同, 在保存的指令后面,可能会填充必要的指令。 44 /// 例如x86架构下支持单步执行的特性, 而其它架构下通常没有,因此我们使用break异常来进行模拟,所以会填充 45 /// 一条断点指令。 single_step_address(&self) -> usize46 fn single_step_address(&self) -> usize; 47 /// # 返回单步执行指令触发异常的地址 48 /// 49 /// 其值等于`single_step_address`的值加上探测点指令的长度 debug_address(&self) -> usize50 fn debug_address(&self) -> usize; 51 /// # 返回设置break断点的地址 52 /// 53 /// 其值与探测点地址相等 break_address(&self) -> usize54 fn break_address(&self) -> usize; 55 } 56 57 struct ProbeHandler { 58 func: fn(&dyn ProbeArgs), 59 } 60 61 impl ProbeHandler { new(func: fn(&dyn ProbeArgs)) -> Self62 pub fn new(func: fn(&dyn ProbeArgs)) -> Self { 63 ProbeHandler { func } 64 } 65 /// 调用探测点处理函数 call(&self, trap_frame: &dyn ProbeArgs)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 { call(&self, trap_frame: &dyn ProbeArgs)84 fn call(&self, trap_frame: &dyn ProbeArgs); 85 } 86 87 impl KprobeBuilder { new( symbol: Option<String>, symbol_addr: usize, offset: usize, pre_handler: fn(&dyn ProbeArgs), post_handler: fn(&dyn ProbeArgs), enable: bool, ) -> Self88 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 with_fault_handler(mut self, func: fn(&dyn ProbeArgs)) -> Self109 pub fn with_fault_handler(mut self, func: fn(&dyn ProbeArgs)) -> Self { 110 self.fault_handler = Some(ProbeHandler::new(func)); 111 self 112 } 113 with_probe_point(mut self, point: Arc<KprobePoint>) -> Self114 pub fn with_probe_point(mut self, point: Arc<KprobePoint>) -> Self { 115 self.probe_point = Some(point); 116 self 117 } 118 with_event_callback(mut self, event_callback: Box<dyn CallBackFunc>) -> Self119 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指令的地址 probe_addr(&self) -> usize127 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 { call(&self, trap_frame: &dyn ProbeArgs)144 fn call(&self, trap_frame: &dyn ProbeArgs); 145 } 146 147 impl Debug for KprobeBasic { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result148 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 { call_pre_handler(&self, trap_frame: &dyn ProbeArgs)158 pub fn call_pre_handler(&self, trap_frame: &dyn ProbeArgs) { 159 self.pre_handler.call(trap_frame); 160 } 161 call_post_handler(&self, trap_frame: &dyn ProbeArgs)162 pub fn call_post_handler(&self, trap_frame: &dyn ProbeArgs) { 163 self.post_handler.call(trap_frame); 164 } 165 call_fault_handler(&self, trap_frame: &dyn ProbeArgs)166 pub fn call_fault_handler(&self, trap_frame: &dyn ProbeArgs) { 167 self.fault_handler.call(trap_frame); 168 } 169 call_event_callback(&self, trap_frame: &dyn ProbeArgs)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 update_event_callback(&mut self, callback: Box<dyn CallBackFunc>)176 pub fn update_event_callback(&mut self, callback: Box<dyn CallBackFunc>) { 177 self.event_callback = Some(callback); 178 } 179 disable(&mut self)180 pub fn disable(&mut self) { 181 self.enable = false; 182 } 183 enable(&mut self)184 pub fn enable(&mut self) { 185 self.enable = true; 186 } 187 is_enabled(&self) -> bool188 pub fn is_enabled(&self) -> bool { 189 self.enable 190 } 191 /// 返回探测点的函数名称 symbol(&self) -> Option<&str>192 pub fn symbol(&self) -> Option<&str> { 193 self.symbol.as_deref() 194 } 195 } 196 197 impl From<KprobeBuilder> for KprobeBasic { from(value: KprobeBuilder) -> Self198 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