[−][src]Struct solana_rbpf::EbpfVmNoData
A virtual machine to run eBPF program. This kind of VM is used for programs that do not work with any memory area—no metadata buffer, no packet data either.
Examples
let prog = &[ 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0 0xb7, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // mov r1, 1 0xb7, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // mov r2, 2 0xb7, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, // mov r3, 3 0xb7, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, // mov r4, 4 0xb7, 0x05, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, // mov r5, 5 0xb7, 0x06, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, // mov r6, 6 0xb7, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, // mov r7, 7 0xb7, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, // mov r8, 8 0x4f, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // or r0, r5 0x47, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, // or r0, 0xa0 0x57, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, // and r0, 0xa3 0xb7, 0x09, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, // mov r9, 0x91 0x5f, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // and r0, r9 0x67, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, // lsh r0, 32 0x67, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, // lsh r0, 22 0x6f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // lsh r0, r8 0x77, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, // rsh r0, 32 0x77, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, // rsh r0, 19 0x7f, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // rsh r0, r7 0xa7, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, // xor r0, 0x03 0xaf, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // xor r0, r2 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit ]; // Instantiate a VM. let mut vm = solana_rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); // Provide only a reference to the packet data. let res = vm.execute_program().unwrap(); assert_eq!(res, 0x11);
Methods
impl<'a> EbpfVmNoData<'a>
[src]
pub fn new(prog: Option<&'a [u8]>) -> Result<EbpfVmNoData<'a>, Error>
[src]
Create a new virtual machine instance, and load an eBPF program into that instance. When attempting to load the program, it passes through a simple verifier.
Examples
let prog = &[ 0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211 0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit ]; // Instantiate a VM. let vm = solana_rbpf::EbpfVmNoData::new(Some(prog));
pub fn set_program(&mut self, prog: &'a [u8]) -> Result<(), Error>
[src]
Load a new eBPF program into the virtual machine instance.
Examples
let prog1 = &[ 0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit ]; let prog2 = &[ 0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211 0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit ]; let mut vm = solana_rbpf::EbpfVmNoData::new(Some(prog1)).unwrap(); let res = vm.execute_program().unwrap(); assert_eq!(res, 0x2211); vm.set_program(prog2); let res = vm.execute_program().unwrap(); assert_eq!(res, 0x1122);
pub fn set_elf(&mut self, elf: &'a [u8]) -> Result<(), Error>
[src]
Load a new eBPF program into the virtual machine instance.
pub fn set_verifier(&mut self, verifier: Verifier) -> Result<(), Error>
[src]
Set a new verifier function. The function should return an Error
if the program should be
rejected by the virtual machine. If a program has been loaded to the VM already, the
verifier is immediately run.
Examples
use std::io::{Error, ErrorKind}; use solana_rbpf::ebpf; // Define a simple verifier function. fn verifier(prog: &[u8]) -> Result<(), Error> { let last_insn = ebpf::get_insn(prog, (prog.len() / ebpf::INSN_SIZE) - 1); if last_insn.opc != ebpf::EXIT { return Err(Error::new(ErrorKind::Other, "[Verifier] Error: program does not end with “EXIT” instruction")); } Ok(()) } let prog1 = &[ 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit ]; // Instantiate a VM. let mut vm = solana_rbpf::EbpfVmMbuff::new(Some(prog1)).unwrap(); // Change the verifier. vm.set_verifier(verifier).unwrap();
pub fn set_max_instruction_count(&mut self, count: u64) -> Result<(), Error>
[src]
Set a cap on the maximum number of instructions that a program may execute. If the maximum is set to zero, then no cap will be applied.
Examples
use std::io::{Error, ErrorKind}; use solana_rbpf::ebpf; let prog = &[ 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit ]; // Instantiate a VM. let mut vm = solana_rbpf::EbpfVmMbuff::new(Some(prog)).unwrap(); // Set maximum instruction count. vm.set_max_instruction_count(1000).unwrap();
pub fn get_last_instruction_count(&self) -> u64
[src]
Returns the number of instruction executed by the last program.
Examples
use std::io::{Error, ErrorKind}; use solana_rbpf::ebpf; let prog = &[ 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit ]; // Instantiate a VM. let mut vm = solana_rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); // Execute the program. let res = vm.execute_program().unwrap(); // Get the number of instructions executed. let count = vm.get_last_instruction_count();
pub fn register_helper(
&mut self,
key: u32,
function: HelperFunction
) -> Result<(), Error>
[src]
&mut self,
key: u32,
function: HelperFunction
) -> Result<(), Error>
Register a built-in or user-defined helper function in order to use it later from within
the eBPF program. The helper is registered into a hashmap, so the key
can be any u32
.
If using JIT-compiled eBPF programs, be sure to register all helpers before compiling the program. You should be able to change registered helpers after compiling, but not to add new ones (i.e. with new keys).
Examples
use solana_rbpf::helpers; let prog = &[ 0xb7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // mov r1, 0x010000000 0xb7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r2, 0 0xb7, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r3, 0 0xb7, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r4, 0 0xb7, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r5, 0 0x85, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // call helper with key 1 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit ]; let mut vm = solana_rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); // Register a helper. This helper will store the result of the square root of r1 into r0. vm.register_helper(1, helpers::sqrti).unwrap(); let res = vm.execute_program().unwrap(); assert_eq!(res, 0x1000);
pub fn register_helper_ex(
&mut self,
name: &str,
verifier: Option<HelperVerifier>,
function: HelperFunction
) -> Result<(), Error>
[src]
&mut self,
name: &str,
verifier: Option<HelperVerifier>,
function: HelperFunction
) -> Result<(), Error>
Register a user-defined helper function in order to use it later from within
the eBPF program. Normally helper functions are referred to by an index. (See helpers)
but this function takes the name of the function. The name is then hashed into a 32 bit
number and used in the call
instructions imm field. If calling set_elf
then
the elf's relocations must reference this symbol using the same name. This can usually be
achieved by building the elf with unresolved symbols (think extern foo(void)
). If
providing a program directly via set_program
then any call
instructions must already
have the hash of the symbol name in its imm field. To generate the correct hash of the
symbol name use ebpf::helpers::hash_symbol_name
.
Helper functions may treat their arguments as pointers, but there are safety issues in doing so. To protect against bad pointer usage the VM will call the helper verifier function before calling the real helper. The user-supplied helper verifier should be implemented so that it checks the usage of the pointers and returns an error if a problem is encountered. For example, if the helper function treats argument 1 as a pointer to a string then the helper verification function must validate that argument 1 is indeed a valid pointer and that it is fully contained in one of the provided memory regions.
This function can be used along with jitted programs but be aware that unlike interpreted programs, jitted programs will not call the verification functions. If you don't inherently trust the parameters being passed to helpers then jitted programs must only use helper's arguments as values.
If using JIT-compiled eBPF programs, be sure to register all helpers before compiling the program. You should be able to change registered helpers after compiling, but not to add new ones (i.e. with new keys).
pub fn jit_compile(&mut self) -> Result<(), Error>
[src]
JIT-compile the loaded program. No argument required for this.
If using helper functions, be sure to register them into the VM before calling this function.
Examples
let prog = &[ 0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211 0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit ]; let mut vm = solana_rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); vm.jit_compile();
pub fn execute_program(&mut self) -> Result<u64, Error>
[src]
Execute the program loaded, without providing pointers to any memory area whatsoever.
Examples
let prog = &[ 0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211 0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit ]; let mut vm = solana_rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); // For this kind of VM, the `execute_program()` function needs no argument. let res = vm.execute_program().unwrap(); assert_eq!(res, 0x1122);
pub unsafe fn execute_program_jit(&self) -> Result<u64, Error>
[src]
Execute the previously JIT-compiled program, without providing pointers to any memory area
whatsoever, in a manner very similar to execute_program()
.
Safety
WARNING: JIT-compiled assembly code is not safe, in particular there is no runtime check for memory access; so if the eBPF program attempts erroneous accesses, this may end very bad (program may segfault). It may be wise to check that the program works with the interpreter before running the JIT-compiled version of it.
For this reason the function should be called from within an unsafe
bloc.
Examples
let prog = &[ 0xb7, 0x00, 0x00, 0x00, 0x11, 0x22, 0x00, 0x00, // mov r0, 0x2211 0xdc, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, // be16 r0 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit ]; let mut vm = solana_rbpf::EbpfVmNoData::new(Some(prog)).unwrap(); vm.jit_compile(); unsafe { let res = vm.execute_program_jit().unwrap(); assert_eq!(res, 0x1122); }
Auto Trait Implementations
impl<'a> Send for EbpfVmNoData<'a>
impl<'a> Sync for EbpfVmNoData<'a>
Blanket Implementations
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,