Преглед изворни кода

rbpf: Apply rustfmt on the whole repository

Let's fix formatting using rustfmt, at last.

    $ rustfmt --version
    rustfmt 1.8.0-nightly (50aa041807 2025-05-08)

    $ rustfmt **/**.rs

Signed-off-by: Quentin Monnet <qmo@qmon.net>
Quentin Monnet пре 1 месец
родитељ
комит
487d0bd781
22 измењених фајлова са 2015 додато и 1017 уклоњено
  1. 2 2
      examples/load_elf.rs
  2. 22 17
      examples/rbpf_plugin.rs
  3. 19 19
      examples/to_json.rs
  4. 2 1
      examples/uptime.rs
  5. 14 20
      src/asm_parser.rs
  6. 73 49
      src/assembler.rs
  7. 11 6
      src/cranelift.rs
  8. 52 23
      src/disassembler.rs
  9. 16 18
      src/helpers.rs
  10. 461 156
      src/insn_builder.rs
  11. 56 27
      src/interpreter.rs
  12. 56 39
      src/jit.rs
  13. 17 10
      src/lib.rs
  14. 0 1
      src/no_std_error.rs
  15. 24 12
      src/verifier.rs
  16. 340 220
      tests/assembler.rs
  17. 25 8
      tests/cranelift.rs
  18. 88 42
      tests/disassembler.rs
  19. 52 43
      tests/misc.rs
  20. 362 153
      tests/ubpf_jit_x86_64.rs
  21. 46 20
      tests/ubpf_verifier.rs
  22. 277 131
      tests/ubpf_vm.rs

+ 2 - 2
examples/load_elf.rs

@@ -46,7 +46,6 @@ use rbpf::helpers;
 // Once the bytecode has been edited, we can load the bytecode directly from the ELF object file.
 // Once the bytecode has been edited, we can load the bytecode directly from the ELF object file.
 
 
 fn main() {
 fn main() {
-
     let filename = "examples/load_elf__block_a_port.o";
     let filename = "examples/load_elf__block_a_port.o";
 
 
     let path = PathBuf::from(filename);
     let path = PathBuf::from(filename);
@@ -109,7 +108,8 @@ fn main() {
     ];
     ];
 
 
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf).unwrap();
+    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf)
+        .unwrap();
 
 
     let res = vm.execute_program(packet1).unwrap();
     let res = vm.execute_program(packet1).unwrap();
     println!("Packet #1, program returned: {res:?} ({res:#x})");
     println!("Packet #1, program returned: {res:?} ({res:#x})");

+ 22 - 17
examples/rbpf_plugin.rs

@@ -5,8 +5,7 @@
 use std::io::Read;
 use std::io::Read;
 
 
 // Helper function used by https://github.com/Alan-Jowett/bpf_conformance/blob/main/tests/call_unwind_fail.data
 // Helper function used by https://github.com/Alan-Jowett/bpf_conformance/blob/main/tests/call_unwind_fail.data
-fn _unwind(a: u64, _b: u64, _c: u64, _d: u64, _e: u64) -> u64
-{
+fn _unwind(a: u64, _b: u64, _c: u64, _d: u64, _e: u64) -> u64 {
     a
     a
 }
 }
 
 
@@ -16,8 +15,8 @@ fn _unwind(a: u64, _b: u64, _c: u64, _d: u64, _e: u64) -> u64
 fn main() {
 fn main() {
     let mut args: Vec<String> = std::env::args().collect();
     let mut args: Vec<String> = std::env::args().collect();
     #[cfg_attr(not(feature = "std"), allow(unused_mut))] // in no_std, jit variable isn't mutated
     #[cfg_attr(not(feature = "std"), allow(unused_mut))] // in no_std, jit variable isn't mutated
-    let mut jit : bool = false;
-    let mut cranelift : bool = false;
+    let mut jit: bool = false;
+    let mut cranelift: bool = false;
     let mut program_text = String::new();
     let mut program_text = String::new();
     let mut memory_text = String::new();
     let mut memory_text = String::new();
 
 
@@ -37,20 +36,23 @@ fn main() {
             "--help" => {
             "--help" => {
                 println!("Usage: rbpf_plugin [memory] < program");
                 println!("Usage: rbpf_plugin [memory] < program");
                 return;
                 return;
-            },
+            }
             "--jit" => {
             "--jit" => {
-                #[cfg(any(windows, not(feature = "std")))] {
+                #[cfg(any(windows, not(feature = "std")))]
+                {
                     println!("JIT not supported");
                     println!("JIT not supported");
                     return;
                     return;
                 }
                 }
-                #[cfg(all(not(windows), feature = "std"))] {
+                #[cfg(all(not(windows), feature = "std"))]
+                {
                     jit = true;
                     jit = true;
                 }
                 }
-            },
+            }
             "--cranelift" => {
             "--cranelift" => {
                 cranelift = true;
                 cranelift = true;
 
 
-                #[cfg(not(feature = "cranelift"))] {
+                #[cfg(not(feature = "cranelift"))]
+                {
                     let _ = cranelift;
                     let _ = cranelift;
                     println!("Cranelift is not enabled");
                     println!("Cranelift is not enabled");
                     return;
                     return;
@@ -66,7 +68,7 @@ fn main() {
                     program_text = args[0].clone();
                     program_text = args[0].clone();
                     args.remove(0);
                     args.remove(0);
                 }
                 }
-            },
+            }
             _ => panic!("Unknown argument {}", args[0]),
             _ => panic!("Unknown argument {}", args[0]),
         }
         }
         args.remove(0);
         args.remove(0);
@@ -92,29 +94,32 @@ fn main() {
     // Register the helper function used by call_unwind_fail.data test.
     // Register the helper function used by call_unwind_fail.data test.
     vm.register_helper(5, _unwind).unwrap();
     vm.register_helper(5, _unwind).unwrap();
 
 
-    let result : u64;
+    let result: u64;
     if jit {
     if jit {
-        #[cfg(any(windows, not(feature = "std")))] {
+        #[cfg(any(windows, not(feature = "std")))]
+        {
             println!("JIT not supported");
             println!("JIT not supported");
             return;
             return;
         }
         }
-        #[cfg(all(not(windows), feature = "std"))] {
+        #[cfg(all(not(windows), feature = "std"))]
+        {
             unsafe {
             unsafe {
                 vm.jit_compile().unwrap();
                 vm.jit_compile().unwrap();
                 result = vm.execute_program_jit(&mut memory).unwrap();
                 result = vm.execute_program_jit(&mut memory).unwrap();
             }
             }
         }
         }
     } else if cranelift {
     } else if cranelift {
-        #[cfg(not(feature = "cranelift"))] {
+        #[cfg(not(feature = "cranelift"))]
+        {
             println!("Cranelift is not enabled");
             println!("Cranelift is not enabled");
             return;
             return;
         }
         }
-        #[cfg(feature = "cranelift")] {
+        #[cfg(feature = "cranelift")]
+        {
             vm.cranelift_compile().unwrap();
             vm.cranelift_compile().unwrap();
             result = vm.execute_program_cranelift(&mut memory).unwrap();
             result = vm.execute_program_cranelift(&mut memory).unwrap();
         }
         }
-    }
-    else {
+    } else {
         result = vm.execute_program(&mut memory).unwrap();
         result = vm.execute_program(&mut memory).unwrap();
     }
     }
     println!("{result:x}");
     println!("{result:x}");

+ 19 - 19
examples/to_json.rs

@@ -20,7 +20,6 @@ use rbpf::disassembler;
 // * Print integers as integers, and not as strings containing their hexadecimal representation
 // * Print integers as integers, and not as strings containing their hexadecimal representation
 //   (just replace the relevant `format!()` calls by the commented values.
 //   (just replace the relevant `format!()` calls by the commented values.
 fn to_json(prog: &[u8]) -> String {
 fn to_json(prog: &[u8]) -> String {
-
     // This call returns a high-level representation of the instructions, with the two parts of
     // This call returns a high-level representation of the instructions, with the two parts of
     // `LD_DW_IMM` instructions merged, and name and descriptions of the instructions.
     // `LD_DW_IMM` instructions merged, and name and descriptions of the instructions.
     // If you prefer to use a lower-level representation, use `ebpf::to_insn_vec()` function
     // If you prefer to use a lower-level representation, use `ebpf::to_insn_vec()` function
@@ -29,31 +28,32 @@ fn to_json(prog: &[u8]) -> String {
     let mut json_insns = vec![];
     let mut json_insns = vec![];
     for insn in insns {
     for insn in insns {
         json_insns.push(object!(
         json_insns.push(object!(
-                "opc"  => format!("{:#x}", insn.opc), // => insn.opc,
-                "dst"  => format!("{:#x}", insn.dst), // => insn.dst,
-                "src"  => format!("{:#x}", insn.src), // => insn.src,
-                "off"  => format!("{:#x}", insn.off), // => insn.off,
-                // Warning: for imm we use a i64 instead of a i32 (to have correct values for
-                // `lddw` operation. If we print a number in the JSON this is not a problem, the
-                // internal i64 has the same value with extended sign on 32 most significant bytes.
-                // If we print the hexadecimal value as a string however, we want to cast as a i32
-                // to prevent all other instructions to print spurious `ffffffff` prefix if the
-                // number is negative. When values takes more than 32 bits with `lddw`, the cast
-                // has no effect and the complete value is printed anyway.
-                "imm"  => format!("{:#x}", insn.imm as i32), // => insn.imm,
-                "desc" => insn.desc
-            )
-        );
+            "opc"  => format!("{:#x}", insn.opc), // => insn.opc,
+            "dst"  => format!("{:#x}", insn.dst), // => insn.dst,
+            "src"  => format!("{:#x}", insn.src), // => insn.src,
+            "off"  => format!("{:#x}", insn.off), // => insn.off,
+            // Warning: for imm we use a i64 instead of a i32 (to have correct values for
+            // `lddw` operation. If we print a number in the JSON this is not a problem, the
+            // internal i64 has the same value with extended sign on 32 most significant bytes.
+            // If we print the hexadecimal value as a string however, we want to cast as a i32
+            // to prevent all other instructions to print spurious `ffffffff` prefix if the
+            // number is negative. When values takes more than 32 bits with `lddw`, the cast
+            // has no effect and the complete value is printed anyway.
+            "imm"  => format!("{:#x}", insn.imm as i32), // => insn.imm,
+            "desc" => insn.desc
+        ));
     }
     }
-    json::stringify_pretty(object!(
+    json::stringify_pretty(
+        object!(
         "size"  => json_insns.len(),
         "size"  => json_insns.len(),
         "insns" => json_insns
         "insns" => json_insns
-        ), 4)
+        ),
+        4,
+    )
 }
 }
 
 
 // Load a program from an object file, and prints it to standard output as a JSON string.
 // Load a program from an object file, and prints it to standard output as a JSON string.
 fn main() {
 fn main() {
-
     // Let's reuse this file from `load_elf` example.
     // Let's reuse this file from `load_elf` example.
     let filename = "examples/load_elf__block_a_port.o";
     let filename = "examples/load_elf__block_a_port.o";
 
 

+ 2 - 1
examples/uptime.rs

@@ -50,7 +50,8 @@ fn main() {
     // reimplement uptime in eBPF, in Rust. Because why not.
     // reimplement uptime in eBPF, in Rust. Because why not.
 
 
     vm.set_program(prog2).unwrap();
     vm.set_program(prog2).unwrap();
-    vm.register_helper(helpers::BPF_KTIME_GETNS_IDX, helpers::bpf_time_getns).unwrap();
+    vm.register_helper(helpers::BPF_KTIME_GETNS_IDX, helpers::bpf_time_getns)
+        .unwrap();
 
 
     let time;
     let time;
 
 

+ 14 - 20
src/asm_parser.rs

@@ -116,7 +116,6 @@ pub fn parse(input: &str) -> Result<Vec<Instruction>, String> {
             Err(err) => Err(err.to_string()),
             Err(err) => Err(err.to_string()),
         }
         }
     }
     }
-
 }
 }
 
 
 #[cfg(test)]
 #[cfg(test)]
@@ -591,21 +590,19 @@ mod tests {
     #[test]
     #[test]
     fn test_error_eof() {
     fn test_error_eof() {
         let expected_error;
         let expected_error;
-        #[cfg(feature = "std")] {
+        #[cfg(feature = "std")]
+        {
             expected_error = Err(
             expected_error = Err(
-                "Parse error at line: 1, column: 6\nUnexpected end of input\nExpected digit\n".to_string()
+                "Parse error at line: 1, column: 6\nUnexpected end of input\nExpected digit\n"
+                    .to_string(),
             );
             );
         }
         }
-        #[cfg(not(feature = "std"))] {
-            expected_error = Err(
-                "unexpected parse".to_string()
-            );
+        #[cfg(not(feature = "std"))]
+        {
+            expected_error = Err("unexpected parse".to_string());
         }
         }
         // Unexpected end of input in a register name.
         // Unexpected end of input in a register name.
-        assert_eq!(
-            parse("lsh r"),
-            expected_error
-        );
+        assert_eq!(parse("lsh r"), expected_error);
     }
     }
 
 
     /// When running without `std` the `EasyParser` provided by `combine`
     /// When running without `std` the `EasyParser` provided by `combine`
@@ -614,21 +611,18 @@ mod tests {
     #[test]
     #[test]
     fn test_error_unexpected_character() {
     fn test_error_unexpected_character() {
         let expected_error;
         let expected_error;
-        #[cfg(feature = "std")] {
+        #[cfg(feature = "std")]
+        {
             expected_error = Err(
             expected_error = Err(
                 "Parse error at line: 2, column: 1\nUnexpected `^`\nExpected letter or digit, whitespaces, `r`, `-`, `+`, `[` or end of input\n".to_string()
                 "Parse error at line: 2, column: 1\nUnexpected `^`\nExpected letter or digit, whitespaces, `r`, `-`, `+`, `[` or end of input\n".to_string()
             );
             );
         }
         }
-        #[cfg(not(feature = "std"))] {
-            expected_error = Err(
-                "unexpected parse".to_string()
-            );
+        #[cfg(not(feature = "std"))]
+        {
+            expected_error = Err("unexpected parse".to_string());
         }
         }
         // Unexpected character at end of input.
         // Unexpected character at end of input.
-        assert_eq!(
-            parse("exit\n^"),
-            expected_error
-        );
+        assert_eq!(parse("exit\n^"), expected_error);
     }
     }
 
 
     #[test]
     #[test]

+ 73 - 49
src/assembler.rs

@@ -3,12 +3,14 @@
 
 
 //! This module translates eBPF assembly language to binary.
 //! This module translates eBPF assembly language to binary.
 
 
-use crate::asm_parser::{Instruction, Operand, parse};
-use crate::asm_parser::Operand::{Integer, Memory, Register, Nil};
+use self::InstructionType::{
+    AluBinary, AluUnary, Call, Callx, Endian, JumpConditional, JumpUnconditional, LoadAbs, LoadImm,
+    LoadInd, LoadReg, NoOperand, StoreImm, StoreReg,
+};
+use crate::asm_parser::Operand::{Integer, Memory, Nil, Register};
+use crate::asm_parser::{parse, Instruction, Operand};
 use crate::ebpf;
 use crate::ebpf;
 use crate::ebpf::Insn;
 use crate::ebpf::Insn;
-use self::InstructionType::{AluBinary, AluUnary, LoadAbs, LoadInd, LoadImm, LoadReg, StoreImm,
-                            StoreReg, JumpUnconditional, JumpConditional, Call, Callx, Endian, NoOperand};
 use crate::lib::*;
 use crate::lib::*;
 
 
 #[derive(Clone, Copy, Debug, PartialEq)]
 #[derive(Clone, Copy, Debug, PartialEq)]
@@ -32,33 +34,41 @@ enum InstructionType {
 fn make_instruction_map() -> HashMap<String, (InstructionType, u8)> {
 fn make_instruction_map() -> HashMap<String, (InstructionType, u8)> {
     let mut result = HashMap::new();
     let mut result = HashMap::new();
 
 
-    let alu_binary_ops = [("add", ebpf::BPF_ADD),
-                          ("sub", ebpf::BPF_SUB),
-                          ("mul", ebpf::BPF_MUL),
-                          ("div", ebpf::BPF_DIV),
-                          ("or", ebpf::BPF_OR),
-                          ("and", ebpf::BPF_AND),
-                          ("lsh", ebpf::BPF_LSH),
-                          ("rsh", ebpf::BPF_RSH),
-                          ("mod", ebpf::BPF_MOD),
-                          ("xor", ebpf::BPF_XOR),
-                          ("mov", ebpf::BPF_MOV),
-                          ("arsh", ebpf::BPF_ARSH)];
-
-    let mem_sizes =
-        [("w", ebpf::BPF_W), ("h", ebpf::BPF_H), ("b", ebpf::BPF_B), ("dw", ebpf::BPF_DW)];
-
-    let jump_conditions = [("jeq", ebpf::BPF_JEQ),
-                           ("jgt", ebpf::BPF_JGT),
-                           ("jge", ebpf::BPF_JGE),
-                           ("jlt", ebpf::BPF_JLT),
-                           ("jle", ebpf::BPF_JLE),
-                           ("jset", ebpf::BPF_JSET),
-                           ("jne", ebpf::BPF_JNE),
-                           ("jsgt", ebpf::BPF_JSGT),
-                           ("jsge", ebpf::BPF_JSGE),
-                           ("jslt", ebpf::BPF_JSLT),
-                           ("jsle", ebpf::BPF_JSLE)];
+    let alu_binary_ops = [
+        ("add", ebpf::BPF_ADD),
+        ("sub", ebpf::BPF_SUB),
+        ("mul", ebpf::BPF_MUL),
+        ("div", ebpf::BPF_DIV),
+        ("or", ebpf::BPF_OR),
+        ("and", ebpf::BPF_AND),
+        ("lsh", ebpf::BPF_LSH),
+        ("rsh", ebpf::BPF_RSH),
+        ("mod", ebpf::BPF_MOD),
+        ("xor", ebpf::BPF_XOR),
+        ("mov", ebpf::BPF_MOV),
+        ("arsh", ebpf::BPF_ARSH),
+    ];
+
+    let mem_sizes = [
+        ("w", ebpf::BPF_W),
+        ("h", ebpf::BPF_H),
+        ("b", ebpf::BPF_B),
+        ("dw", ebpf::BPF_DW),
+    ];
+
+    let jump_conditions = [
+        ("jeq", ebpf::BPF_JEQ),
+        ("jgt", ebpf::BPF_JGT),
+        ("jge", ebpf::BPF_JGE),
+        ("jlt", ebpf::BPF_JLT),
+        ("jle", ebpf::BPF_JLE),
+        ("jset", ebpf::BPF_JSET),
+        ("jne", ebpf::BPF_JNE),
+        ("jsgt", ebpf::BPF_JSGT),
+        ("jsge", ebpf::BPF_JSGE),
+        ("jslt", ebpf::BPF_JSLT),
+        ("jsle", ebpf::BPF_JSLE),
+    ];
 
 
     {
     {
         let mut entry = |name: &str, inst_type: InstructionType, opc: u8| {
         let mut entry = |name: &str, inst_type: InstructionType, opc: u8| {
@@ -86,27 +96,41 @@ fn make_instruction_map() -> HashMap<String, (InstructionType, u8)> {
 
 
         // LoadAbs, LoadInd, LoadReg, StoreImm, and StoreReg.
         // LoadAbs, LoadInd, LoadReg, StoreImm, and StoreReg.
         for &(suffix, size) in &mem_sizes {
         for &(suffix, size) in &mem_sizes {
-            entry(&format!("ldabs{suffix}"),
-                  LoadAbs,
-                  ebpf::BPF_ABS | ebpf::BPF_LD | size);
-            entry(&format!("ldind{suffix}"),
-                  LoadInd,
-                  ebpf::BPF_IND | ebpf::BPF_LD | size);
-            entry(&format!("ldx{suffix}"),
-                  LoadReg,
-                  ebpf::BPF_MEM | ebpf::BPF_LDX | size);
-            entry(&format!("st{suffix}"),
-                  StoreImm,
-                  ebpf::BPF_MEM | ebpf::BPF_ST | size);
-            entry(&format!("stx{suffix}"),
-                  StoreReg,
-                  ebpf::BPF_MEM | ebpf::BPF_STX | size);
+            entry(
+                &format!("ldabs{suffix}"),
+                LoadAbs,
+                ebpf::BPF_ABS | ebpf::BPF_LD | size,
+            );
+            entry(
+                &format!("ldind{suffix}"),
+                LoadInd,
+                ebpf::BPF_IND | ebpf::BPF_LD | size,
+            );
+            entry(
+                &format!("ldx{suffix}"),
+                LoadReg,
+                ebpf::BPF_MEM | ebpf::BPF_LDX | size,
+            );
+            entry(
+                &format!("st{suffix}"),
+                StoreImm,
+                ebpf::BPF_MEM | ebpf::BPF_ST | size,
+            );
+            entry(
+                &format!("stx{suffix}"),
+                StoreReg,
+                ebpf::BPF_MEM | ebpf::BPF_STX | size,
+            );
         }
         }
 
 
         // JumpConditional.
         // JumpConditional.
         for &(name, condition) in &jump_conditions {
         for &(name, condition) in &jump_conditions {
             entry(name, JumpConditional, ebpf::BPF_JMP | condition);
             entry(name, JumpConditional, ebpf::BPF_JMP | condition);
-            entry(&format!("{name}32"), JumpConditional, ebpf::BPF_JMP32 | condition);
+            entry(
+                &format!("{name}32"),
+                JumpConditional,
+                ebpf::BPF_JMP32 | condition,
+            );
         }
         }
 
 
         // Endian.
         // Endian.
@@ -160,8 +184,8 @@ fn encode(inst_type: InstructionType, opc: u8, operands: &[Operand]) -> Result<I
         (AluUnary, Register(dst), Nil, Nil) => insn(opc, dst, 0, 0, 0),
         (AluUnary, Register(dst), Nil, Nil) => insn(opc, dst, 0, 0, 0),
         (LoadAbs, Integer(imm), Nil, Nil) => insn(opc, 0, 0, 0, imm),
         (LoadAbs, Integer(imm), Nil, Nil) => insn(opc, 0, 0, 0, imm),
         (LoadInd, Register(src), Integer(imm), Nil) => insn(opc, 0, src, 0, imm),
         (LoadInd, Register(src), Integer(imm), Nil) => insn(opc, 0, src, 0, imm),
-        (LoadReg, Register(dst), Memory(src, off), Nil) |
-        (StoreReg, Memory(dst, off), Register(src), Nil) => insn(opc, dst, src, off, 0),
+        (LoadReg, Register(dst), Memory(src, off), Nil)
+        | (StoreReg, Memory(dst, off), Register(src), Nil) => insn(opc, dst, src, off, 0),
         (StoreImm, Memory(dst, off), Integer(imm), Nil) => insn(opc, dst, 0, off, imm),
         (StoreImm, Memory(dst, off), Integer(imm), Nil) => insn(opc, dst, 0, off, imm),
         (NoOperand, Nil, Nil, Nil) => insn(opc, 0, 0, 0, 0),
         (NoOperand, Nil, Nil, Nil) => insn(opc, 0, 0, 0, 0),
         (JumpUnconditional, Integer(off), Nil, Nil) => insn(opc, 0, 0, off, 0),
         (JumpUnconditional, Integer(off), Nil, Nil) => insn(opc, 0, 0, off, 0),

+ 11 - 6
src/cranelift.rs

@@ -16,8 +16,8 @@ use cranelift_jit::{JITBuilder, JITModule};
 use cranelift_module::{FuncId, Linkage, Module};
 use cranelift_module::{FuncId, Linkage, Module};
 
 
 use crate::ebpf::{
 use crate::ebpf::{
-    self, Insn, BPF_ALU_OP_MASK, BPF_JEQ, BPF_JGE, BPF_JGT, BPF_JLE, BPF_JLT, BPF_JMP32, BPF_JNE,
-    BPF_JSET, BPF_JSGE, BPF_JSGT, BPF_JSLE, BPF_JSLT, BPF_X, STACK_SIZE, BPF_IND,
+    self, Insn, BPF_ALU_OP_MASK, BPF_IND, BPF_JEQ, BPF_JGE, BPF_JGT, BPF_JLE, BPF_JLT, BPF_JMP32,
+    BPF_JNE, BPF_JSET, BPF_JSGE, BPF_JSGT, BPF_JSLE, BPF_JSLT, BPF_X, STACK_SIZE,
 };
 };
 use crate::lib::*;
 use crate::lib::*;
 
 
@@ -906,13 +906,18 @@ impl CraneliftCompiler {
                 // Do not delegate the check to the verifier, since registered functions can be
                 // Do not delegate the check to the verifier, since registered functions can be
                 // changed after the program has been verified.
                 // changed after the program has been verified.
                 ebpf::CALL => {
                 ebpf::CALL => {
-                    let func_ref = self.helper_func_refs
+                    let func_ref = self
+                        .helper_func_refs
                         .get(&(insn.imm as u32))
                         .get(&(insn.imm as u32))
                         .copied()
                         .copied()
                         .ok_or_else(|| {
                         .ok_or_else(|| {
-                            Error::new(ErrorKind::Other,
-                                format!("[CRANELIFT] Error: unknown helper function (id: {:#x})",
-                                        insn.imm as u32))
+                            Error::new(
+                                ErrorKind::Other,
+                                format!(
+                                    "[CRANELIFT] Error: unknown helper function (id: {:#x})",
+                                    insn.imm as u32
+                                ),
+                            )
                         })?;
                         })?;
 
 
                     let arg0 = bcx.use_var(self.registers[1]);
                     let arg0 = bcx.use_var(self.registers[1]);

+ 52 - 23
src/disassembler.rs

@@ -4,9 +4,9 @@
 //! Functions in this module are used to handle eBPF programs with a higher level representation,
 //! Functions in this module are used to handle eBPF programs with a higher level representation,
 //! for example to disassemble the code into a human-readable format.
 //! for example to disassemble the code into a human-readable format.
 
 
-use log::warn;
 #[cfg(not(feature = "std"))]
 #[cfg(not(feature = "std"))]
 use log::info;
 use log::info;
+use log::warn;
 
 
 use crate::ebpf;
 use crate::ebpf;
 use crate::lib::*;
 use crate::lib::*;
@@ -24,8 +24,8 @@ fn alu_reg_str(name: &str, insn: &ebpf::Insn) -> String {
 #[inline]
 #[inline]
 fn byteswap_str(name: &str, insn: &ebpf::Insn) -> String {
 fn byteswap_str(name: &str, insn: &ebpf::Insn) -> String {
     match insn.imm {
     match insn.imm {
-        16 | 32 | 64 => {},
-        _ => warn!("[Disassembler] Warning: Invalid offset value for {name} insn")
+        16 | 32 | 64 => {}
+        _ => warn!("[Disassembler] Warning: Invalid offset value for {name} insn"),
     }
     }
     format!("{name}{} r{}", insn.imm, insn.dst)
     format!("{name}{} r{}", insn.imm, insn.dst)
 }
 }
@@ -35,7 +35,12 @@ fn ld_st_imm_str(name: &str, insn: &ebpf::Insn) -> String {
     if insn.off >= 0 {
     if insn.off >= 0 {
         format!("{name} [r{}+{:#x}], {:#x}", insn.dst, insn.off, insn.imm)
         format!("{name} [r{}+{:#x}], {:#x}", insn.dst, insn.off, insn.imm)
     } else {
     } else {
-        format!("{name} [r{}-{:#x}], {:#x}", insn.dst, -(insn.off as isize), insn.imm)
+        format!(
+            "{name} [r{}-{:#x}], {:#x}",
+            insn.dst,
+            -(insn.off as isize),
+            insn.imm
+        )
     }
     }
 }
 }
 
 
@@ -44,7 +49,12 @@ fn ld_reg_str(name: &str, insn: &ebpf::Insn) -> String {
     if insn.off >= 0 {
     if insn.off >= 0 {
         format!("{name} r{}, [r{}+{:#x}]", insn.dst, insn.src, insn.off)
         format!("{name} r{}, [r{}+{:#x}]", insn.dst, insn.src, insn.off)
     } else {
     } else {
-        format!("{name} r{}, [r{}-{:#x}]", insn.dst, insn.src, -(insn.off as isize))
+        format!(
+            "{name} r{}, [r{}-{:#x}]",
+            insn.dst,
+            insn.src,
+            -(insn.off as isize)
+        )
     }
     }
 }
 }
 
 
@@ -53,7 +63,12 @@ fn st_reg_str(name: &str, insn: &ebpf::Insn) -> String {
     if insn.off >= 0 {
     if insn.off >= 0 {
         format!("{name} [r{}+{:#x}], r{}", insn.dst, insn.off, insn.src)
         format!("{name} [r{}+{:#x}], r{}", insn.dst, insn.off, insn.src)
     } else {
     } else {
-        format!("{name} [r{}-{:#x}], r{}", insn.dst, -(insn.off as isize), insn.src)
+        format!(
+            "{name} [r{}-{:#x}], r{}",
+            insn.dst,
+            -(insn.off as isize),
+            insn.src
+        )
     }
     }
 }
 }
 
 
@@ -72,7 +87,12 @@ fn jmp_imm_str(name: &str, insn: &ebpf::Insn) -> String {
     if insn.off >= 0 {
     if insn.off >= 0 {
         format!("{name} r{}, {:#x}, +{:#x}", insn.dst, insn.imm, insn.off)
         format!("{name} r{}, {:#x}, +{:#x}", insn.dst, insn.imm, insn.off)
     } else {
     } else {
-        format!("{name} r{}, {:#x}, -{:#x}", insn.dst, insn.imm, -(insn.off as isize))
+        format!(
+            "{name} r{}, {:#x}, -{:#x}",
+            insn.dst,
+            insn.imm,
+            -(insn.off as isize)
+        )
     }
     }
 }
 }
 
 
@@ -81,7 +101,12 @@ fn jmp_reg_str(name: &str, insn: &ebpf::Insn) -> String {
     if insn.off >= 0 {
     if insn.off >= 0 {
         format!("{name} r{}, r{}, +{:#x}", insn.dst, insn.src, insn.off)
         format!("{name} r{}, r{}, +{:#x}", insn.dst, insn.src, insn.off)
     } else {
     } else {
-        format!("{name} r{}, r{}, -{:#x}", insn.dst, insn.src, -(insn.off as isize))
+        format!(
+            "{name} r{}, r{}, -{:#x}",
+            insn.dst,
+            insn.src,
+            -(insn.off as isize)
+        )
     }
     }
 }
 }
 
 
@@ -103,20 +128,20 @@ fn jmp_reg_str(name: &str, insn: &ebpf::Insn) -> String {
 #[derive(Debug, PartialEq, Eq)]
 #[derive(Debug, PartialEq, Eq)]
 pub struct HLInsn {
 pub struct HLInsn {
     /// Operation code.
     /// Operation code.
-    pub opc:  u8,
+    pub opc: u8,
     /// Name (mnemonic). This name is not canon.
     /// Name (mnemonic). This name is not canon.
     pub name: String,
     pub name: String,
     /// Description of the instruction. This is not canon.
     /// Description of the instruction. This is not canon.
     pub desc: String,
     pub desc: String,
     /// Destination register operand.
     /// Destination register operand.
-    pub dst:  u8,
+    pub dst: u8,
     /// Source register operand.
     /// Source register operand.
-    pub src:  u8,
+    pub src: u8,
     /// Offset operand.
     /// Offset operand.
-    pub off:  i16,
+    pub off: i16,
     /// Immediate value operand. For `LD_DW_IMM` instructions, contains the whole value merged from
     /// Immediate value operand. For `LD_DW_IMM` instructions, contains the whole value merged from
     /// the two 8-bytes parts of the instruction.
     /// the two 8-bytes parts of the instruction.
-    pub imm:  i64,
+    pub imm: i64,
 }
 }
 
 
 /// Return a vector of `struct HLInsn` built from an eBPF program.
 /// Return a vector of `struct HLInsn` built from an eBPF program.
@@ -172,15 +197,17 @@ pub struct HLInsn {
 /// ```
 /// ```
 pub fn to_insn_vec(prog: &[u8]) -> Vec<HLInsn> {
 pub fn to_insn_vec(prog: &[u8]) -> Vec<HLInsn> {
     if prog.len() % ebpf::INSN_SIZE != 0 {
     if prog.len() % ebpf::INSN_SIZE != 0 {
-        panic!("[Disassembler] Error: eBPF program length must be a multiple of {:?} octets",
-               ebpf::INSN_SIZE);
+        panic!(
+            "[Disassembler] Error: eBPF program length must be a multiple of {:?} octets",
+            ebpf::INSN_SIZE
+        );
     }
     }
     if prog.is_empty() {
     if prog.is_empty() {
         return vec![];
         return vec![];
     }
     }
 
 
     let mut res = vec![];
     let mut res = vec![];
-    let mut insn_ptr:usize = 0;
+    let mut insn_ptr: usize = 0;
 
 
     while insn_ptr * ebpf::INSN_SIZE < prog.len() {
     while insn_ptr * ebpf::INSN_SIZE < prog.len() {
         let insn = ebpf::get_insn(prog, insn_ptr);
         let insn = ebpf::get_insn(prog, insn_ptr);
@@ -350,19 +377,19 @@ pub fn to_insn_vec(prog: &[u8]) -> Vec<HLInsn> {
         };
         };
 
 
         let hl_insn = HLInsn {
         let hl_insn = HLInsn {
-            opc:  insn.opc,
+            opc: insn.opc,
             name: name.to_string(),
             name: name.to_string(),
             desc,
             desc,
-            dst:  insn.dst,
-            src:  insn.src,
-            off:  insn.off,
+            dst: insn.dst,
+            src: insn.src,
+            off: insn.off,
             imm,
             imm,
         };
         };
 
 
         res.push(hl_insn);
         res.push(hl_insn);
 
 
         insn_ptr += 1;
         insn_ptr += 1;
-    };
+    }
     res
     res
 }
 }
 
 
@@ -397,12 +424,14 @@ pub fn to_insn_vec(prog: &[u8]) -> Vec<HLInsn> {
 /// exit
 /// exit
 /// ```
 /// ```
 pub fn disassemble(prog: &[u8]) {
 pub fn disassemble(prog: &[u8]) {
-    #[cfg(feature = "std")] {
+    #[cfg(feature = "std")]
+    {
         for insn in to_insn_vec(prog) {
         for insn in to_insn_vec(prog) {
             println!("{}", insn.desc);
             println!("{}", insn.desc);
         }
         }
     }
     }
-    #[cfg(not(feature = "std"))] {
+    #[cfg(not(feature = "std"))]
+    {
         for insn in to_insn_vec(prog) {
         for insn in to_insn_vec(prog) {
             info!("{}", insn.desc);
             info!("{}", insn.desc);
         }
         }

+ 16 - 18
src/helpers.rs

@@ -47,7 +47,7 @@ pub const BPF_KTIME_GETNS_IDX: u32 = 5;
 #[allow(unused_variables)]
 #[allow(unused_variables)]
 #[allow(deprecated)]
 #[allow(deprecated)]
 #[cfg(feature = "std")]
 #[cfg(feature = "std")]
-pub fn bpf_time_getns (unused1: u64, unused2: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
+pub fn bpf_time_getns(unused1: u64, unused2: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
     time::precise_time_ns()
     time::precise_time_ns()
 }
 }
 
 
@@ -95,20 +95,18 @@ pub const BPF_TRACE_PRINTK_IDX: u32 = 6;
 #[allow(dead_code)]
 #[allow(dead_code)]
 #[allow(unused_variables)]
 #[allow(unused_variables)]
 #[cfg(feature = "std")]
 #[cfg(feature = "std")]
-pub fn bpf_trace_printf (unused1: u64, unused2: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 {
+pub fn bpf_trace_printf(unused1: u64, unused2: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 {
     println!("bpf_trace_printf: {arg3:#x}, {arg4:#x}, {arg5:#x}");
     println!("bpf_trace_printf: {arg3:#x}, {arg4:#x}, {arg5:#x}");
-    let size_arg = | x | {
+    let size_arg = |x| {
         if x == 0 {
         if x == 0 {
             1
             1
         } else {
         } else {
             (x as f64).log(16.0).floor() as u64 + 1
             (x as f64).log(16.0).floor() as u64 + 1
         }
         }
     };
     };
-    "bpf_trace_printf: 0x, 0x, 0x\n".len() as u64
-        + size_arg(arg3) + size_arg(arg4) + size_arg(arg5)
+    "bpf_trace_printf: 0x, 0x, 0x\n".len() as u64 + size_arg(arg3) + size_arg(arg4) + size_arg(arg5)
 }
 }
 
 
-
 // Helpers coming from uBPF <https://github.com/iovisor/ubpf/blob/master/vm/test.c>
 // Helpers coming from uBPF <https://github.com/iovisor/ubpf/blob/master/vm/test.c>
 
 
 /// The idea is to assemble five bytes into a single `u64`. For compatibility with the helpers API,
 /// The idea is to assemble five bytes into a single `u64`. For compatibility with the helpers API,
@@ -122,12 +120,12 @@ pub fn bpf_trace_printf (unused1: u64, unused2: u64, arg3: u64, arg4: u64, arg5:
 /// let gathered = helpers::gather_bytes(0x11, 0x22, 0x33, 0x44, 0x55);
 /// let gathered = helpers::gather_bytes(0x11, 0x22, 0x33, 0x44, 0x55);
 /// assert_eq!(gathered, 0x1122334455);
 /// assert_eq!(gathered, 0x1122334455);
 /// ```
 /// ```
-pub fn gather_bytes (arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 {
-    arg1.wrapping_shl(32) |
-    arg2.wrapping_shl(24) |
-    arg3.wrapping_shl(16) |
-    arg4.wrapping_shl(8)  |
-    arg5
+pub fn gather_bytes(arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 {
+    arg1.wrapping_shl(32)
+        | arg2.wrapping_shl(24)
+        | arg3.wrapping_shl(16)
+        | arg4.wrapping_shl(8)
+        | arg5
 }
 }
 
 
 /// Same as `void *memfrob(void *s, size_t n);` in `string.h` in C. See the GNU manual page (in
 /// Same as `void *memfrob(void *s, size_t n);` in `string.h` in C. See the GNU manual page (in
@@ -148,7 +146,7 @@ pub fn gather_bytes (arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> u
 /// assert_eq!(val, 0x112233);
 /// assert_eq!(val, 0x112233);
 /// ```
 /// ```
 #[allow(unused_variables)]
 #[allow(unused_variables)]
-pub fn memfrob (ptr: u64, len: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
+pub fn memfrob(ptr: u64, len: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
     for i in 0..len {
     for i in 0..len {
         unsafe {
         unsafe {
             let p = (ptr + i) as *mut u8;
             let p = (ptr + i) as *mut u8;
@@ -193,7 +191,7 @@ pub fn memfrob (ptr: u64, len: u64, unused3: u64, unused4: u64, unused5: u64) ->
 #[allow(dead_code)]
 #[allow(dead_code)]
 #[allow(unused_variables)]
 #[allow(unused_variables)]
 #[cfg(feature = "std")] // sqrt is only available when using `std`
 #[cfg(feature = "std")] // sqrt is only available when using `std`
-pub fn sqrti (arg1: u64, unused2: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
+pub fn sqrti(arg1: u64, unused2: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
     (arg1 as f64).sqrt() as u64
     (arg1 as f64).sqrt() as u64
 }
 }
 
 
@@ -212,7 +210,7 @@ pub fn sqrti (arg1: u64, unused2: u64, unused3: u64, unused4: u64, unused5: u64)
 /// ```
 /// ```
 #[allow(dead_code)]
 #[allow(dead_code)]
 #[allow(unused_variables)]
 #[allow(unused_variables)]
-pub fn strcmp (arg1: u64, arg2: u64, arg3: u64, unused4: u64, unused5: u64) -> u64 {
+pub fn strcmp(arg1: u64, arg2: u64, arg3: u64, unused4: u64, unused5: u64) -> u64 {
     // C-like strcmp, maybe shorter than converting the bytes to string and comparing?
     // C-like strcmp, maybe shorter than converting the bytes to string and comparing?
     if arg1 == 0 || arg2 == 0 {
     if arg1 == 0 || arg2 == 0 {
         return u64::MAX;
         return u64::MAX;
@@ -223,8 +221,8 @@ pub fn strcmp (arg1: u64, arg2: u64, arg3: u64, unused4: u64, unused5: u64) -> u
         let mut a_val = *(a as *const u8);
         let mut a_val = *(a as *const u8);
         let mut b_val = *(b as *const u8);
         let mut b_val = *(b as *const u8);
         while a_val == b_val && a_val != 0 && b_val != 0 {
         while a_val == b_val && a_val != 0 && b_val != 0 {
-            a +=1 ;
-            b +=1 ;
+            a += 1;
+            b += 1;
             a_val = *(a as *const u8);
             a_val = *(a as *const u8);
             b_val = *(b as *const u8);
             b_val = *(b as *const u8);
         }
         }
@@ -243,7 +241,7 @@ pub fn strcmp (arg1: u64, arg2: u64, arg3: u64, unused4: u64, unused5: u64) -> u
 #[allow(dead_code)]
 #[allow(dead_code)]
 #[allow(unused_variables)]
 #[allow(unused_variables)]
 #[cfg(feature = "std")]
 #[cfg(feature = "std")]
-pub fn rand (min: u64, max: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
+pub fn rand(min: u64, max: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
     use std::cell::Cell;
     use std::cell::Cell;
     use std::collections::hash_map::DefaultHasher;
     use std::collections::hash_map::DefaultHasher;
     use std::hash::{Hash, Hasher};
     use std::hash::{Hash, Hasher};

Разлика између датотеке није приказан због своје велике величине
+ 461 - 156
src/insn_builder.rs


+ 56 - 27
src/interpreter.rs

@@ -19,21 +19,21 @@ fn check_mem(
     mbuff: &[u8],
     mbuff: &[u8],
     mem: &[u8],
     mem: &[u8],
     stack: &[u8],
     stack: &[u8],
-    allowed_memory: &HashSet<u64>
+    allowed_memory: &HashSet<u64>,
 ) -> Result<(), Error> {
 ) -> Result<(), Error> {
     if let Some(addr_end) = addr.checked_add(len as u64) {
     if let Some(addr_end) = addr.checked_add(len as u64) {
-      if mbuff.as_ptr() as u64 <= addr && addr_end <= mbuff.as_ptr() as u64 + mbuff.len() as u64 {
-          return Ok(());
-      }
-      if mem.as_ptr() as u64 <= addr && addr_end <= mem.as_ptr() as u64 + mem.len() as u64 {
-          return Ok(());
-      }
-      if stack.as_ptr() as u64 <= addr && addr_end <= stack.as_ptr() as u64 + stack.len() as u64 {
-          return Ok(());
-      }
-      if allowed_memory.contains(&addr) {
-          return Ok(());
-      }
+        if mbuff.as_ptr() as u64 <= addr && addr_end <= mbuff.as_ptr() as u64 + mbuff.len() as u64 {
+            return Ok(());
+        }
+        if mem.as_ptr() as u64 <= addr && addr_end <= mem.as_ptr() as u64 + mem.len() as u64 {
+            return Ok(());
+        }
+        if stack.as_ptr() as u64 <= addr && addr_end <= stack.as_ptr() as u64 + stack.len() as u64 {
+            return Ok(());
+        }
+        if allowed_memory.contains(&addr) {
+            return Ok(());
+        }
     }
     }
 
 
     Err(Error::new(ErrorKind::Other, format!(
     Err(Error::new(ErrorKind::Other, format!(
@@ -58,36 +58,65 @@ pub fn execute_program(
 
 
     let (prog, stack_usage) = match prog_ {
     let (prog, stack_usage) = match prog_ {
         Some(prog) => (prog, stack_usage.unwrap()),
         Some(prog) => (prog, stack_usage.unwrap()),
-        None => Err(Error::new(ErrorKind::Other,
-                    "Error: No program set, call prog_set() to load one"))?,
+        None => Err(Error::new(
+            ErrorKind::Other,
+            "Error: No program set, call prog_set() to load one",
+        ))?,
     };
     };
-    let stack = vec![0u8;ebpf::STACK_SIZE];
-    let mut stacks = [StackFrame::new();MAX_CALL_DEPTH];
+    let stack = vec![0u8; ebpf::STACK_SIZE];
+    let mut stacks = [StackFrame::new(); MAX_CALL_DEPTH];
     let mut stack_frame_idx = 0;
     let mut stack_frame_idx = 0;
 
 
     // R1 points to beginning of memory area, R10 to stack
     // R1 points to beginning of memory area, R10 to stack
-    let mut reg: [u64;11] = [
-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, stack.as_ptr() as u64 + stack.len() as u64
+    let mut reg: [u64; 11] = [
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        0,
+        stack.as_ptr() as u64 + stack.len() as u64,
     ];
     ];
     if !mbuff.is_empty() {
     if !mbuff.is_empty() {
         reg[1] = mbuff.as_ptr() as u64;
         reg[1] = mbuff.as_ptr() as u64;
-    }
-    else if !mem.is_empty() {
+    } else if !mem.is_empty() {
         reg[1] = mem.as_ptr() as u64;
         reg[1] = mem.as_ptr() as u64;
     }
     }
 
 
-    let check_mem_load = | addr: u64, len: usize, insn_ptr: usize | {
-        check_mem(addr, len, "load", insn_ptr, mbuff, mem, &stack, allowed_memory)
+    let check_mem_load = |addr: u64, len: usize, insn_ptr: usize| {
+        check_mem(
+            addr,
+            len,
+            "load",
+            insn_ptr,
+            mbuff,
+            mem,
+            &stack,
+            allowed_memory,
+        )
     };
     };
-    let check_mem_store = | addr: u64, len: usize, insn_ptr: usize | {
-        check_mem(addr, len, "store", insn_ptr, mbuff, mem, &stack, allowed_memory)
+    let check_mem_store = |addr: u64, len: usize, insn_ptr: usize| {
+        check_mem(
+            addr,
+            len,
+            "store",
+            insn_ptr,
+            mbuff,
+            mem,
+            &stack,
+            allowed_memory,
+        )
     };
     };
 
 
     // Loop on instructions
     // Loop on instructions
-    let mut insn_ptr:usize = 0;
+    let mut insn_ptr: usize = 0;
     while insn_ptr * ebpf::INSN_SIZE < prog.len() {
     while insn_ptr * ebpf::INSN_SIZE < prog.len() {
         let insn = ebpf::get_insn(prog, insn_ptr);
         let insn = ebpf::get_insn(prog, insn_ptr);
-        if stack_frame_idx < MAX_CALL_DEPTH{
+        if stack_frame_idx < MAX_CALL_DEPTH {
             if let Some(usage) = stack_usage.stack_usage_for_local_func(insn_ptr) {
             if let Some(usage) = stack_usage.stack_usage_for_local_func(insn_ptr) {
                 stacks[stack_frame_idx].set_stack_usage(usage);
                 stacks[stack_frame_idx].set_stack_usage(usage);
             }
             }

+ 56 - 39
src/jit.rs

@@ -8,11 +8,11 @@
 #![allow(clippy::single_match)]
 #![allow(clippy::single_match)]
 
 
 use std::alloc;
 use std::alloc;
-use std::mem;
 use std::collections::HashMap;
 use std::collections::HashMap;
-use std::fmt::Formatter;
 use std::fmt::Error as FormatterError;
 use std::fmt::Error as FormatterError;
+use std::fmt::Formatter;
 use std::io::{Error, ErrorKind};
 use std::io::{Error, ErrorKind};
+use std::mem;
 use std::ops::{Index, IndexMut};
 use std::ops::{Index, IndexMut};
 use std::ptr;
 use std::ptr;
 
 
@@ -33,7 +33,7 @@ const TARGET_PC_EXIT: isize = TARGET_OFFSET + 1;
 
 
 #[derive(Copy, Clone)]
 #[derive(Copy, Clone)]
 enum OperandSize {
 enum OperandSize {
-    S8  = 8,
+    S8 = 8,
     S16 = 16,
     S16 = 16,
     S32 = 32,
     S32 = 32,
     S64 = 64,
     S64 = 64,
@@ -48,8 +48,8 @@ const RSP: u8 = 4;
 const RBP: u8 = 5;
 const RBP: u8 = 5;
 const RSI: u8 = 6;
 const RSI: u8 = 6;
 const RDI: u8 = 7;
 const RDI: u8 = 7;
-const R8:  u8 = 8;
-const R9:  u8 = 9;
+const R8: u8 = 8;
+const R9: u8 = 9;
 const R10: u8 = 10;
 const R10: u8 = 10;
 const R11: u8 = 11;
 const R11: u8 = 11;
 //const R12: u8 = 12;
 //const R12: u8 = 12;
@@ -58,7 +58,7 @@ const R14: u8 = 14;
 const R15: u8 = 15;
 const R15: u8 = 15;
 
 
 const REGISTER_MAP_SIZE: usize = 11;
 const REGISTER_MAP_SIZE: usize = 11;
-const REGISTER_MAP: [u8;REGISTER_MAP_SIZE] = [
+const REGISTER_MAP: [u8; REGISTER_MAP_SIZE] = [
     RAX, // 0  return value
     RAX, // 0  return value
     RDI, // 1  arg 1
     RDI, // 1  arg 1
     RSI, // 2  arg 2
     RSI, // 2  arg 2
@@ -70,8 +70,8 @@ const REGISTER_MAP: [u8;REGISTER_MAP_SIZE] = [
     R14, // 8  callee-saved
     R14, // 8  callee-saved
     R15, // 9  callee-saved
     R15, // 9  callee-saved
     RBP, // 10 stack pointer
     RBP, // 10 stack pointer
-    // R10 and R11 are used to compute store a constant pointer to mem and to compute offset for
-    // LD_ABS_* and LD_IND_* operations, so they are not mapped to any eBPF register.
+         // R10 and R11 are used to compute store a constant pointer to mem and to compute offset for
+         // LD_ABS_* and LD_IND_* operations, so they are not mapped to any eBPF register.
 ];
 ];
 
 
 // Return the x86 register for the given eBPF register
 // Return the x86 register for the given eBPF register
@@ -89,27 +89,27 @@ macro_rules! emit_bytes {
             ptr.write_unaligned($data);
             ptr.write_unaligned($data);
         }
         }
         $mem.offset += size;
         $mem.offset += size;
-    }}
+    }};
 }
 }
 
 
 #[derive(Debug)]
 #[derive(Debug)]
 struct Jump {
 struct Jump {
     offset_loc: usize,
     offset_loc: usize,
-    target_pc:  isize,
+    target_pc: isize,
 }
 }
 
 
 #[derive(Debug)]
 #[derive(Debug)]
 struct JitCompiler {
 struct JitCompiler {
-    pc_locs:         Vec<usize>,
+    pc_locs: Vec<usize>,
     special_targets: HashMap<isize, usize>,
     special_targets: HashMap<isize, usize>,
-    jumps:           Vec<Jump>,
+    jumps: Vec<Jump>,
 }
 }
 
 
 impl JitCompiler {
 impl JitCompiler {
     fn new() -> JitCompiler {
     fn new() -> JitCompiler {
         JitCompiler {
         JitCompiler {
-            pc_locs:         vec![],
-            jumps:           vec![],
+            pc_locs: vec![],
+            jumps: vec![],
             special_targets: HashMap::new(),
             special_targets: HashMap::new(),
         }
         }
     }
     }
@@ -167,10 +167,10 @@ impl JitCompiler {
     // Skipped if no bits would be set.
     // Skipped if no bits would be set.
     fn emit_basic_rex(&self, mem: &mut JitMemory, w: u8, src: u8, dst: u8) {
     fn emit_basic_rex(&self, mem: &mut JitMemory, w: u8, src: u8, dst: u8) {
         if self.basix_rex_would_set_bits(w, src, dst) {
         if self.basix_rex_would_set_bits(w, src, dst) {
-            let is_masked = | val, mask | { match val & mask {
+            let is_masked = |val, mask| match val & mask {
                 0 => 0,
                 0 => 0,
-                _ => 1
-            }};
+                _ => 1,
+            };
             self.emit_rex(mem, w, is_masked(src, 8), 0, is_masked(dst, 8));
             self.emit_rex(mem, w, is_masked(src, 8), 0, is_masked(dst, 8));
         }
         }
     }
     }
@@ -252,7 +252,7 @@ impl JitCompiler {
     fn emit_load(&self, mem: &mut JitMemory, size: OperandSize, src: u8, dst: u8, offset: i32) {
     fn emit_load(&self, mem: &mut JitMemory, size: OperandSize, src: u8, dst: u8, offset: i32) {
         let data = match size {
         let data = match size {
             OperandSize::S64 => 1,
             OperandSize::S64 => 1,
-            _ => 0
+            _ => 0,
         };
         };
         self.emit_basic_rex(mem, data, dst, src);
         self.emit_basic_rex(mem, data, dst, src);
 
 
@@ -261,12 +261,12 @@ impl JitCompiler {
                 // movzx
                 // movzx
                 self.emit1(mem, 0x0f);
                 self.emit1(mem, 0x0f);
                 self.emit1(mem, 0xb6);
                 self.emit1(mem, 0xb6);
-            },
+            }
             OperandSize::S16 => {
             OperandSize::S16 => {
                 // movzx
                 // movzx
                 self.emit1(mem, 0x0f);
                 self.emit1(mem, 0x0f);
                 self.emit1(mem, 0xb7);
                 self.emit1(mem, 0xb7);
-            },
+            }
             OperandSize::S32 | OperandSize::S64 => {
             OperandSize::S32 | OperandSize::S64 => {
                 // mov
                 // mov
                 self.emit1(mem, 0x8b);
                 self.emit1(mem, 0x8b);
@@ -377,7 +377,15 @@ impl JitCompiler {
         self.special_targets.insert(target, mem.offset);
         self.special_targets.insert(target, mem.offset);
     }
     }
 
 
-    fn emit_muldivmod(&mut self, mem: &mut JitMemory, pc: u16, opc: u8, src: u8, dst: u8, imm: i32) {
+    fn emit_muldivmod(
+        &mut self,
+        mem: &mut JitMemory,
+        pc: u16,
+        opc: u8,
+        src: u8,
+        dst: u8,
+        imm: i32,
+    ) {
         let mul = (opc & ebpf::BPF_ALU_OP_MASK) == (ebpf::MUL32_IMM & ebpf::BPF_ALU_OP_MASK);
         let mul = (opc & ebpf::BPF_ALU_OP_MASK) == (ebpf::MUL32_IMM & ebpf::BPF_ALU_OP_MASK);
         let div = (opc & ebpf::BPF_ALU_OP_MASK) == (ebpf::DIV32_IMM & ebpf::BPF_ALU_OP_MASK);
         let div = (opc & ebpf::BPF_ALU_OP_MASK) == (ebpf::DIV32_IMM & ebpf::BPF_ALU_OP_MASK);
         let modrm = (opc & ebpf::BPF_ALU_OP_MASK) == (ebpf::MOD32_IMM & ebpf::BPF_ALU_OP_MASK);
         let modrm = (opc & ebpf::BPF_ALU_OP_MASK) == (ebpf::MOD32_IMM & ebpf::BPF_ALU_OP_MASK);
@@ -469,7 +477,7 @@ impl JitCompiler {
         self.emit_push(mem, map_register(8));
         self.emit_push(mem, map_register(8));
         self.emit_push(mem, map_register(9));
         self.emit_push(mem, map_register(9));
         // 0xe8 is the opcode for a CALL
         // 0xe8 is the opcode for a CALL
-        self.emit1(mem, 0xe8); 
+        self.emit1(mem, 0xe8);
         self.emit_jump_offset(mem, target_pc);
         self.emit_jump_offset(mem, target_pc);
         self.emit_pop(mem, map_register(9));
         self.emit_pop(mem, map_register(9));
         self.emit_pop(mem, map_register(8));
         self.emit_pop(mem, map_register(8));
@@ -477,8 +485,14 @@ impl JitCompiler {
         self.emit_pop(mem, map_register(6));
         self.emit_pop(mem, map_register(6));
     }
     }
 
 
-    fn jit_compile(&mut self, mem: &mut JitMemory, prog: &[u8], use_mbuff: bool, update_data_ptr: bool,
-                   helpers: &HashMap<u32, ebpf::Helper>) -> Result<(), Error> {
+    fn jit_compile(
+        &mut self,
+        mem: &mut JitMemory,
+        prog: &[u8],
+        use_mbuff: bool,
+        update_data_ptr: bool,
+        helpers: &HashMap<u32, ebpf::Helper>,
+    ) -> Result<(), Error> {
         self.emit_push(mem, RBP);
         self.emit_push(mem, RBP);
         self.emit_push(mem, RBX);
         self.emit_push(mem, RBX);
         self.emit_push(mem, R13);
         self.emit_push(mem, R13);
@@ -501,25 +515,25 @@ impl JitCompiler {
                 if map_register(1) != RDX {
                 if map_register(1) != RDX {
                     self.emit_mov(mem, RDX, map_register(1));
                     self.emit_mov(mem, RDX, map_register(1));
                 }
                 }
-            },
+            }
             (true, false) => {
             (true, false) => {
                 // We use a mbuff already pointing to mem and mem_end: move it to register 1.
                 // We use a mbuff already pointing to mem and mem_end: move it to register 1.
                 if map_register(1) != RDI {
                 if map_register(1) != RDI {
                     self.emit_mov(mem, RDI, map_register(1));
                     self.emit_mov(mem, RDI, map_register(1));
                 }
                 }
-            },
+            }
             (true, true) => {
             (true, true) => {
                 // We have a fixed (simulated) mbuff: update mem and mem_end offset values in it.
                 // We have a fixed (simulated) mbuff: update mem and mem_end offset values in it.
 
 
                 // Store mem at mbuff + mem_offset. Trash R8.
                 // Store mem at mbuff + mem_offset. Trash R8.
-                self.emit_alu64(mem, 0x01, RDI, R8);                // add mbuff to mem_offset in R8
+                self.emit_alu64(mem, 0x01, RDI, R8); // add mbuff to mem_offset in R8
                 self.emit_store(mem, OperandSize::S64, RDX, R8, 0); // set mem at mbuff + mem_offset
                 self.emit_store(mem, OperandSize::S64, RDX, R8, 0); // set mem at mbuff + mem_offset
 
 
                 // Store mem_end at mbuff + mem_end_offset. Trash R9.
                 // Store mem_end at mbuff + mem_end_offset. Trash R9.
-                self.emit_load(mem, OperandSize::S64, RDX, R8, 0);  // load mem into R8
-                self.emit_alu64(mem, 0x01, RCX, R8);                // add mem_len to mem (= mem_end)
-                self.emit_alu64(mem, 0x01, RDI, R9);                // add mbuff to mem_end_offset
-                self.emit_store(mem, OperandSize::S64, R8, R9, 0);  // store mem_end
+                self.emit_load(mem, OperandSize::S64, RDX, R8, 0); // load mem into R8
+                self.emit_alu64(mem, 0x01, RCX, R8); // add mem_len to mem (= mem_end)
+                self.emit_alu64(mem, 0x01, RDI, R9); // add mbuff to mem_end_offset
+                self.emit_store(mem, OperandSize::S64, R8, R9, 0); // store mem_end
 
 
                 // Move rdi into register 1
                 // Move rdi into register 1
                 if map_register(1) != RDI {
                 if map_register(1) != RDI {
@@ -546,7 +560,7 @@ impl JitCompiler {
 
 
         self.pc_locs = vec![0; prog.len() / ebpf::INSN_SIZE + 1];
         self.pc_locs = vec![0; prog.len() / ebpf::INSN_SIZE + 1];
 
 
-        let mut insn_ptr:usize = 0;
+        let mut insn_ptr: usize = 0;
         while insn_ptr * ebpf::INSN_SIZE < prog.len() {
         while insn_ptr * ebpf::INSN_SIZE < prog.len() {
             let insn = ebpf::get_insn(prog, insn_ptr);
             let insn = ebpf::get_insn(prog, insn_ptr);
 
 
@@ -978,12 +992,11 @@ impl JitCompiler {
         Ok(())
         Ok(())
     }
     }
 
 
-    fn resolve_jumps(&mut self, mem: &mut JitMemory) -> Result<(), Error>
-    {
+    fn resolve_jumps(&mut self, mem: &mut JitMemory) -> Result<(), Error> {
         for jump in &self.jumps {
         for jump in &self.jumps {
             let target_loc = match self.special_targets.get(&jump.target_pc) {
             let target_loc = match self.special_targets.get(&jump.target_pc) {
                 Some(target) => *target,
                 Some(target) => *target,
-                None         => self.pc_locs[jump.target_pc as usize]
+                None => self.pc_locs[jump.target_pc as usize],
             };
             };
 
 
             // Assumes jump offset is at end of instruction
             // Assumes jump offset is at end of instruction
@@ -1001,13 +1014,17 @@ impl JitCompiler {
 
 
 pub struct JitMemory<'a> {
 pub struct JitMemory<'a> {
     contents: &'a mut [u8],
     contents: &'a mut [u8],
-    layout:   alloc::Layout,
-    offset:   usize,
+    layout: alloc::Layout,
+    offset: usize,
 }
 }
 
 
 impl<'a> JitMemory<'a> {
 impl<'a> JitMemory<'a> {
-    pub fn new(prog: &[u8], helpers: &HashMap<u32, ebpf::Helper>, use_mbuff: bool,
-               update_data_ptr: bool) -> Result<JitMemory<'a>, Error> {
+    pub fn new(
+        prog: &[u8],
+        helpers: &HashMap<u32, ebpf::Helper>,
+        use_mbuff: bool,
+        update_data_ptr: bool,
+    ) -> Result<JitMemory<'a>, Error> {
         let layout;
         let layout;
 
 
         // Allocate the appropriately sized memory.
         // Allocate the appropriately sized memory.

+ 17 - 10
src/lib.rs

@@ -46,11 +46,11 @@ pub mod ebpf;
 pub mod helpers;
 pub mod helpers;
 pub mod insn_builder;
 pub mod insn_builder;
 mod interpreter;
 mod interpreter;
-mod stack;
 #[cfg(all(not(windows), feature = "std"))]
 #[cfg(all(not(windows), feature = "std"))]
 mod jit;
 mod jit;
 #[cfg(not(feature = "std"))]
 #[cfg(not(feature = "std"))]
 mod no_std_error;
 mod no_std_error;
+mod stack;
 mod verifier;
 mod verifier;
 
 
 /// Reexports all the types needed from the `std`, `core`, and `alloc`
 /// Reexports all the types needed from the `std`, `core`, and `alloc`
@@ -64,12 +64,12 @@ pub mod lib {
         pub use std::*;
         pub use std::*;
     }
     }
 
 
+    pub use self::core::any::Any;
     pub use self::core::convert::TryInto;
     pub use self::core::convert::TryInto;
+    pub use self::core::f64;
     pub use self::core::mem;
     pub use self::core::mem;
     pub use self::core::mem::ManuallyDrop;
     pub use self::core::mem::ManuallyDrop;
     pub use self::core::ptr;
     pub use self::core::ptr;
-    pub use self::core::any::Any;
-    pub use self::core::f64;
 
 
     #[cfg(feature = "std")]
     #[cfg(feature = "std")]
     pub use std::println;
     pub use std::println;
@@ -124,7 +124,7 @@ pub type Verifier = fn(prog: &[u8]) -> Result<(), Error>;
 pub type Helper = fn(u64, u64, u64, u64, u64) -> u64;
 pub type Helper = fn(u64, u64, u64, u64, u64) -> u64;
 
 
 /// eBPF stack usage calculator function.
 /// eBPF stack usage calculator function.
-pub type StackUsageCalculator = fn(prog:&[u8], pc:usize, data:&mut dyn Any) -> u16;
+pub type StackUsageCalculator = fn(prog: &[u8], pc: usize, data: &mut dyn Any) -> u16;
 
 
 // A metadata buffer with two offset indications. It can be used in one kind of eBPF VM to simulate
 // A metadata buffer with two offset indications. It can be used in one kind of eBPF VM to simulate
 // the use of a metadata buffer each time the program is executed, without the user having to
 // the use of a metadata buffer each time the program is executed, without the user having to
@@ -216,7 +216,7 @@ impl<'a> EbpfVmMbuff<'a> {
             helpers: HashMap::new(),
             helpers: HashMap::new(),
             allowed_memory: HashSet::new(),
             allowed_memory: HashSet::new(),
             stack_usage,
             stack_usage,
-            stack_verifier
+            stack_verifier,
         })
         })
     }
     }
 
 
@@ -288,9 +288,9 @@ impl<'a> EbpfVmMbuff<'a> {
     /// Set a new stack usage calculator function. The function should return the stack usage
     /// Set a new stack usage calculator function. The function should return the stack usage
     /// of the program in bytes. If a program has been loaded to the VM already, the calculator
     /// of the program in bytes. If a program has been loaded to the VM already, the calculator
     /// is immediately run.
     /// is immediately run.
-    /// 
+    ///
     /// # Examples
     /// # Examples
-    /// 
+    ///
     /// ```
     /// ```
     /// use rbpf::lib::{Error, ErrorKind};
     /// use rbpf::lib::{Error, ErrorKind};
     /// use rbpf::ebpf;
     /// use rbpf::ebpf;
@@ -302,12 +302,12 @@ impl<'a> EbpfVmMbuff<'a> {
     ///    // Here we just return a fixed value.
     ///    // Here we just return a fixed value.
     ///    16
     ///    16
     /// }
     /// }
-    /// 
+    ///
     /// let prog1 = &[
     /// let prog1 = &[
     ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
     ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
     ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
     ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
     /// ];
     /// ];
-    /// 
+    ///
     /// // Instantiate a VM.
     /// // Instantiate a VM.
     /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
     /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
     /// // Change the stack usage calculator.
     /// // Change the stack usage calculator.
@@ -445,7 +445,14 @@ impl<'a> EbpfVmMbuff<'a> {
     /// ```
     /// ```
     pub fn execute_program(&self, mem: &[u8], mbuff: &[u8]) -> Result<u64, Error> {
     pub fn execute_program(&self, mem: &[u8], mbuff: &[u8]) -> Result<u64, Error> {
         let stack_usage = self.stack_usage.as_ref();
         let stack_usage = self.stack_usage.as_ref();
-        interpreter::execute_program(self.prog, stack_usage, mem, mbuff, &self.helpers, &self.allowed_memory)
+        interpreter::execute_program(
+            self.prog,
+            stack_usage,
+            mem,
+            mbuff,
+            &self.helpers,
+            &self.allowed_memory,
+        )
     }
     }
 
 
     /// JIT-compile the loaded program. No argument required for this.
     /// JIT-compile the loaded program. No argument required for this.

+ 0 - 1
src/no_std_error.rs

@@ -39,4 +39,3 @@ pub enum ErrorKind {
     #[allow(dead_code)]
     #[allow(dead_code)]
     Other,
     Other,
 }
 }
-

+ 24 - 12
src/verifier.rs

@@ -18,7 +18,6 @@
 //
 //
 // Contrary to the verifier of the Linux kernel, this one does not modify the bytecode at all.
 // Contrary to the verifier of the Linux kernel, this one does not modify the bytecode at all.
 
 
-
 use crate::ebpf;
 use crate::ebpf;
 use crate::lib::*;
 use crate::lib::*;
 
 
@@ -29,12 +28,17 @@ fn reject<S: AsRef<str>>(msg: S) -> Result<(), Error> {
 
 
 fn check_prog_len(prog: &[u8]) -> Result<(), Error> {
 fn check_prog_len(prog: &[u8]) -> Result<(), Error> {
     if prog.len() % ebpf::INSN_SIZE != 0 {
     if prog.len() % ebpf::INSN_SIZE != 0 {
-        reject(format!("eBPF program length must be a multiple of {:?} octets",
-                       ebpf::INSN_SIZE))?;
+        reject(format!(
+            "eBPF program length must be a multiple of {:?} octets",
+            ebpf::INSN_SIZE
+        ))?;
     }
     }
     if prog.len() > ebpf::PROG_MAX_SIZE {
     if prog.len() > ebpf::PROG_MAX_SIZE {
-        reject(format!("eBPF program length limited to {:?}, here {:?}",
-                       ebpf::PROG_MAX_INSNS, prog.len() / ebpf::INSN_SIZE))?;
+        reject(format!(
+            "eBPF program length limited to {:?}, here {:?}",
+            ebpf::PROG_MAX_INSNS,
+            prog.len() / ebpf::INSN_SIZE
+        ))?;
     }
     }
 
 
     if prog.is_empty() {
     if prog.is_empty() {
@@ -51,7 +55,9 @@ fn check_prog_len(prog: &[u8]) -> Result<(), Error> {
 fn check_imm_endian(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), Error> {
 fn check_imm_endian(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), Error> {
     match insn.imm {
     match insn.imm {
         16 | 32 | 64 => Ok(()),
         16 | 32 | 64 => Ok(()),
-        _ => reject(format!("unsupported argument for LE/BE (insn #{insn_ptr:?})"))
+        _ => reject(format!(
+            "unsupported argument for LE/BE (insn #{insn_ptr:?})"
+        )),
     }
     }
 }
 }
 
 
@@ -74,12 +80,16 @@ fn check_jmp_offset(prog: &[u8], insn_ptr: usize) -> Result<(), Error> {
 
 
     let dst_insn_ptr = insn_ptr as isize + 1 + insn.off as isize;
     let dst_insn_ptr = insn_ptr as isize + 1 + insn.off as isize;
     if dst_insn_ptr < 0 || dst_insn_ptr as usize >= (prog.len() / ebpf::INSN_SIZE) {
     if dst_insn_ptr < 0 || dst_insn_ptr as usize >= (prog.len() / ebpf::INSN_SIZE) {
-        reject(format!("jump out of code to #{dst_insn_ptr:?} (insn #{insn_ptr:?})"))?;
+        reject(format!(
+            "jump out of code to #{dst_insn_ptr:?} (insn #{insn_ptr:?})"
+        ))?;
     }
     }
 
 
     let dst_insn = ebpf::get_insn(prog, dst_insn_ptr as usize);
     let dst_insn = ebpf::get_insn(prog, dst_insn_ptr as usize);
     if dst_insn.opc == 0 {
     if dst_insn.opc == 0 {
-        reject(format!("jump to middle of LD_DW at #{dst_insn_ptr:?} (insn #{insn_ptr:?})"))?;
+        reject(format!(
+            "jump to middle of LD_DW at #{dst_insn_ptr:?} (insn #{insn_ptr:?})"
+        ))?;
     }
     }
 
 
     Ok(())
     Ok(())
@@ -91,16 +101,18 @@ fn check_registers(insn: &ebpf::Insn, store: bool, insn_ptr: usize) -> Result<()
     }
     }
 
 
     match (insn.dst, store) {
     match (insn.dst, store) {
-        (0 ..= 9, _) | (10, true) => Ok(()),
-        (10, false) => reject(format!("cannot write into register r10 (insn #{insn_ptr:?})")),
-        (_, _)      => reject(format!("invalid destination register (insn #{insn_ptr:?})"))
+        (0..=9, _) | (10, true) => Ok(()),
+        (10, false) => reject(format!(
+            "cannot write into register r10 (insn #{insn_ptr:?})"
+        )),
+        (_, _) => reject(format!("invalid destination register (insn #{insn_ptr:?})")),
     }
     }
 }
 }
 
 
 pub fn check(prog: &[u8]) -> Result<(), Error> {
 pub fn check(prog: &[u8]) -> Result<(), Error> {
     check_prog_len(prog)?;
     check_prog_len(prog)?;
 
 
-    let mut insn_ptr:usize = 0;
+    let mut insn_ptr: usize = 0;
     while insn_ptr * ebpf::INSN_SIZE < prog.len() {
     while insn_ptr * ebpf::INSN_SIZE < prog.len() {
         let insn = ebpf::get_insn(prog, insn_ptr);
         let insn = ebpf::get_insn(prog, insn_ptr);
         let mut store = false;
         let mut store = false;

+ 340 - 220
tests/assembler.rs

@@ -36,10 +36,14 @@ fn test_exit() {
 // Example for InstructionType::AluBinary.
 // Example for InstructionType::AluBinary.
 #[test]
 #[test]
 fn test_add64() {
 fn test_add64() {
-    assert_eq!(asm("add64 r1, r3"),
-               Ok(vec![insn(ebpf::ADD64_REG, 1, 3, 0, 0)]));
-    assert_eq!(asm("add64 r1, 5"),
-               Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, 5)]));
+    assert_eq!(
+        asm("add64 r1, r3"),
+        Ok(vec![insn(ebpf::ADD64_REG, 1, 3, 0, 0)])
+    );
+    assert_eq!(
+        asm("add64 r1, 5"),
+        Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, 5)])
+    );
 }
 }
 
 
 // Example for InstructionType::AluUnary.
 // Example for InstructionType::AluUnary.
@@ -51,22 +55,28 @@ fn test_neg64() {
 // Example for InstructionType::LoadReg.
 // Example for InstructionType::LoadReg.
 #[test]
 #[test]
 fn test_ldxw() {
 fn test_ldxw() {
-    assert_eq!(asm("ldxw r1, [r2+5]"),
-               Ok(vec![insn(ebpf::LD_W_REG, 1, 2, 5, 0)]));
+    assert_eq!(
+        asm("ldxw r1, [r2+5]"),
+        Ok(vec![insn(ebpf::LD_W_REG, 1, 2, 5, 0)])
+    );
 }
 }
 
 
 // Example for InstructionType::StoreImm.
 // Example for InstructionType::StoreImm.
 #[test]
 #[test]
 fn test_stw() {
 fn test_stw() {
-    assert_eq!(asm("stw [r2+5], 7"),
-               Ok(vec![insn(ebpf::ST_W_IMM, 2, 0, 5, 7)]));
+    assert_eq!(
+        asm("stw [r2+5], 7"),
+        Ok(vec![insn(ebpf::ST_W_IMM, 2, 0, 5, 7)])
+    );
 }
 }
 
 
 // Example for InstructionType::StoreReg.
 // Example for InstructionType::StoreReg.
 #[test]
 #[test]
 fn test_stxw() {
 fn test_stxw() {
-    assert_eq!(asm("stxw [r2+5], r8"),
-               Ok(vec![insn(ebpf::ST_W_REG, 2, 8, 5, 0)]));
+    assert_eq!(
+        asm("stxw [r2+5], r8"),
+        Ok(vec![insn(ebpf::ST_W_REG, 2, 8, 5, 0)])
+    );
 }
 }
 
 
 // Example for InstructionType::JumpUnconditional.
 // Example for InstructionType::JumpUnconditional.
@@ -79,10 +89,14 @@ fn test_ja() {
 // Example for InstructionType::JumpConditional.
 // Example for InstructionType::JumpConditional.
 #[test]
 #[test]
 fn test_jeq() {
 fn test_jeq() {
-    assert_eq!(asm("jeq r1, 4, +8"),
-               Ok(vec![insn(ebpf::JEQ_IMM, 1, 0, 8, 4)]));
-    assert_eq!(asm("jeq r1, r3, +8"),
-               Ok(vec![insn(ebpf::JEQ_REG, 1, 3, 8, 0)]));
+    assert_eq!(
+        asm("jeq r1, 4, +8"),
+        Ok(vec![insn(ebpf::JEQ_IMM, 1, 0, 8, 4)])
+    );
+    assert_eq!(
+        asm("jeq r1, r3, +8"),
+        Ok(vec![insn(ebpf::JEQ_REG, 1, 3, 8, 0)])
+    );
 }
 }
 
 
 // Example for InstructionType::Call.
 // Example for InstructionType::Call.
@@ -100,11 +114,20 @@ fn test_be32() {
 // Example for InstructionType::LoadImm.
 // Example for InstructionType::LoadImm.
 #[test]
 #[test]
 fn test_lddw() {
 fn test_lddw() {
-    assert_eq!(asm("lddw r1, 0x1234abcd5678eeff"),
-               Ok(vec![insn(ebpf::LD_DW_IMM, 1, 0, 0, 0x5678eeff), insn(0, 0, 0, 0, 0x1234abcd)]));
-    assert_eq!(asm("lddw r1, 0xff11ee22dd33cc44"),
-               Ok(vec![insn(ebpf::LD_DW_IMM, 1, 0, 0, 0xdd33cc44u32 as i32),
-                       insn(0, 0, 0, 0, 0xff11ee22u32 as i32)]));
+    assert_eq!(
+        asm("lddw r1, 0x1234abcd5678eeff"),
+        Ok(vec![
+            insn(ebpf::LD_DW_IMM, 1, 0, 0, 0x5678eeff),
+            insn(0, 0, 0, 0, 0x1234abcd)
+        ])
+    );
+    assert_eq!(
+        asm("lddw r1, 0xff11ee22dd33cc44"),
+        Ok(vec![
+            insn(ebpf::LD_DW_IMM, 1, 0, 0, 0xdd33cc44u32 as i32),
+            insn(0, 0, 0, 0, 0xff11ee22u32 as i32)
+        ])
+    );
 }
 }
 
 
 // Example for InstructionType::LoadAbs.
 // Example for InstructionType::LoadAbs.
@@ -116,35 +139,44 @@ fn test_ldabsw() {
 // Example for InstructionType::LoadInd.
 // Example for InstructionType::LoadInd.
 #[test]
 #[test]
 fn test_ldindw() {
 fn test_ldindw() {
-    assert_eq!(asm("ldindw r1, 2"),
-               Ok(vec![insn(ebpf::LD_IND_W, 0, 1, 0, 2)]));
+    assert_eq!(
+        asm("ldindw r1, 2"),
+        Ok(vec![insn(ebpf::LD_IND_W, 0, 1, 0, 2)])
+    );
 }
 }
 
 
 // Example for InstructionType::LoadReg.
 // Example for InstructionType::LoadReg.
 #[test]
 #[test]
 fn test_ldxdw() {
 fn test_ldxdw() {
-    assert_eq!(asm("ldxdw r1, [r2+3]"),
-               Ok(vec![insn(ebpf::LD_DW_REG, 1, 2, 3, 0)]));
+    assert_eq!(
+        asm("ldxdw r1, [r2+3]"),
+        Ok(vec![insn(ebpf::LD_DW_REG, 1, 2, 3, 0)])
+    );
 }
 }
 
 
 // Example for InstructionType::StoreImm.
 // Example for InstructionType::StoreImm.
 #[test]
 #[test]
 fn test_sth() {
 fn test_sth() {
-    assert_eq!(asm("sth [r1+2], 3"),
-               Ok(vec![insn(ebpf::ST_H_IMM, 1, 0, 2, 3)]));
+    assert_eq!(
+        asm("sth [r1+2], 3"),
+        Ok(vec![insn(ebpf::ST_H_IMM, 1, 0, 2, 3)])
+    );
 }
 }
 
 
 // Example for InstructionType::StoreReg.
 // Example for InstructionType::StoreReg.
 #[test]
 #[test]
 fn test_stxh() {
 fn test_stxh() {
-    assert_eq!(asm("stxh [r1+2], r3"),
-               Ok(vec![insn(ebpf::ST_H_REG, 1, 3, 2, 0)]));
+    assert_eq!(
+        asm("stxh [r1+2], r3"),
+        Ok(vec![insn(ebpf::ST_H_REG, 1, 3, 2, 0)])
+    );
 }
 }
 
 
 // Test all supported AluBinary mnemonics.
 // Test all supported AluBinary mnemonics.
 #[test]
 #[test]
 fn test_alu_binary() {
 fn test_alu_binary() {
-    assert_eq!(asm("
+    assert_eq!(
+        asm("
             add r1, r2
             add r1, r2
             sub r1, r2
             sub r1, r2
             mul r1, r2
             mul r1, r2
@@ -158,20 +190,24 @@ fn test_alu_binary() {
             mov r1, r2
             mov r1, r2
             arsh r1, r2
             arsh r1, r2
         "),
         "),
-               Ok(vec![insn(ebpf::ADD64_REG, 1, 2, 0, 0),
-                       insn(ebpf::SUB64_REG, 1, 2, 0, 0),
-                       insn(ebpf::MUL64_REG, 1, 2, 0, 0),
-                       insn(ebpf::DIV64_REG, 1, 2, 0, 0),
-                       insn(ebpf::OR64_REG, 1, 2, 0, 0),
-                       insn(ebpf::AND64_REG, 1, 2, 0, 0),
-                       insn(ebpf::LSH64_REG, 1, 2, 0, 0),
-                       insn(ebpf::RSH64_REG, 1, 2, 0, 0),
-                       insn(ebpf::MOD64_REG, 1, 2, 0, 0),
-                       insn(ebpf::XOR64_REG, 1, 2, 0, 0),
-                       insn(ebpf::MOV64_REG, 1, 2, 0, 0),
-                       insn(ebpf::ARSH64_REG, 1, 2, 0, 0)]));
-
-    assert_eq!(asm("
+        Ok(vec![
+            insn(ebpf::ADD64_REG, 1, 2, 0, 0),
+            insn(ebpf::SUB64_REG, 1, 2, 0, 0),
+            insn(ebpf::MUL64_REG, 1, 2, 0, 0),
+            insn(ebpf::DIV64_REG, 1, 2, 0, 0),
+            insn(ebpf::OR64_REG, 1, 2, 0, 0),
+            insn(ebpf::AND64_REG, 1, 2, 0, 0),
+            insn(ebpf::LSH64_REG, 1, 2, 0, 0),
+            insn(ebpf::RSH64_REG, 1, 2, 0, 0),
+            insn(ebpf::MOD64_REG, 1, 2, 0, 0),
+            insn(ebpf::XOR64_REG, 1, 2, 0, 0),
+            insn(ebpf::MOV64_REG, 1, 2, 0, 0),
+            insn(ebpf::ARSH64_REG, 1, 2, 0, 0)
+        ])
+    );
+
+    assert_eq!(
+        asm("
             add r1, 2
             add r1, 2
             sub r1, 2
             sub r1, 2
             mul r1, 2
             mul r1, 2
@@ -185,20 +221,24 @@ fn test_alu_binary() {
             mov r1, 2
             mov r1, 2
             arsh r1, 2
             arsh r1, 2
         "),
         "),
-               Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::SUB64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::MUL64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::DIV64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::OR64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::AND64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::LSH64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::RSH64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::MOD64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::XOR64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::MOV64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::ARSH64_IMM, 1, 0, 0, 2)]));
-
-    assert_eq!(asm("
+        Ok(vec![
+            insn(ebpf::ADD64_IMM, 1, 0, 0, 2),
+            insn(ebpf::SUB64_IMM, 1, 0, 0, 2),
+            insn(ebpf::MUL64_IMM, 1, 0, 0, 2),
+            insn(ebpf::DIV64_IMM, 1, 0, 0, 2),
+            insn(ebpf::OR64_IMM, 1, 0, 0, 2),
+            insn(ebpf::AND64_IMM, 1, 0, 0, 2),
+            insn(ebpf::LSH64_IMM, 1, 0, 0, 2),
+            insn(ebpf::RSH64_IMM, 1, 0, 0, 2),
+            insn(ebpf::MOD64_IMM, 1, 0, 0, 2),
+            insn(ebpf::XOR64_IMM, 1, 0, 0, 2),
+            insn(ebpf::MOV64_IMM, 1, 0, 0, 2),
+            insn(ebpf::ARSH64_IMM, 1, 0, 0, 2)
+        ])
+    );
+
+    assert_eq!(
+        asm("
             add64 r1, r2
             add64 r1, r2
             sub64 r1, r2
             sub64 r1, r2
             mul64 r1, r2
             mul64 r1, r2
@@ -212,20 +252,24 @@ fn test_alu_binary() {
             mov64 r1, r2
             mov64 r1, r2
             arsh64 r1, r2
             arsh64 r1, r2
         "),
         "),
-               Ok(vec![insn(ebpf::ADD64_REG, 1, 2, 0, 0),
-                       insn(ebpf::SUB64_REG, 1, 2, 0, 0),
-                       insn(ebpf::MUL64_REG, 1, 2, 0, 0),
-                       insn(ebpf::DIV64_REG, 1, 2, 0, 0),
-                       insn(ebpf::OR64_REG, 1, 2, 0, 0),
-                       insn(ebpf::AND64_REG, 1, 2, 0, 0),
-                       insn(ebpf::LSH64_REG, 1, 2, 0, 0),
-                       insn(ebpf::RSH64_REG, 1, 2, 0, 0),
-                       insn(ebpf::MOD64_REG, 1, 2, 0, 0),
-                       insn(ebpf::XOR64_REG, 1, 2, 0, 0),
-                       insn(ebpf::MOV64_REG, 1, 2, 0, 0),
-                       insn(ebpf::ARSH64_REG, 1, 2, 0, 0)]));
-
-    assert_eq!(asm("
+        Ok(vec![
+            insn(ebpf::ADD64_REG, 1, 2, 0, 0),
+            insn(ebpf::SUB64_REG, 1, 2, 0, 0),
+            insn(ebpf::MUL64_REG, 1, 2, 0, 0),
+            insn(ebpf::DIV64_REG, 1, 2, 0, 0),
+            insn(ebpf::OR64_REG, 1, 2, 0, 0),
+            insn(ebpf::AND64_REG, 1, 2, 0, 0),
+            insn(ebpf::LSH64_REG, 1, 2, 0, 0),
+            insn(ebpf::RSH64_REG, 1, 2, 0, 0),
+            insn(ebpf::MOD64_REG, 1, 2, 0, 0),
+            insn(ebpf::XOR64_REG, 1, 2, 0, 0),
+            insn(ebpf::MOV64_REG, 1, 2, 0, 0),
+            insn(ebpf::ARSH64_REG, 1, 2, 0, 0)
+        ])
+    );
+
+    assert_eq!(
+        asm("
             add64 r1, 2
             add64 r1, 2
             sub64 r1, 2
             sub64 r1, 2
             mul64 r1, 2
             mul64 r1, 2
@@ -239,20 +283,24 @@ fn test_alu_binary() {
             mov64 r1, 2
             mov64 r1, 2
             arsh64 r1, 2
             arsh64 r1, 2
         "),
         "),
-               Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::SUB64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::MUL64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::DIV64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::OR64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::AND64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::LSH64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::RSH64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::MOD64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::XOR64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::MOV64_IMM, 1, 0, 0, 2),
-                       insn(ebpf::ARSH64_IMM, 1, 0, 0, 2)]));
-
-    assert_eq!(asm("
+        Ok(vec![
+            insn(ebpf::ADD64_IMM, 1, 0, 0, 2),
+            insn(ebpf::SUB64_IMM, 1, 0, 0, 2),
+            insn(ebpf::MUL64_IMM, 1, 0, 0, 2),
+            insn(ebpf::DIV64_IMM, 1, 0, 0, 2),
+            insn(ebpf::OR64_IMM, 1, 0, 0, 2),
+            insn(ebpf::AND64_IMM, 1, 0, 0, 2),
+            insn(ebpf::LSH64_IMM, 1, 0, 0, 2),
+            insn(ebpf::RSH64_IMM, 1, 0, 0, 2),
+            insn(ebpf::MOD64_IMM, 1, 0, 0, 2),
+            insn(ebpf::XOR64_IMM, 1, 0, 0, 2),
+            insn(ebpf::MOV64_IMM, 1, 0, 0, 2),
+            insn(ebpf::ARSH64_IMM, 1, 0, 0, 2)
+        ])
+    );
+
+    assert_eq!(
+        asm("
             add32 r1, r2
             add32 r1, r2
             sub32 r1, r2
             sub32 r1, r2
             mul32 r1, r2
             mul32 r1, r2
@@ -266,20 +314,24 @@ fn test_alu_binary() {
             mov32 r1, r2
             mov32 r1, r2
             arsh32 r1, r2
             arsh32 r1, r2
         "),
         "),
-               Ok(vec![insn(ebpf::ADD32_REG, 1, 2, 0, 0),
-                       insn(ebpf::SUB32_REG, 1, 2, 0, 0),
-                       insn(ebpf::MUL32_REG, 1, 2, 0, 0),
-                       insn(ebpf::DIV32_REG, 1, 2, 0, 0),
-                       insn(ebpf::OR32_REG, 1, 2, 0, 0),
-                       insn(ebpf::AND32_REG, 1, 2, 0, 0),
-                       insn(ebpf::LSH32_REG, 1, 2, 0, 0),
-                       insn(ebpf::RSH32_REG, 1, 2, 0, 0),
-                       insn(ebpf::MOD32_REG, 1, 2, 0, 0),
-                       insn(ebpf::XOR32_REG, 1, 2, 0, 0),
-                       insn(ebpf::MOV32_REG, 1, 2, 0, 0),
-                       insn(ebpf::ARSH32_REG, 1, 2, 0, 0)]));
-
-    assert_eq!(asm("
+        Ok(vec![
+            insn(ebpf::ADD32_REG, 1, 2, 0, 0),
+            insn(ebpf::SUB32_REG, 1, 2, 0, 0),
+            insn(ebpf::MUL32_REG, 1, 2, 0, 0),
+            insn(ebpf::DIV32_REG, 1, 2, 0, 0),
+            insn(ebpf::OR32_REG, 1, 2, 0, 0),
+            insn(ebpf::AND32_REG, 1, 2, 0, 0),
+            insn(ebpf::LSH32_REG, 1, 2, 0, 0),
+            insn(ebpf::RSH32_REG, 1, 2, 0, 0),
+            insn(ebpf::MOD32_REG, 1, 2, 0, 0),
+            insn(ebpf::XOR32_REG, 1, 2, 0, 0),
+            insn(ebpf::MOV32_REG, 1, 2, 0, 0),
+            insn(ebpf::ARSH32_REG, 1, 2, 0, 0)
+        ])
+    );
+
+    assert_eq!(
+        asm("
             add32 r1, 2
             add32 r1, 2
             sub32 r1, 2
             sub32 r1, 2
             mul32 r1, 2
             mul32 r1, 2
@@ -293,112 +345,140 @@ fn test_alu_binary() {
             mov32 r1, 2
             mov32 r1, 2
             arsh32 r1, 2
             arsh32 r1, 2
         "),
         "),
-               Ok(vec![insn(ebpf::ADD32_IMM, 1, 0, 0, 2),
-                       insn(ebpf::SUB32_IMM, 1, 0, 0, 2),
-                       insn(ebpf::MUL32_IMM, 1, 0, 0, 2),
-                       insn(ebpf::DIV32_IMM, 1, 0, 0, 2),
-                       insn(ebpf::OR32_IMM, 1, 0, 0, 2),
-                       insn(ebpf::AND32_IMM, 1, 0, 0, 2),
-                       insn(ebpf::LSH32_IMM, 1, 0, 0, 2),
-                       insn(ebpf::RSH32_IMM, 1, 0, 0, 2),
-                       insn(ebpf::MOD32_IMM, 1, 0, 0, 2),
-                       insn(ebpf::XOR32_IMM, 1, 0, 0, 2),
-                       insn(ebpf::MOV32_IMM, 1, 0, 0, 2),
-                       insn(ebpf::ARSH32_IMM, 1, 0, 0, 2)]));
+        Ok(vec![
+            insn(ebpf::ADD32_IMM, 1, 0, 0, 2),
+            insn(ebpf::SUB32_IMM, 1, 0, 0, 2),
+            insn(ebpf::MUL32_IMM, 1, 0, 0, 2),
+            insn(ebpf::DIV32_IMM, 1, 0, 0, 2),
+            insn(ebpf::OR32_IMM, 1, 0, 0, 2),
+            insn(ebpf::AND32_IMM, 1, 0, 0, 2),
+            insn(ebpf::LSH32_IMM, 1, 0, 0, 2),
+            insn(ebpf::RSH32_IMM, 1, 0, 0, 2),
+            insn(ebpf::MOD32_IMM, 1, 0, 0, 2),
+            insn(ebpf::XOR32_IMM, 1, 0, 0, 2),
+            insn(ebpf::MOV32_IMM, 1, 0, 0, 2),
+            insn(ebpf::ARSH32_IMM, 1, 0, 0, 2)
+        ])
+    );
 }
 }
 
 
 // Test all supported AluUnary mnemonics.
 // Test all supported AluUnary mnemonics.
 #[test]
 #[test]
 fn test_alu_unary() {
 fn test_alu_unary() {
-    assert_eq!(asm("
+    assert_eq!(
+        asm("
             neg r1
             neg r1
             neg64 r1
             neg64 r1
             neg32 r1
             neg32 r1
         "),
         "),
-               Ok(vec![insn(ebpf::NEG64, 1, 0, 0, 0),
-                       insn(ebpf::NEG64, 1, 0, 0, 0),
-                       insn(ebpf::NEG32, 1, 0, 0, 0)]));
+        Ok(vec![
+            insn(ebpf::NEG64, 1, 0, 0, 0),
+            insn(ebpf::NEG64, 1, 0, 0, 0),
+            insn(ebpf::NEG32, 1, 0, 0, 0)
+        ])
+    );
 }
 }
 
 
 // Test all supported LoadAbs mnemonics.
 // Test all supported LoadAbs mnemonics.
 #[test]
 #[test]
 fn test_load_abs() {
 fn test_load_abs() {
-    assert_eq!(asm("
+    assert_eq!(
+        asm("
             ldabsw 1
             ldabsw 1
             ldabsh 1
             ldabsh 1
             ldabsb 1
             ldabsb 1
             ldabsdw 1
             ldabsdw 1
         "),
         "),
-               Ok(vec![insn(ebpf::LD_ABS_W, 0, 0, 0, 1),
-                       insn(ebpf::LD_ABS_H, 0, 0, 0, 1),
-                       insn(ebpf::LD_ABS_B, 0, 0, 0, 1),
-                       insn(ebpf::LD_ABS_DW, 0, 0, 0, 1)]));
+        Ok(vec![
+            insn(ebpf::LD_ABS_W, 0, 0, 0, 1),
+            insn(ebpf::LD_ABS_H, 0, 0, 0, 1),
+            insn(ebpf::LD_ABS_B, 0, 0, 0, 1),
+            insn(ebpf::LD_ABS_DW, 0, 0, 0, 1)
+        ])
+    );
 }
 }
 
 
 // Test all supported LoadInd mnemonics.
 // Test all supported LoadInd mnemonics.
 #[test]
 #[test]
 fn test_load_ind() {
 fn test_load_ind() {
-    assert_eq!(asm("
+    assert_eq!(
+        asm("
             ldindw r1, 2
             ldindw r1, 2
             ldindh r1, 2
             ldindh r1, 2
             ldindb r1, 2
             ldindb r1, 2
             ldinddw r1, 2
             ldinddw r1, 2
         "),
         "),
-               Ok(vec![insn(ebpf::LD_IND_W, 0, 1, 0, 2),
-                       insn(ebpf::LD_IND_H, 0, 1, 0, 2),
-                       insn(ebpf::LD_IND_B, 0, 1, 0, 2),
-                       insn(ebpf::LD_IND_DW, 0, 1, 0, 2)]));
+        Ok(vec![
+            insn(ebpf::LD_IND_W, 0, 1, 0, 2),
+            insn(ebpf::LD_IND_H, 0, 1, 0, 2),
+            insn(ebpf::LD_IND_B, 0, 1, 0, 2),
+            insn(ebpf::LD_IND_DW, 0, 1, 0, 2)
+        ])
+    );
 }
 }
 
 
 // Test all supported LoadReg mnemonics.
 // Test all supported LoadReg mnemonics.
 #[test]
 #[test]
 fn test_load_reg() {
 fn test_load_reg() {
-    assert_eq!(asm("
+    assert_eq!(
+        asm("
             ldxw r1, [r2+3]
             ldxw r1, [r2+3]
             ldxh r1, [r2+3]
             ldxh r1, [r2+3]
             ldxb r1, [r2+3]
             ldxb r1, [r2+3]
             ldxdw r1, [r2+3]
             ldxdw r1, [r2+3]
         "),
         "),
-               Ok(vec![insn(ebpf::LD_W_REG, 1, 2, 3, 0),
-                       insn(ebpf::LD_H_REG, 1, 2, 3, 0),
-                       insn(ebpf::LD_B_REG, 1, 2, 3, 0),
-                       insn(ebpf::LD_DW_REG, 1, 2, 3, 0)]));
+        Ok(vec![
+            insn(ebpf::LD_W_REG, 1, 2, 3, 0),
+            insn(ebpf::LD_H_REG, 1, 2, 3, 0),
+            insn(ebpf::LD_B_REG, 1, 2, 3, 0),
+            insn(ebpf::LD_DW_REG, 1, 2, 3, 0)
+        ])
+    );
 }
 }
 
 
 // Test all supported StoreImm mnemonics.
 // Test all supported StoreImm mnemonics.
 #[test]
 #[test]
 fn test_store_imm() {
 fn test_store_imm() {
-    assert_eq!(asm("
+    assert_eq!(
+        asm("
             stw [r1+2], 3
             stw [r1+2], 3
             sth [r1+2], 3
             sth [r1+2], 3
             stb [r1+2], 3
             stb [r1+2], 3
             stdw [r1+2], 3
             stdw [r1+2], 3
         "),
         "),
-               Ok(vec![insn(ebpf::ST_W_IMM, 1, 0, 2, 3),
-                       insn(ebpf::ST_H_IMM, 1, 0, 2, 3),
-                       insn(ebpf::ST_B_IMM, 1, 0, 2, 3),
-                       insn(ebpf::ST_DW_IMM, 1, 0, 2, 3)]));
+        Ok(vec![
+            insn(ebpf::ST_W_IMM, 1, 0, 2, 3),
+            insn(ebpf::ST_H_IMM, 1, 0, 2, 3),
+            insn(ebpf::ST_B_IMM, 1, 0, 2, 3),
+            insn(ebpf::ST_DW_IMM, 1, 0, 2, 3)
+        ])
+    );
 }
 }
 
 
 // Test all supported StoreReg mnemonics.
 // Test all supported StoreReg mnemonics.
 #[test]
 #[test]
 fn test_store_reg() {
 fn test_store_reg() {
-    assert_eq!(asm("
+    assert_eq!(
+        asm("
             stxw [r1+2], r3
             stxw [r1+2], r3
             stxh [r1+2], r3
             stxh [r1+2], r3
             stxb [r1+2], r3
             stxb [r1+2], r3
             stxdw [r1+2], r3
             stxdw [r1+2], r3
         "),
         "),
-               Ok(vec![insn(ebpf::ST_W_REG, 1, 3, 2, 0),
-                       insn(ebpf::ST_H_REG, 1, 3, 2, 0),
-                       insn(ebpf::ST_B_REG, 1, 3, 2, 0),
-                       insn(ebpf::ST_DW_REG, 1, 3, 2, 0)]));
+        Ok(vec![
+            insn(ebpf::ST_W_REG, 1, 3, 2, 0),
+            insn(ebpf::ST_H_REG, 1, 3, 2, 0),
+            insn(ebpf::ST_B_REG, 1, 3, 2, 0),
+            insn(ebpf::ST_DW_REG, 1, 3, 2, 0)
+        ])
+    );
 }
 }
 
 
 // Test all supported JumpConditional mnemonics.
 // Test all supported JumpConditional mnemonics.
 #[test]
 #[test]
 fn test_jump_conditional() {
 fn test_jump_conditional() {
-    assert_eq!(asm("
+    assert_eq!(
+        asm("
             jeq r1, r2, +3
             jeq r1, r2, +3
             jgt r1, r2, +3
             jgt r1, r2, +3
             jge r1, r2, +3
             jge r1, r2, +3
@@ -411,19 +491,23 @@ fn test_jump_conditional() {
             jslt r1, r2, +3
             jslt r1, r2, +3
             jsle r1, r2, +3
             jsle r1, r2, +3
         "),
         "),
-               Ok(vec![insn(ebpf::JEQ_REG, 1, 2, 3, 0),
-                       insn(ebpf::JGT_REG, 1, 2, 3, 0),
-                       insn(ebpf::JGE_REG, 1, 2, 3, 0),
-                       insn(ebpf::JLT_REG, 1, 2, 3, 0),
-                       insn(ebpf::JLE_REG, 1, 2, 3, 0),
-                       insn(ebpf::JSET_REG, 1, 2, 3, 0),
-                       insn(ebpf::JNE_REG, 1, 2, 3, 0),
-                       insn(ebpf::JSGT_REG, 1, 2, 3, 0),
-                       insn(ebpf::JSGE_REG, 1, 2, 3, 0),
-                       insn(ebpf::JSLT_REG, 1, 2, 3, 0),
-                       insn(ebpf::JSLE_REG, 1, 2, 3, 0)]));
-
-    assert_eq!(asm("
+        Ok(vec![
+            insn(ebpf::JEQ_REG, 1, 2, 3, 0),
+            insn(ebpf::JGT_REG, 1, 2, 3, 0),
+            insn(ebpf::JGE_REG, 1, 2, 3, 0),
+            insn(ebpf::JLT_REG, 1, 2, 3, 0),
+            insn(ebpf::JLE_REG, 1, 2, 3, 0),
+            insn(ebpf::JSET_REG, 1, 2, 3, 0),
+            insn(ebpf::JNE_REG, 1, 2, 3, 0),
+            insn(ebpf::JSGT_REG, 1, 2, 3, 0),
+            insn(ebpf::JSGE_REG, 1, 2, 3, 0),
+            insn(ebpf::JSLT_REG, 1, 2, 3, 0),
+            insn(ebpf::JSLE_REG, 1, 2, 3, 0)
+        ])
+    );
+
+    assert_eq!(
+        asm("
             jeq r1, 2, +3
             jeq r1, 2, +3
             jgt r1, 2, +3
             jgt r1, 2, +3
             jge r1, 2, +3
             jge r1, 2, +3
@@ -436,19 +520,23 @@ fn test_jump_conditional() {
             jslt r1, 2, +3
             jslt r1, 2, +3
             jsle r1, 2, +3
             jsle r1, 2, +3
         "),
         "),
-               Ok(vec![insn(ebpf::JEQ_IMM, 1, 0, 3, 2),
-                       insn(ebpf::JGT_IMM, 1, 0, 3, 2),
-                       insn(ebpf::JGE_IMM, 1, 0, 3, 2),
-                       insn(ebpf::JLT_IMM, 1, 0, 3, 2),
-                       insn(ebpf::JLE_IMM, 1, 0, 3, 2),
-                       insn(ebpf::JSET_IMM, 1, 0, 3, 2),
-                       insn(ebpf::JNE_IMM, 1, 0, 3, 2),
-                       insn(ebpf::JSGT_IMM, 1, 0, 3, 2),
-                       insn(ebpf::JSGE_IMM, 1, 0, 3, 2),
-                       insn(ebpf::JSLT_IMM, 1, 0, 3, 2),
-                       insn(ebpf::JSLE_IMM, 1, 0, 3, 2)]));
-
-    assert_eq!(asm("
+        Ok(vec![
+            insn(ebpf::JEQ_IMM, 1, 0, 3, 2),
+            insn(ebpf::JGT_IMM, 1, 0, 3, 2),
+            insn(ebpf::JGE_IMM, 1, 0, 3, 2),
+            insn(ebpf::JLT_IMM, 1, 0, 3, 2),
+            insn(ebpf::JLE_IMM, 1, 0, 3, 2),
+            insn(ebpf::JSET_IMM, 1, 0, 3, 2),
+            insn(ebpf::JNE_IMM, 1, 0, 3, 2),
+            insn(ebpf::JSGT_IMM, 1, 0, 3, 2),
+            insn(ebpf::JSGE_IMM, 1, 0, 3, 2),
+            insn(ebpf::JSLT_IMM, 1, 0, 3, 2),
+            insn(ebpf::JSLE_IMM, 1, 0, 3, 2)
+        ])
+    );
+
+    assert_eq!(
+        asm("
             jeq32 r1, r2, +3
             jeq32 r1, r2, +3
             jgt32 r1, r2, +3
             jgt32 r1, r2, +3
             jge32 r1, r2, +3
             jge32 r1, r2, +3
@@ -461,19 +549,23 @@ fn test_jump_conditional() {
             jslt32 r1, r2, +3
             jslt32 r1, r2, +3
             jsle32 r1, r2, +3
             jsle32 r1, r2, +3
         "),
         "),
-               Ok(vec![insn(ebpf::JEQ_REG32, 1, 2, 3, 0),
-                       insn(ebpf::JGT_REG32, 1, 2, 3, 0),
-                       insn(ebpf::JGE_REG32, 1, 2, 3, 0),
-                       insn(ebpf::JLT_REG32, 1, 2, 3, 0),
-                       insn(ebpf::JLE_REG32, 1, 2, 3, 0),
-                       insn(ebpf::JSET_REG32, 1, 2, 3, 0),
-                       insn(ebpf::JNE_REG32, 1, 2, 3, 0),
-                       insn(ebpf::JSGT_REG32, 1, 2, 3, 0),
-                       insn(ebpf::JSGE_REG32, 1, 2, 3, 0),
-                       insn(ebpf::JSLT_REG32, 1, 2, 3, 0),
-                       insn(ebpf::JSLE_REG32, 1, 2, 3, 0)]));
-
-    assert_eq!(asm("
+        Ok(vec![
+            insn(ebpf::JEQ_REG32, 1, 2, 3, 0),
+            insn(ebpf::JGT_REG32, 1, 2, 3, 0),
+            insn(ebpf::JGE_REG32, 1, 2, 3, 0),
+            insn(ebpf::JLT_REG32, 1, 2, 3, 0),
+            insn(ebpf::JLE_REG32, 1, 2, 3, 0),
+            insn(ebpf::JSET_REG32, 1, 2, 3, 0),
+            insn(ebpf::JNE_REG32, 1, 2, 3, 0),
+            insn(ebpf::JSGT_REG32, 1, 2, 3, 0),
+            insn(ebpf::JSGE_REG32, 1, 2, 3, 0),
+            insn(ebpf::JSLT_REG32, 1, 2, 3, 0),
+            insn(ebpf::JSLE_REG32, 1, 2, 3, 0)
+        ])
+    );
+
+    assert_eq!(
+        asm("
             jeq32 r1, 2, +3
             jeq32 r1, 2, +3
             jgt32 r1, 2, +3
             jgt32 r1, 2, +3
             jge32 r1, 2, +3
             jge32 r1, 2, +3
@@ -486,23 +578,27 @@ fn test_jump_conditional() {
             jslt32 r1, 2, +3
             jslt32 r1, 2, +3
             jsle32 r1, 2, +3
             jsle32 r1, 2, +3
         "),
         "),
-               Ok(vec![insn(ebpf::JEQ_IMM32, 1, 0, 3, 2),
-                       insn(ebpf::JGT_IMM32, 1, 0, 3, 2),
-                       insn(ebpf::JGE_IMM32, 1, 0, 3, 2),
-                       insn(ebpf::JLT_IMM32, 1, 0, 3, 2),
-                       insn(ebpf::JLE_IMM32, 1, 0, 3, 2),
-                       insn(ebpf::JSET_IMM32, 1, 0, 3, 2),
-                       insn(ebpf::JNE_IMM32, 1, 0, 3, 2),
-                       insn(ebpf::JSGT_IMM32, 1, 0, 3, 2),
-                       insn(ebpf::JSGE_IMM32, 1, 0, 3, 2),
-                       insn(ebpf::JSLT_IMM32, 1, 0, 3, 2),
-                       insn(ebpf::JSLE_IMM32, 1, 0, 3, 2)]));
+        Ok(vec![
+            insn(ebpf::JEQ_IMM32, 1, 0, 3, 2),
+            insn(ebpf::JGT_IMM32, 1, 0, 3, 2),
+            insn(ebpf::JGE_IMM32, 1, 0, 3, 2),
+            insn(ebpf::JLT_IMM32, 1, 0, 3, 2),
+            insn(ebpf::JLE_IMM32, 1, 0, 3, 2),
+            insn(ebpf::JSET_IMM32, 1, 0, 3, 2),
+            insn(ebpf::JNE_IMM32, 1, 0, 3, 2),
+            insn(ebpf::JSGT_IMM32, 1, 0, 3, 2),
+            insn(ebpf::JSGE_IMM32, 1, 0, 3, 2),
+            insn(ebpf::JSLT_IMM32, 1, 0, 3, 2),
+            insn(ebpf::JSLE_IMM32, 1, 0, 3, 2)
+        ])
+    );
 }
 }
 
 
 // Test all supported Endian mnemonics.
 // Test all supported Endian mnemonics.
 #[test]
 #[test]
 fn test_endian() {
 fn test_endian() {
-    assert_eq!(asm("
+    assert_eq!(
+        asm("
             be16 r1
             be16 r1
             be32 r1
             be32 r1
             be64 r1
             be64 r1
@@ -510,20 +606,27 @@ fn test_endian() {
             le32 r1
             le32 r1
             le64 r1
             le64 r1
         "),
         "),
-               Ok(vec![insn(ebpf::BE, 1, 0, 0, 16),
-                       insn(ebpf::BE, 1, 0, 0, 32),
-                       insn(ebpf::BE, 1, 0, 0, 64),
-                       insn(ebpf::LE, 1, 0, 0, 16),
-                       insn(ebpf::LE, 1, 0, 0, 32),
-                       insn(ebpf::LE, 1, 0, 0, 64)]));
+        Ok(vec![
+            insn(ebpf::BE, 1, 0, 0, 16),
+            insn(ebpf::BE, 1, 0, 0, 32),
+            insn(ebpf::BE, 1, 0, 0, 64),
+            insn(ebpf::LE, 1, 0, 0, 16),
+            insn(ebpf::LE, 1, 0, 0, 32),
+            insn(ebpf::LE, 1, 0, 0, 64)
+        ])
+    );
 }
 }
 
 
 #[test]
 #[test]
 fn test_large_immediate() {
 fn test_large_immediate() {
-    assert_eq!(asm("add64 r1, 2147483647"),
-               Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, 2147483647)]));
-    assert_eq!(asm("add64 r1, -2147483648"),
-               Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, -2147483648)]));
+    assert_eq!(
+        asm("add64 r1, 2147483647"),
+        Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, 2147483647)])
+    );
+    assert_eq!(
+        asm("add64 r1, -2147483648"),
+        Ok(vec![insn(ebpf::ADD64_IMM, 1, 0, 0, -2147483648)])
+    );
 }
 }
 
 
 #[test]
 #[test]
@@ -538,31 +641,48 @@ fn test_error_invalid_instruction() {
 
 
 #[test]
 #[test]
 fn test_error_unexpected_operands() {
 fn test_error_unexpected_operands() {
-    assert_eq!(asm("add 1, 2"),
-               Err("Failed to encode add: Unexpected operands: [Integer(1), Integer(2)]"
-                   .to_string()));
+    assert_eq!(
+        asm("add 1, 2"),
+        Err("Failed to encode add: Unexpected operands: [Integer(1), Integer(2)]".to_string())
+    );
 }
 }
 
 
 #[test]
 #[test]
 fn test_error_too_many_operands() {
 fn test_error_too_many_operands() {
-    assert_eq!(asm("add 1, 2, 3, 4"),
-               Err("Failed to encode add: Too many operands".to_string()));
+    assert_eq!(
+        asm("add 1, 2, 3, 4"),
+        Err("Failed to encode add: Too many operands".to_string())
+    );
 }
 }
 
 
 #[test]
 #[test]
 fn test_error_operands_out_of_range() {
 fn test_error_operands_out_of_range() {
-    assert_eq!(asm("add r16, r2"),
-               Err("Failed to encode add: Invalid destination register 16".to_string()));
-    assert_eq!(asm("add r1, r16"),
-               Err("Failed to encode add: Invalid source register 16".to_string()));
-    assert_eq!(asm("ja -32769"),
-               Err("Failed to encode ja: Invalid offset -32769".to_string()));
-    assert_eq!(asm("ja 32768"),
-               Err("Failed to encode ja: Invalid offset 32768".to_string()));
-    assert_eq!(asm("add r1, 4294967296"),
-               Err("Failed to encode add: Invalid immediate 4294967296".to_string()));
-    assert_eq!(asm("add r1, 2147483648"),
-               Err("Failed to encode add: Invalid immediate 2147483648".to_string()));
-    assert_eq!(asm("add r1, -2147483649"),
-               Err("Failed to encode add: Invalid immediate -2147483649".to_string()));
+    assert_eq!(
+        asm("add r16, r2"),
+        Err("Failed to encode add: Invalid destination register 16".to_string())
+    );
+    assert_eq!(
+        asm("add r1, r16"),
+        Err("Failed to encode add: Invalid source register 16".to_string())
+    );
+    assert_eq!(
+        asm("ja -32769"),
+        Err("Failed to encode ja: Invalid offset -32769".to_string())
+    );
+    assert_eq!(
+        asm("ja 32768"),
+        Err("Failed to encode ja: Invalid offset 32768".to_string())
+    );
+    assert_eq!(
+        asm("add r1, 4294967296"),
+        Err("Failed to encode add: Invalid immediate 4294967296".to_string())
+    );
+    assert_eq!(
+        asm("add r1, 2147483648"),
+        Err("Failed to encode add: Invalid immediate 2147483648".to_string())
+    );
+    assert_eq!(
+        asm("add r1, -2147483649"),
+        Err("Failed to encode add: Invalid immediate -2147483649".to_string())
+    );
 }
 }

+ 25 - 8
tests/cranelift.rs

@@ -278,7 +278,8 @@ fn test_cranelift_call() {
 #[test]
 #[test]
 #[should_panic(expected = "[CRANELIFT] Error: unknown helper function (id: 0x3f)")]
 #[should_panic(expected = "[CRANELIFT] Error: unknown helper function (id: 0x3f)")]
 fn test_cranelift_err_call_unreg() {
 fn test_cranelift_err_call_unreg() {
-    let prog = assemble("
+    let prog = assemble(
+        "
          mov r1, 1
          mov r1, 1
          mov r2, 2
          mov r2, 2
          mov r3, 3
          mov r3, 3
@@ -286,7 +287,9 @@ fn test_cranelift_err_call_unreg() {
          mov r5, 5
          mov r5, 5
          call 63
          call 63
          exit
          exit
-    ").unwrap();
+    ",
+    )
+    .unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.cranelift_compile().unwrap();
     vm.cranelift_compile().unwrap();
 }
 }
@@ -309,7 +312,10 @@ fn test_cranelift_call_memfrob() {
     vm.register_helper(1, helpers::memfrob).unwrap();
     vm.register_helper(1, helpers::memfrob).unwrap();
     let mem = &mut [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
     let mem = &mut [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08];
     vm.cranelift_compile().unwrap();
     vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem).unwrap(), 0x102292e2f2c0708);
+    assert_eq!(
+        vm.execute_program_cranelift(mem).unwrap(),
+        0x102292e2f2c0708
+    );
 }
 }
 
 
 test_cranelift!(
 test_cranelift!(
@@ -2108,7 +2114,10 @@ fn test_cranelift_tcp_sack_match() {
     let prog = assemble(TCP_SACK_ASM).unwrap();
     let prog = assemble(TCP_SACK_ASM).unwrap();
     let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.cranelift_compile().unwrap();
     vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem.as_mut_slice()).unwrap(), 0x1);
+    assert_eq!(
+        vm.execute_program_cranelift(mem.as_mut_slice()).unwrap(),
+        0x1
+    );
 }
 }
 
 
 #[test]
 #[test]
@@ -2117,10 +2126,12 @@ fn test_cranelift_tcp_sack_nomatch() {
     let prog = assemble(TCP_SACK_ASM).unwrap();
     let prog = assemble(TCP_SACK_ASM).unwrap();
     let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.cranelift_compile().unwrap();
     vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem.as_mut_slice()).unwrap(), 0x0);
+    assert_eq!(
+        vm.execute_program_cranelift(mem.as_mut_slice()).unwrap(),
+        0x0
+    );
 }
 }
 
 
-
 #[test]
 #[test]
 fn test_cranelift_ldabsb() {
 fn test_cranelift_ldabsb() {
     #[rustfmt::skip]
     #[rustfmt::skip]
@@ -2190,7 +2201,10 @@ fn test_cranelift_ldabsdw() {
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x00, 0x08).unwrap();
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x00, 0x08).unwrap();
 
 
     vm.cranelift_compile().unwrap();
     vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem).unwrap(), 0xaa99887766554433);
+    assert_eq!(
+        vm.execute_program_cranelift(mem).unwrap(),
+        0xaa99887766554433
+    );
 }
 }
 
 
 #[test]
 #[test]
@@ -2266,5 +2280,8 @@ fn test_cranelift_ldinddw() {
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x00, 0x08).unwrap();
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x00, 0x08).unwrap();
 
 
     vm.cranelift_compile().unwrap();
     vm.cranelift_compile().unwrap();
-    assert_eq!(vm.execute_program_cranelift(mem).unwrap(), 0xccbbaa9988776655);
+    assert_eq!(
+        vm.execute_program_cranelift(mem).unwrap(),
+        0xccbbaa9988776655
+    );
 }
 }

+ 88 - 42
tests/disassembler.rs

@@ -11,16 +11,23 @@ use rbpf::disassembler::to_insn_vec;
 
 
 // Using a macro to keep actual line numbers in failure output
 // Using a macro to keep actual line numbers in failure output
 macro_rules! disasm {
 macro_rules! disasm {
-    ($src:expr) => {
-        {
-            let src = $src.trim().lines().map(|l| l.trim()).collect::<Vec<_>>().join("\n");
-            let asm = assemble(&src).expect("Can't assemble from string");
-            let insn = to_insn_vec(&asm);
-            let reasm = insn.into_iter().map(|ins| ins.desc).collect::<Vec<_>>().join("\n");
-
-            assert_eq!(src, reasm);
-        }
-    }
+    ($src:expr) => {{
+        let src = $src
+            .trim()
+            .lines()
+            .map(|l| l.trim())
+            .collect::<Vec<_>>()
+            .join("\n");
+        let asm = assemble(&src).expect("Can't assemble from string");
+        let insn = to_insn_vec(&asm);
+        let reasm = insn
+            .into_iter()
+            .map(|ins| ins.desc)
+            .collect::<Vec<_>>()
+            .join("\n");
+
+        assert_eq!(src, reasm);
+    }};
 }
 }
 
 
 #[test]
 #[test]
@@ -130,7 +137,8 @@ fn test_stxh() {
 // Test all supported AluBinary mnemonics.
 // Test all supported AluBinary mnemonics.
 #[test]
 #[test]
 fn test_alu_binary() {
 fn test_alu_binary() {
-    disasm!("
+    disasm!(
+        "
         add64 r1, r2
         add64 r1, r2
         sub64 r1, r2
         sub64 r1, r2
         mul64 r1, r2
         mul64 r1, r2
@@ -143,9 +151,11 @@ fn test_alu_binary() {
         xor64 r1, r2
         xor64 r1, r2
         mov64 r1, r2
         mov64 r1, r2
         arsh64 r1, r2
         arsh64 r1, r2
-        ");
+        "
+    );
 
 
-    disasm!("
+    disasm!(
+        "
         add64 r1, 0x2
         add64 r1, 0x2
         sub64 r1, 0x2
         sub64 r1, 0x2
         mul64 r1, 0x2
         mul64 r1, 0x2
@@ -158,9 +168,11 @@ fn test_alu_binary() {
         xor64 r1, 0x2
         xor64 r1, 0x2
         mov64 r1, 0x2
         mov64 r1, 0x2
         arsh64 r1, 0x2
         arsh64 r1, 0x2
-        ");
+        "
+    );
 
 
-    disasm!("
+    disasm!(
+        "
         add32 r1, r2
         add32 r1, r2
         sub32 r1, r2
         sub32 r1, r2
         mul32 r1, r2
         mul32 r1, r2
@@ -173,9 +185,11 @@ fn test_alu_binary() {
         xor32 r1, r2
         xor32 r1, r2
         mov32 r1, r2
         mov32 r1, r2
         arsh32 r1, r2
         arsh32 r1, r2
-        ");
+        "
+    );
 
 
-    disasm!("
+    disasm!(
+        "
         add32 r1, 0x2
         add32 r1, 0x2
         sub32 r1, 0x2
         sub32 r1, 0x2
         mul32 r1, 0x2
         mul32 r1, 0x2
@@ -188,77 +202,91 @@ fn test_alu_binary() {
         xor32 r1, 0x2
         xor32 r1, 0x2
         mov32 r1, 0x2
         mov32 r1, 0x2
         arsh32 r1, 0x2
         arsh32 r1, 0x2
-        ");
+        "
+    );
 }
 }
 
 
 // Test all supported AluUnary mnemonics.
 // Test all supported AluUnary mnemonics.
 #[test]
 #[test]
 fn test_alu_unary() {
 fn test_alu_unary() {
-    disasm!("
+    disasm!(
+        "
         neg64 r1
         neg64 r1
         neg32 r1
         neg32 r1
-        ");
+        "
+    );
 }
 }
 
 
 // Test all supported LoadAbs mnemonics.
 // Test all supported LoadAbs mnemonics.
 #[test]
 #[test]
 fn test_load_abs() {
 fn test_load_abs() {
-    disasm!("
+    disasm!(
+        "
         ldabsw 0x1
         ldabsw 0x1
         ldabsh 0x1
         ldabsh 0x1
         ldabsb 0x1
         ldabsb 0x1
         ldabsdw 0x1
         ldabsdw 0x1
-        ");
+        "
+    );
 }
 }
 
 
 // Test all supported LoadInd mnemonics.
 // Test all supported LoadInd mnemonics.
 #[test]
 #[test]
 fn test_load_ind() {
 fn test_load_ind() {
-    disasm!("
+    disasm!(
+        "
         ldindw r1, 0x2
         ldindw r1, 0x2
         ldindh r1, 0x2
         ldindh r1, 0x2
         ldindb r1, 0x2
         ldindb r1, 0x2
         ldinddw r1, 0x2
         ldinddw r1, 0x2
-        ");
+        "
+    );
 }
 }
 
 
 // Test all supported LoadReg mnemonics.
 // Test all supported LoadReg mnemonics.
 #[test]
 #[test]
 fn test_load_reg() {
 fn test_load_reg() {
-    disasm!(r"
+    disasm!(
+        r"
         ldxw r1, [r2+0x3]
         ldxw r1, [r2+0x3]
         ldxh r1, [r2+0x3]
         ldxh r1, [r2+0x3]
         ldxb r1, [r2+0x3]
         ldxb r1, [r2+0x3]
         ldxdw r1, [r2+0x3]
         ldxdw r1, [r2+0x3]
-        ");
+        "
+    );
 }
 }
 
 
 // Test all supported StoreImm mnemonics.
 // Test all supported StoreImm mnemonics.
 #[test]
 #[test]
 fn test_store_imm() {
 fn test_store_imm() {
-    disasm!("
+    disasm!(
+        "
         stw [r1+0x2], 0x3
         stw [r1+0x2], 0x3
         sth [r1+0x2], 0x3
         sth [r1+0x2], 0x3
         stb [r1+0x2], 0x3
         stb [r1+0x2], 0x3
         stdw [r1+0x2], 0x3
         stdw [r1+0x2], 0x3
-        ");
+        "
+    );
 }
 }
 
 
 // Test all supported StoreReg mnemonics.
 // Test all supported StoreReg mnemonics.
 #[test]
 #[test]
 fn test_store_reg() {
 fn test_store_reg() {
-    disasm!("
+    disasm!(
+        "
         stxw [r1+0x2], r3
         stxw [r1+0x2], r3
         stxh [r1+0x2], r3
         stxh [r1+0x2], r3
         stxb [r1+0x2], r3
         stxb [r1+0x2], r3
         stxdw [r1+0x2], r3
         stxdw [r1+0x2], r3
-        ");
+        "
+    );
 }
 }
 
 
 // Test all supported JumpConditional mnemonics.
 // Test all supported JumpConditional mnemonics.
 #[test]
 #[test]
 fn test_jump_conditional() {
 fn test_jump_conditional() {
-    disasm!("
+    disasm!(
+        "
         jeq r1, r2, +0x3
         jeq r1, r2, +0x3
         jgt r1, r2, +0x3
         jgt r1, r2, +0x3
         jge r1, r2, +0x3
         jge r1, r2, +0x3
@@ -270,9 +298,11 @@ fn test_jump_conditional() {
         jsge r1, r2, -0x3
         jsge r1, r2, -0x3
         jslt r1, r2, +0x3
         jslt r1, r2, +0x3
         jsle r1, r2, -0x3
         jsle r1, r2, -0x3
-        ");
+        "
+    );
 
 
-    disasm!("
+    disasm!(
+        "
         jeq r1, 0x2, +0x3
         jeq r1, 0x2, +0x3
         jgt r1, 0x2, +0x3
         jgt r1, 0x2, +0x3
         jge r1, 0x2, +0x3
         jge r1, 0x2, +0x3
@@ -284,9 +314,11 @@ fn test_jump_conditional() {
         jsge r1, 0x2, -0x3
         jsge r1, 0x2, -0x3
         jslt r1, 0x2, +0x3
         jslt r1, 0x2, +0x3
         jsle r1, 0x2, -0x3
         jsle r1, 0x2, -0x3
-        ");
+        "
+    );
 
 
-    disasm!("
+    disasm!(
+        "
         jeq32 r1, r2, +0x3
         jeq32 r1, r2, +0x3
         jgt32 r1, r2, +0x3
         jgt32 r1, r2, +0x3
         jge32 r1, r2, +0x3
         jge32 r1, r2, +0x3
@@ -298,9 +330,11 @@ fn test_jump_conditional() {
         jsge32 r1, r2, -0x3
         jsge32 r1, r2, -0x3
         jslt32 r1, r2, +0x3
         jslt32 r1, r2, +0x3
         jsle32 r1, r2, -0x3
         jsle32 r1, r2, -0x3
-        ");
+        "
+    );
 
 
-    disasm!("
+    disasm!(
+        "
         jeq32 r1, 0x2, +0x3
         jeq32 r1, 0x2, +0x3
         jgt32 r1, 0x2, +0x3
         jgt32 r1, 0x2, +0x3
         jge32 r1, 0x2, +0x3
         jge32 r1, 0x2, +0x3
@@ -312,20 +346,23 @@ fn test_jump_conditional() {
         jsge32 r1, 0x2, -0x3
         jsge32 r1, 0x2, -0x3
         jslt32 r1, 0x2, +0x3
         jslt32 r1, 0x2, +0x3
         jsle32 r1, 0x2, -0x3
         jsle32 r1, 0x2, -0x3
-        ");
+        "
+    );
 }
 }
 
 
 // Test all supported Endian mnemonics.
 // Test all supported Endian mnemonics.
 #[test]
 #[test]
 fn test_endian() {
 fn test_endian() {
-    disasm!("
+    disasm!(
+        "
         be16 r1
         be16 r1
         be32 r1
         be32 r1
         be64 r1
         be64 r1
         le16 r1
         le16 r1
         le32 r1
         le32 r1
         le64 r1
         le64 r1
-        ");
+        "
+    );
 }
 }
 
 
 #[test]
 #[test]
@@ -366,10 +403,19 @@ fn test_offset_overflow() {
         jeq r1, r2, -0x8000
         jeq r1, r2, -0x8000
         jeq32 r1, 0x2, -0x8000
         jeq32 r1, 0x2, -0x8000
         jeq32 r1, r2, -0x8000
         jeq32 r1, r2, -0x8000
-    ".trim().lines().map(|l| l.trim()).collect::<Vec<_>>().join("\n");
+    "
+    .trim()
+    .lines()
+    .map(|l| l.trim())
+    .collect::<Vec<_>>()
+    .join("\n");
 
 
     let prog = to_insn_vec(&insns);
     let prog = to_insn_vec(&insns);
-    let asm = prog.into_iter().map(|ins| ins.desc).collect::<Vec<_>>().join("\n");
+    let asm = prog
+        .into_iter()
+        .map(|ins| ins.desc)
+        .collect::<Vec<_>>()
+        .join("\n");
 
 
     assert_eq!(asm, expected_output);
     assert_eq!(asm, expected_output);
 }
 }

+ 52 - 43
tests/misc.rs

@@ -15,10 +15,10 @@
 
 
 extern crate rbpf;
 extern crate rbpf;
 
 
-use rbpf::lib::{Error, ErrorKind};
 use rbpf::assembler::assemble;
 use rbpf::assembler::assemble;
 #[cfg(feature = "std")]
 #[cfg(feature = "std")]
 use rbpf::helpers;
 use rbpf::helpers;
+use rbpf::lib::{Error, ErrorKind};
 
 
 // The following two examples have been compiled from C with the following command:
 // The following two examples have been compiled from C with the following command:
 //
 //
@@ -163,7 +163,8 @@ fn test_vm_block_port() {
     ];
     ];
 
 
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf).unwrap();
+    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf)
+        .unwrap();
 
 
     let res = vm.execute_program(packet).unwrap();
     let res = vm.execute_program(packet).unwrap();
     println!("Program returned: {res:?} ({res:#x})");
     println!("Program returned: {res:?} ({res:#x})");
@@ -247,7 +248,8 @@ fn test_jit_block_port() {
     ];
     ];
 
 
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf).unwrap();
+    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf)
+        .unwrap();
     vm.jit_compile().unwrap();
     vm.jit_compile().unwrap();
 
 
     unsafe {
     unsafe {
@@ -268,13 +270,11 @@ fn test_vm_mbuff() {
         0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     ];
     ];
-    let mem = &[
-        0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
-    ];
+    let mem = &[0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd];
 
 
     let mbuff = [0u8; 32];
     let mbuff = [0u8; 32];
     unsafe {
     unsafe {
-        let data     = mbuff.as_ptr().offset(8)  as *mut u64;
+        let data = mbuff.as_ptr().offset(8) as *mut u64;
         let data_end = mbuff.as_ptr().offset(24) as *mut u64;
         let data_end = mbuff.as_ptr().offset(24) as *mut u64;
         data.write_unaligned(mem.as_ptr() as u64);
         data.write_unaligned(mem.as_ptr() as u64);
         data_end.write_unaligned(mem.as_ptr() as u64 + mem.len() as u64);
         data_end.write_unaligned(mem.as_ptr() as u64 + mem.len() as u64);
@@ -291,19 +291,26 @@ fn test_vm_mbuff_with_rust_api() {
 
 
     let mut program = BpfCode::new();
     let mut program = BpfCode::new();
     program
     program
-        .load_x(MemSize::DoubleWord).set_dst(0x01).set_src(0x01).set_off(0x00_08).push()
-        .load_x(MemSize::HalfWord).set_dst(0x00).set_src(0x01).set_off(0x00_02).push()
-        .exit().push();
-
-    let mem = &[
-        0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
-    ];
+        .load_x(MemSize::DoubleWord)
+        .set_dst(0x01)
+        .set_src(0x01)
+        .set_off(0x00_08)
+        .push()
+        .load_x(MemSize::HalfWord)
+        .set_dst(0x00)
+        .set_src(0x01)
+        .set_off(0x00_02)
+        .push()
+        .exit()
+        .push();
+
+    let mem = &[0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd];
 
 
     let mbuff = [0u8; 32];
     let mbuff = [0u8; 32];
     unsafe {
     unsafe {
-        let data     = mbuff.as_ptr().offset(8)  as *mut u64;
+        let data = mbuff.as_ptr().offset(8) as *mut u64;
         let data_end = mbuff.as_ptr().offset(24) as *mut u64;
         let data_end = mbuff.as_ptr().offset(24) as *mut u64;
-        *data     = mem.as_ptr() as u64;
+        *data = mem.as_ptr() as u64;
         *data_end = mem.as_ptr() as u64 + mem.len() as u64;
         *data_end = mem.as_ptr() as u64 + mem.len() as u64;
     }
     }
 
 
@@ -323,15 +330,13 @@ fn test_jit_mbuff() {
         0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x69, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     ];
     ];
-    let mem = &mut [
-        0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
-    ];
+    let mem = &mut [0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd];
 
 
     let mut mbuff = [0u8; 32];
     let mut mbuff = [0u8; 32];
     unsafe {
     unsafe {
-        let data     = mbuff.as_ptr().offset(8)  as *mut u64;
+        let data = mbuff.as_ptr().offset(8) as *mut u64;
         let data_end = mbuff.as_ptr().offset(24) as *mut u64;
         let data_end = mbuff.as_ptr().offset(24) as *mut u64;
-        *data     = mem.as_ptr() as u64;
+        *data = mem.as_ptr() as u64;
         *data_end = mem.as_ptr() as u64 + mem.len() as u64;
         *data_end = mem.as_ptr() as u64 + mem.len() as u64;
     }
     }
 
 
@@ -602,8 +607,7 @@ fn verifier_success(_prog: &[u8]) -> Result<(), Error> {
 }
 }
 
 
 fn verifier_fail(_prog: &[u8]) -> Result<(), Error> {
 fn verifier_fail(_prog: &[u8]) -> Result<(), Error> {
-    Err(Error::new(ErrorKind::Other,
-                   "Gaggablaghblagh!"))
+    Err(Error::new(ErrorKind::Other, "Gaggablaghblagh!"))
 }
 }
 
 
 #[test]
 #[test]
@@ -611,7 +615,8 @@ fn test_verifier_success() {
     let prog = assemble(
     let prog = assemble(
         "mov32 r0, 0xBEE
         "mov32 r0, 0xBEE
          exit",
          exit",
-    ).unwrap();
+    )
+    .unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
     vm.set_verifier(verifier_success).unwrap();
     vm.set_verifier(verifier_success).unwrap();
     vm.set_program(&prog).unwrap();
     vm.set_program(&prog).unwrap();
@@ -624,7 +629,8 @@ fn test_verifier_fail() {
     let prog = assemble(
     let prog = assemble(
         "mov32 r0, 0xBEE
         "mov32 r0, 0xBEE
          exit",
          exit",
-    ).unwrap();
+    )
+    .unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
     vm.set_verifier(verifier_fail).unwrap();
     vm.set_verifier(verifier_fail).unwrap();
     vm.set_program(&prog).unwrap();
     vm.set_program(&prog).unwrap();
@@ -632,7 +638,7 @@ fn test_verifier_fail() {
 }
 }
 
 
 #[test]
 #[test]
-fn test_vm_bpf_to_bpf_call(){
+fn test_vm_bpf_to_bpf_call() {
     let test_code = assemble(
     let test_code = assemble(
         "
         "
         mov64 r1, 0x10
         mov64 r1, 0x10
@@ -648,15 +654,17 @@ fn test_vm_bpf_to_bpf_call(){
         mov64 r0, r2
         mov64 r0, r2
         add64 r0, r1
         add64 r0, r1
         exit
         exit
-        ").unwrap();
+        ",
+    )
+    .unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&test_code)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&test_code)).unwrap();
-    let vm_res= vm.execute_program().unwrap();
+    let vm_res = vm.execute_program().unwrap();
     assert_eq!(vm_res, 0x10);
     assert_eq!(vm_res, 0x10);
 }
 }
 
 
 #[cfg(all(not(windows), feature = "std"))]
 #[cfg(all(not(windows), feature = "std"))]
 #[test]
 #[test]
-fn test_vm_jit_bpf_to_bpf_call(){
+fn test_vm_jit_bpf_to_bpf_call() {
     let test_code = assemble(
     let test_code = assemble(
         "
         "
         mov64 r1, 0x10
         mov64 r1, 0x10
@@ -672,16 +680,18 @@ fn test_vm_jit_bpf_to_bpf_call(){
         mov64 r0, r2
         mov64 r0, r2
         add64 r0, r1
         add64 r0, r1
         exit
         exit
-        ").unwrap();
+        ",
+    )
+    .unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(Some(&test_code)).unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(Some(&test_code)).unwrap();
     vm.jit_compile().unwrap();
     vm.jit_compile().unwrap();
-    let vm_res= unsafe { vm.execute_program_jit().unwrap() };
+    let vm_res = unsafe { vm.execute_program_jit().unwrap() };
     assert_eq!(vm_res, 0x10);
     assert_eq!(vm_res, 0x10);
 }
 }
 
 
 #[test]
 #[test]
 #[should_panic(expected = "[Verifier] Error: unsupported call type #2 (insn #0)")]
 #[should_panic(expected = "[Verifier] Error: unsupported call type #2 (insn #0)")]
-fn test_verifier_err_other_type_call(){
+fn test_verifier_err_other_type_call() {
     #[rustfmt::skip]
     #[rustfmt::skip]
     let prog = &[
     let prog = &[
         0x85, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
         0x85, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
@@ -693,16 +703,14 @@ fn test_verifier_err_other_type_call(){
 
 
 #[test]
 #[test]
 #[should_panic(expected = "Error: unsupported call type #2 (insn #0)")]
 #[should_panic(expected = "Error: unsupported call type #2 (insn #0)")]
-fn test_vm_other_type_call(){
+fn test_vm_other_type_call() {
     #[rustfmt::skip]
     #[rustfmt::skip]
     let prog = &[
     let prog = &[
         0x85, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
         0x85, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
-    vm.set_verifier(|_|{
-        Ok(())
-    }).unwrap();
+    vm.set_verifier(|_| Ok(())).unwrap();
     vm.set_program(prog).unwrap();
     vm.set_program(prog).unwrap();
     vm.execute_program().unwrap();
     vm.execute_program().unwrap();
 }
 }
@@ -710,16 +718,14 @@ fn test_vm_other_type_call(){
 #[cfg(all(not(windows), feature = "std"))]
 #[cfg(all(not(windows), feature = "std"))]
 #[test]
 #[test]
 #[should_panic(expected = "[JIT] Error: unexpected call type #2 (insn #0)")]
 #[should_panic(expected = "[JIT] Error: unexpected call type #2 (insn #0)")]
-fn test_vm_jit_other_type_call(){
+fn test_vm_jit_other_type_call() {
     #[rustfmt::skip]
     #[rustfmt::skip]
     let prog = &[
     let prog = &[
         0x85, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
         0x85, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     ];
     ];
     let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
-    vm.set_verifier(|_|{
-        Ok(())
-    }).unwrap();
+    vm.set_verifier(|_| Ok(())).unwrap();
     vm.set_program(prog).unwrap();
     vm.set_program(prog).unwrap();
     vm.jit_compile().unwrap();
     vm.jit_compile().unwrap();
     unsafe { vm.execute_program_jit().unwrap() };
     unsafe { vm.execute_program_jit().unwrap() };
@@ -727,7 +733,7 @@ fn test_vm_jit_other_type_call(){
 
 
 #[test]
 #[test]
 #[should_panic(expected = "Error: out of bounds memory store (insn #8)")]
 #[should_panic(expected = "Error: out of bounds memory store (insn #8)")]
-fn test_stack_overflow(){
+fn test_stack_overflow() {
     // The stdw instruction is used to test the stack overflow.
     // The stdw instruction is used to test the stack overflow.
     let test_code = assemble(
     let test_code = assemble(
         "
         "
@@ -745,8 +751,11 @@ fn test_stack_overflow(){
         mov64 r0, r2
         mov64 r0, r2
         add64 r0, r1
         add64 r0, r1
         exit
         exit
-        ").unwrap();
+        ",
+    )
+    .unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(Some(&test_code)).unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(Some(&test_code)).unwrap();
-    vm.set_stack_usage_calculator(|_,_,_| 512, Box::new(())).unwrap();
+    vm.set_stack_usage_calculator(|_, _, _| 512, Box::new(()))
+        .unwrap();
     vm.execute_program().unwrap();
     vm.execute_program().unwrap();
 }
 }

Разлика између датотеке није приказан због своје велике величине
+ 362 - 153
tests/ubpf_jit_x86_64.rs


+ 46 - 20
tests/ubpf_verifier.rs

@@ -50,10 +50,13 @@ fn test_verifier_err_incomplete_lddw() {
 #[test]
 #[test]
 #[should_panic(expected = "[Verifier] Error: infinite loop")]
 #[should_panic(expected = "[Verifier] Error: infinite loop")]
 fn test_verifier_err_infinite_loop() {
 fn test_verifier_err_infinite_loop() {
-    let prog = assemble("
+    let prog = assemble(
+        "
         ja -1
         ja -1
         exit
         exit
-        ").unwrap();
+        ",
+    )
+    .unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.execute_program().unwrap();
     vm.execute_program().unwrap();
 }
 }
@@ -61,10 +64,13 @@ fn test_verifier_err_infinite_loop() {
 #[test]
 #[test]
 #[should_panic(expected = "[Verifier] Error: invalid destination register (insn #0)")]
 #[should_panic(expected = "[Verifier] Error: invalid destination register (insn #0)")]
 fn test_verifier_err_invalid_reg_dst() {
 fn test_verifier_err_invalid_reg_dst() {
-    let prog = assemble("
+    let prog = assemble(
+        "
         mov r11, 1
         mov r11, 1
         exit
         exit
-        ").unwrap();
+        ",
+    )
+    .unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.execute_program().unwrap();
     vm.execute_program().unwrap();
 }
 }
@@ -72,10 +78,13 @@ fn test_verifier_err_invalid_reg_dst() {
 #[test]
 #[test]
 #[should_panic(expected = "[Verifier] Error: invalid source register (insn #0)")]
 #[should_panic(expected = "[Verifier] Error: invalid source register (insn #0)")]
 fn test_verifier_err_invalid_reg_src() {
 fn test_verifier_err_invalid_reg_src() {
-    let prog = assemble("
+    let prog = assemble(
+        "
         mov r0, r11
         mov r0, r11
         exit
         exit
-        ").unwrap();
+        ",
+    )
+    .unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.execute_program().unwrap();
     vm.execute_program().unwrap();
 }
 }
@@ -83,11 +92,14 @@ fn test_verifier_err_invalid_reg_src() {
 #[test]
 #[test]
 #[should_panic(expected = "[Verifier] Error: jump to middle of LD_DW at #2 (insn #0)")]
 #[should_panic(expected = "[Verifier] Error: jump to middle of LD_DW at #2 (insn #0)")]
 fn test_verifier_err_jmp_lddw() {
 fn test_verifier_err_jmp_lddw() {
-    let prog = assemble("
+    let prog = assemble(
+        "
         ja +1
         ja +1
         lddw r0, 0x1122334455667788
         lddw r0, 0x1122334455667788
         exit
         exit
-        ").unwrap();
+        ",
+    )
+    .unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.execute_program().unwrap();
     vm.execute_program().unwrap();
 }
 }
@@ -95,10 +107,13 @@ fn test_verifier_err_jmp_lddw() {
 #[test]
 #[test]
 #[should_panic(expected = "[Verifier] Error: jump out of code to #3 (insn #0)")]
 #[should_panic(expected = "[Verifier] Error: jump out of code to #3 (insn #0)")]
 fn test_verifier_err_jmp_out() {
 fn test_verifier_err_jmp_out() {
-    let prog = assemble("
+    let prog = assemble(
+        "
         ja +2
         ja +2
         exit
         exit
-        ").unwrap();
+        ",
+    )
+    .unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.execute_program().unwrap();
     vm.execute_program().unwrap();
 }
 }
@@ -106,18 +121,24 @@ fn test_verifier_err_jmp_out() {
 #[test]
 #[test]
 #[should_panic(expected = "[Verifier] Error: program does not end with “EXIT” instruction")]
 #[should_panic(expected = "[Verifier] Error: program does not end with “EXIT” instruction")]
 fn test_verifier_err_no_exit() {
 fn test_verifier_err_no_exit() {
-    let prog = assemble("
-        mov32 r0, 0").unwrap();
+    let prog = assemble(
+        "
+        mov32 r0, 0",
+    )
+    .unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.execute_program().unwrap();
     vm.execute_program().unwrap();
 }
 }
 
 
 #[test]
 #[test]
 fn test_verifier_err_no_exit_backward_jump() {
 fn test_verifier_err_no_exit_backward_jump() {
-    let prog = assemble("
+    let prog = assemble(
+        "
         ja +1
         ja +1
         exit
         exit
-        ja -2").unwrap();
+        ja -2",
+    )
+    .unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.execute_program().unwrap();
     vm.execute_program().unwrap();
 }
 }
@@ -127,12 +148,14 @@ fn test_verifier_err_no_exit_backward_jump() {
 fn test_verifier_err_too_many_instructions() {
 fn test_verifier_err_too_many_instructions() {
     // uBPF uses 65637 instructions, because it sets its limit at 65636.
     // uBPF uses 65637 instructions, because it sets its limit at 65636.
     // We use the classic 4096 limit from kernel, so no need to produce as many instructions.
     // We use the classic 4096 limit from kernel, so no need to produce as many instructions.
-    let mut prog = (0..(1_000_000 * ebpf::INSN_SIZE)).map( |x| match x % 8 {
+    let mut prog = (0..(1_000_000 * ebpf::INSN_SIZE))
+        .map(|x| match x % 8 {
             0 => 0xb7,
             0 => 0xb7,
             1 => 0x01,
             1 => 0x01,
-            _ => 0
-    }).collect::<Vec<u8>>();
-    prog.append(&mut vec![ 0x95, 0, 0, 0, 0, 0, 0, 0 ]);
+            _ => 0,
+        })
+        .collect::<Vec<u8>>();
+    prog.append(&mut vec![0x95, 0, 0, 0, 0, 0, 0, 0]);
 
 
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.execute_program().unwrap();
     vm.execute_program().unwrap();
@@ -153,10 +176,13 @@ fn test_verifier_err_unknown_opcode() {
 #[test]
 #[test]
 #[should_panic(expected = "[Verifier] Error: cannot write into register r10 (insn #0)")]
 #[should_panic(expected = "[Verifier] Error: cannot write into register r10 (insn #0)")]
 fn test_verifier_err_write_r10() {
 fn test_verifier_err_write_r10() {
-    let prog = assemble("
+    let prog = assemble(
+        "
         mov r10, 1
         mov r10, 1
         exit
         exit
-        ").unwrap();
+        ",
+    )
+    .unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.execute_program().unwrap();
     vm.execute_program().unwrap();
 }
 }

Разлика између датотеке није приказан због своје велике величине
+ 277 - 131
tests/ubpf_vm.rs


Неке датотеке нису приказане због велике количине промена