Browse Source

Exit gracefully on program exit (#38)

Modify interfaces to support Result
jackcmay 6 years ago
parent
commit
b31d366489
9 changed files with 511 additions and 546 deletions
  1. 22 21
      README.md
  2. 5 5
      examples/load_elf.rs
  3. 5 5
      examples/uptime.rs
  4. 19 12
      src/jit.rs
  5. 113 156
      src/lib.rs
  6. 40 40
      tests/misc.rs
  7. 187 187
      tests/ubpf_jit_x86_64.rs
  8. 12 12
      tests/ubpf_verifier.rs
  9. 108 108
      tests/ubpf_vm.rs

+ 22 - 21
README.md

@@ -194,7 +194,8 @@ method when creating the VM).
 ```rust,ignore
 ```rust,ignore
 pub fn register_helper(&mut self,
 pub fn register_helper(&mut self,
                        key: u32,
                        key: u32,
-                       function: fn (u64, u64, u64, u64, u64) -> u64)
+                       function: fn (u64, u64, u64, u64, u64) -> u64) 
+                       -> Result<(), Error>
 ```
 ```
 
 
 This function is used to register a helper function. The VM stores its
 This function is used to register a helper function. The VM stores its
@@ -206,14 +207,14 @@ therefore must use specific helper numbers.
 // for struct EbpfVmMbuff
 // for struct EbpfVmMbuff
 pub fn prog_exec(&self,
 pub fn prog_exec(&self,
                  mem: &'a mut [u8],
                  mem: &'a mut [u8],
-                 mbuff: &'a mut [u8]) -> u64
+                 mbuff: &'a mut [u8]) -> Result<(u64), Error>
 
 
 // for struct EbpfVmFixedMbuff and struct EbpfVmRaw
 // for struct EbpfVmFixedMbuff and struct EbpfVmRaw
 pub fn prog_exec(&self,
 pub fn prog_exec(&self,
-                 mem: &'a mut [u8]) -> u64
+                 mem: &'a mut [u8]) -> Result<(u64), Error>
 
 
 // for struct EbpfVmNoData
 // for struct EbpfVmNoData
-pub fn prog_exec(&self) -> u64
+pub fn prog_exec(&self) -> Result<(u64), Error>
 ```
 ```
 
 
 Interprets the loaded program. The function takes a reference to the packet
 Interprets the loaded program. The function takes a reference to the packet
@@ -222,7 +223,7 @@ depending on the kind of the VM used. The value returned is the result of the
 eBPF program.
 eBPF program.
 
 
 ```rust,ignore
 ```rust,ignore
-pub fn jit_compile(&mut self)
+pub fn jit_compile(&mut self) -> Result<(), Error>
 ```
 ```
 
 
 JIT-compile the loaded program, for x86_64 architecture. If the program is to
 JIT-compile the loaded program, for x86_64 architecture. If the program is to
@@ -232,13 +233,13 @@ is called. The generated assembly function is internally stored in the VM.
 ```rust,ignore
 ```rust,ignore
 // for struct EbpfVmMbuff
 // for struct EbpfVmMbuff
 pub unsafe fn prog_exec_jit(&self, mem: &'a mut [u8],
 pub unsafe fn prog_exec_jit(&self, mem: &'a mut [u8],
-                            mbuff: &'a mut [u8]) -> u64
+                            mbuff: &'a mut [u8]) -> Result<(u64), Error>
 
 
 // for struct EbpfVmFixedMbuff and struct EbpfVmRaw
 // for struct EbpfVmFixedMbuff and struct EbpfVmRaw
-pub unsafe fn prog_exec_jit(&self, mem: &'a mut [u8]) -> u64
+pub unsafe fn prog_exec_jit(&self, mem: &'a mut [u8]) -> Result<(u64), Error>
 
 
 // for struct EbpfVmNoData
 // for struct EbpfVmNoData
-pub unsafe fn prog_exec_jit(&self) -> u64
+pub unsafe fn prog_exec_jit(&self) -> Result<(u64), Error>
 ```
 ```
 
 
 Calls the JIT-compiled program. The arguments to provide are the same as for
 Calls the JIT-compiled program. The arguments to provide are the same as for
@@ -274,7 +275,7 @@ fn main() {
     let vm = rbpf::EbpfVmNoData::new(prog).unwrap();
     let vm = rbpf::EbpfVmNoData::new(prog).unwrap();
 
 
     // Execute (interpret) the program. No argument required for this VM.
     // Execute (interpret) the program. No argument required for this VM.
-    assert_eq!(vm.prog_exec(), 0x3);
+    assert_eq!(vm.prog_exec().unwrap(), 0x3);
 }
 }
 ```
 ```
 
 
@@ -301,11 +302,11 @@ fn main() {
     let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
     let mut vm = rbpf::EbpfVmRaw::new(prog).unwrap();
 
 
     // This time we JIT-compile the program.
     // This time we JIT-compile the program.
-    vm.jit_compile();
+    vm.jit_compile().unwrap();
 
 
     // Then we execute it. For this kind of VM, a reference to the packet data
     // Then we execute it. For this kind of VM, a reference to the packet data
     // must be passed to the function that executes the program.
     // must be passed to the function that executes the program.
-    unsafe { assert_eq!(vm.prog_exec_jit(mem), 0x11); }
+    unsafe { assert_eq!(vm.prog_exec_jit(mem).unwrap(), 0x11); }
 }
 }
 ```
 ```
 ### Using a metadata buffer
 ### Using a metadata buffer
@@ -342,11 +343,11 @@ fn main() {
     let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
     let mut vm = rbpf::EbpfVmMbuff::new(prog).unwrap();
 
 
     // Here again we JIT-compile the program.
     // Here again we JIT-compile the program.
-    vm.jit_compile();
+    vm.jit_compile().unwrap();
 
 
     // Here we must provide both a reference to the packet data, and to the
     // Here we must provide both a reference to the packet data, and to the
     // metadata buffer we use.
     // metadata buffer we use.
-    unsafe { assert_eq!(vm.prog_exec_jit(mem, mbuff), 0x2211); }
+    unsafe { assert_eq!(vm.prog_exec_jit(mem, mbuff).unwrap(), 0x2211); }
 }
 }
 ```
 ```
 
 
@@ -430,12 +431,13 @@ fn main() {
 
 
     // We register a helper function, that can be called by the program, into
     // We register a helper function, that can be called by the program, into
     // the VM.
     // the VM.
-    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf);
+    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX,
+                       helpers::bpf_trace_printf).unwrap();
 
 
     // This kind of VM takes a reference to the packet data, but does not need
     // This kind of VM takes a reference to the packet data, but does not need
     // any reference to the metadata buffer: a fixed buffer is handled
     // any reference to the metadata buffer: a fixed buffer is handled
     // internally by the VM.
     // internally by the VM.
-    let res = vm.prog_exec(packet);
+    let res = vm.prog_exec(packet).unwrap();
     println!("Program returned: {:?} ({:#x})", res, res);
     println!("Program returned: {:?} ({:#x})", res, res);
 }
 }
 ```
 ```
@@ -458,7 +460,7 @@ let prog = assemble("add64 r1, 0x605
                      mov64 r1, r0
                      mov64 r1, r0
                      be16 r0
                      be16 r0
                      neg64 r2
                      neg64 r2
-                     exit");
+                     exit").unwrap();
 
 
 println!("{:?}", prog);
 println!("{:?}", prog);
 ```
 ```
@@ -561,9 +563,9 @@ Other than the language, obviously? Well, there are some differences:
   stack, differs between uBPF and rbpf. The latter uses the same values as the
   stack, differs between uBPF and rbpf. The latter uses the same values as the
   Linux kernel, while uBPF has its own values.
   Linux kernel, while uBPF has its own values.
 
 
-* When an error occur while a program is run by uBPF, the function running the
+* When an error occurs while a program is run by uBPF, the function running the
   program silently returns the maximum value as an error code, while rbpf
   program silently returns the maximum value as an error code, while rbpf
-  `panic!()`.
+  returns Rust type `Error`.
 
 
 * The registration of helper functions, that can be called from within an eBPF
 * The registration of helper functions, that can be called from within an eBPF
   program, is not handled in the same way.
   program, is not handled in the same way.
@@ -615,8 +617,8 @@ not trivial, and we cannot “copy” it since it is under GPL license.
 ### What about safety then?
 ### What about safety then?
 
 
 Rust has a strong emphasize on safety. Yet to have the eBPF VM work, some
 Rust has a strong emphasize on safety. Yet to have the eBPF VM work, some
-“unsafe” blocks of code are used. The VM, taken as an eBPF interpreter, can
-`panic!()` but should not crash. Please file an issue otherwise.
+`unsafe` blocks of code are used. The VM, taken as an eBPF interpreter, can
+return an error but should not crash. Please file an issue otherwise.
 
 
 As for the JIT-compiler, it is a different story, since runtime memory checks
 As for the JIT-compiler, it is a different story, since runtime memory checks
 are more complicated to implement in assembly. It _will_ crash if your
 are more complicated to implement in assembly. It _will_ crash if your
@@ -648,7 +650,6 @@ on your own.
 * Implement some traits (`Clone`, `Drop`, `Debug` are good candidate).
 * Implement some traits (`Clone`, `Drop`, `Debug` are good candidate).
 * Provide built-in support for user-space array and hash BPF maps.
 * Provide built-in support for user-space array and hash BPF maps.
 * Improve safety of JIT-compiled programs with runtime memory checks.
 * Improve safety of JIT-compiled programs with runtime memory checks.
-* Replace `panic!()` by cleaner error handling.
 * Add helpers (some of those supported in the kernel, such as checksum update,
 * Add helpers (some of those supported in the kernel, such as checksum update,
   could be helpful).
   could be helpful).
 * Improve verifier. Could we find a way to directly support programs compiled
 * Improve verifier. Could we find a way to directly support programs compiled

+ 5 - 5
examples/load_elf.rs

@@ -112,24 +112,24 @@ fn main() {
     ];
     ];
 
 
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf);
+    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf).unwrap();
 
 
-    let res = vm.prog_exec(packet1);
+    let res = vm.prog_exec(packet1).unwrap();
     println!("Packet #1, program returned: {:?} ({:#x})", res, res);
     println!("Packet #1, program returned: {:?} ({:#x})", res, res);
     assert_eq!(res, 0xffffffff);
     assert_eq!(res, 0xffffffff);
 
 
     #[cfg(not(windows))]
     #[cfg(not(windows))]
     {
     {
-        vm.jit_compile();
+        vm.jit_compile().unwrap();
 
 
-        let res = unsafe { vm.prog_exec_jit(packet2) };
+        let res = unsafe { vm.prog_exec_jit(packet2).unwrap() };
         println!("Packet #2, program returned: {:?} ({:#x})", res, res);
         println!("Packet #2, program returned: {:?} ({:#x})", res, res);
         assert_eq!(res, 0);
         assert_eq!(res, 0);
     }
     }
 
 
     #[cfg(windows)]
     #[cfg(windows)]
     {
     {
-        let res = vm.prog_exec(packet2);
+        let res = vm.prog_exec(packet2).unwrap();
         println!("Packet #2, program returned: {:?} ({:#x})", res, res);
         println!("Packet #2, program returned: {:?} ({:#x})", res, res);
         assert_eq!(res, 0);
         assert_eq!(res, 0);
     }
     }

+ 5 - 5
examples/uptime.rs

