Quellcode durchsuchen

Customizable verifier (#34)

Customizable bytecode verifier
jackcmay vor 6 Jahren
Ursprung
Commit
4bcf67ad4c
8 geänderte Dateien mit 512 neuen und 288 gelöschten Zeilen
  1. 1 1
      examples/load_elf.rs
  2. 1 1
      examples/uptime.rs
  3. 228 51
      src/lib.rs
  4. 1 0
      src/verifier.rs
  5. 63 17
      tests/misc.rs
  6. 103 103
      tests/ubpf_jit_x86_64.rs
  7. 12 12
      tests/ubpf_verifier.rs
  8. 103 103
      tests/ubpf_vm.rs

+ 1 - 1
examples/load_elf.rs

@@ -111,7 +111,7 @@ fn main() {
         0x64, 0x66, 0x0au8
     ];
 
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(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);
 
     let res = vm.prog_exec(packet1);

+ 1 - 1
examples/uptime.rs

@@ -39,7 +39,7 @@ fn main() {
     ];
 
     // Create a VM: this one takes no data. Load prog1 in it.
-    let mut vm = rbpf::EbpfVmNoData::new(prog1).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(prog1)).unwrap();
     // Execute prog1.
     assert_eq!(vm.prog_exec(), 0x3);
 

+ 228 - 51
src/lib.rs

@@ -40,6 +40,15 @@ mod asm_parser;
 mod jit;
 mod verifier;
 
+/// eBPF verification function that panics if the program does not meet its requirements.
+///
+/// Some examples of things the verifier may panic for:
+///   - program does not terminate
+///   - unknown instructions
+///   - bad formed instruction
+///   - unknown eBPF helper index
+pub type Verifier = fn(prog: &[u8]) -> Result<(), Error>;
+
 // 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
 // actually handle it. The offsets are used to tell the VM where in the buffer the pointers to
