logo
pub struct EbpfVm<'a, E: UserDefinedError, I: InstructionMeter> { /* private fields */ }
Expand description

A virtual machine to run eBPF program.

Examples

use solana_rbpf::{ebpf, elf::{Executable, register_bpf_function}, vm::{Config, EbpfVm, TestInstructionMeter, SyscallRegistry}, 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 bpf_functions = std::collections::BTreeMap::new();
register_bpf_function(&mut bpf_functions, 0, "entrypoint", false).unwrap();
let mut executable = Executable::<UserError, TestInstructionMeter>::from_text_bytes(prog, None, Config::default(), SyscallRegistry::default(), bpf_functions).unwrap();
let mut vm = EbpfVm::<UserError, TestInstructionMeter>::new(&executable, &mut [], mem).unwrap();

// Provide a reference to the packet data.
let res = vm.execute_program_interpreted(&mut TestInstructionMeter { remaining: 1 }).unwrap();
assert_eq!(res, 0);

Implementations

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::{ebpf, elf::{Executable, register_bpf_function}, vm::{Config, EbpfVm, TestInstructionMeter, SyscallRegistry}, user_error::UserError};

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

// Instantiate a VM.
let mut bpf_functions = std::collections::BTreeMap::new();
register_bpf_function(&mut bpf_functions, 0, "entrypoint", false).unwrap();
let mut executable = Executable::<UserError, TestInstructionMeter>::from_text_bytes(prog, None, Config::default(), SyscallRegistry::default(), bpf_functions).unwrap();
let mut vm = EbpfVm::<UserError, TestInstructionMeter>::new(&executable, &mut [], &mut []).unwrap();

Returns the number of instructions executed by the last program.

Returns the program

Returns the tracer

Bind a context object instance to a previously registered syscall

Examples
use solana_rbpf::{ebpf, elf::{Executable, register_bpf_function}, vm::{Config, EbpfVm, SyscallObject, SyscallRegistry, TestInstructionMeter}, syscalls::BpfTracePrintf, 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 syscall with key 6
    0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // exit
];

// Register a syscall.
// On running the program this syscall will print the content of registers r3, r4 and r5 to
// standard output.
let mut syscall_registry = SyscallRegistry::default();
syscall_registry.register_syscall_by_hash(6, BpfTracePrintf::call).unwrap();
// Instantiate an Executable and VM
let mut bpf_functions = std::collections::BTreeMap::new();
register_bpf_function(&mut bpf_functions, 0, "entrypoint", false).unwrap();
let mut executable = Executable::<UserError, TestInstructionMeter>::from_text_bytes(prog, None, Config::default(), syscall_registry, bpf_functions).unwrap();
let mut vm = EbpfVm::<UserError, TestInstructionMeter>::new(&executable, &mut [], &mut []).unwrap();
// Bind a context object instance to the previously registered syscall
vm.bind_syscall_context_object(Box::new(BpfTracePrintf {}), None);

Lookup a syscall context object by its function pointer. Used for testing and validation.

Execute the program loaded, with the given packet data.

Warning: The program is executed without limiting the number of instructions that can be executed

Examples
use solana_rbpf::{ebpf, elf::{Executable, register_bpf_function}, vm::{Config, EbpfVm, TestInstructionMeter, SyscallRegistry}, 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 bpf_functions = std::collections::BTreeMap::new();
register_bpf_function(&mut bpf_functions, 0, "entrypoint", false).unwrap();
let mut executable = Executable::<UserError, TestInstructionMeter>::from_text_bytes(prog, None, Config::default(), SyscallRegistry::default(), bpf_functions).unwrap();
let mut vm = EbpfVm::<UserError, TestInstructionMeter>::new(&executable, &mut [], mem).unwrap();

// Provide a reference to the packet data.
let res = vm.execute_program_interpreted(&mut TestInstructionMeter { remaining: 1 }).unwrap();
assert_eq!(res, 0);

Execute the previously JIT-compiled program, with the given packet data in a manner very similar to execute_program_interpreted().

Safety

WARNING: JIT-compiled assembly code is not safe. It may be wise to check that the program works with the interpreter before running the JIT-compiled version of it.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.