@@ -41,7 +41,7 @@ fn main() {
     // Create a VM: this one takes no data. Load prog1 in it.
     // Create a VM: this one takes no data. Load prog1 in it.
     let mut vm = rbpf::EbpfVmNoData::new(Some(prog1)).unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(Some(prog1)).unwrap();
     // Execute prog1.
     // Execute prog1.
-    assert_eq!(vm.prog_exec(), 0x3);
+    assert_eq!(vm.prog_exec().unwrap(), 0x3);
 
 
     // As struct EbpfVmNoData does not takes any memory area, its return value is mostly
     // As struct EbpfVmNoData does not takes any memory area, its return value is mostly
     // deterministic. So we know prog1 will always return 3. There is an exception: when it uses
     // deterministic. So we know prog1 will always return 3. There is an exception: when it uses
@@ -52,20 +52,20 @@ fn main() {
     // reimplement uptime in eBPF, in Rust. Because why not.
     // reimplement uptime in eBPF, in Rust. Because why not.
 
 
     vm.set_prog(prog2).unwrap();
     vm.set_prog(prog2).unwrap();
-    vm.register_helper(helpers::BPF_KTIME_GETNS_IDX, helpers::bpf_time_getns);
+    vm.register_helper(helpers::BPF_KTIME_GETNS_IDX, helpers::bpf_time_getns).unwrap();
 
 
     let time;
     let time;
 
 
     #[cfg(not(windows))]
     #[cfg(not(windows))]
     {
     {
-        vm.jit_compile();
+        vm.jit_compile().unwrap();
 
 
-        time = unsafe { vm.prog_exec_jit() };
+        time = unsafe { vm.prog_exec_jit().unwrap() };
     }
     }
 
 
     #[cfg(windows)]
     #[cfg(windows)]
     {
     {
-        time = vm.prog_exec();
+        time = vm.prog_exec().unwrap();
     }
     }
 
 
     let days    =  time / 10u64.pow(9)  / 60   / 60  / 24;
     let days    =  time / 10u64.pow(9)  / 60   / 60  / 24;

+ 19 - 12
src/jit.rs

@@ -12,10 +12,13 @@
 use std;
 use std;
 use std::mem;
 use std::mem;
 use std::collections::HashMap;
 use std::collections::HashMap;
-use std::fmt::{Error, Formatter};
+use std::fmt::Formatter;
+use std::fmt::Error as FormatterError;
+use std::io::{Error, ErrorKind};
 use std::ops::{Index, IndexMut};
 use std::ops::{Index, IndexMut};
 
 
 use ebpf;
 use ebpf;
+use JitProgram;
 
 
 extern crate libc;
 extern crate libc;
 
 
@@ -453,7 +456,7 @@ impl<'a> JitMemory<'a> {
     }
     }
 
 
     fn jit_compile(&mut self, prog: &[u8], use_mbuff: bool, update_data_ptr: bool,
     fn jit_compile(&mut self, prog: &[u8], use_mbuff: bool, update_data_ptr: bool,
-                   helpers: &HashMap<u32, ebpf::Helper>) {
+                   helpers: &HashMap<u32, ebpf::Helper>) -> Result<(), Error> {
         emit_push(self, RBP);
         emit_push(self, RBP);
         emit_push(self, RBX);
         emit_push(self, RBX);
         emit_push(self, R13);
         emit_push(self, R13);
@@ -778,8 +781,9 @@ impl<'a> JitMemory<'a> {
                         emit_mov(self, R9, RCX);
                         emit_mov(self, R9, RCX);
                         emit_call(self, *helper as usize);
                         emit_call(self, *helper as usize);
                     } else {
                     } else {
-                        panic!("[JIT] Error: unknown helper function (id: {:#x})",
-                               insn.imm as u32);
+                        Err(Error::new(ErrorKind::Other,
+                                       format!("[JIT] Error: unknown helper function (id: {:#x})",
+                                               insn.imm as u32)))?;
                     };
                     };
                 },
                 },
                 ebpf::TAIL_CALL  => { unimplemented!() },
                 ebpf::TAIL_CALL  => { unimplemented!() },
@@ -790,8 +794,9 @@ impl<'a> JitMemory<'a> {
                 },
                 },
 
 
                 _                => {
                 _                => {
-                    panic!("[JIT] Error: unknown eBPF opcode {:#2x} (insn #{:?})",
-                           insn.opc, insn_ptr);
+                    Err(Error::new(ErrorKind::Other,
+                                   format!("[JIT] Error: unknown eBPF opcode {:#2x} (insn #{:?})",
+                                           insn.opc, insn_ptr)))?;
                 },
                 },
             }
             }
 
 
@@ -836,9 +841,10 @@ impl<'a> JitMemory<'a> {
         emit_call(self, log as usize);
         emit_call(self, log as usize);
         emit_load_imm(self, map_register(0), -1);
         emit_load_imm(self, map_register(0), -1);
         emit_jmp(self, TARGET_PC_EXIT);
         emit_jmp(self, TARGET_PC_EXIT);
+        Ok(())
     }
     }
 
 
-    fn resolve_jumps(&mut self)
+    fn resolve_jumps(&mut self) -> Result<(), Error>
     {
     {
         for jump in &self.jumps {
         for jump in &self.jumps {
             let target_loc = match self.special_targets.get(&jump.target_pc) {
             let target_loc = match self.special_targets.get(&jump.target_pc) {
@@ -857,6 +863,7 @@ impl<'a> JitMemory<'a> {
                              std::mem::size_of::<i32>());
                              std::mem::size_of::<i32>());
             }
             }
         }
         }
+        Ok(())
     }
     }
 } // struct JitMemory
 } // struct JitMemory
 
 