@@ -76,16 +85,17 @@ struct MetaBuff {
 /// }
 ///
 /// // Instantiate a VM.
-/// let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
+/// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
 ///
 /// // Provide both a reference to the packet data, and to the metadata buffer.
 /// let res = vm.prog_exec(mem, &mut mbuff);
 /// assert_eq!(res, 0x2211);
 /// ```
 pub struct EbpfVmMbuff<'a> {
-    prog:    &'a [u8],
-    jit:     (unsafe fn (*mut u8, usize, *mut u8, usize, usize, usize) -> u64),
-    helpers: HashMap<u32, ebpf::Helper>,
+    prog:     Option<&'a [u8]>,
+    verifier: Verifier,
+    jit:      (unsafe fn(*mut u8, usize, *mut u8, usize, usize, usize) -> u64),
+    helpers:  HashMap<u32, ebpf::Helper>,
 }
 
 impl<'a> EbpfVmMbuff<'a> {
@@ -103,10 +113,12 @@ impl<'a> EbpfVmMbuff<'a> {
     /// ];
     ///
     /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
+    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
     /// ```
-    pub fn new(prog: &'a [u8]) -> Result<EbpfVmMbuff<'a>, Error> {
-        verifier::check(prog)?;
+    pub fn new(prog: Option<&'a [u8]>) -> Result<EbpfVmMbuff<'a>, Error> {
+        if let Some(prog) = prog {
+            verifier::check(prog)?;
+        }
 
         fn no_jit(_mbuff: *mut u8, _len: usize, _mem: *mut u8, _mem_len: usize,
                   _nodata_offset: usize, _nodata_end_offset: usize) -> u64 {
@@ -114,9 +126,10 @@ impl<'a> EbpfVmMbuff<'a> {
         }
 
         Ok(EbpfVmMbuff {
-            prog:    prog,
-            jit:     no_jit,
-            helpers: HashMap::new(),
+            prog:     prog,
+            verifier: verifier::check,
+            jit:      no_jit,
+            helpers:  HashMap::new(),
         })
     }
 
@@ -136,12 +149,52 @@ impl<'a> EbpfVmMbuff<'a> {
     /// ];
     ///
     /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(prog1).unwrap();
-    /// vm.set_prog(prog2);
+    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
+    /// vm.set_prog(prog2).unwrap();
     /// ```
     pub fn set_prog(&mut self, prog: &'a [u8]) -> Result<(), Error> {
-        verifier::check(prog)?;
-        self.prog = prog;
+        (self.verifier)(prog)?;
+        self.prog = Some(prog);
+        Ok(())
+    }
+
+    /// Set a new verifier function.
+    ///
+    /// # Panics
+    ///
+    /// The simple verifier may panic if it finds errors in the eBPF program at load time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::io::{Error, ErrorKind};
+    /// use rbpf::ebpf;
+    ///
+    /// // simple verifier.
+    /// fn verifier(prog: &[u8]) -> Result<(), Error> {
+    ///     let last_insn = ebpf::get_insn(prog, (prog.len() / ebpf::INSN_SIZE) - 1);
+    ///     if last_insn.opc != ebpf::EXIT {
+    ///         return Err(Error::new(ErrorKind::Other,
+    ///                    "[Verifier] Error: program does not end with “EXIT” instruction"));
+    ///     }
+    ///     Ok(())
+    /// }
+    ///
+    /// let prog1 = &[
+    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
+    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
+    /// ];
+    ///
+    /// // Instantiate a VM.
+    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
+    /// // Change the verifier.
+    /// vm.set_verifier(verifier).unwrap();
+    /// ```
+    pub fn set_verifier(&mut self, verifier: Verifier) -> Result<(), Error> {
+        if let Some(prog) = self.prog {
+            verifier(prog)?;
+        }
+        self.verifier = verifier;
         Ok(())
     }
 
@@ -173,7 +226,7 @@ impl<'a> EbpfVmMbuff<'a> {
     /// ];
     ///
     /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
+    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
     ///
     /// // Register a helper.
     /// // On running the program this helper will print the content of registers r3, r4 and r5 to
@@ -220,7 +273,7 @@ impl<'a> EbpfVmMbuff<'a> {
     /// }
     ///
     /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
+    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
     ///
     /// // Provide both a reference to the packet data, and to the metadata buffer.
     /// let res = vm.prog_exec(mem, &mut mbuff);
@@ -231,6 +284,10 @@ impl<'a> EbpfVmMbuff<'a> {
     pub fn prog_exec(&self, mem: &[u8], mbuff: &[u8]) -> u64 {
         const U32MAX: u64 = u32::MAX as u64;
 
+        let prog = match self.prog { 
+            Some(prog) => prog,
+            None => panic!("Error: No program set, call prog_set() to load one"),
+        };
         let stack = vec![0u8;ebpf::STACK_SIZE];
 
         // R1 points to beginning of memory area, R10 to stack
@@ -253,11 +310,11 @@ impl<'a> EbpfVmMbuff<'a> {
 
         // Loop on instructions
         let mut insn_ptr:usize = 0;
-        while insn_ptr * ebpf::INSN_SIZE < self.prog.len() {
-            let insn = ebpf::get_insn(self.prog, insn_ptr);
+        while insn_ptr * ebpf::INSN_SIZE < prog.len() {
+            let insn = ebpf::get_insn(prog, insn_ptr);
             insn_ptr += 1;
-            let _dst    = insn.dst as usize;
-            let _src    = insn.src as usize;
+            let _dst = insn.dst as usize;
+            let _src = insn.src as usize;
 
             match insn.opc {
 
@@ -307,7 +364,7 @@ impl<'a> EbpfVmMbuff<'a> {
                 },
 
                 ebpf::LD_DW_IMM  => {
-                    let next_insn = ebpf::get_insn(self.prog, insn_ptr);
+                    let next_insn = ebpf::get_insn(prog, insn_ptr);
                     insn_ptr += 1;
                     reg[_dst] = ((insn.imm as u32) as u64) + ((next_insn.imm as u64) << 32);
                 },
@@ -566,13 +623,17 @@ impl<'a> EbpfVmMbuff<'a> {
     /// ];
     ///
     /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
+    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
     ///
     /// vm.jit_compile();
     /// ```
     #[cfg(not(windows))]
     pub fn jit_compile(&mut self) {
-        self.jit = jit::compile(self.prog, &self.helpers, true, false);
+        let prog = match self.prog { 
+            Some(prog) => prog,
+            None => panic!("Error: No program set, call prog_set() to load one"),
+        };
+        self.jit = jit::compile(prog, &self.helpers, true, false);
     }
 
     /// Execute the previously JIT-compiled program, with the given packet data and metadata
@@ -619,7 +680,7 @@ impl<'a> EbpfVmMbuff<'a> {
     /// }
     ///
     /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
+    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
     ///
     /// # #[cfg(not(windows))]
     /// vm.jit_compile();
@@ -705,7 +766,7 @@ impl<'a> EbpfVmMbuff<'a> {
 /// ];
 ///
 /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
-/// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50).unwrap();
+/// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
 ///
 /// // Provide only a reference to the packet data. We do not manage the metadata buffer.
 /// let res = vm.prog_exec(mem1);
@@ -738,9 +799,9 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     /// ];
     ///
     /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
-    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50).unwrap();
+    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
     /// ```
-    pub fn new(prog: &'a [u8], data_offset: usize, data_end_offset: usize) -> Result<EbpfVmFixedMbuff<'a>, Error> {
+    pub fn new(prog: Option<&'a [u8]>, data_offset: usize, data_end_offset: usize) -> Result<EbpfVmFixedMbuff<'a>, Error> {
         let parent = EbpfVmMbuff::new(prog)?;
         let get_buff_len = | x: usize, y: usize | if x >= y { x + 8 } else { y + 8 };
         let buffer = vec![0u8; get_buff_len(data_offset, data_end_offset)];
@@ -781,7 +842,7 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27,
     /// ];
     ///
-    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog1, 0, 0).unwrap();
+    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog1), 0, 0).unwrap();
     /// vm.set_prog(prog2, 0x40, 0x50);
     ///
     /// let res = vm.prog_exec(mem);
@@ -797,6 +858,42 @@ impl<'a> EbpfVmFixedMbuff<'a> {
         Ok(())
     }
 
+    /// Set a new verifier function.
+    ///
+    /// # Panics
+    ///
+    /// The simple verifier may panic if it finds errors in the eBPF program at load time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::io::{Error, ErrorKind};
+    /// use rbpf::ebpf;
+    ///
+    /// // simple verifier.
+    /// fn verifier(prog: &[u8]) -> Result<(), Error> {
+    ///     let last_insn = ebpf::get_insn(prog, (prog.len() / ebpf::INSN_SIZE) - 1);
+    ///     if last_insn.opc != ebpf::EXIT {
+    ///         return Err(Error::new(ErrorKind::Other, 
+    ///                    "[Verifier] Error: program does not end with “EXIT” instruction"));
+    ///     }
+    ///     Ok(())
+    /// }
+    ///
+    /// let prog1 = &[
+    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
+    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
+    /// ];
+    ///
+    /// // Instantiate a VM.
+    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
+    /// // Change the verifier.
+    /// vm.set_verifier(verifier).unwrap();
+    /// ```
+    pub fn set_verifier(&mut self, verifier: Verifier) -> Result<(), Error> {
+        self.parent.set_verifier(verifier)
+    }
+
     /// Register a built-in or user-defined helper function in order to use it later from within
     /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
     ///
@@ -831,7 +928,7 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     /// ];
     ///
     /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50).unwrap();
+    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
     ///
     /// // Register a helper. This helper will store the result of the square root of r1 into r0.
     /// vm.register_helper(1, helpers::sqrti);
@@ -873,7 +970,7 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     /// ];
     ///
     /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
-    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50).unwrap();
+    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
     ///
     /// // Provide only a reference to the packet data. We do not manage the metadata buffer.
     /// let res = vm.prog_exec(mem);
@@ -915,13 +1012,17 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     /// ];
     ///
     /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
-    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50).unwrap();
+    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
     ///
     /// vm.jit_compile();
     /// ```
     #[cfg(not(windows))]
     pub fn jit_compile(&mut self) {
-        self.parent.jit = jit::compile(self.parent.prog, &self.parent.helpers, true, true);
+        let prog = match self.parent.prog { 
+            Some(prog) => prog,
+            None => panic!("Error: No program set, call prog_set() to load one"),
+        };
+        self.parent.jit = jit::compile(prog, &self.parent.helpers, true, true);
     }
 
     /// Execute the previously JIT-compiled program, with the given packet data, in a manner very
@@ -962,7 +1063,7 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     /// ];
     ///
     /// // Instantiate a VM. Note that we provide the start and end offsets for mem pointers.
-    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(prog, 0x40, 0x50).unwrap();
+    /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
     ///
     /// # #[cfg(not(windows))]
     /// vm.jit_compile();
@@ -1007,7 +1108,7 @@ impl<'a> EbpfVmFixedMbuff<'a> {
 /// ];
 ///
 /// // Instantiate a VM.
-/// let vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+/// let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
 ///
 /// // Provide only a reference to the packet data.
 /// let res = vm.prog_exec(mem);
@@ -1033,11 +1134,11 @@ impl<'a> EbpfVmRaw<'a> {
     /// ];
     ///
     /// // Instantiate a VM.
-    /// let vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    /// let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     /// ```
-    pub fn new(prog: &'a [u8]) -> Result<EbpfVmRaw<'a>, Error> {
+    pub fn new(prog: Option<&'a [u8]>) -> Result<EbpfVmRaw<'a>, Error> {
         let parent = EbpfVmMbuff::new(prog)?;
-        Ok(EbpfVmRaw {
+         Ok(EbpfVmRaw {
             parent: parent,
         })
     }
@@ -1062,7 +1163,7 @@ impl<'a> EbpfVmRaw<'a> {
     ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27,
     /// ];
     ///
-    /// let mut vm = rbpf::EbpfVmRaw::new(prog1).unwrap();
+    /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog1)).unwrap();
     /// vm.set_prog(prog2);
     ///
     /// let res = vm.prog_exec(mem);
@@ -1073,6 +1174,42 @@ impl<'a> EbpfVmRaw<'a> {
         Ok(())
     }
 
+    /// Set a new verifier function.
+    ///
+    /// # Panics
+    ///
+    /// The simple verifier may panic if it finds errors in the eBPF program at load time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::io::{Error, ErrorKind};
+    /// use rbpf::ebpf;
+    ///
+    /// // simple verifier.
+    /// fn verifier(prog: &[u8]) -> Result<(), Error> {
+    ///     let last_insn = ebpf::get_insn(prog, (prog.len() / ebpf::INSN_SIZE) - 1);
+    ///     if last_insn.opc != ebpf::EXIT {
+    ///         return Err(Error::new(ErrorKind::Other,
+    ///                    "[Verifier] Error: program does not end with “EXIT” instruction"));
+    ///     }
+    ///     Ok(())
+    /// }
+    ///
+    /// let prog1 = &[
+    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
+    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
+    /// ];
+    ///
+    /// // Instantiate a VM.
+    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
+    /// // Change the verifier.
+    /// vm.set_verifier(verifier).unwrap();
+    /// ```
+    pub fn set_verifier(&mut self, verifier: Verifier) -> Result<(), Error> {
+        self.parent.set_verifier(verifier)
+    }
+
     /// Register a built-in or user-defined helper function in order to use it later from within
     /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
     ///
@@ -1100,7 +1237,7 @@ impl<'a> EbpfVmRaw<'a> {
     /// ];
     ///
     /// // Instantiate a VM.
-    /// let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     ///
     /// // Register a helper. This helper will store the result of the square root of r1 into r0.
     /// vm.register_helper(1, helpers::sqrti);
@@ -1134,7 +1271,7 @@ impl<'a> EbpfVmRaw<'a> {
     ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27
     /// ];
     ///
-    /// let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     ///
     /// let res = vm.prog_exec(mem);
     /// assert_eq!(res, 0x22cc);
@@ -1163,13 +1300,17 @@ impl<'a> EbpfVmRaw<'a> {
     ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
     /// ];
     ///
-    /// let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     ///
     /// vm.jit_compile();
     /// ```
     #[cfg(not(windows))]
     pub fn jit_compile(&mut self) {
-        self.parent.jit = jit::compile(self.parent.prog, &self.parent.helpers, false, false);
+        let prog = match self.parent.prog { 
+            Some(prog) => prog,
+            None => panic!("Error: No program set, call prog_set() to load one"),
+        };
+        self.parent.jit = jit::compile(prog, &self.parent.helpers, false, false);
     }
 
     /// Execute the previously JIT-compiled program, with the given packet data, in a manner very
@@ -1202,7 +1343,7 @@ impl<'a> EbpfVmRaw<'a> {
     ///     0xaa, 0xbb, 0x11, 0x22, 0xcc, 0x27
     /// ];
     ///
-    /// let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     ///
     /// # #[cfg(not(windows))]
     /// vm.jit_compile();
@@ -1252,7 +1393,7 @@ impl<'a> EbpfVmRaw<'a> {
 /// ];
 ///
 /// // Instantiate a VM.
-/// let vm = rbpf::EbpfVmNoData::new(prog).unwrap();
+/// let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
 ///
 /// // Provide only a reference to the packet data.
 /// let res = vm.prog_exec();
@@ -1277,9 +1418,9 @@ impl<'a> EbpfVmNoData<'a> {
     /// ];
     ///
     /// // Instantiate a VM.
-    /// let vm = rbpf::EbpfVmNoData::new(prog).unwrap();
+    /// let vm = rbpf::EbpfVmNoData::new(Some(prog));
     /// ```
-    pub fn new(prog: &'a [u8]) -> Result<EbpfVmNoData<'a>, Error> {
+    pub fn new(prog: Option<&'a [u8]>) -> Result<EbpfVmNoData<'a>, Error> {
         let parent = EbpfVmRaw::new(prog)?;
         Ok(EbpfVmNoData {
             parent: parent,
@@ -1301,7 +1442,7 @@ impl<'a> EbpfVmNoData<'a> {
     ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
     /// ];
     ///
-    /// let mut vm = rbpf::EbpfVmNoData::new(prog1).unwrap();
+    /// let mut vm = rbpf::EbpfVmNoData::new(Some(prog1)).unwrap();
     ///
     /// let res = vm.prog_exec();
     /// assert_eq!(res, 0x2211);
@@ -1316,6 +1457,42 @@ impl<'a> EbpfVmNoData<'a> {
         Ok(())
     }
 
+    /// Set a new verifier function.
+    ///
+    /// # Panics
+    ///
+    /// The simple verifier may panic if it finds errors in the eBPF program at load time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::io::{Error, ErrorKind};
+    /// use rbpf::ebpf;
+    ///
+    /// // simple verifier.
+    /// fn verifier(prog: &[u8]) -> Result<(), Error> {
+    ///     let last_insn = ebpf::get_insn(prog, (prog.len() / ebpf::INSN_SIZE) - 1);
+    ///     if last_insn.opc != ebpf::EXIT {
+    ///         return Err(Error::new(ErrorKind::Other,
+    ///                    "[Verifier] Error: program does not end with “EXIT” instruction"));
+    ///     }
+    ///     Ok(())
+    /// }
+    ///
+    /// let prog1 = &[
+    ///     0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
+    ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
+    /// ];
+    ///
+    /// // Instantiate a VM.
+    /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap();
+    /// // Change the verifier.
+    /// vm.set_verifier(verifier).unwrap();
+    /// ```
+    pub fn set_verifier(&mut self, verifier: Verifier) -> Result<(), Error> {
+        self.parent.set_verifier(verifier)
+    }
+
     /// Register a built-in or user-defined helper function in order to use it later from within
     /// the eBPF program. The helper is registered into a hashmap, so the `key` can be any `u32`.
     ///
@@ -1338,7 +1515,7 @@ impl<'a> EbpfVmNoData<'a> {
     ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
     /// ];
     ///
-    /// let mut vm = rbpf::EbpfVmNoData::new(prog).unwrap();
+    /// let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     ///
     /// // Register a helper. This helper will store the result of the square root of r1 into r0.
     /// vm.register_helper(1, helpers::sqrti);
@@ -1369,7 +1546,7 @@ impl<'a> EbpfVmNoData<'a> {
     ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
     /// ];
     ///
-    /// let mut vm = rbpf::EbpfVmNoData::new(prog).unwrap();
+    /// let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     ///
     ///
     /// vm.jit_compile();
@@ -1396,7 +1573,7 @@ impl<'a> EbpfVmNoData<'a> {
     ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
     /// ];
     ///
-    /// let vm = rbpf::EbpfVmNoData::new(prog).unwrap();
+    /// let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     ///
     /// // For this kind of VM, the `prog_exec()` function needs no argument.
     /// let res = vm.prog_exec();
@@ -1431,7 +1608,7 @@ impl<'a> EbpfVmNoData<'a> {
     ///     0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
     /// ];
     ///
-    /// let mut vm = rbpf::EbpfVmNoData::new(prog).unwrap();
+    /// let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     ///
     /// # #[cfg(not(windows))]
     /// vm.jit_compile();

+ 1 - 0
src/verifier.rs

@@ -26,6 +26,7 @@
 use ebpf;
 use std::io::{Error, ErrorKind};
 
+#[allow(needless_pass_by_value)]
 fn reject(msg: String) -> Result<(), Error> {
     let full_msg = format!("[Verifier] Error: {}", msg);
     Err(Error::new(ErrorKind::Other, full_msg))

+ 63 - 17
tests/misc.rs

@@ -21,6 +21,9 @@
 // use std::path::PathBuf;
 
 extern crate rbpf;
+
+use std::io::{Error, ErrorKind};
+use rbpf::assembler::assemble;
 use rbpf::helpers;
 
 // The following two examples have been compiled from C with the following command:
@@ -162,7 +165,7 @@ fn test_vm_block_port() {
         0x64, 0x66, 0x0au8
     ];
 
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(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);
 
     let res = vm.prog_exec(packet);
@@ -244,7 +247,7 @@ fn test_jit_block_port() {
         0x64, 0x66, 0x0au8
     ];
 
-    let mut vm = rbpf::EbpfVmFixedMbuff::new(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);
     vm.jit_compile();
 
@@ -277,7 +280,7 @@ fn test_vm_mbuff() {
         *data_end = mem.as_ptr() as u64 + mem.len() as u64;
     }
 
-    let vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
+    let vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
     assert_eq!(vm.prog_exec(mem, &mbuff), 0x2211);
 }
 
@@ -304,7 +307,7 @@ fn test_vm_mbuff_with_rust_api() {
         *data_end = mem.as_ptr() as u64 + mem.len() as u64;
     }
 
-    let vm = rbpf::EbpfVmMbuff::new(program.into_bytes()).unwrap();
+    let vm = rbpf::EbpfVmMbuff::new(Some(program.into_bytes())).unwrap();
     assert_eq!(vm.prog_exec(mem, &mbuff), 0x2211);
 }
 
@@ -332,7 +335,7 @@ fn test_jit_mbuff() {
     }
 
     unsafe {
-        let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
+        let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
         vm.jit_compile();
         assert_eq!(vm.prog_exec_jit(mem, &mut mbuff), 0x2211);
     }
@@ -349,7 +352,7 @@ fn test_vm_jit_ldabsb() {
         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x33);
 
     vm.jit_compile();
@@ -369,7 +372,7 @@ fn test_vm_jit_ldabsh() {
         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x4433);
 
     vm.jit_compile();
@@ -389,7 +392,7 @@ fn test_vm_jit_ldabsw() {
         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x66554433);
     vm.jit_compile();
 
@@ -409,7 +412,7 @@ fn test_vm_jit_ldabsdw() {
         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0xaa99887766554433);
     vm.jit_compile();
 
@@ -429,7 +432,7 @@ fn test_vm_err_ldabsb_oob() {
         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
-    let vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     vm.prog_exec(mem);
 
     // Memory check not implemented for JIT yet.
@@ -442,7 +445,7 @@ fn test_vm_err_ldabsb_nomem() {
         0x38, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     ];
-    let vm = rbpf::EbpfVmNoData::new(prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     vm.prog_exec();
 
     // Memory check not implemented for JIT yet.
@@ -460,7 +463,7 @@ fn test_vm_jit_ldindb() {
         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x88);
 
     vm.jit_compile();
@@ -481,7 +484,7 @@ fn test_vm_jit_ldindh() {
         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x9988);
 
     vm.jit_compile();
@@ -502,7 +505,7 @@ fn test_vm_jit_ldindw() {
         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x88776655);
     vm.jit_compile();
 
@@ -523,7 +526,7 @@ fn test_vm_jit_ldinddw() {
         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0xccbbaa9988776655);
     vm.jit_compile();
 
@@ -544,7 +547,7 @@ fn test_vm_err_ldindb_oob() {
         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
-    let vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     vm.prog_exec(mem);
 
     // Memory check not implemented for JIT yet.
@@ -558,8 +561,51 @@ fn test_vm_err_ldindb_nomem() {
         0x38, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     ];
-    let vm = rbpf::EbpfVmNoData::new(prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     vm.prog_exec();
 
     // Memory check not implemented for JIT yet.
 }
+
+#[test]
+#[should_panic(expected = "Error: No program set, call prog_set() to load one")]
+fn test_vm_exec_no_program() {
+    let vm = rbpf::EbpfVmNoData::new(None).unwrap();
+    assert_eq!(vm.prog_exec(), 0xBEE);
+}
+
+fn verifier_success(_prog: &[u8]) -> Result<(), Error> {
+    Ok(())
+}
+
+fn verifier_fail(_prog: &[u8]) -> Result<(), Error> {
+    Err(Error::new(ErrorKind::Other,
+                   "Gaggablaghblagh!"))
+}
+
+#[test]
+fn test_verifier_success() {
+    let prog = assemble(
+        "mov32 r0, 0xBEE
+         exit",
+    ).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
+    vm.set_verifier(verifier_success).unwrap();
+    vm.set_prog(&prog).unwrap();
+    assert_eq!(vm.prog_exec(), 0xBEE);
+}
+
+#[test]
+#[should_panic(expected = "Gaggablaghblagh!")]
+fn test_verifier_fail() {
+    let prog = assemble(
+        "mov32 r0, 0xBEE
+         exit",
+    ).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
+    vm.set_verifier(verifier_fail).unwrap();
+    vm.set_prog(&prog).unwrap();
+    assert_eq!(vm.prog_exec(), 0xBEE);
+}
+
+

+ 103 - 103
tests/ubpf_jit_x86_64.rs

@@ -38,7 +38,7 @@ fn test_jit_add() {
         add32 r0, 1
         add32 r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x3); }
 }
@@ -65,7 +65,7 @@ fn test_jit_alu64_arith() {
         div r0, 2
         div r0, r4
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x2a); }
 }
@@ -96,7 +96,7 @@ fn test_jit_alu64_bit() {
         xor r0, 0x03
         xor r0, r2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x11); }
 }
@@ -123,7 +123,7 @@ fn test_jit_alu_arith() {
         div32 r0, 2
         div32 r0, r4
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x2a); }
 }
@@ -152,7 +152,7 @@ fn test_jit_alu_bit() {
         xor32 r0, 0x03
         xor32 r0, r2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x11); }
 }
@@ -164,7 +164,7 @@ fn test_jit_arsh32_high_shift() {
         lddw r1, 0x100000001
         arsh32 r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x4); }
 }
@@ -176,7 +176,7 @@ fn test_jit_arsh() {
         lsh32 r0, 28
         arsh32 r0, 16
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0xffff8000); }
 }
@@ -190,7 +190,7 @@ fn test_jit_arsh64() {
         mov32 r1, 5
         arsh r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0xfffffffffffffff8); }
 }
@@ -203,7 +203,7 @@ fn test_jit_arsh_reg() {
         lsh32 r0, 28
         arsh32 r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0xffff8000); }
 }
@@ -217,7 +217,7 @@ fn test_jit_be16() {
     let mem = &mut [
         0x11, 0x22
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x1122); }
 }
@@ -231,7 +231,7 @@ fn test_jit_be16_high() {
     let mem = &mut [
         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x1122); }
 }
@@ -245,7 +245,7 @@ fn test_jit_be32() {
     let mem = &mut [
         0x11, 0x22, 0x33, 0x44
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x11223344); }
 }
@@ -259,7 +259,7 @@ fn test_jit_be32_high() {
     let mem = &mut [
         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x11223344); }
 }
@@ -273,7 +273,7 @@ fn test_jit_be64() {
     let mem = &mut [
         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x1122334455667788); }
 }
@@ -288,7 +288,7 @@ fn test_jit_call() {
         mov r5, 5
         call 0
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.register_helper(0, helpers::gather_bytes);
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x0102030405); }
@@ -307,7 +307,7 @@ fn test_jit_call_memfrob() {
     let mem = &mut [
         0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.register_helper(1, helpers::memfrob);
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x102292e2f2c0708); }
@@ -330,7 +330,7 @@ fn test_jit_call_memfrob() {
         //0x4f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         //0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     //];
-    //let mut vm = rbpf::EbpfVmNoData::new(prog).unwrap();
+    //let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     //vm.register_helper(2, helpers::trash_registers);
     //vm.jit_compile();
     //unsafe { assert_eq!(vm.prog_exec_jit(), 0x4321); }
@@ -343,7 +343,7 @@ fn test_jit_div32_high_divisor() {
         lddw r1, 0x100000004
         div32 r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x3); }
 }
@@ -354,7 +354,7 @@ fn test_jit_div32_imm() {
         lddw r0, 0x10000000c
         div32 r0, 4
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x3); }
 }
@@ -366,7 +366,7 @@ fn test_jit_div32_reg() {
         mov r1, 4
         div32 r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x3); }
 }
@@ -378,7 +378,7 @@ fn test_jit_div64_imm() {
         lsh r0, 32
         div r0, 4
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x300000000); }
 }
@@ -391,7 +391,7 @@ fn test_jit_div64_reg() {
         mov r1, 4
         div r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x300000000); }
 }
@@ -403,7 +403,7 @@ fn test_jit_early_exit() {
         exit
         mov r0, 4
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x3); }
 }
@@ -424,7 +424,7 @@ fn test_jit_err_call_unreg() {
         mov r5, 5
         call 63
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { vm.prog_exec_jit(); }
 }
@@ -439,7 +439,7 @@ fn test_jit_err_div64_by_zero_reg() {
         mov32 r1, 0
         div r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0xffffffffffffffff); }
 }
@@ -453,7 +453,7 @@ fn test_jit_err_div_by_zero_reg() {
         mov32 r1, 0
         div32 r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0xffffffffffffffff); }
 }
@@ -467,7 +467,7 @@ fn test_jit_err_mod64_by_zero_reg() {
         mov32 r1, 0
         mod r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0xffffffffffffffff); }
 }
