xref: /DragonOS/kernel/crates/rbpf/examples/rbpf_plugin.rs (revision fae6e9ade46a52976ad5d099643d51cc20876448)
1*fae6e9adSlinfeng // Copyright Microsoft Corporation
2*fae6e9adSlinfeng // SPDX-License-Identifier: (Apache-2.0 OR MIT)
3*fae6e9adSlinfeng 
4*fae6e9adSlinfeng // Path: examples/rbpf_plugin.rs
5*fae6e9adSlinfeng use std::io::Read;
6*fae6e9adSlinfeng 
7*fae6e9adSlinfeng // Helper function used by https://github.com/Alan-Jowett/bpf_conformance/blob/main/tests/call_unwind_fail.data
_unwind(a: u64, _b: u64, _c: u64, _d: u64, _e: u64) -> u648*fae6e9adSlinfeng fn _unwind(a: u64, _b: u64, _c: u64, _d: u64, _e: u64) -> u64 {
9*fae6e9adSlinfeng     a
10*fae6e9adSlinfeng }
11*fae6e9adSlinfeng 
12*fae6e9adSlinfeng // This is a plugin for the bpf_conformance test suite (https://github.com/Alan-Jowett/bpf_conformance)
13*fae6e9adSlinfeng // It accepts a single argument, the memory contents to pass to the VM.
14*fae6e9adSlinfeng // It reads the program from stdin.
main()15*fae6e9adSlinfeng fn main() {
16*fae6e9adSlinfeng     let mut args: Vec<String> = std::env::args().collect();
17*fae6e9adSlinfeng     #[allow(unused_mut)] // In no_std the jit variable isn't mutated.
18*fae6e9adSlinfeng     let mut jit: bool = false;
19*fae6e9adSlinfeng     let mut cranelift: bool = false;
20*fae6e9adSlinfeng     let mut program_text = String::new();
21*fae6e9adSlinfeng     let mut memory_text = String::new();
22*fae6e9adSlinfeng 
23*fae6e9adSlinfeng     args.remove(0);
24*fae6e9adSlinfeng 
25*fae6e9adSlinfeng     // Memory is always the first argument.
26*fae6e9adSlinfeng     if !args.is_empty() {
27*fae6e9adSlinfeng         memory_text.clone_from(&args[0]);
28*fae6e9adSlinfeng         // Strip whitespace
29*fae6e9adSlinfeng         memory_text.retain(|c| !c.is_whitespace());
30*fae6e9adSlinfeng         args.remove(0);
31*fae6e9adSlinfeng     }
32*fae6e9adSlinfeng 
33*fae6e9adSlinfeng     // Process the rest of the arguments.
34*fae6e9adSlinfeng     while !args.is_empty() {
35*fae6e9adSlinfeng         match args[0].as_str() {
36*fae6e9adSlinfeng             "--help" => {
37*fae6e9adSlinfeng                 println!("Usage: rbpf_plugin [memory] < program");
38*fae6e9adSlinfeng                 return;
39*fae6e9adSlinfeng             }
40*fae6e9adSlinfeng             "--jit" => {
41*fae6e9adSlinfeng                 #[cfg(any(windows, not(feature = "std")))]
42*fae6e9adSlinfeng                 {
43*fae6e9adSlinfeng                     println!("JIT not supported");
44*fae6e9adSlinfeng                     return;
45*fae6e9adSlinfeng                 }
46*fae6e9adSlinfeng                 #[cfg(all(not(windows), feature = "std"))]
47*fae6e9adSlinfeng                 {
48*fae6e9adSlinfeng                     jit = true;
49*fae6e9adSlinfeng                 }
50*fae6e9adSlinfeng             }
51*fae6e9adSlinfeng             "--cranelift" => {
52*fae6e9adSlinfeng                 cranelift = true;
53*fae6e9adSlinfeng 
54*fae6e9adSlinfeng                 #[cfg(not(feature = "cranelift"))]
55*fae6e9adSlinfeng                 {
56*fae6e9adSlinfeng                     let _ = cranelift;
57*fae6e9adSlinfeng                     println!("Cranelift is not enabled");
58*fae6e9adSlinfeng                     return;
59*fae6e9adSlinfeng                 }
60*fae6e9adSlinfeng             }
61*fae6e9adSlinfeng             "--program" => {
62*fae6e9adSlinfeng                 if args.len() < 2 {
63*fae6e9adSlinfeng                     println!("Missing argument to --program");
64*fae6e9adSlinfeng                     return;
65*fae6e9adSlinfeng                 }
66*fae6e9adSlinfeng                 args.remove(0);
67*fae6e9adSlinfeng                 if !args.is_empty() {
68*fae6e9adSlinfeng                     program_text.clone_from(&args[0]);
69*fae6e9adSlinfeng                     args.remove(0);
70*fae6e9adSlinfeng                 }
71*fae6e9adSlinfeng             }
72*fae6e9adSlinfeng             _ => panic!("Unknown argument {}", args[0]),
73*fae6e9adSlinfeng         }
74*fae6e9adSlinfeng         args.remove(0);
75*fae6e9adSlinfeng     }
76*fae6e9adSlinfeng 
77*fae6e9adSlinfeng     if program_text.is_empty() {
78*fae6e9adSlinfeng         // Read program text from stdin
79*fae6e9adSlinfeng         std::io::stdin().read_to_string(&mut program_text).unwrap();
80*fae6e9adSlinfeng     }
81*fae6e9adSlinfeng 
82*fae6e9adSlinfeng     // Strip whitespace
83*fae6e9adSlinfeng     program_text.retain(|c| !c.is_whitespace());
84*fae6e9adSlinfeng 
85*fae6e9adSlinfeng     // Convert program from hex to bytecode
86*fae6e9adSlinfeng     let bytecode = hex::decode(program_text).unwrap();
87*fae6e9adSlinfeng 
88*fae6e9adSlinfeng     // Convert memory from hex to bytes
89*fae6e9adSlinfeng     let mut memory: Vec<u8> = hex::decode(memory_text).unwrap();
90*fae6e9adSlinfeng 
91*fae6e9adSlinfeng     // Create rbpf vm
92*fae6e9adSlinfeng     let mut vm = rbpf::EbpfVmRaw::new(Some(&bytecode)).unwrap();
93*fae6e9adSlinfeng 
94*fae6e9adSlinfeng     // Register the helper function used by call_unwind_fail.data test.
95*fae6e9adSlinfeng     vm.register_helper(5, _unwind).unwrap();
96*fae6e9adSlinfeng 
97*fae6e9adSlinfeng     let result: u64;
98*fae6e9adSlinfeng     if jit {
99*fae6e9adSlinfeng         #[cfg(any(windows, not(feature = "std")))]
100*fae6e9adSlinfeng         {
101*fae6e9adSlinfeng             println!("JIT not supported");
102*fae6e9adSlinfeng             return;
103*fae6e9adSlinfeng         }
104*fae6e9adSlinfeng         #[cfg(all(not(windows), feature = "std"))]
105*fae6e9adSlinfeng         {
106*fae6e9adSlinfeng             unsafe {
107*fae6e9adSlinfeng                 vm.jit_compile().unwrap();
108*fae6e9adSlinfeng                 result = vm.execute_program_jit(&mut memory).unwrap();
109*fae6e9adSlinfeng             }
110*fae6e9adSlinfeng         }
111*fae6e9adSlinfeng     } else if cranelift {
112*fae6e9adSlinfeng         #[cfg(not(feature = "cranelift"))]
113*fae6e9adSlinfeng         {
114*fae6e9adSlinfeng             println!("Cranelift is not enabled");
115*fae6e9adSlinfeng             return;
116*fae6e9adSlinfeng         }
117*fae6e9adSlinfeng         #[cfg(feature = "cranelift")]
118*fae6e9adSlinfeng         {
119*fae6e9adSlinfeng             vm.cranelift_compile().unwrap();
120*fae6e9adSlinfeng             result = vm.execute_program_cranelift(&mut memory).unwrap();
121*fae6e9adSlinfeng         }
122*fae6e9adSlinfeng     } else {
123*fae6e9adSlinfeng         result = vm.execute_program(&mut memory).unwrap();
124*fae6e9adSlinfeng     }
125*fae6e9adSlinfeng     println!("{result:x}");
126*fae6e9adSlinfeng }
127