@@ -875,7 +882,7 @@ impl<'a> IndexMut<usize> for JitMemory<'a> {
 }
 }
 
 
 impl<'a> std::fmt::Debug for JitMemory<'a> {
 impl<'a> std::fmt::Debug for JitMemory<'a> {
-    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
+    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FormatterError> {
         fmt.write_str("JIT contents: [")?;
         fmt.write_str("JIT contents: [")?;
         for i in self.contents as &[u8] {
         for i in self.contents as &[u8] {
             fmt.write_fmt(format_args!(" {:#04x},", i))?;
             fmt.write_fmt(format_args!(" {:#04x},", i))?;
@@ -894,13 +901,13 @@ impl<'a> std::fmt::Debug for JitMemory<'a> {
 pub fn compile(prog: &[u8],
 pub fn compile(prog: &[u8],
                helpers: &HashMap<u32, ebpf::Helper>,
                helpers: &HashMap<u32, ebpf::Helper>,
                use_mbuff: bool, update_data_ptr: bool)
                use_mbuff: bool, update_data_ptr: bool)
-    -> (unsafe fn(*mut u8, usize, *mut u8, usize, usize, usize) -> u64) {
+    -> Result<(JitProgram), Error> {
 
 
     // TODO: check how long the page must be to be sure to support an eBPF program of maximum
     // TODO: check how long the page must be to be sure to support an eBPF program of maximum
     // possible length
     // possible length
     let mut jit = JitMemory::new(1);
     let mut jit = JitMemory::new(1);
-    jit.jit_compile(prog, use_mbuff, update_data_ptr, helpers);
-    jit.resolve_jumps();
+    jit.jit_compile(prog, use_mbuff, update_data_ptr, helpers)?;
+    jit.resolve_jumps()?;
 
 
-    unsafe { mem::transmute(jit.contents.as_ptr()) }
+    Ok(unsafe { mem::transmute(jit.contents.as_ptr()) })
 }
 }

+ 113 - 156
src/lib.rs

@@ -27,7 +27,7 @@ extern crate time;
 
 
 use std::u32;
 use std::u32;
 use std::collections::HashMap;
 use std::collections::HashMap;
-use std::io::Error;
+use std::io::{Error, ErrorKind};
 use byteorder::{ByteOrder, LittleEndian};
 use byteorder::{ByteOrder, LittleEndian};
 
 
 pub mod assembler;
 pub mod assembler;
@@ -50,6 +50,9 @@ mod verifier;
 ///   - Unknown eBPF helper index.
 ///   - Unknown eBPF helper index.
 pub type Verifier = fn(prog: &[u8]) -> Result<(), Error>;
 pub type Verifier = fn(prog: &[u8]) -> Result<(), Error>;
 
 
+/// eBPF Jit-compiled program.
+pub type JitProgram = unsafe fn(*mut u8, usize, *mut u8, usize, usize, usize) -> u64;
+
 // A metadata buffer with two offset indications. It can be used in one kind of eBPF VM to simulate
 // A metadata buffer with two offset indications. It can be used in one kind of eBPF VM to simulate
 // the use of a metadata buffer each time the program is executed, without the user having to
 // the use of a metadata buffer each time the program is executed, without the user having to
 // actually handle it. The offsets are used to tell the VM where in the buffer the pointers to
 // actually handle it. The offsets are used to tell the VM where in the buffer the pointers to
@@ -89,13 +92,13 @@ struct MetaBuff {
 /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
 /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
 ///
 ///
 /// // Provide both a reference to the packet data, and to the metadata buffer.
 /// // Provide both a reference to the packet data, and to the metadata buffer.
-/// let res = vm.prog_exec(mem, &mut mbuff);
+/// let res = vm.prog_exec(mem, &mut mbuff).unwrap();
 /// assert_eq!(res, 0x2211);
 /// assert_eq!(res, 0x2211);
 /// ```
 /// ```
 pub struct EbpfVmMbuff<'a> {
 pub struct EbpfVmMbuff<'a> {
     prog:     Option<&'a [u8]>,
     prog:     Option<&'a [u8]>,
     verifier: Verifier,
     verifier: Verifier,
-    jit:      (unsafe fn(*mut u8, usize, *mut u8, usize, usize, usize) -> u64),
+    jit:      Option<JitProgram>,
     helpers:  HashMap<u32, ebpf::Helper>,
     helpers:  HashMap<u32, ebpf::Helper>,
 }
 }
 
 
@@ -121,15 +124,10 @@ impl<'a> EbpfVmMbuff<'a> {
             verifier::check(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 {
-            panic!("Error: program has not been JIT-compiled");
-        }
-
         Ok(EbpfVmMbuff {
         Ok(EbpfVmMbuff {
             prog:     prog,
             prog:     prog,
             verifier: verifier::check,
             verifier: verifier::check,
-            jit:      no_jit,
+            jit:      None,
             helpers:  HashMap::new(),
             helpers:  HashMap::new(),
         })
         })
     }
     }
@@ -230,10 +228,11 @@ impl<'a> EbpfVmMbuff<'a> {
     /// // Register a helper.
     /// // Register a helper.
     /// // On running the program this helper will print the content of registers r3, r4 and r5 to
     /// // On running the program this helper will print the content of registers r3, r4 and r5 to
     /// // standard output.
     /// // standard output.
-    /// vm.register_helper(6, helpers::bpf_trace_printf);
+    /// vm.register_helper(6, helpers::bpf_trace_printf).unwrap();
     /// ```
     /// ```
-    pub fn register_helper(&mut self, key: u32, function: fn (u64, u64, u64, u64, u64) -> u64) {
+    pub fn register_helper(&mut self, key: u32, function: fn (u64, u64, u64, u64, u64) -> u64) -> Result<(), Error> {
         self.helpers.insert(key, function);
         self.helpers.insert(key, function);
+        Ok(())
     }
     }
 
 
     /// Execute the program loaded, with the given packet data and metadata buffer.
     /// Execute the program loaded, with the given packet data and metadata buffer.
@@ -243,12 +242,6 @@ impl<'a> EbpfVmMbuff<'a> {
     /// metadata buffer, at some appointed offsets. It is up to the user to ensure that these
     /// metadata buffer, at some appointed offsets. It is up to the user to ensure that these
     /// pointers are correctly stored in the buffer.
     /// pointers are correctly stored in the buffer.
     ///
     ///
-    /// # Panics
-    ///
-    /// This function is currently expected to panic if it encounters any error during the program
-    /// execution, such as out of bounds accesses or division by zero attempts. This may be changed
-    /// in the future (we could raise errors instead).
-    ///
     /// # Examples
     /// # Examples
     ///
     ///
     /// ```
     /// ```
@@ -275,17 +268,18 @@ impl<'a> EbpfVmMbuff<'a> {
     /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
     /// let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
     ///
     ///
     /// // Provide both a reference to the packet data, and to the metadata buffer.
     /// // Provide both a reference to the packet data, and to the metadata buffer.
-    /// let res = vm.prog_exec(mem, &mut mbuff);
+    /// let res = vm.prog_exec(mem, &mut mbuff).unwrap();
     /// assert_eq!(res, 0x2211);
     /// assert_eq!(res, 0x2211);
     /// ```
     /// ```
     #[allow(unknown_lints)]
     #[allow(unknown_lints)]
     #[allow(cyclomatic_complexity)]
     #[allow(cyclomatic_complexity)]
-    pub fn prog_exec(&self, mem: &[u8], mbuff: &[u8]) -> u64 {
+    pub fn prog_exec(&self, mem: &[u8], mbuff: &[u8]) -> Result<u64, Error> {
         const U32MAX: u64 = u32::MAX as u64;
         const U32MAX: u64 = u32::MAX as u64;
 
 
         let prog = match self.prog { 
         let prog = match self.prog { 
             Some(prog) => prog,
             Some(prog) => prog,
-            None => panic!("Error: No program set, call prog_set() to load one"),
+            None => Err(Error::new(ErrorKind::Other,
+                        "Error: No program set, call prog_set() to load one"))?,
         };
         };
         let stack = vec![0u8;ebpf::STACK_SIZE];
         let stack = vec![0u8;ebpf::STACK_SIZE];
 
 
@@ -301,10 +295,10 @@ impl<'a> EbpfVmMbuff<'a> {
         }
         }
 
 
         let check_mem_load = | addr: u64, len: usize, insn_ptr: usize | {
         let check_mem_load = | addr: u64, len: usize, insn_ptr: usize | {
-            EbpfVmMbuff::check_mem(addr, len, "load", insn_ptr, mbuff, mem, &stack);
+            EbpfVmMbuff::check_mem(addr, len, "load", insn_ptr, mbuff, mem, &stack)
         };
         };
         let check_mem_store = | addr: u64, len: usize, insn_ptr: usize | {
         let check_mem_store = | addr: u64, len: usize, insn_ptr: usize | {
-            EbpfVmMbuff::check_mem(addr, len, "store", insn_ptr, mbuff, mem, &stack);
+            EbpfVmMbuff::check_mem(addr, len, "store", insn_ptr, mbuff, mem, &stack)
         };
         };
 
 
         // Loop on instructions
         // Loop on instructions
@@ -323,42 +317,42 @@ impl<'a> EbpfVmMbuff<'a> {
                 // bother re-fetching it, just use mem already.
                 // bother re-fetching it, just use mem already.
                 ebpf::LD_ABS_B   => reg[0] = unsafe {
                 ebpf::LD_ABS_B   => reg[0] = unsafe {
                     let x = (mem.as_ptr() as u64 + (insn.imm as u32) as u64) as *const u8;
                     let x = (mem.as_ptr() as u64 + (insn.imm as u32) as u64) as *const u8;
-                    check_mem_load(x as u64, 8, insn_ptr);
+                    check_mem_load(x as u64, 8, insn_ptr)?;
                     *x as u64
                     *x as u64
                 },
                 },
                 ebpf::LD_ABS_H   => reg[0] = unsafe {
                 ebpf::LD_ABS_H   => reg[0] = unsafe {
                     let x = (mem.as_ptr() as u64 + (insn.imm as u32) as u64) as *const u16;
                     let x = (mem.as_ptr() as u64 + (insn.imm as u32) as u64) as *const u16;
-                    check_mem_load(x as u64, 8, insn_ptr);
+                    check_mem_load(x as u64, 8, insn_ptr)?;
                     *x as u64
                     *x as u64
                 },
                 },
                 ebpf::LD_ABS_W   => reg[0] = unsafe {
                 ebpf::LD_ABS_W   => reg[0] = unsafe {
                     let x = (mem.as_ptr() as u64 + (insn.imm as u32) as u64) as *const u32;
                     let x = (mem.as_ptr() as u64 + (insn.imm as u32) as u64) as *const u32;
-                    check_mem_load(x as u64, 8, insn_ptr);
+                    check_mem_load(x as u64, 8, insn_ptr)?;
                     *x as u64
                     *x as u64
                 },
                 },
                 ebpf::LD_ABS_DW  => reg[0] = unsafe {
                 ebpf::LD_ABS_DW  => reg[0] = unsafe {
                     let x = (mem.as_ptr() as u64 + (insn.imm as u32) as u64) as *const u64;
                     let x = (mem.as_ptr() as u64 + (insn.imm as u32) as u64) as *const u64;
-                    check_mem_load(x as u64, 8, insn_ptr);
+                    check_mem_load(x as u64, 8, insn_ptr)?;
                     *x as u64
                     *x as u64
                 },
                 },
                 ebpf::LD_IND_B   => reg[0] = unsafe {
                 ebpf::LD_IND_B   => reg[0] = unsafe {
                     let x = (mem.as_ptr() as u64 + reg[_src] + (insn.imm as u32) as u64) as *const u8;
                     let x = (mem.as_ptr() as u64 + reg[_src] + (insn.imm as u32) as u64) as *const u8;
-                    check_mem_load(x as u64, 8, insn_ptr);
+                    check_mem_load(x as u64, 8, insn_ptr)?;
                     *x as u64
                     *x as u64
                 },
                 },
                 ebpf::LD_IND_H   => reg[0] = unsafe {
                 ebpf::LD_IND_H   => reg[0] = unsafe {
                     let x = (mem.as_ptr() as u64 + reg[_src] + (insn.imm as u32) as u64) as *const u16;
                     let x = (mem.as_ptr() as u64 + reg[_src] + (insn.imm as u32) as u64) as *const u16;
-                    check_mem_load(x as u64, 8, insn_ptr);
+                    check_mem_load(x as u64, 8, insn_ptr)?;
                     *x as u64
                     *x as u64
                 },
                 },
                 ebpf::LD_IND_W   => reg[0] = unsafe {
                 ebpf::LD_IND_W   => reg[0] = unsafe {
                     let x = (mem.as_ptr() as u64 + reg[_src] + (insn.imm as u32) as u64) as *const u32;
                     let x = (mem.as_ptr() as u64 + reg[_src] + (insn.imm as u32) as u64) as *const u32;
-                    check_mem_load(x as u64, 8, insn_ptr);
+                    check_mem_load(x as u64, 8, insn_ptr)?;
                     *x as u64
                     *x as u64
                 },
                 },
                 ebpf::LD_IND_DW  => reg[0] = unsafe {
                 ebpf::LD_IND_DW  => reg[0] = unsafe {
                     let x = (mem.as_ptr() as u64 + reg[_src] + (insn.imm as u32) as u64) as *const u64;
                     let x = (mem.as_ptr() as u64 + reg[_src] + (insn.imm as u32) as u64) as *const u64;
-                    check_mem_load(x as u64, 8, insn_ptr);
+                    check_mem_load(x as u64, 8, insn_ptr)?;
                     *x as u64
                     *x as u64
                 },
                 },
 
 
@@ -372,75 +366,75 @@ impl<'a> EbpfVmMbuff<'a> {
                 ebpf::LD_B_REG   => reg[_dst] = unsafe {
                 ebpf::LD_B_REG   => reg[_dst] = unsafe {
                     #[allow(cast_ptr_alignment)]
                     #[allow(cast_ptr_alignment)]
                     let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u8;
                     let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u8;
-                    check_mem_load(x as u64, 1, insn_ptr);
+                    check_mem_load(x as u64, 1, insn_ptr)?;
                     *x as u64
                     *x as u64
                 },
                 },
                 ebpf::LD_H_REG   => reg[_dst] = unsafe {
                 ebpf::LD_H_REG   => reg[_dst] = unsafe {
                     #[allow(cast_ptr_alignment)]
                     #[allow(cast_ptr_alignment)]
                     let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u16;
                     let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u16;
-                    check_mem_load(x as u64, 2, insn_ptr);
+                    check_mem_load(x as u64, 2, insn_ptr)?;
                     *x as u64
                     *x as u64
                 },
                 },
                 ebpf::LD_W_REG   => reg[_dst] = unsafe {
                 ebpf::LD_W_REG   => reg[_dst] = unsafe {
                     #[allow(cast_ptr_alignment)]
                     #[allow(cast_ptr_alignment)]
                     let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u32;
                     let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u32;
-                    check_mem_load(x as u64, 4, insn_ptr);
+                    check_mem_load(x as u64, 4, insn_ptr)?;
                     *x as u64
                     *x as u64
                 },
                 },
                 ebpf::LD_DW_REG  => reg[_dst] = unsafe {
                 ebpf::LD_DW_REG  => reg[_dst] = unsafe {
                     #[allow(cast_ptr_alignment)]
                     #[allow(cast_ptr_alignment)]
                     let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u64;
                     let x = (reg[_src] as *const u8).offset(insn.off as isize) as *const u64;
-                    check_mem_load(x as u64, 8, insn_ptr);
+                    check_mem_load(x as u64, 8, insn_ptr)?;
                     *x as u64
                     *x as u64
                 },
                 },
 
 
                 // BPF_ST class
                 // BPF_ST class
                 ebpf::ST_B_IMM   => unsafe {
                 ebpf::ST_B_IMM   => unsafe {
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u8;
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u8;
-                    check_mem_store(x as u64, 1, insn_ptr);
+                    check_mem_store(x as u64, 1, insn_ptr)?;
                     *x = insn.imm as u8;
                     *x = insn.imm as u8;
                 },
                 },
                 ebpf::ST_H_IMM   => unsafe {
                 ebpf::ST_H_IMM   => unsafe {
                     #[allow(cast_ptr_alignment)]
                     #[allow(cast_ptr_alignment)]
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u16;
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u16;
-                    check_mem_store(x as u64, 2, insn_ptr);
+                    check_mem_store(x as u64, 2, insn_ptr)?;
                     *x = insn.imm as u16;
                     *x = insn.imm as u16;
                 },
                 },
                 ebpf::ST_W_IMM   => unsafe {
                 ebpf::ST_W_IMM   => unsafe {
                     #[allow(cast_ptr_alignment)]
                     #[allow(cast_ptr_alignment)]
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u32;
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u32;
-                    check_mem_store(x as u64, 4, insn_ptr);
+                    check_mem_store(x as u64, 4, insn_ptr)?;
                     *x = insn.imm as u32;
                     *x = insn.imm as u32;
                 },
                 },
                 ebpf::ST_DW_IMM  => unsafe {
                 ebpf::ST_DW_IMM  => unsafe {
                     #[allow(cast_ptr_alignment)]
                     #[allow(cast_ptr_alignment)]
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u64;
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u64;
-                    check_mem_store(x as u64, 8, insn_ptr);
+                    check_mem_store(x as u64, 8, insn_ptr)?;
                     *x = insn.imm as u64;
                     *x = insn.imm as u64;
                 },
                 },
 
 
                 // BPF_STX class
                 // BPF_STX class
                 ebpf::ST_B_REG   => unsafe {
                 ebpf::ST_B_REG   => unsafe {
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u8;
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u8;
-                    check_mem_store(x as u64, 1, insn_ptr);
+                    check_mem_store(x as u64, 1, insn_ptr)?;
                     *x = reg[_src] as u8;
                     *x = reg[_src] as u8;
                 },
                 },
                 ebpf::ST_H_REG   => unsafe {
                 ebpf::ST_H_REG   => unsafe {
                     #[allow(cast_ptr_alignment)]
                     #[allow(cast_ptr_alignment)]
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u16;
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u16;
-                    check_mem_store(x as u64, 2, insn_ptr);
+                    check_mem_store(x as u64, 2, insn_ptr)?;
                     *x = reg[_src] as u16;
                     *x = reg[_src] as u16;
                 },
                 },
                 ebpf::ST_W_REG   => unsafe {
                 ebpf::ST_W_REG   => unsafe {
                     #[allow(cast_ptr_alignment)]
                     #[allow(cast_ptr_alignment)]
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u32;
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u32;
-                    check_mem_store(x as u64, 4, insn_ptr);
+                    check_mem_store(x as u64, 4, insn_ptr)?;
                     *x = reg[_src] as u32;
                     *x = reg[_src] as u32;
                 },
                 },
                 ebpf::ST_DW_REG  => unsafe {
                 ebpf::ST_DW_REG  => unsafe {
                     #[allow(cast_ptr_alignment)]
                     #[allow(cast_ptr_alignment)]
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u64;
                     let x = (reg[_dst] as *const u8).offset(insn.off as isize) as *mut u64;
-                    check_mem_store(x as u64, 8, insn_ptr);
+                    check_mem_store(x as u64, 8, insn_ptr)?;
                     *x = reg[_src] as u64;
                     *x = reg[_src] as u64;
                 },
                 },
                 ebpf::ST_W_XADD  => unimplemented!(),
                 ebpf::ST_W_XADD  => unimplemented!(),
@@ -459,7 +453,7 @@ impl<'a> EbpfVmMbuff<'a> {
                 ebpf::DIV32_IMM  => reg[_dst] = (reg[_dst] as u32 / insn.imm              as u32) as u64,
                 ebpf::DIV32_IMM  => reg[_dst] = (reg[_dst] as u32 / insn.imm              as u32) as u64,
                 ebpf::DIV32_REG  => {
                 ebpf::DIV32_REG  => {
                     if reg[_src] == 0 {
                     if reg[_src] == 0 {
-                        panic!("Error: division by 0");
+                        Err(Error::new(ErrorKind::Other,"Error: division by 0"))?;
                     }
                     }
                     reg[_dst] = (reg[_dst] as u32 / reg[_src] as u32) as u64;
                     reg[_dst] = (reg[_dst] as u32 / reg[_src] as u32) as u64;
                 },
                 },
@@ -475,7 +469,7 @@ impl<'a> EbpfVmMbuff<'a> {
                 ebpf::MOD32_IMM  =>   reg[_dst] = (reg[_dst] as u32             % insn.imm  as u32) as u64,
                 ebpf::MOD32_IMM  =>   reg[_dst] = (reg[_dst] as u32             % insn.imm  as u32) as u64,
                 ebpf::MOD32_REG  => {
                 ebpf::MOD32_REG  => {
                     if reg[_src] == 0 {
                     if reg[_src] == 0 {
-                        panic!("Error: division by 0");
+                        Err(Error::new(ErrorKind::Other,"Error: division by 0"))?;
                     }
                     }
                     reg[_dst] = (reg[_dst] as u32 % reg[_src] as u32) as u64;
                     reg[_dst] = (reg[_dst] as u32 % reg[_src] as u32) as u64;
                 },
                 },
@@ -512,7 +506,7 @@ impl<'a> EbpfVmMbuff<'a> {
                 ebpf::DIV64_IMM  => reg[_dst]                       /= insn.imm as u64,
                 ebpf::DIV64_IMM  => reg[_dst]                       /= insn.imm as u64,
                 ebpf::DIV64_REG  => {
                 ebpf::DIV64_REG  => {
                     if reg[_src] == 0 {
                     if reg[_src] == 0 {
-                        panic!("Error: division by 0");
+                        Err(Error::new(ErrorKind::Other,"Error: division by 0"))?;
                     }
                     }
                     reg[_dst] /= reg[_src];
                     reg[_dst] /= reg[_src];
                 },
                 },
@@ -528,7 +522,7 @@ impl<'a> EbpfVmMbuff<'a> {
                 ebpf::MOD64_IMM  => reg[_dst] %=  insn.imm as u64,
                 ebpf::MOD64_IMM  => reg[_dst] %=  insn.imm as u64,
                 ebpf::MOD64_REG  => {
                 ebpf::MOD64_REG  => {
                     if reg[_src] == 0 {
                     if reg[_src] == 0 {
-                        panic!("Error: division by 0");
+                        Err(Error::new(ErrorKind::Other,"Error: division by 0"))?;
                     }
                     }
                     reg[_dst] %= reg[_src];
                     reg[_dst] %= reg[_src];
                 },
                 },
@@ -569,10 +563,10 @@ impl<'a> EbpfVmMbuff<'a> {
                 ebpf::CALL       => if let Some(function) = self.helpers.get(&(insn.imm as u32)) {
                 ebpf::CALL       => if let Some(function) = self.helpers.get(&(insn.imm as u32)) {
                     reg[0] = function(reg[1], reg[2], reg[3], reg[4], reg[5]);
                     reg[0] = function(reg[1], reg[2], reg[3], reg[4], reg[5]);
                 } else {
                 } else {
-                    panic!("Error: unknown helper function (id: {:#x})", insn.imm as u32);
+                    Err(Error::new(ErrorKind::Other, format!("Error: unknown helper function (id: {:#x})", insn.imm as u32)))?;
                 },
                 },
                 ebpf::TAIL_CALL  => unimplemented!(),
                 ebpf::TAIL_CALL  => unimplemented!(),
-                ebpf::EXIT       => return reg[0],
+                ebpf::EXIT       => return Ok(reg[0]),
 
 
                 _                => unreachable!()
                 _                => unreachable!()
             }
             }
@@ -582,24 +576,24 @@ impl<'a> EbpfVmMbuff<'a> {
     }
     }
 
 
     fn check_mem(addr: u64, len: usize, access_type: &str, insn_ptr: usize,
     fn check_mem(addr: u64, len: usize, access_type: &str, insn_ptr: usize,
-                 mbuff: &[u8], mem: &[u8], stack: &[u8]) {
+                 mbuff: &[u8], mem: &[u8], stack: &[u8]) -> Result<(), Error> {
         if mbuff.as_ptr() as u64 <= addr && addr + len as u64 <= mbuff.as_ptr() as u64 + mbuff.len() as u64 {
         if mbuff.as_ptr() as u64 <= addr && addr + len as u64 <= mbuff.as_ptr() as u64 + mbuff.len() as u64 {
-            return
+            return Ok(())
         }
         }
         if mem.as_ptr() as u64 <= addr && addr + len as u64 <= mem.as_ptr() as u64 + mem.len() as u64 {
         if mem.as_ptr() as u64 <= addr && addr + len as u64 <= mem.as_ptr() as u64 + mem.len() as u64 {
-            return
+            return Ok(())
         }
         }
         if stack.as_ptr() as u64 <= addr && addr + len as u64 <= stack.as_ptr() as u64 + stack.len() as u64 {
         if stack.as_ptr() as u64 <= addr && addr + len as u64 <= stack.as_ptr() as u64 + stack.len() as u64 {
-            return
+            return Ok(())
         }
         }
 
 
-        panic!(
+        Err(Error::new(ErrorKind::Other, format!(
             "Error: out of bounds memory {} (insn #{:?}), addr {:#x}, size {:?}\nmbuff: {:#x}/{:#x}, mem: {:#x}/{:#x}, stack: {:#x}/{:#x}",
             "Error: out of bounds memory {} (insn #{:?}), addr {:#x}, size {:?}\nmbuff: {:#x}/{:#x}, mem: {:#x}/{:#x}, stack: {:#x}/{:#x}",
             access_type, insn_ptr, addr, len,
             access_type, insn_ptr, addr, len,
             mbuff.as_ptr() as u64, mbuff.len(),
             mbuff.as_ptr() as u64, mbuff.len(),
             mem.as_ptr() as u64, mem.len(),
             mem.as_ptr() as u64, mem.len(),
             stack.as_ptr() as u64, stack.len()
             stack.as_ptr() as u64, stack.len()
-        );
+        )))
     }
     }
 
 
     /// JIT-compile the loaded program. No argument required for this.
     /// JIT-compile the loaded program. No argument required for this.
@@ -607,11 +601,6 @@ impl<'a> EbpfVmMbuff<'a> {
     /// If using helper functions, be sure to register them into the VM before calling this
     /// If using helper functions, be sure to register them into the VM before calling this
     /// function.
     /// function.
     ///
     ///
-    /// # Panics
-    ///
-    /// This function panics if an error occurs during JIT-compiling, such as the occurrence of an
-    /// unknown eBPF operation code.
-    ///
     /// # Examples
     /// # Examples
     ///
     ///
     /// ```
     /// ```
@@ -627,12 +616,13 @@ impl<'a> EbpfVmMbuff<'a> {
     /// vm.jit_compile();
     /// vm.jit_compile();
     /// ```
     /// ```
     #[cfg(not(windows))]
     #[cfg(not(windows))]
-    pub fn jit_compile(&mut self) {
+    pub fn jit_compile(&mut self) -> Result<(), Error> {
         let prog = match self.prog { 
         let prog = match self.prog { 
             Some(prog) => prog,
             Some(prog) => prog,
-            None => panic!("Error: No program set, call prog_set() to load one"),
+            None => Err(Error::new(ErrorKind::Other, "Error: No program set, call prog_set() to load one"))?,
         };
         };
-        self.jit = jit::compile(prog, &self.helpers, true, false);
+        self.jit = Some(jit::compile(prog, &self.helpers, true, false)?);
+        Ok(())
     }
     }
 
 
     /// Execute the previously JIT-compiled program, with the given packet data and metadata
     /// Execute the previously JIT-compiled program, with the given packet data and metadata
@@ -643,10 +633,6 @@ impl<'a> EbpfVmMbuff<'a> {
     /// metadata buffer, at some appointed offsets. It is up to the user to ensure that these
     /// metadata buffer, at some appointed offsets. It is up to the user to ensure that these
     /// pointers are correctly stored in the buffer.
     /// pointers are correctly stored in the buffer.
     ///
     ///
-    /// # Panics
-    ///
-    /// This function panics if an error occurs during the execution of the program.
-    ///
     /// # Safety
     /// # Safety
     ///
     ///
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
@@ -687,11 +673,11 @@ impl<'a> EbpfVmMbuff<'a> {
     /// // Provide both a reference to the packet data, and to the metadata buffer.
     /// // Provide both a reference to the packet data, and to the metadata buffer.
     /// # #[cfg(not(windows))]
     /// # #[cfg(not(windows))]
     /// unsafe {
     /// unsafe {
-    ///     let res = vm.prog_exec_jit(mem, &mut mbuff);
+    ///     let res = vm.prog_exec_jit(mem, &mut mbuff).unwrap();
     ///     assert_eq!(res, 0x2211);
     ///     assert_eq!(res, 0x2211);
     /// }
     /// }
     /// ```
     /// ```
-    pub unsafe fn prog_exec_jit(&self, mem: &mut [u8], mbuff: &'a mut [u8]) -> u64 {
+    pub unsafe fn prog_exec_jit(&self, mem: &mut [u8], mbuff: &'a mut [u8]) -> Result<u64, Error> {
         // If packet data is empty, do not send the address of an empty slice; send a null pointer
         // If packet data is empty, do not send the address of an empty slice; send a null pointer
         //  as first argument instead, as this is uBPF's behavior (empty packet should not happen
         //  as first argument instead, as this is uBPF's behavior (empty packet should not happen
         //  in the kernel; anyway the verifier would prevent the use of uninitialized registers).
         //  in the kernel; anyway the verifier would prevent the use of uninitialized registers).
@@ -703,7 +689,11 @@ impl<'a> EbpfVmMbuff<'a> {
         // The last two arguments are not used in this function. They would be used if there was a
         // The last two arguments are not used in this function. They would be used if there was a
         // need to indicate to the JIT at which offset in the mbuff mem_ptr and mem_ptr + mem.len()
         // need to indicate to the JIT at which offset in the mbuff mem_ptr and mem_ptr + mem.len()
         // should be stored; this is what happens with struct EbpfVmFixedMbuff.
         // should be stored; this is what happens with struct EbpfVmFixedMbuff.
-        (self.jit)(mbuff.as_ptr() as *mut u8, mbuff.len(), mem_ptr, mem.len(), 0, 0)
+        match self.jit {
+            Some(jit) => Ok(jit(mbuff.as_ptr() as *mut u8, mbuff.len(), mem_ptr, mem.len(), 0, 0)),
+            None => Err(Error::new(ErrorKind::Other,
+                        "Error: program has not been JIT-compiled")),
+        }
     }
     }
 }
 }
 
 
@@ -768,10 +758,10 @@ impl<'a> EbpfVmMbuff<'a> {
 /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(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.
 /// // Provide only a reference to the packet data. We do not manage the metadata buffer.
-/// let res = vm.prog_exec(mem1);
+/// let res = vm.prog_exec(mem1).unwrap();
 /// assert_eq!(res, 0xffffffffffffffdd);
 /// assert_eq!(res, 0xffffffffffffffdd);
 ///
 ///
-/// let res = vm.prog_exec(mem2);
+/// let res = vm.prog_exec(mem2).unwrap();
 /// assert_eq!(res, 0x27);
 /// assert_eq!(res, 0x27);
 /// ```
 /// ```
 pub struct EbpfVmFixedMbuff<'a> {
 pub struct EbpfVmFixedMbuff<'a> {
@@ -844,7 +834,7 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog1), 0, 0).unwrap();
     /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog1), 0, 0).unwrap();
     /// vm.set_prog(prog2, 0x40, 0x50);
     /// vm.set_prog(prog2, 0x40, 0x50);
     ///
     ///
-    /// let res = vm.prog_exec(mem);
+    /// let res = vm.prog_exec(mem).unwrap();
     /// assert_eq!(res, 0x27);
     /// assert_eq!(res, 0x27);
     /// ```
     /// ```
     pub fn set_prog(&mut self, prog: &'a [u8], data_offset: usize, data_end_offset: usize) -> Result<(), Error> {
     pub fn set_prog(&mut self, prog: &'a [u8], data_offset: usize, data_end_offset: usize) -> Result<(), Error> {
@@ -930,11 +920,11 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     /// // Register a helper. This helper will store the result of the square root of r1 into r0.
     /// // Register a helper. This helper will store the result of the square root of r1 into r0.
     /// vm.register_helper(1, helpers::sqrti);
     /// vm.register_helper(1, helpers::sqrti);
     ///
     ///
-    /// let res = vm.prog_exec(mem);
+    /// let res = vm.prog_exec(mem).unwrap();
     /// assert_eq!(res, 3);
     /// assert_eq!(res, 3);
     /// ```
     /// ```
-    pub fn register_helper(&mut self, key: u32, function: fn (u64, u64, u64, u64, u64) -> u64) {
-        self.parent.register_helper(key, function);
+    pub fn register_helper(&mut self, key: u32, function: fn (u64, u64, u64, u64, u64) -> u64) -> Result<(), Error> {
+        self.parent.register_helper(key, function)
     }
     }
 
 
     /// Execute the program loaded, with the given packet data.
     /// Execute the program loaded, with the given packet data.
@@ -944,12 +934,6 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     /// metadata buffer, which in the case of this VM is handled internally. The offsets at which
     /// metadata buffer, which in the case of this VM is handled internally. The offsets at which
     /// the addresses should be placed should have be set at the creation of the VM.
     /// the addresses should be placed should have be set at the creation of the VM.
     ///
     ///
-    /// # Panics
-    ///
-    /// This function is currently expected to panic if it encounters any error during the program
-    /// execution, such as out of bounds accesses or division by zero attempts. This may be changed
-    /// in the future (we could raise errors instead).
-    ///
     /// # Examples
     /// # Examples
     ///
     ///
     /// ```
     /// ```
@@ -970,15 +954,15 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     /// let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(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.
     /// // Provide only a reference to the packet data. We do not manage the metadata buffer.
-    /// let res = vm.prog_exec(mem);
+    /// let res = vm.prog_exec(mem).unwrap();
     /// assert_eq!(res, 0xdd);
     /// assert_eq!(res, 0xdd);
     /// ```
     /// ```
-    pub fn prog_exec(&mut self, mem: &'a mut [u8]) -> u64 {
+    pub fn prog_exec(&mut self, mem: &'a mut [u8]) -> Result<u64, Error> {
         let l = self.mbuff.buffer.len();
         let l = self.mbuff.buffer.len();
         // Can this ever happen? Probably not, should be ensured at mbuff creation.
         // Can this ever happen? Probably not, should be ensured at mbuff creation.
         if self.mbuff.data_offset + 8 > l || self.mbuff.data_end_offset + 8 > l {
         if self.mbuff.data_offset + 8 > l || self.mbuff.data_end_offset + 8 > l {
-            panic!("Error: buffer too small ({:?}), cannot use data_offset {:?} and data_end_offset {:?}",
-            l, self.mbuff.data_offset, self.mbuff.data_end_offset);
+            Err(Error::new(ErrorKind::Other, format!("Error: buffer too small ({:?}), cannot use data_offset {:?} and data_end_offset {:?}",
+            l, self.mbuff.data_offset, self.mbuff.data_end_offset)))?;
         }
         }
         LittleEndian::write_u64(&mut self.mbuff.buffer[(self.mbuff.data_offset) .. ], mem.as_ptr() as u64);
         LittleEndian::write_u64(&mut self.mbuff.buffer[(self.mbuff.data_offset) .. ], mem.as_ptr() as u64);
         LittleEndian::write_u64(&mut self.mbuff.buffer[(self.mbuff.data_end_offset) .. ], mem.as_ptr() as u64 + mem.len() as u64);
         LittleEndian::write_u64(&mut self.mbuff.buffer[(self.mbuff.data_end_offset) .. ], mem.as_ptr() as u64 + mem.len() as u64);
@@ -990,11 +974,6 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     /// If using helper functions, be sure to register them into the VM before calling this
     /// If using helper functions, be sure to register them into the VM before calling this
     /// function.
     /// function.
     ///
     ///
-    /// # Panics
-    ///
-    /// This function panics if an error occurs during JIT-compiling, such as the occurrence of an
-    /// unknown eBPF operation code.
-    ///
     /// # Examples
     /// # Examples
     ///
     ///
     /// ```
     /// ```
@@ -1014,12 +993,13 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     /// vm.jit_compile();
     /// vm.jit_compile();
     /// ```
     /// ```
     #[cfg(not(windows))]
     #[cfg(not(windows))]
-    pub fn jit_compile(&mut self) {
+    pub fn jit_compile(&mut self) -> Result<(), Error> {
         let prog = match self.parent.prog { 
         let prog = match self.parent.prog { 
             Some(prog) => prog,
             Some(prog) => prog,
-            None => panic!("Error: No program set, call prog_set() to load one"),
+            None => Err(Error::new(ErrorKind::Other, "Error: No program set, call prog_set() to load one"))?,
         };
         };
-        self.parent.jit = jit::compile(prog, &self.parent.helpers, true, true);
+        self.parent.jit = Some(jit::compile(prog, &self.parent.helpers, true, true)?);
+        Ok(())
     }
     }
 
 
     /// Execute the previously JIT-compiled program, with the given packet data, in a manner very
     /// Execute the previously JIT-compiled program, with the given packet data, in a manner very
@@ -1030,10 +1010,6 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     /// metadata buffer, which in the case of this VM is handled internally. The offsets at which
     /// metadata buffer, which in the case of this VM is handled internally. The offsets at which
     /// the addresses should be placed should have be set at the creation of the VM.
     /// the addresses should be placed should have be set at the creation of the VM.
     ///
     ///
-    /// # Panics
-    ///
-    /// This function panics if an error occurs during the execution of the program.
-    ///
     /// # Safety
     /// # Safety
     ///
     ///
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
@@ -1068,13 +1044,13 @@ impl<'a> EbpfVmFixedMbuff<'a> {
     /// // Provide only a reference to the packet data. We do not manage the metadata buffer.
     /// // Provide only a reference to the packet data. We do not manage the metadata buffer.
     /// # #[cfg(not(windows))]
     /// # #[cfg(not(windows))]
     /// unsafe {
     /// unsafe {
-    ///     let res = vm.prog_exec_jit(mem);
+    ///     let res = vm.prog_exec_jit(mem).unwrap();
     ///     assert_eq!(res, 0xdd);
     ///     assert_eq!(res, 0xdd);
     /// }
     /// }
     /// ```
     /// ```
     // This struct redefines the `prog_exec_jit()` function, in order to pass the offsets
     // This struct redefines the `prog_exec_jit()` function, in order to pass the offsets
     // associated with the fixed mbuff.
     // associated with the fixed mbuff.
-    pub unsafe fn prog_exec_jit(&mut self, mem: &'a mut [u8]) -> u64 {
+    pub unsafe fn prog_exec_jit(&mut self, mem: &'a mut [u8]) -> Result<u64, Error> {
         // If packet data is empty, do not send the address of an empty slice; send a null pointer
         // If packet data is empty, do not send the address of an empty slice; send a null pointer
         //  as first argument instead, as this is uBPF's behavior (empty packet should not happen
         //  as first argument instead, as this is uBPF's behavior (empty packet should not happen
         //  in the kernel; anyway the verifier would prevent the use of uninitialized registers).
         //  in the kernel; anyway the verifier would prevent the use of uninitialized registers).
@@ -1083,8 +1059,17 @@ impl<'a> EbpfVmFixedMbuff<'a> {
             0 => std::ptr::null_mut(),
             0 => std::ptr::null_mut(),
             _ => mem.as_ptr() as *mut u8
             _ => mem.as_ptr() as *mut u8
         };
         };
-        (self.parent.jit)(self.mbuff.buffer.as_ptr() as *mut u8, self.mbuff.buffer.len(),
-                          mem_ptr, mem.len(), self.mbuff.data_offset, self.mbuff.data_end_offset)
+        
+        match self.parent.jit {
+            Some(jit) => Ok(jit(self.mbuff.buffer.as_ptr() as *mut u8,
+                                self.mbuff.buffer.len(),
+                                mem_ptr,
+                                mem.len(), 
+                                self.mbuff.data_offset,
+                                self.mbuff.data_end_offset)),
+            None => Err(Error::new(ErrorKind::Other,
+                                   "Error: program has not been JIT-compiled"))
+        }
     }
     }
 }
 }
 
 
@@ -1108,7 +1093,7 @@ impl<'a> EbpfVmFixedMbuff<'a> {
 /// let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
 /// let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
 ///
 ///
 /// // Provide only a reference to the packet data.
 /// // Provide only a reference to the packet data.
-/// let res = vm.prog_exec(mem);
+/// let res = vm.prog_exec(mem).unwrap();
 /// assert_eq!(res, 0x22cc);
 /// assert_eq!(res, 0x22cc);
 /// ```
 /// ```
 pub struct EbpfVmRaw<'a> {
 pub struct EbpfVmRaw<'a> {
@@ -1163,7 +1148,7 @@ impl<'a> EbpfVmRaw<'a> {
     /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog1)).unwrap();
     /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog1)).unwrap();
     /// vm.set_prog(prog2);
     /// vm.set_prog(prog2);
     ///
     ///
-    /// let res = vm.prog_exec(mem);
+    /// let res = vm.prog_exec(mem).unwrap();
     /// assert_eq!(res, 0x22cc);
     /// assert_eq!(res, 0x22cc);
     /// ```
     /// ```
     pub fn set_prog(&mut self, prog: &'a [u8]) -> Result<(), Error> {
     pub fn set_prog(&mut self, prog: &'a [u8]) -> Result<(), Error> {
@@ -1237,21 +1222,15 @@ impl<'a> EbpfVmRaw<'a> {
     /// // Register a helper. This helper will store the result of the square root of r1 into r0.
     /// // Register a helper. This helper will store the result of the square root of r1 into r0.
     /// vm.register_helper(1, helpers::sqrti);
     /// vm.register_helper(1, helpers::sqrti);
     ///
     ///
-    /// let res = vm.prog_exec(mem);
+    /// let res = vm.prog_exec(mem).unwrap();
     /// assert_eq!(res, 0x10000000);
     /// assert_eq!(res, 0x10000000);
     /// ```
     /// ```
-    pub fn register_helper(&mut self, key: u32, function: fn (u64, u64, u64, u64, u64) -> u64) {
-        self.parent.register_helper(key, function);
+    pub fn register_helper(&mut self, key: u32, function: fn (u64, u64, u64, u64, u64) -> u64) -> Result<(), Error> {
+        self.parent.register_helper(key, function)
     }
     }
 
 
     /// Execute the program loaded, with the given packet data.
     /// Execute the program loaded, with the given packet data.
     ///
     ///
-    /// # Panics
-    ///
-    /// This function is currently expected to panic if it encounters any error during the program
-    /// execution, such as out of bounds accesses or division by zero attempts. This may be changed
-    /// in the future (we could raise errors instead).
-    ///
     /// # Examples
     /// # Examples
     ///
     ///
     /// ```
     /// ```
@@ -1268,10 +1247,10 @@ impl<'a> EbpfVmRaw<'a> {
     ///
     ///
     /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     /// let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     ///
     ///
-    /// let res = vm.prog_exec(mem);
+    /// let res = vm.prog_exec(mem).unwrap();
     /// assert_eq!(res, 0x22cc);
     /// assert_eq!(res, 0x22cc);
     /// ```
     /// ```
-    pub fn prog_exec(&self, mem: &'a mut [u8]) -> u64 {
+    pub fn prog_exec(&self, mem: &'a mut [u8]) -> Result<u64, Error> {
         self.parent.prog_exec(mem, &[])
         self.parent.prog_exec(mem, &[])
     }
     }
 
 
@@ -1280,11 +1259,6 @@ impl<'a> EbpfVmRaw<'a> {
     /// If using helper functions, be sure to register them into the VM before calling this
     /// If using helper functions, be sure to register them into the VM before calling this
     /// function.
     /// function.
     ///
     ///
-    /// # Panics
-    ///
-    /// This function panics if an error occurs during JIT-compiling, such as the occurrence of an
-    /// unknown eBPF operation code.
-    ///
     /// # Examples
     /// # Examples
     ///
     ///
     /// ```
     /// ```
@@ -1300,21 +1274,19 @@ impl<'a> EbpfVmRaw<'a> {
     /// vm.jit_compile();
     /// vm.jit_compile();
     /// ```
     /// ```
     #[cfg(not(windows))]
     #[cfg(not(windows))]
-    pub fn jit_compile(&mut self) {
+    pub fn jit_compile(&mut self) -> Result<(), Error> {
         let prog = match self.parent.prog { 
         let prog = match self.parent.prog { 
             Some(prog) => prog,
             Some(prog) => prog,
-            None => panic!("Error: No program set, call prog_set() to load one"),
+            None => Err(Error::new(ErrorKind::Other,
+                        "Error: No program set, call prog_set() to load one"))?,
         };
         };
-        self.parent.jit = jit::compile(prog, &self.parent.helpers, false, false);
+        self.parent.jit = Some(jit::compile(prog, &self.parent.helpers, false, false)?);
+        Ok(())
     }
     }
 
 
     /// Execute the previously JIT-compiled program, with the given packet data, in a manner very
     /// Execute the previously JIT-compiled program, with the given packet data, in a manner very
     /// similar to `prog_exec()`.
     /// similar to `prog_exec()`.
     ///
     ///
-    /// # Panics
-    ///
-    /// This function panics if an error occurs during the execution of the program.
-    ///
     /// # Safety
     /// # Safety
     ///
     ///
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
@@ -1345,11 +1317,11 @@ impl<'a> EbpfVmRaw<'a> {
     ///
     ///
     /// # #[cfg(not(windows))]
     /// # #[cfg(not(windows))]
     /// unsafe {
     /// unsafe {
-    ///     let res = vm.prog_exec_jit(mem);
+    ///     let res = vm.prog_exec_jit(mem).unwrap();
     ///     assert_eq!(res, 0x22cc);
     ///     assert_eq!(res, 0x22cc);
     /// }
     /// }
     /// ```
     /// ```
-    pub unsafe fn prog_exec_jit(&self, mem: &'a mut [u8]) -> u64 {
+    pub unsafe fn prog_exec_jit(&self, mem: &'a mut [u8]) -> Result<u64, Error> {
         let mut mbuff = vec![];
         let mut mbuff = vec![];
         self.parent.prog_exec_jit(mem, &mut mbuff)
         self.parent.prog_exec_jit(mem, &mut mbuff)
     }
     }
@@ -1391,7 +1363,7 @@ impl<'a> EbpfVmRaw<'a> {
 /// let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
 /// let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
 ///
 ///
 /// // Provide only a reference to the packet data.
 /// // Provide only a reference to the packet data.
-/// let res = vm.prog_exec();
+/// let res = vm.prog_exec().unwrap();
 /// assert_eq!(res, 0x11);
 /// assert_eq!(res, 0x11);
 /// ```
 /// ```
 pub struct EbpfVmNoData<'a> {
 pub struct EbpfVmNoData<'a> {
@@ -1439,12 +1411,12 @@ impl<'a> EbpfVmNoData<'a> {
     ///
     ///
     /// let mut vm = rbpf::EbpfVmNoData::new(Some(prog1)).unwrap();
     /// let mut vm = rbpf::EbpfVmNoData::new(Some(prog1)).unwrap();
     ///
     ///
-    /// let res = vm.prog_exec();
+    /// let res = vm.prog_exec().unwrap();
     /// assert_eq!(res, 0x2211);
     /// assert_eq!(res, 0x2211);
     ///
     ///
     /// vm.set_prog(prog2);
     /// vm.set_prog(prog2);
     ///
     ///
-    /// let res = vm.prog_exec();
+    /// let res = vm.prog_exec().unwrap();
     /// assert_eq!(res, 0x1122);
     /// assert_eq!(res, 0x1122);
     /// ```
     /// ```
     pub fn set_prog(&mut self, prog: &'a [u8]) -> Result<(), Error> {
     pub fn set_prog(&mut self, prog: &'a [u8]) -> Result<(), Error> {
@@ -1511,13 +1483,13 @@ impl<'a> EbpfVmNoData<'a> {
     /// let mut vm = rbpf::EbpfVmNoData::new(Some(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.
     /// // Register a helper. This helper will store the result of the square root of r1 into r0.
-    /// vm.register_helper(1, helpers::sqrti);
+    /// vm.register_helper(1, helpers::sqrti).unwrap();
     ///
     ///
-    /// let res = vm.prog_exec();
+    /// let res = vm.prog_exec().unwrap();
     /// assert_eq!(res, 0x1000);
     /// assert_eq!(res, 0x1000);
     /// ```
     /// ```
-    pub fn register_helper(&mut self, key: u32, function: fn (u64, u64, u64, u64, u64) -> u64) {
-        self.parent.register_helper(key, function);
+    pub fn register_helper(&mut self, key: u32, function: fn (u64, u64, u64, u64, u64) -> u64) -> Result<(), Error> {
+        self.parent.register_helper(key, function)
     }
     }
 
 
     /// JIT-compile the loaded program. No argument required for this.
     /// JIT-compile the loaded program. No argument required for this.
@@ -1525,11 +1497,6 @@ impl<'a> EbpfVmNoData<'a> {
     /// If using helper functions, be sure to register them into the VM before calling this
     /// If using helper functions, be sure to register them into the VM before calling this
     /// function.
     /// function.
     ///
     ///
-    /// # Panics
-    ///
-    /// This function panics if an error occurs during JIT-compiling, such as the occurrence of an
-    /// unknown eBPF operation code.
-    ///
     /// # Examples
     /// # Examples
     ///
     ///
     /// ```
     /// ```
@@ -1545,18 +1512,12 @@ impl<'a> EbpfVmNoData<'a> {
     /// vm.jit_compile();
     /// vm.jit_compile();
     /// ```
     /// ```
     #[cfg(not(windows))]
     #[cfg(not(windows))]
-    pub fn jit_compile(&mut self) {
-        self.parent.jit_compile();
+    pub fn jit_compile(&mut self) -> Result<(), Error> {
+        self.parent.jit_compile()
     }
     }
 
 
     /// Execute the program loaded, without providing pointers to any memory area whatsoever.
     /// Execute the program loaded, without providing pointers to any memory area whatsoever.
     ///
     ///
-    /// # Panics
-    ///
-    /// This function is currently expected to panic if it encounters any error during the program
-    /// execution, such as memory accesses or division by zero attempts. This may be changed in the
-    /// future (we could raise errors instead).
-    ///
     /// # Examples
     /// # Examples
     ///
     ///
     /// ```
     /// ```
@@ -1569,20 +1530,16 @@ impl<'a> EbpfVmNoData<'a> {
     /// let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     /// let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     ///
     ///
     /// // For this kind of VM, the `prog_exec()` function needs no argument.
     /// // For this kind of VM, the `prog_exec()` function needs no argument.
-    /// let res = vm.prog_exec();
+    /// let res = vm.prog_exec().unwrap();
     /// assert_eq!(res, 0x1122);
     /// assert_eq!(res, 0x1122);
     /// ```
     /// ```
-    pub fn prog_exec(&self) -> u64 {
+    pub fn prog_exec(&self) -> Result<(u64), Error> {
         self.parent.prog_exec(&mut [])
         self.parent.prog_exec(&mut [])
     }
     }
 
 
     /// Execute the previously JIT-compiled program, without providing pointers to any memory area
     /// Execute the previously JIT-compiled program, without providing pointers to any memory area
     /// whatsoever, in a manner very similar to `prog_exec()`.
     /// whatsoever, in a manner very similar to `prog_exec()`.
     ///
     ///
-    /// # Panics
-    ///
-    /// This function panics if an error occurs during the execution of the program.
-    ///
     /// # Safety
     /// # Safety
     ///
     ///
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
     /// **WARNING:** JIT-compiled assembly code is not safe, in particular there is no runtime
@@ -1608,11 +1565,11 @@ impl<'a> EbpfVmNoData<'a> {
     ///
     ///
     /// # #[cfg(not(windows))]
     /// # #[cfg(not(windows))]
     /// unsafe {
     /// unsafe {
-    ///     let res = vm.prog_exec_jit();
+    ///     let res = vm.prog_exec_jit().unwrap();
     ///     assert_eq!(res, 0x1122);
     ///     assert_eq!(res, 0x1122);
     /// }
     /// }
     /// ```
     /// ```
-    pub unsafe fn prog_exec_jit(&self) -> u64 {
+    pub unsafe fn prog_exec_jit(&self) -> Result<(u64), Error> {
         self.parent.prog_exec_jit(&mut [])
         self.parent.prog_exec_jit(&mut [])
     }
     }
 }
 }

+ 40 - 40
tests/misc.rs

@@ -166,9 +166,9 @@ fn test_vm_block_port() {
     ];
     ];
 
 
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf);
+    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf).unwrap();
 
 
-    let res = vm.prog_exec(packet);
+    let res = vm.prog_exec(packet).unwrap();
     println!("Program returned: {:?} ({:#x})", res, res);
     println!("Program returned: {:?} ({:#x})", res, res);
     assert_eq!(res, 0xffffffff);
     assert_eq!(res, 0xffffffff);
 }
 }
@@ -248,11 +248,11 @@ fn test_jit_block_port() {
     ];
     ];
 
 
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
     let mut vm = rbpf::EbpfVmFixedMbuff::new(Some(prog), 0x40, 0x50).unwrap();
-    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf);
-    vm.jit_compile();
+    vm.register_helper(helpers::BPF_TRACE_PRINTK_IDX, helpers::bpf_trace_printf).unwrap();
+    vm.jit_compile().unwrap();
 
 
     unsafe {
     unsafe {
-        let res = vm.prog_exec_jit(packet);
+        let res = vm.prog_exec_jit(packet).unwrap();
         println!("Program returned: {:?} ({:#x})", res, res);
         println!("Program returned: {:?} ({:#x})", res, res);
         assert_eq!(res, 0xffffffff);
         assert_eq!(res, 0xffffffff);
     }
     }
@@ -281,7 +281,7 @@ fn test_vm_mbuff() {
     }
     }
 
 
     let vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
     let vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem, &mbuff), 0x2211);
+    assert_eq!(vm.prog_exec(mem, &mbuff).unwrap(), 0x2211);
 }
 }
 
 
 // Program and memory come from uBPF test ldxh.
 // Program and memory come from uBPF test ldxh.
@@ -308,7 +308,7 @@ fn test_vm_mbuff_with_rust_api() {
     }
     }
 
 
     let vm = rbpf::EbpfVmMbuff::new(Some(program.into_bytes())).unwrap();
     let vm = rbpf::EbpfVmMbuff::new(Some(program.into_bytes())).unwrap();
-    assert_eq!(vm.prog_exec(mem, &mbuff), 0x2211);
+    assert_eq!(vm.prog_exec(mem, &mbuff).unwrap(), 0x2211);
 }
 }
 
 
 // Program and memory come from uBPF test ldxh.
 // Program and memory come from uBPF test ldxh.
@@ -336,8 +336,8 @@ fn test_jit_mbuff() {
 
 
     unsafe {
     unsafe {
         let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
         let mut vm = rbpf::EbpfVmMbuff::new(Some(prog)).unwrap();
-        vm.jit_compile();
-        assert_eq!(vm.prog_exec_jit(mem, &mut mbuff), 0x2211);
+        vm.jit_compile().unwrap();
+        assert_eq!(vm.prog_exec_jit(mem, &mut mbuff).unwrap(), 0x2211);
     }
     }
 }
 }
 
 
@@ -353,11 +353,11 @@ fn test_vm_jit_ldabsb() {
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x33);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x33);
 
 
-    vm.jit_compile();
+    vm.jit_compile().unwrap();
     unsafe {
     unsafe {
-        assert_eq!(vm.prog_exec_jit(mem), 0x33);
+        assert_eq!(vm.prog_exec_jit(mem).unwrap(), 0x33);
     };
     };
 }
 }
 
 
@@ -373,11 +373,11 @@ fn test_vm_jit_ldabsh() {
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x4433);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x4433);
 
 
-    vm.jit_compile();
+    vm.jit_compile().unwrap();
     unsafe {
     unsafe {
-        assert_eq!(vm.prog_exec_jit(mem), 0x4433);
+        assert_eq!(vm.prog_exec_jit(mem).unwrap(), 0x4433);
     };
     };
 }
 }
 
 
@@ -393,11 +393,11 @@ fn test_vm_jit_ldabsw() {
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x66554433);
-    vm.jit_compile();
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x66554433);
+    vm.jit_compile().unwrap();
 
 
     unsafe {
     unsafe {
-        assert_eq!(vm.prog_exec_jit(mem), 0x66554433);
+        assert_eq!(vm.prog_exec_jit(mem).unwrap(), 0x66554433);
     };
     };
 }
 }
 
 
@@ -413,11 +413,11 @@ fn test_vm_jit_ldabsdw() {
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0xaa99887766554433);
-    vm.jit_compile();
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0xaa99887766554433);
+    vm.jit_compile().unwrap();
 
 
     unsafe {
     unsafe {
-        assert_eq!(vm.prog_exec_jit(mem), 0xaa99887766554433);
+        assert_eq!(vm.prog_exec_jit(mem).unwrap(), 0xaa99887766554433);
     };
     };
 }
 }
 
 