@@ -481,7 +481,7 @@ fn test_jit_err_mod_by_zero_reg() {
         mov32 r1, 0
         mod32 r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0xffffffffffffffff); }
 }
@@ -494,7 +494,7 @@ fn test_jit_err_mod_by_zero_reg() {
 //         0x72, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 //         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 //     ];
-//     let mut vm = rbpf::EbpfVmNoData::new(prog).unwrap();
+//     let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
 //     vm.jit_compile();
 //     unsafe { vm.prog_exec_jit(); }
 // }
@@ -504,7 +504,7 @@ fn test_jit_exit() {
     let prog = assemble("
         mov r0, 0
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x0); }
 }
@@ -516,7 +516,7 @@ fn test_jit_ja() {
         ja +1
         mov r0, 2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -532,7 +532,7 @@ fn test_jit_jeq_imm() {
         jeq r1, 0xb, +1
         mov32 r0, 2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -549,7 +549,7 @@ fn test_jit_jeq_reg() {
         jeq r1, r2, +1
         mov32 r0, 2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -565,7 +565,7 @@ fn test_jit_jge_imm() {
         jge r1, 0xb, +1
         mov32 r0, 2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -582,7 +582,7 @@ fn test_jit_jle_imm() {
         exit
         mov32 r0, 1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -601,7 +601,7 @@ fn test_jit_jle_reg() {
         exit
         mov r0, 1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -617,7 +617,7 @@ fn test_jit_jgt_imm() {
         exit
         mov32 r0, 1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -635,7 +635,7 @@ fn test_jit_jgt_reg() {
         exit
         mov r0, 1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -651,7 +651,7 @@ fn test_jit_jlt_imm() {
         exit
         mov32 r0, 1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -669,7 +669,7 @@ fn test_jit_jlt_reg() {
         exit
         mov r0, 1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -684,7 +684,7 @@ fn test_jit_jit_bounce() {
         mov r9, r8
         mov r0, r9
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -701,7 +701,7 @@ fn test_jit_jne_reg() {
         jne r1, r2, +1
         mov32 r0, 2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -717,7 +717,7 @@ fn test_jit_jset_imm() {
         jset r1, 0x8, +1
         mov32 r0, 2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -734,7 +734,7 @@ fn test_jit_jset_reg() {
         jset r1, r2, +1
         mov32 r0, 2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -751,7 +751,7 @@ fn test_jit_jsge_imm() {
         jsge r1, -1, +1
         mov32 r0, 2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -770,7 +770,7 @@ fn test_jit_jsge_reg() {
         jsge r1, r2, +1
         mov32 r0, 2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -787,7 +787,7 @@ fn test_jit_jsle_imm() {
         jsle r1, -2, +1
         mov32 r0, 2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -807,7 +807,7 @@ fn test_jit_jsle_reg() {
         jsle r1, r2, +1
         mov32 r0, 2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -823,7 +823,7 @@ fn test_jit_jsgt_imm() {
         jsgt r1, -1, +1
         mov32 r0, 2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -840,7 +840,7 @@ fn test_jit_jsgt_reg() {
         jsgt r1, r2, +1
         mov32 r0, 2
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -856,7 +856,7 @@ fn test_jit_jslt_imm() {
         exit
         mov32 r0, 1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -874,7 +874,7 @@ fn test_jit_jslt_reg() {
         exit
         mov32 r0, 1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -884,7 +884,7 @@ fn test_jit_lddw() {
     let prog = assemble("
         lddw r0, 0x1122334455667788
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1122334455667788); }
 }
@@ -894,7 +894,7 @@ fn test_jit_lddw2() {
     let prog = assemble("
         lddw r0, 0x0000000080000000
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x80000000); }
 }
@@ -937,7 +937,7 @@ fn test_jit_ldxb_all() {
         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
         0x08, 0x09
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x9876543210); }
 }
@@ -950,7 +950,7 @@ fn test_jit_ldxb() {
     let mem = &mut [
         0xaa, 0xbb, 0x11, 0xcc, 0xdd
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x11); }
 }
@@ -964,7 +964,7 @@ fn test_jit_ldxdw() {
         0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
         0x77, 0x88, 0xcc, 0xdd
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x8877665544332211); }
 }
@@ -1018,7 +1018,7 @@ fn test_jit_ldxh_all() {
         0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07,
         0x00, 0x08, 0x00, 0x09
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x9876543210); }
 }
@@ -1062,7 +1062,7 @@ fn test_jit_ldxh_all2() {
         0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80,
         0x01, 0x00, 0x02, 0x00
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x3ff); }
 }
@@ -1075,7 +1075,7 @@ fn test_jit_ldxh() {
     let mem = &mut [
         0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x2211); }
 }
@@ -1090,7 +1090,7 @@ fn test_jit_ldxh_same_reg() {
     let mem = &mut [
         0xff, 0xff
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x1234); }
 }
@@ -1136,7 +1136,7 @@ fn test_jit_ldxw_all() {
         0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00,
         0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x030f0f); }
 }
@@ -1149,7 +1149,7 @@ fn test_jit_ldxw() {
     let mem = &mut [
         0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0xcc, 0xdd
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x44332211); }
 }
@@ -1163,7 +1163,7 @@ fn test_jit_le16() {
     let mem = &mut [
         0x22, 0x11
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x1122); }
 }
@@ -1177,7 +1177,7 @@ fn test_jit_le32() {
     let mem = &mut [
         0x44, 0x33, 0x22, 0x11
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x11223344); }
 }
@@ -1191,7 +1191,7 @@ fn test_jit_le64() {
     let mem = &mut [
         0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x1122334455667788); }
 }
@@ -1203,7 +1203,7 @@ fn test_jit_lsh_reg() {
         mov r7, 4
         lsh r0, r7
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x10); }
 }
@@ -1216,7 +1216,7 @@ fn test_jit_mod() {
         mov32 r1, 13
         mod32 r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x5); }
 }
