Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_vm_jit_fd_jit_h 2 : #define HEADER_fd_src_flamenco_vm_jit_fd_jit_h 3 : 4 : /* fd_vm_jit.h provides an API to transpile sBPF programs to native 5 : machine code. Currently only supports x86 with threads. 6 : 7 : FIXME This is not a "JIT" compiler. Fix the naming ... 8 : 9 : WARNING: WORK IN PROGRESS! 10 : This is an experimental version of the Firedancer JIT compiler. 11 : It is disabled in production. There are known security issues in 12 : this code. It is not covered by the Firedancer bug bounty program. */ 13 : 14 : #include "../fd_vm.h" 15 : #include "../../../ballet/sbpf/fd_sbpf_loader.h" 16 : 17 : /* fd_jit_entrypoint is the entrypoint function of JIT compiled code. 18 : first_rip is a pointer to the x86 instruction in the host address 19 : space that corresponds to the BPF entrypoint. */ 20 : 21 : typedef int (* fd_jit_entrypoint_t)( ulong first_rip ); 22 : 23 : /* fd_jit_prog_t is an instance of a JIT compiled program. It is not 24 : relocatable since the generated code effectively contains absolute 25 : addresses. 26 : 27 : fd_jit_prog_t references an external "code" buffer (the memory region 28 : storing executable code). During the lifetime of a fd_jit_prog_t 29 : object, the backing "code" buffer may not be moved, freed, or written 30 : to */ 31 : 32 : struct fd_jit_prog { 33 : ulong magic; 34 : void * code_buf; 35 : ulong code_sz; 36 : fd_jit_entrypoint_t entrypoint; 37 : ulong first_rip; 38 : }; 39 : 40 : typedef struct fd_jit_prog fd_jit_prog_t; 41 : 42 0 : #define FD_JIT_PROG_MAGIC (0x2c19d91e7ca38c6bUL) 43 : 44 : #if FD_HAS_X86 && FD_HAS_THREADS 45 : 46 : /* fd_jit_est_code_sz returns the estimated x86 code footprint for a 47 : BPF program with bpf_sz .text size. Returns zero if bpf_sz is too 48 : large. 49 : 50 : fd_jit_est_scratch_sz returns the estimated scratch memory size 51 : required to JIT compile a bpf program with bpf_sz .text size. 52 : Returns zero if bpf_sz is too large. 53 : 54 : This estimation is a "best guess", some programs will exceed this 55 : size requirement. */ 56 : 57 : ulong 58 : fd_jit_est_code_sz( ulong bpf_sz ); 59 : 60 : /* fd_jit_est_scratch_sz returns the estimated scratch buffer size 61 : required to call fd_jit_prog_new. This buffer is used to store 62 : intermediate results during compilation. */ 63 : 64 : ulong 65 : fd_jit_est_scratch_sz( ulong bpf_sz ); 66 : 67 : /* fd_jit_prog_new transpiles an sBPF program into native machine code. 68 : 69 : @param jit_prog Output JIT program -- Fully initialized on success 70 : @param prog sBPF program to compile 71 : @param syscalls fd_map_dynamic of enabled syscalls 72 : @param code_buf Buffer to place machine code in 73 : @param code_bufsz Size of code_buf buffer 74 : @param scratch Temporary buffer (released on return) 75 : @param scratch_sz Size of scratch buffer 76 : @param out_err *out_err set to FD_VM_{SUCCESS,ERR_{...}} 77 : 78 : Writes up to scratch_sz bytes for arbitrary use to scratch. This 79 : memory is always released back to the caller on return. 80 : 81 : Writes up to code_bufsz bytes of x86 bytecode to code_buf. The 82 : number of bytes written is set to jit_prog->code_sz. A read interest 83 : remains for the lifetime of the jit_prog object. 84 : 85 : On success, initializes and returns jit_prog. 86 : 87 : On failure, returns NULL and releases any memory back to the caller. 88 : Reasons include FD_VM_ERR_{...}: 89 : 90 : FULL Not enough output or scratch space to compile 91 : FIXME introduce separate error codes for scratch and code sz 92 : UNSUP JIT compiler does not support the given executable. */ 93 : 94 : fd_jit_prog_t * 95 : fd_jit_prog_new( fd_jit_prog_t * jit_prog, 96 : fd_sbpf_program_t const * prog, 97 : fd_sbpf_syscalls_t const * syscalls, 98 : void * code_buf, 99 : ulong code_bufsz, 100 : void * scratch, 101 : ulong scratch_sz, 102 : int * out_err ); 103 : 104 : /* fd_jit_prog_delete releases the memory backing prog and code_buf back 105 : to the caller. */ 106 : 107 : void * 108 : fd_jit_prog_delete( fd_jit_prog_t * prog ); 109 : 110 : /* fd_jit_exec executes a compiled program from entrypoint to halt or 111 : fault. 112 : 113 : On failure, returns NULL and releases any memory back to the caller. 114 : Reasons include FD_VM_ERR_{...}: 115 : 116 : UNSUP JIT compiler does not support the given execution context 117 : (e.g. complex memory map) */ 118 : 119 : int 120 : fd_jit_exec( fd_jit_prog_t * jit_prog, 121 : fd_vm_t * vm ); 122 : 123 : #endif /* FD_HAS_X86 && FD_HAS_THREADS */ 124 : 125 : #endif /* HEADER_fd_src_flamenco_vm_jit_fd_jit_h */