1*fae6e9adSlinfeng use crate::{KprobeBasic, KprobeBuilder, KprobeOps}; 2*fae6e9adSlinfeng use alloc::string::ToString; 3*fae6e9adSlinfeng use alloc::sync::Arc; 4*fae6e9adSlinfeng use core::{ 5*fae6e9adSlinfeng fmt::Debug, 6*fae6e9adSlinfeng ops::{Deref, DerefMut}, 7*fae6e9adSlinfeng }; 8*fae6e9adSlinfeng use yaxpeax_arch::LengthedInstruction; 9*fae6e9adSlinfeng 10*fae6e9adSlinfeng const EBREAK_INST: u8 = 0xcc; // x86_64: 0xcc 11*fae6e9adSlinfeng const MAX_INSTRUCTION_SIZE: usize = 15; // x86_64 max instruction length 12*fae6e9adSlinfeng 13*fae6e9adSlinfeng pub struct Kprobe { 14*fae6e9adSlinfeng basic: KprobeBasic, 15*fae6e9adSlinfeng point: Arc<X86KprobePoint>, 16*fae6e9adSlinfeng } 17*fae6e9adSlinfeng 18*fae6e9adSlinfeng #[derive(Debug)] 19*fae6e9adSlinfeng pub struct X86KprobePoint { 20*fae6e9adSlinfeng addr: usize, 21*fae6e9adSlinfeng old_instruction: [u8; MAX_INSTRUCTION_SIZE], 22*fae6e9adSlinfeng old_instruction_len: usize, 23*fae6e9adSlinfeng } 24*fae6e9adSlinfeng 25*fae6e9adSlinfeng impl Drop for X86KprobePoint { drop(&mut self)26*fae6e9adSlinfeng fn drop(&mut self) { 27*fae6e9adSlinfeng let address = self.addr; 28*fae6e9adSlinfeng unsafe { 29*fae6e9adSlinfeng core::ptr::copy( 30*fae6e9adSlinfeng self.old_instruction.as_ptr(), 31*fae6e9adSlinfeng address as *mut u8, 32*fae6e9adSlinfeng self.old_instruction_len, 33*fae6e9adSlinfeng ); 34*fae6e9adSlinfeng core::arch::x86_64::_mm_mfence(); 35*fae6e9adSlinfeng } 36*fae6e9adSlinfeng let decoder = yaxpeax_x86::amd64::InstDecoder::default(); 37*fae6e9adSlinfeng let inst = decoder.decode_slice(&self.old_instruction).unwrap(); 38*fae6e9adSlinfeng log::trace!( 39*fae6e9adSlinfeng "Kprobe::uninstall: address: {:#x}, old_instruction: {:?}", 40*fae6e9adSlinfeng address, 41*fae6e9adSlinfeng inst.to_string() 42*fae6e9adSlinfeng ); 43*fae6e9adSlinfeng } 44*fae6e9adSlinfeng } 45*fae6e9adSlinfeng 46*fae6e9adSlinfeng impl Debug for Kprobe { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result47*fae6e9adSlinfeng fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 48*fae6e9adSlinfeng f.debug_struct("Kprobe") 49*fae6e9adSlinfeng .field("basic", &self.basic) 50*fae6e9adSlinfeng .field("point", &self.point) 51*fae6e9adSlinfeng .finish() 52*fae6e9adSlinfeng } 53*fae6e9adSlinfeng } 54*fae6e9adSlinfeng 55*fae6e9adSlinfeng impl Deref for Kprobe { 56*fae6e9adSlinfeng type Target = KprobeBasic; 57*fae6e9adSlinfeng deref(&self) -> &Self::Target58*fae6e9adSlinfeng fn deref(&self) -> &Self::Target { 59*fae6e9adSlinfeng &self.basic 60*fae6e9adSlinfeng } 61*fae6e9adSlinfeng } 62*fae6e9adSlinfeng 63*fae6e9adSlinfeng impl DerefMut for Kprobe { deref_mut(&mut self) -> &mut Self::Target64*fae6e9adSlinfeng fn deref_mut(&mut self) -> &mut Self::Target { 65*fae6e9adSlinfeng &mut self.basic 66*fae6e9adSlinfeng } 67*fae6e9adSlinfeng } 68*fae6e9adSlinfeng 69*fae6e9adSlinfeng impl KprobeBuilder { install(self) -> (Kprobe, Arc<X86KprobePoint>)70*fae6e9adSlinfeng pub fn install(self) -> (Kprobe, Arc<X86KprobePoint>) { 71*fae6e9adSlinfeng let probe_point = match &self.probe_point { 72*fae6e9adSlinfeng Some(point) => point.clone(), 73*fae6e9adSlinfeng None => self.replace_inst(), 74*fae6e9adSlinfeng }; 75*fae6e9adSlinfeng let kprobe = Kprobe { 76*fae6e9adSlinfeng basic: KprobeBasic::from(self), 77*fae6e9adSlinfeng point: probe_point.clone(), 78*fae6e9adSlinfeng }; 79*fae6e9adSlinfeng (kprobe, probe_point) 80*fae6e9adSlinfeng } 81*fae6e9adSlinfeng /// # 安装kprobe 82*fae6e9adSlinfeng /// 83*fae6e9adSlinfeng /// 不同的架构下需要保存原指令,然后替换为断点指令 replace_inst(&self) -> Arc<X86KprobePoint>84*fae6e9adSlinfeng fn replace_inst(&self) -> Arc<X86KprobePoint> { 85*fae6e9adSlinfeng let address = self.symbol_addr + self.offset; 86*fae6e9adSlinfeng let mut inst_tmp = [0u8; MAX_INSTRUCTION_SIZE]; 87*fae6e9adSlinfeng unsafe { 88*fae6e9adSlinfeng core::ptr::copy( 89*fae6e9adSlinfeng address as *const u8, 90*fae6e9adSlinfeng inst_tmp.as_mut_ptr(), 91*fae6e9adSlinfeng MAX_INSTRUCTION_SIZE, 92*fae6e9adSlinfeng ); 93*fae6e9adSlinfeng } 94*fae6e9adSlinfeng let decoder = yaxpeax_x86::amd64::InstDecoder::default(); 95*fae6e9adSlinfeng let inst = decoder.decode_slice(&inst_tmp).unwrap(); 96*fae6e9adSlinfeng let len = inst.len().to_const(); 97*fae6e9adSlinfeng log::trace!("inst: {:?}, len: {:?}", inst.to_string(), len); 98*fae6e9adSlinfeng let point = Arc::new(X86KprobePoint { 99*fae6e9adSlinfeng addr: address, 100*fae6e9adSlinfeng old_instruction: inst_tmp, 101*fae6e9adSlinfeng old_instruction_len: len as usize, 102*fae6e9adSlinfeng }); 103*fae6e9adSlinfeng unsafe { 104*fae6e9adSlinfeng core::ptr::write_volatile(address as *mut u8, EBREAK_INST); 105*fae6e9adSlinfeng core::arch::x86_64::_mm_mfence(); 106*fae6e9adSlinfeng } 107*fae6e9adSlinfeng log::trace!( 108*fae6e9adSlinfeng "Kprobe::install: address: {:#x}, func_name: {:?}", 109*fae6e9adSlinfeng address, 110*fae6e9adSlinfeng self.symbol 111*fae6e9adSlinfeng ); 112*fae6e9adSlinfeng point 113*fae6e9adSlinfeng } 114*fae6e9adSlinfeng } 115*fae6e9adSlinfeng 116*fae6e9adSlinfeng impl Kprobe { probe_point(&self) -> &Arc<X86KprobePoint>117*fae6e9adSlinfeng pub fn probe_point(&self) -> &Arc<X86KprobePoint> { 118*fae6e9adSlinfeng &self.point 119*fae6e9adSlinfeng } 120*fae6e9adSlinfeng } 121*fae6e9adSlinfeng 122*fae6e9adSlinfeng impl KprobeOps for X86KprobePoint { return_address(&self) -> usize123*fae6e9adSlinfeng fn return_address(&self) -> usize { 124*fae6e9adSlinfeng self.addr + self.old_instruction_len 125*fae6e9adSlinfeng } single_step_address(&self) -> usize126*fae6e9adSlinfeng fn single_step_address(&self) -> usize { 127*fae6e9adSlinfeng self.old_instruction.as_ptr() as usize 128*fae6e9adSlinfeng } debug_address(&self) -> usize129*fae6e9adSlinfeng fn debug_address(&self) -> usize { 130*fae6e9adSlinfeng self.old_instruction.as_ptr() as usize + self.old_instruction_len 131*fae6e9adSlinfeng } break_address(&self) -> usize132*fae6e9adSlinfeng fn break_address(&self) -> usize { 133*fae6e9adSlinfeng self.addr 134*fae6e9adSlinfeng } 135*fae6e9adSlinfeng } 136