@@ -1227,7 +1227,7 @@ fn test_jit_mod32() {
         lddw r0, 0x100000003
         mod32 r0, 3
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x0); }
 }
@@ -1244,7 +1244,7 @@ fn test_jit_mod64() {
         mod r0, r1
         mod r0, 0x658f1778
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x30ba5a04); }
 }
@@ -1255,7 +1255,7 @@ fn test_jit_mov() {
         mov32 r1, 1
         mov32 r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -1266,7 +1266,7 @@ fn test_jit_mul32_imm() {
         mov r0, 3
         mul32 r0, 4
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0xc); }
 }
@@ -1278,7 +1278,7 @@ fn test_jit_mul32_reg() {
         mov r1, 4
         mul32 r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0xc); }
 }
@@ -1290,7 +1290,7 @@ fn test_jit_mul32_reg_overflow() {
         mov r1, 4
         mul32 r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x4); }
 }
@@ -1301,7 +1301,7 @@ fn test_jit_mul64_imm() {
         mov r0, 0x40000001
         mul r0, 4
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x100000004); }
 }
@@ -1313,7 +1313,7 @@ fn test_jit_mul64_reg() {
         mov r1, 4
         mul r0, r1
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x100000004); }
 }
@@ -1331,7 +1331,7 @@ fn test_jit_mul_loop() {
         add r1, -1
         jne r1, 0x0, -3
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x75db9c97); }
 }
