4
0

rbpf_plugin.rs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. #[allow(unused_mut)] // In no_std the jit variable isn't mutated.
  16. let mut jit : bool = false;
  17. let mut cranelift : bool = false;
  18. let mut program_text = String::new();
  19. let mut memory_text = String::new();
  20. args.remove(0);
  21. // Memory is always the first argument.
  22. if !args.is_empty() {
  23. memory_text = args[0].clone();
  24. // Strip whitespace
  25. memory_text.retain(|c| !c.is_whitespace());
  26. args.remove(0);
  27. }
  28. // Process the rest of the arguments.
  29. while !args.is_empty() {
  30. match args[0].as_str() {
  31. "--help" => {
  32. println!("Usage: rbpf_plugin [memory] < program");
  33. return;
  34. },
  35. "--jit" => {
  36. #[cfg(any(windows, not(feature = "std")))] {
  37. println!("JIT not supported");
  38. return;
  39. }
  40. #[cfg(all(not(windows), feature = "std"))] {
  41. jit = true;
  42. }
  43. },
  44. "--cranelift" => {
  45. cranelift = true;
  46. #[cfg(not(feature = "cranelift"))] {
  47. let _ = cranelift;
  48. println!("Cranelift is not enabled");
  49. return;
  50. }
  51. }
  52. "--program" => {
  53. if args.len() < 2 {
  54. println!("Missing argument to --program");
  55. return;
  56. }
  57. args.remove(0);
  58. if !args.is_empty() {
  59. program_text = args[0].clone();
  60. args.remove(0);
  61. }
  62. },
  63. _ => panic!("Unknown argument {}", args[0]),
  64. }
  65. args.remove(0);
  66. }
  67. if program_text.is_empty() {
  68. // Read program text from stdin
  69. std::io::stdin().read_to_string(&mut program_text).unwrap();
  70. }
  71. // Strip whitespace
  72. program_text.retain(|c| !c.is_whitespace());
  73. // Convert program from hex to bytecode
  74. let bytecode = hex::decode(program_text).unwrap();
  75. // Convert memory from hex to bytes
  76. let mut memory: Vec<u8> = hex::decode(memory_text).unwrap();
  77. // Create rbpf vm
  78. let mut vm = rbpf::EbpfVmRaw::new(Some(&bytecode)).unwrap();
  79. // Register the helper function used by call_unwind_fail.data test.
  80. vm.register_helper(5, _unwind).unwrap();
  81. let result : u64;
  82. if jit {
  83. #[cfg(any(windows, not(feature = "std")))] {
  84. println!("JIT not supported");
  85. return;
  86. }
  87. #[cfg(all(not(windows), feature = "std"))] {
  88. unsafe {
  89. vm.jit_compile().unwrap();
  90. result = vm.execute_program_jit(&mut memory).unwrap();
  91. }
  92. }
  93. } else if cranelift {
  94. #[cfg(not(feature = "cranelift"))] {
  95. println!("Cranelift is not enabled");
  96. return;
  97. }
  98. #[cfg(feature = "cranelift")] {
  99. vm.cranelift_compile().unwrap();
  100. result = vm.execute_program_cranelift(&mut memory).unwrap();
  101. }
  102. }
  103. else {
  104. result = vm.execute_program(&mut memory).unwrap();
  105. }
  106. println!("{result:x}");
  107. }