[][src]Struct solana_rbpf::EbpfVm

pub struct EbpfVm<'a, E: UserDefinedError> { /* fields omitted */ }

A virtual machine to run eBPF program.

Examples

use solana_rbpf::EbpfVm;
use solana_rbpf::user_error::UserError;

let prog = &[
    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
];
let mem = &mut [
    0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
];

// Instantiate a VM.
let mut vm = EbpfVm::<UserError>::new(Some(prog)).unwrap();

// Provide a reference to the packet data.
let res = vm.execute_program(mem, &[], &[]).unwrap();
assert_eq!(res, 0);

Methods

impl<'a, E: UserDefinedError> EbpfVm<'a, E>[src]

pub fn new(prog: Option<&'a [u8]>) -> Result<EbpfVm<'a, E>, EbpfError<E>>[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

use solana_rbpf::EbpfVm;
use solana_rbpf::user_error::UserError;

let prog = &[
    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
];

// Instantiate a VM.
let mut vm = EbpfVm::<UserError>::new(Some(prog)).unwrap();

pub fn set_program(&mut self, prog: &'a [u8]) -> Result<(), EbpfError<E>>[src]

Load a new eBPF program into the virtual machine instance.

Examples

use solana_rbpf::EbpfVm;
use solana_rbpf::user_error::UserError;

let prog1 = &[
    0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov r0, 0
    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
];
let prog2 = &[
    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
];

// Instantiate a VM.
let mut vm = EbpfVm::<UserError>::new(Some(prog1)).unwrap();
vm.set_program(prog2).unwrap();

pub fn set_elf(&mut self, elf_bytes: &'a [u8]) -> Result<(), EbpfError<E>>[src]

Load a new eBPF program into the virtual machine instance.

pub fn set_verifier(
    &mut self,
    verifier: Verifier<E>
) -> Result<(), EbpfError<E>>
[src]

Set a new verifier function. The function should return an EbpfError 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 solana_rbpf::EbpfVm;
use solana_rbpf::ebpf;
use solana_rbpf::verifier::VerifierError;

// Define a simple verifier function.
fn verifier(prog: &[u8]) -> Result<(), VerifierError> {
    let last_insn = ebpf::get_insn(prog, (prog.len() / ebpf::INSN_SIZE) - 1);
    if last_insn.opc != ebpf::EXIT {
       return Err(VerifierError::InvalidLastInstruction.into());
    }
    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 = EbpfVm::<VerifierError>::new(Some(prog1)).unwrap();
// Change the verifier.
vm.set_verifier(verifier).unwrap();

pub fn set_max_instruction_count(
    &mut self,
    count: u64
) -> Result<(), EbpfError<E>>
[src]

Set a cap on the maximum number of instructions that a program may execute.

pub fn get_last_instruction_count(&self) -> u64[src]

Returns the number of instructions executed by the last program.

pub fn register_helper(
    &mut self,
    key: u32,
    helper: HelperFunction<E>
) -> Result<(), EbpfError<E>>
[src]

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::EbpfVm;
use solana_rbpf::helpers::bpf_trace_printf;
use solana_rbpf::user_error::UserError;

// This program was compiled with clang, from a C program containing the following single
// instruction: `return bpf_trace_printk("foo %c %c %c\n", 10, 1, 2, 3);`
let prog = &[
    0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load 0 as u64 into r1 (That would be
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // replaced by tc by the address of
                                                    // the format string, in the .map
                                                    // section of the ELF file).
    0xb7, 0x02, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, // mov r2, 10
    0xb7, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // mov r3, 1
    0xb7, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // mov r4, 2
    0xb7, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, // mov r5, 3
    0x85, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, // call helper with key 6
    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
];

// Instantiate a VM.
let mut vm = EbpfVm::<UserError>::new(Some(prog)).unwrap();

// Register a helper.
// On running the program this helper will print the content of registers r3, r4 and r5 to
// standard output.
vm.register_helper(6, bpf_trace_printf::<UserError>).unwrap();

pub fn register_helper_ex(
    &mut self,
    name: &str,
    helper: HelperFunction<E>
) -> Result<(), EbpfError<E>>
[src]

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.

pub fn register_helper_with_context_ex(
    &mut self,
    name: &str,
    helper: Box<dyn HelperObject<E> + 'a>
) -> Result<(), EbpfError<E>>
[src]

Same as register_helper_ex except reguster a helper trait object that carries along context needed by the helper

pub fn execute_program(
    &mut self,
    mem: &[u8],
    granted_ro_regions: &[MemoryRegion],
    granted_rw_regions: &[MemoryRegion]
) -> Result<u64, EbpfError<E>>
[src]

Execute the program loaded, with the given packet data.

Examples

use solana_rbpf::EbpfVm;
use solana_rbpf::user_error::UserError;

let prog = &[
    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
];
let mem = &mut [
    0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
];

// Instantiate a VM.
let mut vm = EbpfVm::<UserError>::new(Some(prog)).unwrap();

// Provide a reference to the packet data.
let res = vm.execute_program(mem, &[], &[]).unwrap();
assert_eq!(res, 0);

pub fn jit_compile(&mut self) -> Result<(), EbpfError<E>>[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

use solana_rbpf::EbpfVm;
use solana_rbpf::user_error::UserError;

let prog = &[
    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
];

// Instantiate a VM.
let mut vm = EbpfVm::<UserError>::new(Some(prog)).unwrap();

vm.jit_compile();

pub unsafe fn execute_program_jit(
    &self,
    mem: &mut [u8]
) -> Result<u64, EbpfError<E>>
[src]

Execute the previously JIT-compiled program, with the given packet data 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

use solana_rbpf::EbpfVm;
use solana_rbpf::user_error::UserError;

let prog = &[
    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
];
let mem = &mut [
    0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
];

// Instantiate a VM.
let mut vm = EbpfVm::<UserError>::new(Some(prog)).unwrap();

vm.jit_compile();

// Provide a reference to the packet data.
unsafe {
    let res = vm.execute_program_jit(mem).unwrap();
    assert_eq!(res, 0);
}

Auto Trait Implementations

impl<'a, E> !RefUnwindSafe for EbpfVm<'a, E>

impl<'a, E> !Send for EbpfVm<'a, E>

impl<'a, E> !Sync for EbpfVm<'a, E>

impl<'a, E> Unpin for EbpfVm<'a, E>

impl<'a, E> !UnwindSafe for EbpfVm<'a, E>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.