@@ -1342,7 +1342,7 @@ fn test_jit_neg64() {
         mov32 r0, 2
         neg r0
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0xfffffffffffffffe); }
 }
@@ -1353,7 +1353,7 @@ fn test_jit_neg() {
         mov32 r0, 2
         neg32 r0
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0xfffffffe); }
 }
@@ -1377,7 +1377,7 @@ fn test_jit_prime() {
         mov r0, 0x0
         jne r4, 0x0, -10
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -1389,7 +1389,7 @@ fn test_jit_rhs32() {
         sub r0, 1
         rsh32 r0, 8
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x00ffffff); }
 }
@@ -1401,7 +1401,7 @@ fn test_jit_rsh_reg() {
         mov r7, 4
         rsh r0, r7
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x1); }
 }
@@ -1418,7 +1418,7 @@ fn test_jit_stack() {
         add r2, r1
         ldxdw r0, [r2-16]
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0xcd); }
 }
@@ -1442,7 +1442,7 @@ fn test_jit_stack2() {
         call 0
         xor r0, 0x2a2a2a2a
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.register_helper(0, helpers::gather_bytes);
     vm.register_helper(1, helpers::memfrob);
     vm.jit_compile();
@@ -1458,7 +1458,7 @@ fn test_jit_stb() {
     let mem = &mut [
         0xaa, 0xbb, 0xff, 0xcc, 0xdd
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x11); }
 }
