|
@@ -46,7 +46,7 @@ pub mod ebpf;
|
|
|
pub mod helpers;
|
|
|
pub mod insn_builder;
|
|
|
mod interpreter;
|
|
|
-#[cfg(all(not(windows), feature = "std"))]
|
|
|
+#[cfg(not(windows))]
|
|
|
mod jit;
|
|
|
#[cfg(not(feature = "std"))]
|
|
|
mod no_std_error;
|
|
@@ -79,6 +79,8 @@ pub mod lib {
|
|
|
#[cfg(not(feature = "std"))]
|
|
|
pub use alloc::vec::Vec;
|
|
|
#[cfg(feature = "std")]
|
|
|
+ pub use std::vec;
|
|
|
+ #[cfg(feature = "std")]
|
|
|
pub use std::vec::Vec;
|
|
|
|
|
|
#[cfg(not(feature = "std"))]
|
|
@@ -108,6 +110,8 @@ pub mod lib {
|
|
|
|
|
|
#[cfg(not(feature = "std"))]
|
|
|
pub use alloc::format;
|
|
|
+ #[cfg(feature = "std")]
|
|
|
+ pub use std::format;
|
|
|
}
|
|
|
|
|
|
/// eBPF verification function that returns an error if the program does not meet its requirements.
|
|
@@ -171,7 +175,7 @@ struct MetaBuff {
|
|
|
pub struct EbpfVmMbuff<'a> {
|
|
|
prog: Option<&'a [u8]>,
|
|
|
verifier: Verifier,
|
|
|
- #[cfg(all(not(windows), feature = "std"))]
|
|
|
+ #[cfg(not(windows))]
|
|
|
jit: Option<jit::JitMemory<'a>>,
|
|
|
#[cfg(feature = "cranelift")]
|
|
|
cranelift_prog: Option<cranelift::CraneliftProgram>,
|
|
@@ -209,7 +213,7 @@ impl<'a> EbpfVmMbuff<'a> {
|
|
|
Ok(EbpfVmMbuff {
|
|
|
prog,
|
|
|
verifier: verifier::check,
|
|
|
- #[cfg(all(not(windows), feature = "std"))]
|
|
|
+ #[cfg(not(windows))]
|
|
|
jit: None,
|
|
|
#[cfg(feature = "cranelift")]
|
|
|
cranelift_prog: None,
|
|
@@ -487,6 +491,28 @@ impl<'a> EbpfVmMbuff<'a> {
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
+ /// JIT-compile the loaded program. The user has to provide a mutable slice of memory that
|
|
|
+ /// will be used for the JIT-compiled code. For more information, see the [EbpfVmMbuff::jit_compile]
|
|
|
+ /// function.
|
|
|
+ #[cfg(all(not(windows), not(feature = "std")))]
|
|
|
+ pub fn jit_compile(&mut self, executable_memory: &'a mut [u8]) -> Result<(), Error> {
|
|
|
+ let prog = match self.prog {
|
|
|
+ Some(prog) => prog,
|
|
|
+ None => Err(Error::new(
|
|
|
+ ErrorKind::Other,
|
|
|
+ "Error: No program set, call prog_set() to load one",
|
|
|
+ ))?,
|
|
|
+ };
|
|
|
+ self.jit = Some(jit::JitMemory::new(
|
|
|
+ prog,
|
|
|
+ executable_memory,
|
|
|
+ &self.helpers,
|
|
|
+ true,
|
|
|
+ false,
|
|
|
+ )?);
|
|
|
+ Ok(())
|
|
|
+ }
|
|
|
+
|
|
|
/// Execute the previously JIT-compiled program, with the given packet data and metadata
|
|
|
/// buffer, in a manner very similar to `execute_program()`.
|
|
|
///
|
|
@@ -539,7 +565,7 @@ impl<'a> EbpfVmMbuff<'a> {
|
|
|
/// assert_eq!(res, 0x2211);
|
|
|
/// }
|
|
|
/// ```
|
|
|
- #[cfg(all(not(windows), feature = "std"))]
|
|
|
+ #[cfg(not(windows))]
|
|
|
pub unsafe fn execute_program_jit(
|
|
|
&self,
|
|
|
mem: &mut [u8],
|
|
@@ -550,7 +576,7 @@ impl<'a> EbpfVmMbuff<'a> {
|
|
|
// in the kernel; anyway the verifier would prevent the use of uninitialized registers).
|
|
|
// See `mul_loop` test.
|
|
|
let mem_ptr = match mem.len() {
|
|
|
- 0 => std::ptr::null_mut(),
|
|
|
+ 0 => core::ptr::null_mut(),
|
|
|
_ => mem.as_ptr() as *mut u8,
|
|
|
};
|
|
|
// The last two arguments are not used in this function. They would be used if there was a
|
|
@@ -1079,6 +1105,28 @@ impl<'a> EbpfVmFixedMbuff<'a> {
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
+ /// JIT-compile the loaded program. The user has to provide a mutable slice of memory that
|
|
|
+ /// will be used for the JIT-compiled code. For more information, see the [EbpfVmFixedMbuff::jit_compile]
|
|
|
+ /// function.
|
|
|
+ #[cfg(all(not(windows), not(feature = "std")))]
|
|
|
+ pub fn jit_compile(&mut self, executable_memory: &'a mut [u8]) -> Result<(), Error> {
|
|
|
+ let prog = match self.parent.prog {
|
|
|
+ Some(prog) => prog,
|
|
|
+ None => Err(Error::new(
|
|
|
+ ErrorKind::Other,
|
|
|
+ "Error: No program set, call prog_set() to load one",
|
|
|
+ ))?,
|
|
|
+ };
|
|
|
+ self.parent.jit = Some(jit::JitMemory::new(
|
|
|
+ prog,
|
|
|
+ executable_memory,
|
|
|
+ &self.parent.helpers,
|
|
|
+ true,
|
|
|
+ true,
|
|
|
+ )?);
|
|
|
+ Ok(())
|
|
|
+ }
|
|
|
+
|
|
|
/// Execute the previously JIT-compiled program, with the given packet data, in a manner very
|
|
|
/// similar to `execute_program()`.
|
|
|
///
|
|
@@ -1127,7 +1175,7 @@ impl<'a> EbpfVmFixedMbuff<'a> {
|
|
|
/// ```
|
|
|
// This struct redefines the `execute_program_jit()` function, in order to pass the offsets
|
|
|
// associated with the fixed mbuff.
|
|
|
- #[cfg(all(not(windows), feature = "std"))]
|
|
|
+ #[cfg(not(windows))]
|
|
|
pub unsafe fn execute_program_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
|
|
|
// as first argument instead, as this is uBPF's behavior (empty packet should not happen
|
|
@@ -1565,6 +1613,28 @@ impl<'a> EbpfVmRaw<'a> {
|
|
|
Ok(())
|
|
|
}
|
|
|
|
|
|
+ /// JIT-compile the loaded program. The user has to provide a mutable slice of memory that
|
|
|
+ /// will be used for the JIT-compiled code. For more information, see the [EbpfVmRaw::jit_compile]
|
|
|
+ /// function.
|
|
|
+ #[cfg(all(not(windows), not(feature = "std")))]
|
|
|
+ pub fn jit_compile(&mut self, executable_memory: &'a mut [u8]) -> Result<(), Error> {
|
|
|
+ let prog = match self.parent.prog {
|
|
|
+ Some(prog) => prog,
|
|
|
+ None => Err(Error::new(
|
|
|
+ ErrorKind::Other,
|
|
|
+ "Error: No program set, call prog_set() to load one",
|
|
|
+ ))?,
|
|
|
+ };
|
|
|
+ self.parent.jit = Some(jit::JitMemory::new(
|
|
|
+ prog,
|
|
|
+ executable_memory,
|
|
|
+ &self.parent.helpers,
|
|
|
+ false,
|
|
|
+ false,
|
|
|
+ )?);
|
|
|
+ Ok(())
|
|
|
+ }
|
|
|
+
|
|
|
/// Execute the previously JIT-compiled program, with the given packet data, in a manner very
|
|
|
/// similar to `execute_program()`.
|
|
|
///
|
|
@@ -1602,7 +1672,7 @@ impl<'a> EbpfVmRaw<'a> {
|
|
|
/// assert_eq!(res, 0x22cc);
|
|
|
/// }
|
|
|
/// ```
|
|
|
- #[cfg(all(not(windows), feature = "std"))]
|
|
|
+ #[cfg(not(windows))]
|
|
|
pub unsafe fn execute_program_jit(&self, mem: &'a mut [u8]) -> Result<u64, Error> {
|
|
|
let mut mbuff = vec![];
|
|
|
self.parent.execute_program_jit(mem, &mut mbuff)
|
|
@@ -1942,6 +2012,14 @@ impl<'a> EbpfVmNoData<'a> {
|
|
|
self.parent.jit_compile()
|
|
|
}
|
|
|
|
|
|
+ /// JIT-compile the loaded program. The user has to provide a mutable slice of memory that
|
|
|
+ /// will be used for the JIT-compiled code. For more information, see the [EbpfVmNoData::jit_compile]
|
|
|
+ /// function.
|
|
|
+ #[cfg(all(not(windows), not(feature = "std")))]
|
|
|
+ pub fn jit_compile(&mut self, executable_memory: &'a mut [u8]) -> Result<(), Error> {
|
|
|
+ self.parent.jit_compile(executable_memory)
|
|
|
+ }
|
|
|
+
|
|
|
/// Execute the program loaded, without providing pointers to any memory area whatsoever.
|
|
|
///
|
|
|
/// # Examples
|
|
@@ -1995,7 +2073,7 @@ impl<'a> EbpfVmNoData<'a> {
|
|
|
/// assert_eq!(res, 0x1122);
|
|
|
/// }
|
|
|
/// ```
|
|
|
- #[cfg(all(not(windows), feature = "std"))]
|
|
|
+ #[cfg(not(windows))]
|
|
|
pub unsafe fn execute_program_jit(&self) -> Result<u64, Error> {
|
|
|
self.parent.execute_program_jit(&mut [])
|
|
|
}
|