1 use alloc::boxed::Box; 2 use alloc::string::String; 3 use kprobe::{CallBackFunc, KprobeBuilder, ProbeArgs}; 4 use log::warn; 5 use system_error::SystemError; 6 7 pub struct KprobeInfo { 8 pub pre_handler: fn(&dyn ProbeArgs), 9 pub post_handler: fn(&dyn ProbeArgs), 10 pub fault_handler: Option<fn(&dyn ProbeArgs)>, 11 pub event_callback: Option<Box<dyn CallBackFunc>>, 12 pub symbol: Option<String>, 13 pub addr: Option<usize>, 14 pub offset: usize, 15 pub enable: bool, 16 } 17 18 extern "C" { 19 fn addr_from_symbol(symbol: *const u8) -> usize; 20 } 21 22 impl TryFrom<KprobeInfo> for KprobeBuilder { 23 type Error = SystemError; 24 fn try_from(kprobe_info: KprobeInfo) -> Result<Self, Self::Error> { 25 // 检查参数: symbol和addr必须有一个但不能同时有 26 if kprobe_info.symbol.is_none() && kprobe_info.addr.is_none() { 27 return Err(SystemError::EINVAL); 28 } 29 if kprobe_info.symbol.is_some() && kprobe_info.addr.is_some() { 30 return Err(SystemError::EINVAL); 31 } 32 let func_addr = if let Some(symbol) = kprobe_info.symbol.clone() { 33 let mut symbol_sting = symbol; 34 if !symbol_sting.ends_with("\0") { 35 symbol_sting.push('\0'); 36 } 37 let symbol = symbol_sting.as_ptr(); 38 let func_addr = unsafe { addr_from_symbol(symbol) }; 39 if func_addr == 0 { 40 warn!( 41 "register_kprobe: the symbol: {:?} not found", 42 kprobe_info.symbol 43 ); 44 return Err(SystemError::ENXIO); 45 } 46 func_addr 47 } else { 48 kprobe_info.addr.unwrap() 49 }; 50 let mut builder = KprobeBuilder::new( 51 kprobe_info.symbol, 52 func_addr, 53 kprobe_info.offset, 54 kprobe_info.pre_handler, 55 kprobe_info.post_handler, 56 kprobe_info.enable, 57 ); 58 if let Some(fault_handler) = kprobe_info.fault_handler { 59 builder = builder.with_fault_handler(fault_handler); 60 } 61 if let Some(event_callback) = kprobe_info.event_callback { 62 builder = builder.with_event_callback(event_callback); 63 } 64 Ok(builder) 65 } 66 } 67