@@ -1473,7 +1473,7 @@ fn test_jit_stdw() {
         0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
         0xff, 0xff, 0xcc, 0xdd
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x44332211); }
 }
@@ -1487,7 +1487,7 @@ fn test_jit_sth() {
     let mem = &mut [
         0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x2211); }
 }
@@ -1523,7 +1523,7 @@ fn test_jit_string_stack() {
         jeq r1, r6, +1
         mov r0, 0x0
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.register_helper(4, helpers::strcmp);
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(), 0x0); }
@@ -1538,7 +1538,7 @@ fn test_jit_stw() {
     let mem = &mut [
         0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x44332211); }
 }
@@ -1553,7 +1553,7 @@ fn test_jit_stxb() {
     let mem = &mut [
         0xaa, 0xbb, 0xff, 0xcc, 0xdd
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x11); }
 }
@@ -1583,7 +1583,7 @@ fn test_jit_stxb_all() {
     let mem = &mut [
         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0xf0f2f3f4f5f6f7f8); }
 }
@@ -1602,7 +1602,7 @@ fn test_jit_stxb_all2() {
     let mem = &mut [
         0xff, 0xff
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0xf1f9); }
 }
@@ -1635,7 +1635,7 @@ fn test_jit_stxb_chain() {
         0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x2a); }
 }
@@ -1653,7 +1653,7 @@ fn test_jit_stxdw() {
         0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
         0xff, 0xff, 0xcc, 0xdd
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x8877665544332211); }
 }
@@ -1668,7 +1668,7 @@ fn test_jit_stxh() {
     let mem = &mut [
         0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x2211); }
 }
@@ -1683,7 +1683,7 @@ fn test_jit_stxw() {
     let mem = &mut [
         0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x44332211); }
 }
@@ -1717,7 +1717,7 @@ fn test_jit_subnet() {
         0x27, 0x24, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03,
         0x03, 0x00
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x1); }
 }
@@ -1763,7 +1763,7 @@ fn test_jit_tcp_port80_match() {
         0x44, 0x44, 0x44, 0x44
     ];
     let prog = &PROG_TCP_PORT_80;
-    let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x1); }
 }
@@ -1786,7 +1786,7 @@ fn test_jit_tcp_port80_nomatch() {
         0x44, 0x44, 0x44, 0x44
     ];
     let prog = &PROG_TCP_PORT_80;
-    let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x0); }
 }
@@ -1809,7 +1809,7 @@ fn test_jit_tcp_port80_nomatch_ethertype() {
         0x44, 0x44, 0x44, 0x44
     ];
     let prog = &PROG_TCP_PORT_80;
-    let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x0); }
 }
@@ -1832,7 +1832,7 @@ fn test_jit_tcp_port80_nomatch_proto() {
         0x44, 0x44, 0x44, 0x44
     ];
     let prog = &PROG_TCP_PORT_80;
-    let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x0); }
 }
@@ -1841,7 +1841,7 @@ fn test_jit_tcp_port80_nomatch_proto() {
 fn test_jit_tcp_sack_match() {
     let mut mem = TCP_SACK_MATCH.to_vec();
     let prog = assemble(TCP_SACK_ASM).unwrap();
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem.as_mut_slice()), 0x1); }
 }