@@ -433,7 +433,7 @@ fn test_vm_err_ldabsb_oob() {
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    vm.prog_exec(mem);
+    vm.prog_exec(mem).unwrap();
 
 
     // Memory check not implemented for JIT yet.
     // Memory check not implemented for JIT yet.
 }
 }
@@ -446,7 +446,7 @@ fn test_vm_err_ldabsb_nomem() {
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     ];
     ];
     let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 
 
     // Memory check not implemented for JIT yet.
     // Memory check not implemented for JIT yet.
 }
 }
@@ -464,11 +464,11 @@ fn test_vm_jit_ldindb() {
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x88);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x88);
 
 
-    vm.jit_compile();
+    vm.jit_compile().unwrap();
     unsafe {
     unsafe {
-        assert_eq!(vm.prog_exec_jit(mem), 0x88);
+        assert_eq!(vm.prog_exec_jit(mem).unwrap(), 0x88);
     };
     };
 }
 }
 
 
@@ -485,11 +485,11 @@ fn test_vm_jit_ldindh() {
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x9988);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x9988);
 
 
-    vm.jit_compile();
+    vm.jit_compile().unwrap();
     unsafe {
     unsafe {
-        assert_eq!(vm.prog_exec_jit(mem), 0x9988);
+        assert_eq!(vm.prog_exec_jit(mem).unwrap(), 0x9988);
     };
     };
 }
 }
 
 
