1 use super::Result;
2 use crate::arch::interrupt::TrapFrame;
3 use crate::arch::kprobe::KProbeContext;
4 use crate::bpf::helper::BPF_HELPER_FUN_SET;
5 use crate::bpf::prog::BpfProg;
6 use crate::debug::kprobe::args::KprobeInfo;
7 use crate::debug::kprobe::{register_kprobe, unregister_kprobe, LockKprobe};
8 use crate::filesystem::vfs::file::{File, PageCache};
9 use crate::filesystem::vfs::{FilePrivateData, FileSystem, IndexNode};
10 use crate::libs::casting::DowncastArc;
11 use crate::libs::spinlock::SpinLockGuard;
12 use crate::perf::util::PerfProbeArgs;
13 use crate::perf::PerfEventOps;
14 use alloc::boxed::Box;
15 use alloc::string::String;
16 use alloc::sync::Arc;
17 use alloc::vec::Vec;
18 use core::any::Any;
19 use core::fmt::Debug;
20 use kprobe::{CallBackFunc, ProbeArgs};
21 use rbpf::EbpfVmRawOwned;
22 use system_error::SystemError;
23 #[derive(Debug)]
24 pub struct KprobePerfEvent {
25 _args: PerfProbeArgs,
26 kprobe: LockKprobe,
27 }
28
29 impl Drop for KprobePerfEvent {
drop(&mut self)30 fn drop(&mut self) {
31 unregister_kprobe(self.kprobe.clone());
32 }
33 }
34
35 impl KprobePerfEvent {
do_set_bpf_prog(&self, prog_file: Arc<File>) -> Result<()>36 pub fn do_set_bpf_prog(&self, prog_file: Arc<File>) -> Result<()> {
37 let file = prog_file
38 .inode()
39 .downcast_arc::<BpfProg>()
40 .ok_or(SystemError::EINVAL)?;
41 let prog_slice = file.insns();
42 let mut vm =
43 EbpfVmRawOwned::new(Some(prog_slice.to_vec())).map_err(|_| SystemError::EINVAL)?;
44 vm.register_helper_set(BPF_HELPER_FUN_SET.get())
45 .map_err(|_| SystemError::EINVAL)?;
46 // create a callback to execute the ebpf prog
47 let callback = Box::new(KprobePerfCallBack::new(file, vm));
48 // update callback for kprobe
49 self.kprobe.write().update_event_callback(callback);
50 Ok(())
51 }
52 }
53
54 pub struct KprobePerfCallBack {
55 _bpf_prog_file: Arc<BpfProg>,
56 vm: EbpfVmRawOwned,
57 }
58
59 impl KprobePerfCallBack {
new(bpf_prog_file: Arc<BpfProg>, vm: EbpfVmRawOwned) -> Self60 fn new(bpf_prog_file: Arc<BpfProg>, vm: EbpfVmRawOwned) -> Self {
61 Self {
62 _bpf_prog_file: bpf_prog_file,
63 vm,
64 }
65 }
66 }
67
68 impl CallBackFunc for KprobePerfCallBack {
call(&self, trap_frame: &dyn ProbeArgs)69 fn call(&self, trap_frame: &dyn ProbeArgs) {
70 let trap_frame = trap_frame.as_any().downcast_ref::<TrapFrame>().unwrap();
71 let pt_regs = KProbeContext::from(trap_frame);
72 let probe_context = unsafe {
73 core::slice::from_raw_parts_mut(
74 &pt_regs as *const KProbeContext as *mut u8,
75 size_of::<KProbeContext>(),
76 )
77 };
78 let _res = self
79 .vm
80 .execute_program(probe_context)
81 .map_err(|_| SystemError::EINVAL);
82 }
83 }
84
85 impl IndexNode for KprobePerfEvent {
read_at( &self, _offset: usize, _len: usize, _buf: &mut [u8], _data: SpinLockGuard<FilePrivateData>, ) -> Result<usize>86 fn read_at(
87 &self,
88 _offset: usize,
89 _len: usize,
90 _buf: &mut [u8],
91 _data: SpinLockGuard<FilePrivateData>,
92 ) -> Result<usize> {
93 panic!("read_at not implemented for PerfEvent");
94 }
95
write_at( &self, _offset: usize, _len: usize, _buf: &[u8], _data: SpinLockGuard<FilePrivateData>, ) -> Result<usize>96 fn write_at(
97 &self,
98 _offset: usize,
99 _len: usize,
100 _buf: &[u8],
101 _data: SpinLockGuard<FilePrivateData>,
102 ) -> Result<usize> {
103 panic!("write_at not implemented for PerfEvent");
104 }
105
fs(&self) -> Arc<dyn FileSystem>106 fn fs(&self) -> Arc<dyn FileSystem> {
107 panic!("fs not implemented for PerfEvent");
108 }
109
as_any_ref(&self) -> &dyn Any110 fn as_any_ref(&self) -> &dyn Any {
111 self
112 }
113
list(&self) -> Result<Vec<String>>114 fn list(&self) -> Result<Vec<String>> {
115 Err(SystemError::ENOSYS)
116 }
117
page_cache(&self) -> Option<Arc<PageCache>>118 fn page_cache(&self) -> Option<Arc<PageCache>> {
119 None
120 }
121 }
122
123 impl PerfEventOps for KprobePerfEvent {
set_bpf_prog(&self, bpf_prog: Arc<File>) -> Result<()>124 fn set_bpf_prog(&self, bpf_prog: Arc<File>) -> Result<()> {
125 self.do_set_bpf_prog(bpf_prog)
126 }
enable(&self) -> Result<()>127 fn enable(&self) -> Result<()> {
128 self.kprobe.write().enable();
129 Ok(())
130 }
disable(&self) -> Result<()>131 fn disable(&self) -> Result<()> {
132 self.kprobe.write().disable();
133 Ok(())
134 }
135
readable(&self) -> bool136 fn readable(&self) -> bool {
137 true
138 }
139 }
140
perf_event_open_kprobe(args: PerfProbeArgs) -> KprobePerfEvent141 pub fn perf_event_open_kprobe(args: PerfProbeArgs) -> KprobePerfEvent {
142 let symbol = args.name.clone();
143 log::info!("create kprobe for symbol: {symbol}");
144 let kprobe_info = KprobeInfo {
145 pre_handler: |_| {},
146 post_handler: |_| {},
147 fault_handler: None,
148 event_callback: None,
149 symbol: Some(symbol),
150 addr: None,
151 offset: 0,
152 enable: false,
153 };
154 let kprobe = register_kprobe(kprobe_info).expect("create kprobe failed");
155 KprobePerfEvent {
156 _args: args,
157 kprobe,
158 }
159 }
160