1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use {
    crate::{
        config::sealevel_config, context::sealevel_syscall_registry, error::hoist_error,
        vm::ThisInstructionMeter,
    },
    solana_bpf_loader_program::BpfError,
    solana_rbpf::{
        elf::Executable,
        verifier::RequisiteVerifier,
        vm::{Config, SyscallRegistry, VerifiedExecutable},
    },
    std::{os::raw::c_char, ptr::null_mut},
};

/// A loaded and relocated program.
///
/// To execute this program, create a VM with `sealevel_vm_create`.
pub struct sealevel_executable {
    pub(crate) program: VerifiedExecutable<RequisiteVerifier, BpfError, ThisInstructionMeter>,
    pub(crate) is_jit_compiled: bool,
}

/// Access parameters of an account usage in an instruction.
#[repr(C)]
pub struct sealevel_instruction_account {
    pub index_in_transaction: usize,
    pub index_in_caller: usize,
    pub is_signer: bool,
    pub is_writable: bool,
}

/// Loads a Sealevel program from an ELF buffer and verifies its SBF bytecode.
///
/// Sets `sealevel_errno` and returns a null pointer if loading failed.
///
/// Syscalls and config may be null pointers, in which case defaults are used.
/// These defaults is not stable across any libsealevel versions.
///
/// If a syscall registry is provided, it is consumed, and cannot be used a second time.
///
/// # Safety
/// Avoid the following undefined behavior:
/// - Using the syscalls object parameter after calling this function (including a second call of this function).
/// - Providing a config object that has been freed with `sealevel_config_free` before.
#[no_mangle]
pub unsafe extern "C" fn sealevel_load_program(
    config: *const sealevel_config,
    syscalls: sealevel_syscall_registry,
    data: *const c_char,
    data_len: usize,
) -> *mut sealevel_executable {
    let data_slice = std::slice::from_raw_parts(data as *const u8, data_len);
    let config = if config.is_null() {
        Config::default()
    } else {
        (*config).config
    };
    let syscalls = if syscalls.0.is_null() {
        SyscallRegistry::default()
    } else {
        syscalls.take().unwrap() // TODO set error code
    };
    let load_result =
        Executable::<BpfError, ThisInstructionMeter>::from_elf(data_slice, config, syscalls);
    let executable = match hoist_error(load_result) {
        None => return null_mut(),
        Some(v) => v,
    };
    let verify_result = VerifiedExecutable::from_executable(executable);
    match hoist_error(verify_result) {
        None => null_mut(),
        Some(program) => {
            let wrapper = sealevel_executable {
                program,
                is_jit_compiled: false,
            };
            Box::into_raw(Box::new(wrapper))
        }
    }
}

/// Compiles a program to native executable code.
///
/// Sets `sealevel_errno`.
///
/// # Safety
/// Avoid the following undefined behavior:
/// - Calling this function twice on the same program.
/// - Calling this function given a null pointer or an invalid pointer.
#[no_mangle]
pub unsafe extern "C" fn sealevel_program_jit_compile(program: *mut sealevel_executable) {
    let result = (*program).program.jit_compile();
    if hoist_error(result).is_some() {
        (*program).is_jit_compiled = true;
    }
}