@@ -506,11 +506,11 @@ fn test_vm_jit_ldindw() {
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x88776655);
-    vm.jit_compile();
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x88776655);
+    vm.jit_compile().unwrap();
 
 
     unsafe {
     unsafe {
-        assert_eq!(vm.prog_exec_jit(mem), 0x88776655);
+        assert_eq!(vm.prog_exec_jit(mem).unwrap(), 0x88776655);
     };
     };
 }
 }
 
 
@@ -527,11 +527,11 @@ fn test_vm_jit_ldinddw() {
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     let mut vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0xccbbaa9988776655);
-    vm.jit_compile();
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0xccbbaa9988776655);
+    vm.jit_compile().unwrap();
 
 
     unsafe {
     unsafe {
-        assert_eq!(vm.prog_exec_jit(mem), 0xccbbaa9988776655);
+        assert_eq!(vm.prog_exec_jit(mem).unwrap(), 0xccbbaa9988776655);
     };
     };
 }
 }
 
 
@@ -548,7 +548,7 @@ fn test_vm_err_ldindb_oob() {
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    vm.prog_exec(mem);
+    vm.prog_exec(mem).unwrap();
 
 
     // Memory check not implemented for JIT yet.
     // Memory check not implemented for JIT yet.
 }
 }
@@ -562,7 +562,7 @@ fn test_vm_err_ldindb_nomem() {
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     ];
     ];
     let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 
 
     // Memory check not implemented for JIT yet.
     // Memory check not implemented for JIT yet.
 }
 }
