rbpf_plugin.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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 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 = args[0].clone();
  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. println!("JIT not supported");
  37. return;
  38. }
  39. #[cfg(all(not(windows), feature = "std"))] {
  40. jit = true;
  41. }
  42. },
  43. "--cranelift" => {
  44. cranelift = true;
  45. #[cfg(not(feature = "cranelift"))] {
  46. let _ = cranelift;
  47. println!("Cranelift is not enabled");
  48. return;
  49. }
  50. }
  51. "--program" => {
  52. if args.len() < 2 {
  53. println!("Missing argument to --program");
  54. return;
  55. }
  56. args.remove(0);
  57. if !args.is_empty() {
  58. program_text = args[0].clone();
  59. args.remove(0);
  60. }
  61. },
  62. _ => panic!("Unknown argument {}", args[0]),
  63. }
  64. args.remove(0);
  65. }
  66. if program_text.is_empty() {
  67. // Read program text from stdin
  68. std::io::stdin().read_to_string(&mut program_text).unwrap();
  69. }
  70. // Strip whitespace
  71. program_text.retain(|c| !c.is_whitespace());
  72. // Convert program from hex to bytecode
  73. let bytecode = hex::decode(program_text).unwrap();
  74. // Convert memory from hex to bytes
  75. let mut memory: Vec<u8> = hex::decode(memory_text).unwrap();
  76. // Create rbpf vm
  77. let mut vm = rbpf::EbpfVmRaw::new(Some(&bytecode)).unwrap();
  78. // Register the helper function used by call_unwind_fail.data test.
  79. vm.register_helper(5, _unwind).unwrap();
  80. let result : u64;
  81. if jit {
  82. #[cfg(any(windows, not(feature = "std")))] {
  83. println!("JIT not supported");
  84. return;
  85. }
  86. #[cfg(all(not(windows), feature = "std"))] {
  87. unsafe {
  88. vm.jit_compile().unwrap();
  89. result = vm.execute_program_jit(&mut memory).unwrap();
  90. }
  91. }
  92. } else if cranelift {
  93. #[cfg(not(feature = "cranelift"))] {
  94. println!("Cranelift is not enabled");
  95. return;
  96. }
  97. #[cfg(feature = "cranelift")] {
  98. vm.cranelift_compile().unwrap();
  99. result = vm.execute_program_cranelift(&mut memory).unwrap();
  100. }
  101. }
  102. else {
  103. result = vm.execute_program(&mut memory).unwrap();
  104. }
  105. println!("{result:x}");
  106. }