rbpf_plugin.rs 3.8 KB

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