@@ -571,7 +571,7 @@ fn test_vm_err_ldindb_nomem() {
 #[should_panic(expected = "Error: No program set, call prog_set() to load one")]
 #[should_panic(expected = "Error: No program set, call prog_set() to load one")]
 fn test_vm_exec_no_program() {
 fn test_vm_exec_no_program() {
     let vm = rbpf::EbpfVmNoData::new(None).unwrap();
     let vm = rbpf::EbpfVmNoData::new(None).unwrap();
-    assert_eq!(vm.prog_exec(), 0xBEE);
+    assert_eq!(vm.prog_exec().unwrap(), 0xBEE);
 }
 }
 
 
 fn verifier_success(_prog: &[u8]) -> Result<(), Error> {
 fn verifier_success(_prog: &[u8]) -> Result<(), Error> {
@@ -592,7 +592,7 @@ fn test_verifier_success() {
     let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
     vm.set_verifier(verifier_success).unwrap();
     vm.set_verifier(verifier_success).unwrap();
     vm.set_prog(&prog).unwrap();
     vm.set_prog(&prog).unwrap();
-    assert_eq!(vm.prog_exec(), 0xBEE);
+    assert_eq!(vm.prog_exec().unwrap(), 0xBEE);
 }
 }
 
 
 #[test]
 #[test]
@@ -605,5 +605,5 @@ fn test_verifier_fail() {
     let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(None).unwrap();
     vm.set_verifier(verifier_fail).unwrap();
     vm.set_verifier(verifier_fail).unwrap();
     vm.set_prog(&prog).unwrap();
     vm.set_prog(&prog).unwrap();
-    assert_eq!(vm.prog_exec(), 0xBEE);
+    assert_eq!(vm.prog_exec().unwrap(), 0xBEE);
 }
 }

File diff suppressed because it is too large
+ 187 - 187
tests/ubpf_jit_x86_64.rs


+ 12 - 12
tests/ubpf_verifier.rs

@@ -34,7 +34,7 @@ fn test_verifier_err_div_by_zero_imm() {
         div32 r0, 0
         div32 r0, 0
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -46,7 +46,7 @@ fn test_verifier_err_endian_size() {
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     ];
     ];
     let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -57,7 +57,7 @@ fn test_verifier_err_incomplete_lddw() { // Note: ubpf has test-err-incomplete-l
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     ];
     ];
     let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -67,7 +67,7 @@ fn test_verifier_err_infinite_loop() {
         ja -1
         ja -1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -77,7 +77,7 @@ fn test_verifier_err_invalid_reg_dst() {
         mov r11, 1
         mov r11, 1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -87,7 +87,7 @@ fn test_verifier_err_invalid_reg_src() {
         mov r0, r11
         mov r0, r11
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -98,7 +98,7 @@ fn test_verifier_err_jmp_lddw() {
         lddw r0, 0x1122334455667788
         lddw r0, 0x1122334455667788
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -108,7 +108,7 @@ fn test_verifier_err_jmp_out() {
         ja +2
         ja +2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -117,7 +117,7 @@ fn test_verifier_err_no_exit() {
     let prog = assemble("
     let prog = assemble("
         mov32 r0, 0").unwrap();
         mov32 r0, 0").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -133,7 +133,7 @@ fn test_verifier_err_too_many_instructions() {
     prog.append(&mut vec![ 0x95, 0, 0, 0, 0, 0, 0, 0 ]);
     prog.append(&mut vec![ 0x95, 0, 0, 0, 0, 0, 0, 0 ]);
 
 
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -144,7 +144,7 @@ fn test_verifier_err_unknown_opcode() {
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
         0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     ];
     ];
     let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -154,5 +154,5 @@ fn test_verifier_err_write_r10() {
         mov r10, 1
         mov r10, 1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }

+ 108 - 108
tests/ubpf_vm.rs

@@ -38,7 +38,7 @@ fn test_vm_add() {
         add32 r0, r1
         add32 r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x3);
+    assert_eq!(vm.prog_exec().unwrap(), 0x3);
 }
 }
 
 
 #[test]
 #[test]
@@ -64,7 +64,7 @@ fn test_vm_alu64_arith() {
         div r0, r4
         div r0, r4
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x2a);
+    assert_eq!(vm.prog_exec().unwrap(), 0x2a);
 }
 }
 
 
 #[test]
 #[test]
@@ -94,7 +94,7 @@ fn test_vm_alu64_bit() {
         xor r0, r2
         xor r0, r2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x11);
+    assert_eq!(vm.prog_exec().unwrap(), 0x11);
 }
 }
 
 
 #[test]
 #[test]
@@ -120,7 +120,7 @@ fn test_vm_alu_arith() {
         div32 r0, r4
         div32 r0, r4
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x2a);
+    assert_eq!(vm.prog_exec().unwrap(), 0x2a);
 }
 }
 
 
 #[test]
 #[test]
