1*fae6e9adSlinfeng use alloc::sync::Arc; 2*fae6e9adSlinfeng use core::ops::{Deref, DerefMut}; 3*fae6e9adSlinfeng 4*fae6e9adSlinfeng use crate::{KprobeBasic, KprobeBuilder, KprobeOps}; 5*fae6e9adSlinfeng 6*fae6e9adSlinfeng const BRK_KPROBE_BP: u64 = 10; 7*fae6e9adSlinfeng const BRK_KPROBE_SSTEPBP: u64 = 11; 8*fae6e9adSlinfeng const EBREAK_INST: u32 = 0x002a0000; 9*fae6e9adSlinfeng 10*fae6e9adSlinfeng #[derive(Debug)] 11*fae6e9adSlinfeng pub struct Kprobe { 12*fae6e9adSlinfeng basic: KprobeBasic, 13*fae6e9adSlinfeng point: Arc<LA64KprobePoint>, 14*fae6e9adSlinfeng } 15*fae6e9adSlinfeng #[derive(Debug)] 16*fae6e9adSlinfeng pub struct LA64KprobePoint { 17*fae6e9adSlinfeng addr: usize, 18*fae6e9adSlinfeng inst_tmp: [u8; 8], 19*fae6e9adSlinfeng } 20*fae6e9adSlinfeng 21*fae6e9adSlinfeng impl Deref for Kprobe { 22*fae6e9adSlinfeng type Target = KprobeBasic; 23*fae6e9adSlinfeng deref(&self) -> &Self::Target24*fae6e9adSlinfeng fn deref(&self) -> &Self::Target { 25*fae6e9adSlinfeng &self.basic 26*fae6e9adSlinfeng } 27*fae6e9adSlinfeng } 28*fae6e9adSlinfeng 29*fae6e9adSlinfeng impl DerefMut for Kprobe { deref_mut(&mut self) -> &mut Self::Target30*fae6e9adSlinfeng fn deref_mut(&mut self) -> &mut Self::Target { 31*fae6e9adSlinfeng &mut self.basic 32*fae6e9adSlinfeng } 33*fae6e9adSlinfeng } 34*fae6e9adSlinfeng 35*fae6e9adSlinfeng impl Kprobe { probe_point(&self) -> &Arc<LA64KprobePoint>36*fae6e9adSlinfeng pub fn probe_point(&self) -> &Arc<LA64KprobePoint> { 37*fae6e9adSlinfeng &self.point 38*fae6e9adSlinfeng } 39*fae6e9adSlinfeng } 40*fae6e9adSlinfeng 41*fae6e9adSlinfeng impl Drop for LA64KprobePoint { drop(&mut self)42*fae6e9adSlinfeng fn drop(&mut self) { 43*fae6e9adSlinfeng let address = self.addr; 44*fae6e9adSlinfeng let inst_tmp_ptr = self.inst_tmp.as_ptr() as usize; 45*fae6e9adSlinfeng let inst_32 = unsafe { core::ptr::read(inst_tmp_ptr as *const u32) }; 46*fae6e9adSlinfeng unsafe { 47*fae6e9adSlinfeng core::ptr::write(address as *mut u32, inst_32); 48*fae6e9adSlinfeng } 49*fae6e9adSlinfeng log::trace!( 50*fae6e9adSlinfeng "Kprobe::uninstall: address: {:#x}, old_instruction: {:?}", 51*fae6e9adSlinfeng address, 52*fae6e9adSlinfeng inst_32 53*fae6e9adSlinfeng ); 54*fae6e9adSlinfeng } 55*fae6e9adSlinfeng } 56*fae6e9adSlinfeng 57*fae6e9adSlinfeng impl KprobeBuilder { install(self) -> (Kprobe, Arc<LA64KprobePoint>)58*fae6e9adSlinfeng pub fn install(self) -> (Kprobe, Arc<LA64KprobePoint>) { 59*fae6e9adSlinfeng let probe_point = match &self.probe_point { 60*fae6e9adSlinfeng Some(point) => point.clone(), 61*fae6e9adSlinfeng None => self.replace_inst(), 62*fae6e9adSlinfeng }; 63*fae6e9adSlinfeng let kprobe = Kprobe { 64*fae6e9adSlinfeng basic: KprobeBasic::from(self), 65*fae6e9adSlinfeng point: probe_point.clone(), 66*fae6e9adSlinfeng }; 67*fae6e9adSlinfeng (kprobe, probe_point) 68*fae6e9adSlinfeng } 69*fae6e9adSlinfeng /// # 安装kprobe 70*fae6e9adSlinfeng /// 71*fae6e9adSlinfeng /// 不同的架构下需要保存原指令,然后替换为断点指令 replace_inst(&self) -> Arc<LA64KprobePoint>72*fae6e9adSlinfeng fn replace_inst(&self) -> Arc<LA64KprobePoint> { 73*fae6e9adSlinfeng let address = self.symbol_addr + self.offset; 74*fae6e9adSlinfeng let point = LA64KprobePoint { 75*fae6e9adSlinfeng addr: address, 76*fae6e9adSlinfeng inst_tmp: [0u8; 8], 77*fae6e9adSlinfeng }; 78*fae6e9adSlinfeng let inst_tmp_ptr = point.inst_tmp.as_ptr() as usize; 79*fae6e9adSlinfeng let inst_32 = unsafe { core::ptr::read(address as *const u32) }; 80*fae6e9adSlinfeng unsafe { 81*fae6e9adSlinfeng core::ptr::write(address as *mut u32, EBREAK_INST); 82*fae6e9adSlinfeng // inst_32 :0-32 83*fae6e9adSlinfeng // ebreak :32-64 84*fae6e9adSlinfeng core::ptr::write(inst_tmp_ptr as *mut u32, inst_32); 85*fae6e9adSlinfeng core::ptr::write((inst_tmp_ptr + 4) as *mut u32, EBREAK_INST); 86*fae6e9adSlinfeng } 87*fae6e9adSlinfeng log::trace!( 88*fae6e9adSlinfeng "Kprobe::install: address: {:#x}, func_name: {:?}, opcode: {:x?}", 89*fae6e9adSlinfeng address, 90*fae6e9adSlinfeng self.symbol, 91*fae6e9adSlinfeng inst_32 92*fae6e9adSlinfeng ); 93*fae6e9adSlinfeng } 94*fae6e9adSlinfeng } 95*fae6e9adSlinfeng 96*fae6e9adSlinfeng impl KprobeOps for LA64KprobePoint { return_address(&self) -> usize97*fae6e9adSlinfeng fn return_address(&self) -> usize { 98*fae6e9adSlinfeng self.addr + 4 99*fae6e9adSlinfeng } 100*fae6e9adSlinfeng single_step_address(&self) -> usize101*fae6e9adSlinfeng fn single_step_address(&self) -> usize { 102*fae6e9adSlinfeng self.inst_tmp.as_ptr() as usize 103*fae6e9adSlinfeng } 104*fae6e9adSlinfeng debug_address(&self) -> usize105*fae6e9adSlinfeng fn debug_address(&self) -> usize { 106*fae6e9adSlinfeng self.inst_tmp.as_ptr() as usize + 4 107*fae6e9adSlinfeng } 108*fae6e9adSlinfeng break_address(&self) -> usize109*fae6e9adSlinfeng fn break_address(&self) -> usize { 110*fae6e9adSlinfeng self.addr 111*fae6e9adSlinfeng } 112*fae6e9adSlinfeng } 113