rbpf_plugin.rs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // Copyright Microsoft Corporation
  2. // SPDX-License-Identifier: (Apache-2.0 OR MIT)
  3. // Path: examples/rbpf_plugin.rs
  4. use std::io::Read;
  5. // Helper function used by https://github.com/Alan-Jowett/bpf_conformance/blob/main/tests/call_unwind_fail.data
  6. fn _unwind(a: u64, _b: u64, _c: u64, _d: u64, _e: u64) -> u64
  7. {
  8. a
  9. }
  10. // This is a plugin for the bpf_conformance test suite (https://github.com/Alan-Jowett/bpf_conformance)
  11. // It accepts a single argument, the memory contents to pass to the VM.
  12. // It reads the program from stdin.
  13. fn main() {
  14. let mut args: Vec<String> = std::env::args().collect();
  15. let mut jit : bool = false;
  16. let mut program_text = String::new();
  17. let mut memory_text = String::new();
  18. args.remove(0);
  19. // Memory is always the first argument.
  20. if !args.is_empty() {
  21. memory_text = args[0].clone();
  22. // Strip whitespace
  23. memory_text.retain(|c| !c.is_whitespace());
  24. args.remove(0);
  25. }
  26. // Process the rest of the arguments.
  27. while !args.is_empty() {
  28. match args[0].as_str() {
  29. "--help" => {
  30. println!("Usage: rbpf_plugin [memory] < program");
  31. return;
  32. },
  33. "--jit" => {
  34. #[cfg(windows)] {
  35. println!("JIT not supported on Windows");
  36. return;
  37. }
  38. #[cfg(not(windows))] {
  39. jit = true;
  40. }
  41. },
  42. "--program" => {
  43. if args.len() < 2 {
  44. println!("Missing argument to --program");
  45. return;
  46. }
  47. args.remove(0);
  48. if !args.is_empty() {
  49. program_text = args[0].clone();
  50. args.remove(0);
  51. }
  52. },
  53. _ => panic!("Unknown argument {}", args[0]),
  54. }
  55. args.remove(0);
  56. }
  57. if program_text.is_empty() {
  58. // Read program text from stdin
  59. std::io::stdin().read_to_string(&mut program_text).unwrap();
  60. }
  61. // Strip whitespace
  62. program_text.retain(|c| !c.is_whitespace());
  63. // Convert program from hex to bytecode
  64. let bytecode = hex::decode(program_text).unwrap();
  65. // Convert memory from hex to bytes
  66. let mut memory: Vec<u8> = hex::decode(memory_text).unwrap();
  67. // Create rbpf vm
  68. let mut vm = rbpf::EbpfVmRaw::new(Some(&bytecode)).unwrap();
  69. // Register the helper function used by call_unwind_fail.data test.
  70. vm.register_helper(5, _unwind).unwrap();
  71. let result : u64;
  72. if jit {
  73. #[cfg(windows)] {
  74. println!("JIT not supported on Windows");
  75. return;
  76. }
  77. #[cfg(not(windows))] {
  78. unsafe {
  79. vm.jit_compile().unwrap();
  80. result = vm.execute_program_jit(&mut memory).unwrap();
  81. }
  82. }
  83. }
  84. else {
  85. result = vm.execute_program(&mut memory).unwrap();
  86. }
  87. println!("{result:x}");
  88. }