@@ -148,7 +148,7 @@ fn test_vm_alu_bit() {
         xor32 r0, r2
         xor32 r0, r2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x11);
+    assert_eq!(vm.prog_exec().unwrap(), 0x11);
 }
 }
 
 
 #[test]
 #[test]
@@ -159,7 +159,7 @@ fn test_vm_arsh32_high_shift() {
         arsh32 r0, r1
         arsh32 r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x4);
+    assert_eq!(vm.prog_exec().unwrap(), 0x4);
 }
 }
 
 
 #[test]
 #[test]
@@ -170,7 +170,7 @@ fn test_vm_arsh() {
         arsh32 r0, 16
         arsh32 r0, 16
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0xffff8000);
+    assert_eq!(vm.prog_exec().unwrap(), 0xffff8000);
 }
 }
 
 
 #[test]
 #[test]
@@ -183,7 +183,7 @@ fn test_vm_arsh64() {
         arsh r0, r1
         arsh r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0xfffffffffffffff8);
+    assert_eq!(vm.prog_exec().unwrap(), 0xfffffffffffffff8);
 }
 }
 
 
 #[test]
 #[test]
@@ -195,7 +195,7 @@ fn test_vm_arsh_reg() {
         arsh32 r0, r1
         arsh32 r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0xffff8000);
+    assert_eq!(vm.prog_exec().unwrap(), 0xffff8000);
 }
 }
 
 
 #[test]
 #[test]
@@ -208,7 +208,7 @@ fn test_vm_be16() {
         0x11, 0x22
         0x11, 0x22
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x1122);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x1122);
 }
 }
 
 
 #[test]
 #[test]
@@ -221,7 +221,7 @@ fn test_vm_be16_high() {
         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x1122);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x1122);
 }
 }
 
 
 #[test]
 #[test]
@@ -234,7 +234,7 @@ fn test_vm_be32() {
         0x11, 0x22, 0x33, 0x44
         0x11, 0x22, 0x33, 0x44
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x11223344);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x11223344);
 }
 }
 
 
 #[test]
 #[test]
@@ -247,7 +247,7 @@ fn test_vm_be32_high() {
         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x11223344);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x11223344);
 }
 }
 
 
 #[test]
 #[test]
@@ -260,7 +260,7 @@ fn test_vm_be64() {
         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
         0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x1122334455667788);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x1122334455667788);
 }
 }
 
 
 #[test]
 #[test]
@@ -274,8 +274,8 @@ fn test_vm_call() {
         call 0
         call 0
         exit").unwrap();
         exit").unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.register_helper(0, helpers::gather_bytes);
-    assert_eq!(vm.prog_exec(), 0x0102030405);
+    vm.register_helper(0, helpers::gather_bytes).unwrap();
+    assert_eq!(vm.prog_exec().unwrap(), 0x0102030405);
 }
 }
 
 
 #[test]
 #[test]
@@ -292,8 +292,8 @@ fn test_vm_call_memfrob() {
         0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
         0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
     ];
     ];
     let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let mut vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    vm.register_helper(1, helpers::memfrob);
-    assert_eq!(vm.prog_exec(mem), 0x102292e2f2c0708);
+    vm.register_helper(1, helpers::memfrob).unwrap();
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x102292e2f2c0708);
 }
 }
 
 
 // TODO: helpers::trash_registers needs asm!().
 // TODO: helpers::trash_registers needs asm!().
@@ -315,7 +315,7 @@ fn test_vm_call_memfrob() {
     //];
     //];
     //let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     //let mut vm = rbpf::EbpfVmNoData::new(Some(prog)).unwrap();
     //vm.register_helper(2, helpers::trash_registers);
     //vm.register_helper(2, helpers::trash_registers);
-    //assert_eq!(vm.prog_exec(), 0x4321);
+    //assert_eq!(vm.prog_exec().unwrap(), 0x4321);
 //}
 //}
 
 
 #[test]
 #[test]
@@ -326,7 +326,7 @@ fn test_vm_div32_high_divisor() {
         div32 r0, r1
         div32 r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x3);
+    assert_eq!(vm.prog_exec().unwrap(), 0x3);
 }
 }
 
 
 #[test]
 #[test]
@@ -336,7 +336,7 @@ fn test_vm_div32_imm() {
         div32 r0, 4
         div32 r0, 4
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x3);
+    assert_eq!(vm.prog_exec().unwrap(), 0x3);
 }
 }
 
 
 #[test]
 #[test]
@@ -347,7 +347,7 @@ fn test_vm_div32_reg() {
         div32 r0, r1
         div32 r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x3);
+    assert_eq!(vm.prog_exec().unwrap(), 0x3);
 }
 }
 
 
 #[test]
 #[test]
@@ -358,7 +358,7 @@ fn test_vm_div64_imm() {
         div r0, 4
         div r0, 4
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x300000000);
+    assert_eq!(vm.prog_exec().unwrap(), 0x300000000);
 }
 }
 
 
 #[test]
 #[test]
@@ -370,7 +370,7 @@ fn test_vm_div64_reg() {
         div r0, r1
         div r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x300000000);
+    assert_eq!(vm.prog_exec().unwrap(), 0x300000000);
 }
 }
 
 
 #[test]
 #[test]
@@ -381,7 +381,7 @@ fn test_vm_early_exit() {
         mov r0, 4
         mov r0, 4
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x3);
+    assert_eq!(vm.prog_exec().unwrap(), 0x3);
 }
 }
 
 
 // uBPF limits the number of user functions at 64. We don't.
 // uBPF limits the number of user functions at 64. We don't.
@@ -401,7 +401,7 @@ fn test_vm_err_call_unreg() {
         call 63
         call 63
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -413,7 +413,7 @@ fn test_vm_err_div64_by_zero_reg() {
         div r0, r1
         div r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -425,7 +425,7 @@ fn test_vm_err_div_by_zero_reg() {
         div32 r0, r1
         div32 r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -437,7 +437,7 @@ fn test_vm_err_mod64_by_zero_reg() {
         mod r0, r1
         mod r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -449,7 +449,7 @@ fn test_vm_err_mod_by_zero_reg() {
         mod32 r0, r1
         mod32 r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -459,7 +459,7 @@ fn test_vm_err_stack_out_of_bound() {
         stb [r10], 0
         stb [r10], 0
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.prog_exec();
+    vm.prog_exec().unwrap();
 }
 }
 
 
 #[test]
 #[test]
@@ -468,7 +468,7 @@ fn test_vm_exit() {
         mov r0, 0
         mov r0, 0
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x0);
+    assert_eq!(vm.prog_exec().unwrap(), 0x0);
 }
 }
 
 
 #[test]
 #[test]
@@ -479,7 +479,7 @@ fn test_vm_ja() {
         mov r0, 2
         mov r0, 2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -494,7 +494,7 @@ fn test_vm_jeq_imm() {
         mov32 r0, 2
         mov32 r0, 2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -510,7 +510,7 @@ fn test_vm_jeq_reg() {
         mov32 r0, 2
         mov32 r0, 2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -525,7 +525,7 @@ fn test_vm_jge_imm() {
         mov32 r0, 2
         mov32 r0, 2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -541,7 +541,7 @@ fn test_vm_jle_imm() {
         mov32 r0, 1
         mov32 r0, 1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -559,7 +559,7 @@ fn test_vm_jle_reg() {
         mov r0, 1
         mov r0, 1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -574,7 +574,7 @@ fn test_vm_jgt_imm() {
         mov32 r0, 1
         mov32 r0, 1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -591,7 +591,7 @@ fn test_vm_jgt_reg() {
         mov r0, 1
         mov r0, 1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -606,7 +606,7 @@ fn test_vm_jlt_imm() {
         mov32 r0, 1
         mov32 r0, 1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -623,7 +623,7 @@ fn test_vm_jlt_reg() {
         mov r0, 1
         mov r0, 1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -637,7 +637,7 @@ fn test_vm_jit_bounce() {
         mov r0, r9
         mov r0, r9
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -653,7 +653,7 @@ fn test_vm_jne_reg() {
         mov32 r0, 2
         mov32 r0, 2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -668,7 +668,7 @@ fn test_vm_jset_imm() {
         mov32 r0, 2
         mov32 r0, 2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -684,7 +684,7 @@ fn test_vm_jset_reg() {
         mov32 r0, 2
         mov32 r0, 2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -700,7 +700,7 @@ fn test_vm_jsge_imm() {
         mov32 r0, 2
         mov32 r0, 2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -718,7 +718,7 @@ fn test_vm_jsge_reg() {
         mov32 r0, 2
         mov32 r0, 2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -734,7 +734,7 @@ fn test_vm_jsle_imm() {
         mov32 r0, 2
         mov32 r0, 2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -753,7 +753,7 @@ fn test_vm_jsle_reg() {
         mov32 r0, 2
         mov32 r0, 2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -768,7 +768,7 @@ fn test_vm_jsgt_imm() {
         mov32 r0, 2
         mov32 r0, 2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -784,7 +784,7 @@ fn test_vm_jsgt_reg() {
         mov32 r0, 2
         mov32 r0, 2
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -799,7 +799,7 @@ fn test_vm_jslt_imm() {
         mov32 r0, 1
         mov32 r0, 1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -816,7 +816,7 @@ fn test_vm_jslt_reg() {
         mov32 r0, 1
         mov32 r0, 1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -824,7 +824,7 @@ fn test_vm_lddw() {
     let prog = assemble("lddw r0, 0x1122334455667788
     let prog = assemble("lddw r0, 0x1122334455667788
                          exit").unwrap();
                          exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1122334455667788);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1122334455667788);
 }
 }
 
 
 #[test]
 #[test]
@@ -833,7 +833,7 @@ fn test_vm_lddw2() {
         lddw r0, 0x0000000080000000
         lddw r0, 0x0000000080000000
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x80000000);
+    assert_eq!(vm.prog_exec().unwrap(), 0x80000000);
 }
 }
 
 
 #[test]
 #[test]
@@ -875,7 +875,7 @@ fn test_vm_ldxb_all() {
         0x08, 0x09
         0x08, 0x09
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x9876543210);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x9876543210);
 }
 }
 
 
 #[test]
 #[test]
@@ -887,7 +887,7 @@ fn test_vm_ldxb() {
         0xaa, 0xbb, 0x11, 0xcc, 0xdd
         0xaa, 0xbb, 0x11, 0xcc, 0xdd
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x11);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x11);
 }
 }
 
 
 #[test]
 #[test]
@@ -900,7 +900,7 @@ fn test_vm_ldxdw() {
         0x77, 0x88, 0xcc, 0xdd
         0x77, 0x88, 0xcc, 0xdd
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x8877665544332211);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x8877665544332211);
 }
 }
 
 
 #[test]
 #[test]
@@ -953,7 +953,7 @@ fn test_vm_ldxh_all() {
         0x00, 0x08, 0x00, 0x09
         0x00, 0x08, 0x00, 0x09
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x9876543210);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x9876543210);
 }
 }
 
 
 #[test]
 #[test]
@@ -996,7 +996,7 @@ fn test_vm_ldxh_all2() {
         0x01, 0x00, 0x02, 0x00
         0x01, 0x00, 0x02, 0x00
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x3ff);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x3ff);
 }
 }
 
 
 #[test]
 #[test]
@@ -1008,7 +1008,7 @@ fn test_vm_ldxh() {
         0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
         0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x2211);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x2211);
 }
 }
 
 
 #[test]
 #[test]
@@ -1022,7 +1022,7 @@ fn test_vm_ldxh_same_reg() {
         0xff, 0xff
         0xff, 0xff
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x1234);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x1234);
 }
 }
 
 
 #[test]
 #[test]
