xref: /DragonOS/kernel/crates/kprobe/src/arch/x86/mod.rs (revision fae6e9ade46a52976ad5d099643d51cc20876448)
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