@@ -1850,7 +1850,7 @@ fn test_jit_tcp_sack_match() {
 fn test_jit_tcp_sack_nomatch() {
     let mut mem = TCP_SACK_NOMATCH.to_vec();
     let prog = assemble(TCP_SACK_ASM).unwrap();
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.jit_compile();
     unsafe { assert_eq!(vm.prog_exec_jit(mem.as_mut_slice()), 0x0); }
 }

+ 12 - 12
tests/ubpf_verifier.rs

@@ -33,7 +33,7 @@ fn test_verifier_err_div_by_zero_imm() {
         mov32 r0, 1
         div32 r0, 0
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -45,7 +45,7 @@ fn test_verifier_err_endian_size() {
         0xb7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     ];
-    let vm = rbpf::EbpfVmNoData::new(prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -56,7 +56,7 @@ fn test_verifier_err_incomplete_lddw() { // Note: ubpf has test-err-incomplete-l
         0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55,
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     ];
-    let vm = rbpf::EbpfVmNoData::new(prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -66,7 +66,7 @@ fn test_verifier_err_infinite_loop() {
     let prog = assemble("
         ja -1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -76,7 +76,7 @@ fn test_verifier_err_invalid_reg_dst() {
     let prog = assemble("
         mov r11, 1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -86,7 +86,7 @@ fn test_verifier_err_invalid_reg_src() {
     let prog = assemble("
         mov r0, r11
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -97,7 +97,7 @@ fn test_verifier_err_jmp_lddw() {
         ja +1
         lddw r0, 0x1122334455667788
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -107,7 +107,7 @@ fn test_verifier_err_jmp_out() {
     let prog = assemble("
         ja +2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -116,7 +116,7 @@ fn test_verifier_err_jmp_out() {
 fn test_verifier_err_no_exit() {
     let prog = assemble("
         mov32 r0, 0").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -132,7 +132,7 @@ fn test_verifier_err_too_many_instructions() {
     }).collect::<Vec<u8>>();
     prog.append(&mut vec![ 0x95, 0, 0, 0, 0, 0, 0, 0 ]);
 
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -143,7 +143,7 @@ fn test_verifier_err_unknown_opcode() {
         0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     ];
-    let vm = rbpf::EbpfVmNoData::new(prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -153,6 +153,6 @@ fn test_verifier_err_write_r10() {
     let prog = assemble("
         mov r10, 1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }

+ 103 - 103
tests/ubpf_vm.rs

@@ -37,7 +37,7 @@ fn test_vm_add() {
         add32 r0, 1
         add32 r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x3);
 }
 
@@ -63,7 +63,7 @@ fn test_vm_alu64_arith() {
         div r0, 2
         div r0, r4
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x2a);
 }
 
@@ -93,7 +93,7 @@ fn test_vm_alu64_bit() {
         xor r0, 0x03
         xor r0, r2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x11);
 }
 
@@ -119,7 +119,7 @@ fn test_vm_alu_arith() {
         div32 r0, 2
         div32 r0, r4
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x2a);
 }
 
@@ -147,7 +147,7 @@ fn test_vm_alu_bit() {
         xor32 r0, 0x03
         xor32 r0, r2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x11);
 }
 
@@ -158,7 +158,7 @@ fn test_vm_arsh32_high_shift() {
         lddw r1, 0x100000001
         arsh32 r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x4);
 }
 
@@ -169,7 +169,7 @@ fn test_vm_arsh() {
         lsh32 r0, 28
         arsh32 r0, 16
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0xffff8000);
 }
 
@@ -182,7 +182,7 @@ fn test_vm_arsh64() {
         mov32 r1, 5
         arsh r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0xfffffffffffffff8);
 }
 
@@ -194,7 +194,7 @@ fn test_vm_arsh_reg() {
         lsh32 r0, 28
         arsh32 r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0xffff8000);
 }
 
@@ -207,7 +207,7 @@ fn test_vm_be16() {
     let mem = &mut [
         0x11, 0x22
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x1122);
 }
 
@@ -220,7 +220,7 @@ fn test_vm_be16_high() {
     let mem = &mut [
         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x1122);
 }
 
@@ -233,7 +233,7 @@ fn test_vm_be32() {
     let mem = &mut [
         0x11, 0x22, 0x33, 0x44
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x11223344);
 }
 
@@ -246,7 +246,7 @@ fn test_vm_be32_high() {
     let mem = &mut [
         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x11223344);
 }
 
@@ -259,7 +259,7 @@ fn test_vm_be64() {
     let mem = &mut [
         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x1122334455667788);
 }
 
@@ -273,7 +273,7 @@ fn test_vm_call() {
         mov r5, 5
         call 0
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.register_helper(0, helpers::gather_bytes);
     assert_eq!(vm.prog_exec(), 0x0102030405);
 }
@@ -291,7 +291,7 @@ fn test_vm_call_memfrob() {
     let mem = &mut [
         0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
     ];
-    let mut vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     vm.register_helper(1, helpers::memfrob);
     assert_eq!(vm.prog_exec(mem), 0x102292e2f2c0708);
 }
@@ -313,7 +313,7 @@ fn test_vm_call_memfrob() {
         //0x4f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         //0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     //];
-    //let mut vm = rbpf::EbpfVmNoData::new(prog).unwrap();
+    //let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     //vm.register_helper(2, helpers::trash_registers);
     //assert_eq!(vm.prog_exec(), 0x4321);
 //}
@@ -325,7 +325,7 @@ fn test_vm_div32_high_divisor() {
         lddw r1, 0x100000004
         div32 r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x3);
 }
 
@@ -335,7 +335,7 @@ fn test_vm_div32_imm() {
         lddw r0, 0x10000000c
         div32 r0, 4
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x3);
 }
 
@@ -346,7 +346,7 @@ fn test_vm_div32_reg() {
         mov r1, 4
         div32 r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x3);
 }
 
@@ -357,7 +357,7 @@ fn test_vm_div64_imm() {
         lsh r0, 32
         div r0, 4
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x300000000);
 }
 
@@ -369,7 +369,7 @@ fn test_vm_div64_reg() {
         mov r1, 4
         div r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x300000000);
 }
 
@@ -380,7 +380,7 @@ fn test_vm_early_exit() {
         exit
         mov r0, 4
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x3);
 }
 
@@ -400,7 +400,7 @@ fn test_vm_err_call_unreg() {
         mov r5, 5
         call 63
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -412,7 +412,7 @@ fn test_vm_err_div64_by_zero_reg() {
         mov32 r1, 0
         div r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -424,7 +424,7 @@ fn test_vm_err_div_by_zero_reg() {
         mov32 r1, 0
         div32 r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -436,7 +436,7 @@ fn test_vm_err_mod64_by_zero_reg() {
         mov32 r1, 0
         mod r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -448,7 +448,7 @@ fn test_vm_err_mod_by_zero_reg() {
         mov32 r1, 0
         mod32 r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -458,7 +458,7 @@ fn test_vm_err_stack_out_of_bound() {
     let prog = assemble("
         stb [r10], 0
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.prog_exec();
 }
 
@@ -467,7 +467,7 @@ fn test_vm_exit() {
     let prog = assemble("
         mov r0, 0
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x0);
 }
 
@@ -478,7 +478,7 @@ fn test_vm_ja() {
         ja +1
         mov r0, 2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -493,7 +493,7 @@ fn test_vm_jeq_imm() {
         jeq r1, 0xb, +1
         mov32 r0, 2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -509,7 +509,7 @@ fn test_vm_jeq_reg() {
         jeq r1, r2, +1
         mov32 r0, 2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -524,7 +524,7 @@ fn test_vm_jge_imm() {
         jge r1, 0xb, +1
         mov32 r0, 2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -540,7 +540,7 @@ fn test_vm_jle_imm() {
         exit
         mov32 r0, 1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -558,7 +558,7 @@ fn test_vm_jle_reg() {
         exit
         mov r0, 1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -573,7 +573,7 @@ fn test_vm_jgt_imm() {
         exit
         mov32 r0, 1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -590,7 +590,7 @@ fn test_vm_jgt_reg() {
         exit
         mov r0, 1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -605,7 +605,7 @@ fn test_vm_jlt_imm() {
         exit
         mov32 r0, 1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -622,7 +622,7 @@ fn test_vm_jlt_reg() {
         exit
         mov r0, 1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -636,7 +636,7 @@ fn test_vm_jit_bounce() {
         mov r9, r8
         mov r0, r9
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -652,7 +652,7 @@ fn test_vm_jne_reg() {
         jne r1, r2, +1
         mov32 r0, 2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -667,7 +667,7 @@ fn test_vm_jset_imm() {
         jset r1, 0x8, +1
         mov32 r0, 2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -683,7 +683,7 @@ fn test_vm_jset_reg() {
         jset r1, r2, +1
         mov32 r0, 2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -699,7 +699,7 @@ fn test_vm_jsge_imm() {
         jsge r1, -1, +1
         mov32 r0, 2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -717,7 +717,7 @@ fn test_vm_jsge_reg() {
         jsge r1, r2, +1
         mov32 r0, 2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -733,7 +733,7 @@ fn test_vm_jsle_imm() {
         jsle r1, -2, +1
         mov32 r0, 2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -752,7 +752,7 @@ fn test_vm_jsle_reg() {
         jsle r1, r2, +1
         mov32 r0, 2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -767,7 +767,7 @@ fn test_vm_jsgt_imm() {
         jsgt r1, -1, +1
         mov32 r0, 2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -783,7 +783,7 @@ fn test_vm_jsgt_reg() {
         jsgt r1, r2, +1
         mov32 r0, 2
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -798,7 +798,7 @@ fn test_vm_jslt_imm() {
         exit
         mov32 r0, 1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -815,7 +815,7 @@ fn test_vm_jslt_reg() {
         exit
         mov32 r0, 1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -823,7 +823,7 @@ fn test_vm_jslt_reg() {
 fn test_vm_lddw() {
     let prog = assemble("lddw r0, 0x1122334455667788
                          exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1122334455667788);
 }
 
@@ -832,7 +832,7 @@ fn test_vm_lddw2() {
     let prog = assemble("
         lddw r0, 0x0000000080000000
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x80000000);
 }
 
@@ -874,7 +874,7 @@ fn test_vm_ldxb_all() {
         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
         0x08, 0x09
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x9876543210);
 }
 
@@ -886,7 +886,7 @@ fn test_vm_ldxb() {
     let mem = &mut [
         0xaa, 0xbb, 0x11, 0xcc, 0xdd
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x11);
 }
 
@@ -899,7 +899,7 @@ fn test_vm_ldxdw() {
         0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
         0x77, 0x88, 0xcc, 0xdd
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x8877665544332211);
 }
 
@@ -952,7 +952,7 @@ fn test_vm_ldxh_all() {
         0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07,
         0x00, 0x08, 0x00, 0x09
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x9876543210);
 }
 
@@ -995,7 +995,7 @@ fn test_vm_ldxh_all2() {
         0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80,
         0x01, 0x00, 0x02, 0x00
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x3ff);
 }
 
@@ -1007,7 +1007,7 @@ fn test_vm_ldxh() {
     let mem = &mut [
         0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x2211);
 }
 
@@ -1021,7 +1021,7 @@ fn test_vm_ldxh_same_reg() {
     let mem = &mut [
         0xff, 0xff
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x1234);
 }
 
@@ -1066,7 +1066,7 @@ fn test_vm_ldxw_all() {
         0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00,
         0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x030f0f);
 }
 
@@ -1078,7 +1078,7 @@ fn test_vm_ldxw() {
     let mem = &mut [
         0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0xcc, 0xdd
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x44332211);
 }
 
@@ -1091,7 +1091,7 @@ fn test_vm_le16() {
     let mem = &mut [
         0x22, 0x11
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x1122);
 }
 
@@ -1104,7 +1104,7 @@ fn test_vm_le32() {
     let mem = &mut [
         0x44, 0x33, 0x22, 0x11
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x11223344);
 }
 
@@ -1117,7 +1117,7 @@ fn test_vm_le64() {
     let mem = &mut [
         0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x1122334455667788);
 }
 
@@ -1128,7 +1128,7 @@ fn test_vm_lsh_reg() {
         mov r7, 4
         lsh r0, r7
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x10);
 }
 
@@ -1140,7 +1140,7 @@ fn test_vm_mod() {
         mov32 r1, 13
         mod32 r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x5);
 }
 
@@ -1150,7 +1150,7 @@ fn test_vm_mod32() {
         lddw r0, 0x100000003
         mod32 r0, 3
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x0);
 }
 
@@ -1166,7 +1166,7 @@ fn test_vm_mod64() {
         mod r0, r1
         mod r0, 0x658f1778
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x30ba5a04);
 }
 
@@ -1176,7 +1176,7 @@ fn test_vm_mov() {
         mov32 r1, 1
         mov32 r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -1186,7 +1186,7 @@ fn test_vm_mul32_imm() {
         mov r0, 3
         mul32 r0, 4
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0xc);
 }
 
@@ -1197,7 +1197,7 @@ fn test_vm_mul32_reg() {
         mov r1, 4
         mul32 r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0xc);
 }
 
@@ -1208,7 +1208,7 @@ fn test_vm_mul32_reg_overflow() {
         mov r1, 4
         mul32 r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x4);
 }
 
@@ -1218,7 +1218,7 @@ fn test_vm_mul64_imm() {
         mov r0, 0x40000001
         mul r0, 4
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x100000004);
 }
 
@@ -1229,7 +1229,7 @@ fn test_vm_mul64_reg() {
         mov r1, 4
         mul r0, r1
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x100000004);
 }
 
@@ -1246,7 +1246,7 @@ fn test_vm_mul_loop() {
         add r1, -1
         jne r1, 0x0, -3
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x75db9c97);
 }
 
@@ -1256,7 +1256,7 @@ fn test_vm_neg64() {
         mov32 r0, 2
         neg r0
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0xfffffffffffffffe);
 }
 
@@ -1266,7 +1266,7 @@ fn test_vm_neg() {
         mov32 r0, 2
         neg32 r0
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0xfffffffe);
 }
 
@@ -1289,7 +1289,7 @@ fn test_vm_prime() {
         mov r0, 0x0
         jne r4, 0x0, -10
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -1300,7 +1300,7 @@ fn test_vm_rhs32() {
         sub r0, 1
         rsh32 r0, 8
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x00ffffff);
 }
 
@@ -1311,7 +1311,7 @@ fn test_vm_rsh_reg() {
         mov r7, 4
         rsh r0, r7
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0x1);
 }
 
@@ -1327,7 +1327,7 @@ fn test_vm_stack() {
         add r2, r1
         ldxdw r0, [r2-16]
         exit").unwrap();
-    let vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(), 0xcd);
 }
 
@@ -1350,7 +1350,7 @@ fn test_vm_stack2() {
         call 0
         xor r0, 0x2a2a2a2a
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.register_helper(0, helpers::gather_bytes);
     vm.register_helper(1, helpers::memfrob);
     assert_eq!(vm.prog_exec(), 0x01020304);
@@ -1365,7 +1365,7 @@ fn test_vm_stb() {
     let mem = &mut [
         0xaa, 0xbb, 0xff, 0xcc, 0xdd
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x11);
 }
 
@@ -1379,7 +1379,7 @@ fn test_vm_stdw() {
         0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
         0xff, 0xff, 0xcc, 0xdd
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x44332211);
 }
 
@@ -1392,7 +1392,7 @@ fn test_vm_sth() {
     let mem = &mut [
         0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x2211);
 }
 
@@ -1427,7 +1427,7 @@ fn test_vm_string_stack() {
         jeq r1, r6, +1
         mov r0, 0x0
         exit").unwrap();
-    let mut vm = rbpf::EbpfVmNoData::new(&prog).unwrap();
+    let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     vm.register_helper(4, helpers::strcmp);
     assert_eq!(vm.prog_exec(), 0x0);
 }
@@ -1441,7 +1441,7 @@ fn test_vm_stw() {
     let mem = &mut [
         0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x44332211);
 }
 
@@ -1455,7 +1455,7 @@ fn test_vm_stxb() {
     let mem = &mut [
         0xaa, 0xbb, 0xff, 0xcc, 0xdd
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x11);
 }
 
@@ -1484,7 +1484,7 @@ fn test_vm_stxb_all() {
     let mem = &mut [
         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0xf0f2f3f4f5f6f7f8);
 }
 
@@ -1502,7 +1502,7 @@ fn test_vm_stxb_all2() {
     let mem = &mut [
         0xff, 0xff
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0xf1f9);
 }
 
@@ -1534,7 +1534,7 @@ fn test_vm_stxb_chain() {
         0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
         0x00, 0x00
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x2a);
 }
 
@@ -1551,7 +1551,7 @@ fn test_vm_stxdw() {
         0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
         0xff, 0xff, 0xcc, 0xdd
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x8877665544332211);
 }
 
@@ -1565,7 +1565,7 @@ fn test_vm_stxh() {
     let mem = &mut [
         0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x2211);
 }
 
@@ -1579,7 +1579,7 @@ fn test_vm_stxw() {
     let mem = &mut [
         0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x44332211);
 }
 
@@ -1612,7 +1612,7 @@ fn test_vm_subnet() {
         0x27, 0x24, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03,
         0x03, 0x00
     ];
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x1);
 }
 
@@ -1657,7 +1657,7 @@ fn test_vm_tcp_port80_match() {
         0x44, 0x44, 0x44, 0x44
     ];
     let prog = &PROG_TCP_PORT_80;
-    let vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x1);
 }
 
@@ -1679,7 +1679,7 @@ fn test_vm_tcp_port80_nomatch() {
         0x44, 0x44, 0x44, 0x44
     ];
     let prog = &PROG_TCP_PORT_80;
-    let vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x0);
 }
 
@@ -1701,7 +1701,7 @@ fn test_vm_tcp_port80_nomatch_ethertype() {
         0x44, 0x44, 0x44, 0x44
     ];
     let prog = &PROG_TCP_PORT_80;
-    let vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x0);
 }
 
@@ -1723,7 +1723,7 @@ fn test_vm_tcp_port80_nomatch_proto() {
         0x44, 0x44, 0x44, 0x44
     ];
     let prog = &PROG_TCP_PORT_80;
-    let vm = rbpf::EbpfVmRaw::new(prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     assert_eq!(vm.prog_exec(mem), 0x0);
 }
 
@@ -1731,7 +1731,7 @@ fn test_vm_tcp_port80_nomatch_proto() {
 fn test_vm_tcp_sack_match() {
     let mut mem = TCP_SACK_MATCH.to_vec();
     let prog = assemble(TCP_SACK_ASM).unwrap();
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem.as_mut_slice()), 0x1);
 }
 
@@ -1739,6 +1739,6 @@ fn test_vm_tcp_sack_match() {
 fn test_vm_tcp_sack_nomatch() {
     let mut mem = TCP_SACK_NOMATCH.to_vec();
     let prog = assemble(TCP_SACK_ASM).unwrap();
-    let vm = rbpf::EbpfVmRaw::new(&prog).unwrap();
+    let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     assert_eq!(vm.prog_exec(mem.as_mut_slice()), 0x0);
 }