@@ -1067,7 +1067,7 @@ fn test_vm_ldxw_all() {
         0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00
         0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x030f0f);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x030f0f);
 }
 }
 
 
 #[test]
 #[test]
@@ -1079,7 +1079,7 @@ fn test_vm_ldxw() {
         0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0xcc, 0xdd
         0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0xcc, 0xdd
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x44332211);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x44332211);
 }
 }
 
 
 #[test]
 #[test]
@@ -1092,7 +1092,7 @@ fn test_vm_le16() {
         0x22, 0x11
         0x22, 0x11
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x1122);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x1122);
 }
 }
 
 
 #[test]
 #[test]
@@ -1105,7 +1105,7 @@ fn test_vm_le32() {
         0x44, 0x33, 0x22, 0x11
         0x44, 0x33, 0x22, 0x11
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x11223344);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x11223344);
 }
 }
 
 
 #[test]
 #[test]
@@ -1118,7 +1118,7 @@ fn test_vm_le64() {
         0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11
         0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x1122334455667788);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x1122334455667788);
 }
 }
 
 
 #[test]
 #[test]
@@ -1129,7 +1129,7 @@ fn test_vm_lsh_reg() {
         lsh r0, r7
         lsh r0, r7
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x10);
+    assert_eq!(vm.prog_exec().unwrap(), 0x10);
 }
 }
 
 
 #[test]
 #[test]
@@ -1141,7 +1141,7 @@ fn test_vm_mod() {
         mod32 r0, r1
         mod32 r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x5);
+    assert_eq!(vm.prog_exec().unwrap(), 0x5);
 }
 }
 
 
 #[test]
 #[test]
@@ -1151,7 +1151,7 @@ fn test_vm_mod32() {
         mod32 r0, 3
         mod32 r0, 3
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x0);
+    assert_eq!(vm.prog_exec().unwrap(), 0x0);
 }
 }
 
 
 #[test]
 #[test]
@@ -1167,7 +1167,7 @@ fn test_vm_mod64() {
         mod r0, 0x658f1778
         mod r0, 0x658f1778
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x30ba5a04);
+    assert_eq!(vm.prog_exec().unwrap(), 0x30ba5a04);
 }
 }
 
 
 #[test]
 #[test]
@@ -1177,7 +1177,7 @@ fn test_vm_mov() {
         mov32 r0, r1
         mov32 r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -1187,7 +1187,7 @@ fn test_vm_mul32_imm() {
         mul32 r0, 4
         mul32 r0, 4
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0xc);
+    assert_eq!(vm.prog_exec().unwrap(), 0xc);
 }
 }
 
 
 #[test]
 #[test]
@@ -1198,7 +1198,7 @@ fn test_vm_mul32_reg() {
         mul32 r0, r1
         mul32 r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0xc);
+    assert_eq!(vm.prog_exec().unwrap(), 0xc);
 }
 }
 
 
 #[test]
 #[test]
@@ -1209,7 +1209,7 @@ fn test_vm_mul32_reg_overflow() {
         mul32 r0, r1
         mul32 r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x4);
+    assert_eq!(vm.prog_exec().unwrap(), 0x4);
 }
 }
 
 
 #[test]
 #[test]
@@ -1219,7 +1219,7 @@ fn test_vm_mul64_imm() {
         mul r0, 4
         mul r0, 4
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x100000004);
+    assert_eq!(vm.prog_exec().unwrap(), 0x100000004);
 }
 }
 
 
 #[test]
 #[test]
@@ -1230,7 +1230,7 @@ fn test_vm_mul64_reg() {
         mul r0, r1
         mul r0, r1
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x100000004);
+    assert_eq!(vm.prog_exec().unwrap(), 0x100000004);
 }
 }
 
 
 #[test]
 #[test]
@@ -1247,7 +1247,7 @@ fn test_vm_mul_loop() {
         jne r1, 0x0, -3
         jne r1, 0x0, -3
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x75db9c97);
+    assert_eq!(vm.prog_exec().unwrap(), 0x75db9c97);
 }
 }
 
 
 #[test]
 #[test]
@@ -1257,7 +1257,7 @@ fn test_vm_neg64() {
         neg r0
         neg r0
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0xfffffffffffffffe);
+    assert_eq!(vm.prog_exec().unwrap(), 0xfffffffffffffffe);
 }
 }
 
 
 #[test]
 #[test]
@@ -1267,7 +1267,7 @@ fn test_vm_neg() {
         neg32 r0
         neg32 r0
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0xfffffffe);
+    assert_eq!(vm.prog_exec().unwrap(), 0xfffffffe);
 }
 }
 
 
 #[test]
 #[test]
@@ -1290,7 +1290,7 @@ fn test_vm_prime() {
         jne r4, 0x0, -10
         jne r4, 0x0, -10
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -1301,7 +1301,7 @@ fn test_vm_rhs32() {
         rsh32 r0, 8
         rsh32 r0, 8
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x00ffffff);
+    assert_eq!(vm.prog_exec().unwrap(), 0x00ffffff);
 }
 }
 
 
 #[test]
 #[test]
@@ -1312,7 +1312,7 @@ fn test_vm_rsh_reg() {
         rsh r0, r7
         rsh r0, r7
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0x1);
+    assert_eq!(vm.prog_exec().unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -1328,7 +1328,7 @@ fn test_vm_stack() {
         ldxdw r0, [r2-16]
         ldxdw r0, [r2-16]
         exit").unwrap();
         exit").unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(), 0xcd);
+    assert_eq!(vm.prog_exec().unwrap(), 0xcd);
 }
 }
 
 
 #[test]
 #[test]
@@ -1351,9 +1351,9 @@ fn test_vm_stack2() {
         xor r0, 0x2a2a2a2a
         xor r0, 0x2a2a2a2a
         exit").unwrap();
         exit").unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(Some(&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);
+    vm.register_helper(0, helpers::gather_bytes).unwrap();
+    vm.register_helper(1, helpers::memfrob).unwrap();
+    assert_eq!(vm.prog_exec().unwrap(), 0x01020304);
 }
 }
 
 
 #[test]
 #[test]
@@ -1366,7 +1366,7 @@ fn test_vm_stb() {
         0xaa, 0xbb, 0xff, 0xcc, 0xdd
         0xaa, 0xbb, 0xff, 0xcc, 0xdd
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x11);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x11);
 }
 }
 
 
 #[test]
 #[test]
@@ -1380,7 +1380,7 @@ fn test_vm_stdw() {
         0xff, 0xff, 0xcc, 0xdd
         0xff, 0xff, 0xcc, 0xdd
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x44332211);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x44332211);
 }
 }
 
 
 #[test]
 #[test]
@@ -1393,7 +1393,7 @@ fn test_vm_sth() {
         0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd
         0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x2211);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x2211);
 }
 }
 
 
 #[test]
 #[test]
@@ -1428,8 +1428,8 @@ fn test_vm_string_stack() {
         mov r0, 0x0
         mov r0, 0x0
         exit").unwrap();
         exit").unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
     let mut vm = rbpf::EbpfVmNoData::new(Some(&prog)).unwrap();
-    vm.register_helper(4, helpers::strcmp);
-    assert_eq!(vm.prog_exec(), 0x0);
+    vm.register_helper(4, helpers::strcmp).unwrap();
+    assert_eq!(vm.prog_exec().unwrap(), 0x0);
 }
 }
 
 
 #[test]
 #[test]
@@ -1442,7 +1442,7 @@ fn test_vm_stw() {
         0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd
         0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x44332211);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x44332211);
 }
 }
 
 
 #[test]
 #[test]
@@ -1456,7 +1456,7 @@ fn test_vm_stxb() {
         0xaa, 0xbb, 0xff, 0xcc, 0xdd
         0xaa, 0xbb, 0xff, 0xcc, 0xdd
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x11);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x11);
 }
 }
 
 
 #[test]
 #[test]
@@ -1485,7 +1485,7 @@ fn test_vm_stxb_all() {
         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0xf0f2f3f4f5f6f7f8);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0xf0f2f3f4f5f6f7f8);
 }
 }
 
 
 #[test]
 #[test]
@@ -1503,7 +1503,7 @@ fn test_vm_stxb_all2() {
         0xff, 0xff
         0xff, 0xff
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0xf1f9);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0xf1f9);
 }
 }
 
 
 #[test]
 #[test]
@@ -1535,7 +1535,7 @@ fn test_vm_stxb_chain() {
         0x00, 0x00
         0x00, 0x00
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x2a);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x2a);
 }
 }
 
 
 #[test]
 #[test]
@@ -1552,7 +1552,7 @@ fn test_vm_stxdw() {
         0xff, 0xff, 0xcc, 0xdd
         0xff, 0xff, 0xcc, 0xdd
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x8877665544332211);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x8877665544332211);
 }
 }
 
 
 #[test]
 #[test]
@@ -1566,7 +1566,7 @@ fn test_vm_stxh() {
         0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd
         0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x2211);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x2211);
 }
 }
 
 
 #[test]
 #[test]
@@ -1580,7 +1580,7 @@ fn test_vm_stxw() {
         0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd
         0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x44332211);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x44332211);
 }
 }
 
 
 #[test]
 #[test]
@@ -1613,7 +1613,7 @@ fn test_vm_subnet() {
         0x03, 0x00
         0x03, 0x00
     ];
     ];
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x1);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x1);
 }
 }
 
 
 
 
@@ -1658,7 +1658,7 @@ fn test_vm_tcp_port80_match() {
     ];
     ];
     let prog = &PROG_TCP_PORT_80;
     let prog = &PROG_TCP_PORT_80;
     let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x1);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -1680,7 +1680,7 @@ fn test_vm_tcp_port80_nomatch() {
     ];
     ];
     let prog = &PROG_TCP_PORT_80;
     let prog = &PROG_TCP_PORT_80;
     let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x0);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x0);
 }
 }
 
 
 #[test]
 #[test]
@@ -1702,7 +1702,7 @@ fn test_vm_tcp_port80_nomatch_ethertype() {
     ];
     ];
     let prog = &PROG_TCP_PORT_80;
     let prog = &PROG_TCP_PORT_80;
     let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x0);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x0);
 }
 }
 
 
 #[test]
 #[test]
@@ -1724,7 +1724,7 @@ fn test_vm_tcp_port80_nomatch_proto() {
     ];
     ];
     let prog = &PROG_TCP_PORT_80;
     let prog = &PROG_TCP_PORT_80;
     let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem), 0x0);
+    assert_eq!(vm.prog_exec(mem).unwrap(), 0x0);
 }
 }
 
 
 #[test]
 #[test]
@@ -1732,7 +1732,7 @@ fn test_vm_tcp_sack_match() {
     let mut mem = TCP_SACK_MATCH.to_vec();
     let mut mem = TCP_SACK_MATCH.to_vec();
     let prog = assemble(TCP_SACK_ASM).unwrap();
     let prog = assemble(TCP_SACK_ASM).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem.as_mut_slice()), 0x1);
+    assert_eq!(vm.prog_exec(mem.as_mut_slice()).unwrap(), 0x1);
 }
 }
 
 
 #[test]
 #[test]
@@ -1740,5 +1740,5 @@ fn test_vm_tcp_sack_nomatch() {
     let mut mem = TCP_SACK_NOMATCH.to_vec();
     let mut mem = TCP_SACK_NOMATCH.to_vec();
     let prog = assemble(TCP_SACK_ASM).unwrap();
     let prog = assemble(TCP_SACK_ASM).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
     let vm = rbpf::EbpfVmRaw::new(Some(&prog)).unwrap();
-    assert_eq!(vm.prog_exec(mem.as_mut_slice()), 0x0);
+    assert_eq!(vm.prog_exec(mem.as_mut_slice()).unwrap(), 0x0);
 }
 }

Some files were not shown because too many files changed in this diff