LCOV - code coverage report
Current view: top level - ballet/sbpf - fd_sbpf_loader.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 53 68 77.9 %
Date: 2026-10-22 18:10:43 Functions: 14 3392 0.4 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_ballet_sbpf_fd_sbpf_loader_h
       2             : #define HEADER_fd_src_ballet_sbpf_fd_sbpf_loader_h
       3             : 
       4             : /* fd_sbpf_loader prepares an sBPF program for execution.  This involves
       5             :    parsing and dynamic relocation.
       6             : 
       7             :    Due to historical reasons, this loader is neither a pure static
       8             :    linker nor a real dynamic loader.  For instance, it will ignore the
       9             :    program header table and instead load specific sections at predefined
      10             :    addresses.  However, it will perform dynamic relocation. */
      11             : 
      12             : #include "../../util/fd_util_base.h"
      13             : #include "../elf/fd_elf64.h"
      14             : 
      15             : /* Error types ********************************************************/
      16             : 
      17        1547 : #define FD_SBPF_PROG_RODATA_ALIGN 8UL
      18             : 
      19             : /* https://github.com/anza-xyz/sbpf/blob/v0.12.2/src/elf_parser/mod.rs#L17 */
      20             : #define FD_SBPF_ELF_PARSER_SUCCESS                           ( 0)
      21         240 : #define FD_SBPF_ELF_PARSER_ERR_INVALID_FILE_HEADER           (-1)
      22          20 : #define FD_SBPF_ELF_PARSER_ERR_INVALID_PROGRAM_HEADER        (-2)
      23           7 : #define FD_SBPF_ELF_PARSER_ERR_INVALID_SECTION_HEADER        (-3)
      24             : #define FD_SBPF_ELF_PARSER_ERR_INVALID_STRING                (-4)
      25           7 : #define FD_SBPF_ELF_PARSER_ERR_STRING_TOO_LONG               (-5)
      26         153 : #define FD_SBPF_ELF_PARSER_ERR_OUT_OF_BOUNDS                 (-6)
      27           1 : #define FD_SBPF_ELF_PARSER_ERR_INVALID_SIZE                  (-7)
      28          31 : #define FD_SBPF_ELF_PARSER_ERR_OVERLAP                       (-8)
      29           5 : #define FD_SBPF_ELF_PARSER_ERR_SECTION_NOT_IN_ORDER          (-9)
      30           0 : #define FD_SBPF_ELF_PARSER_ERR_NO_SECTION_NAME_STRING_TABLE  (-10)
      31          30 : #define FD_SBPF_ELF_PARSER_ERR_INVALID_DYNAMIC_SECTION_TABLE (-11)
      32             : #define FD_SBPF_ELF_PARSER_ERR_INVALID_RELOCATION_TABLE      (-12)
      33           7 : #define FD_SBPF_ELF_PARSER_ERR_INVALID_ALIGNMENT             (-13)
      34             : #define FD_SBPF_ELF_PARSER_ERR_NO_STRING_TABLE               (-14)
      35             : #define FD_SBPF_ELF_PARSER_ERR_NO_DYNAMIC_STRING_TABLE       (-15)
      36             : 
      37             : /* Map Rust ElfError (elf.rs v0.12.2) to C error codes */
      38             : /* https://github.com/anza-xyz/sbpf/blob/v0.12.2/src/elf.rs#L40-L66 */
      39     2001635 : #define FD_SBPF_ELF_SUCCESS                                  (  0)
      40         327 : #define FD_SBPF_ELF_ERR_FAILED_TO_PARSE                      ( -1)
      41          12 : #define FD_SBPF_ELF_ERR_ENTRYPOINT_OUT_OF_BOUNDS             ( -2)
      42           5 : #define FD_SBPF_ELF_ERR_INVALID_ENTRYPOINT                   ( -3)
      43             : #define FD_SBPF_ELF_ERR_FAILED_TO_GET_SECTION                ( -4)
      44         166 : #define FD_SBPF_ELF_ERR_UNRESOLVED_SYMBOL                    ( -5)
      45             : #define FD_SBPF_ELF_ERR_SECTION_NOT_FOUND                    ( -6)
      46          10 : #define FD_SBPF_ELF_ERR_RELATIVE_JUMP_OUT_OF_BOUNDS          ( -7)
      47           1 : #define FD_SBPF_ELF_ERR_SYMBOL_HASH_COLLISION                ( -8)
      48           0 : #define FD_SBPF_ELF_ERR_WRONG_ENDIANNESS                     ( -9)
      49           4 : #define FD_SBPF_ELF_ERR_WRONG_ABI                            (-10)
      50           3 : #define FD_SBPF_ELF_ERR_WRONG_MACHINE                        (-11)
      51           0 : #define FD_SBPF_ELF_ERR_WRONG_CLASS                          (-12)
      52          29 : #define FD_SBPF_ELF_ERR_NOT_ONE_TEXT_SECTION                 (-13)
      53           6 : #define FD_SBPF_ELF_ERR_WRITABLE_SECTION_NOT_SUPPORTED       (-14)
      54             : #define FD_SBPF_ELF_ERR_ADDRESS_OUTSIDE_LOADABLE_SECTION     (-15)
      55           4 : #define FD_SBPF_ELF_ERR_INVALID_VIRTUAL_ADDRESS              (-16)
      56          20 : #define FD_SBPF_ELF_ERR_UNKNOWN_RELOCATION                   (-17)
      57             : #define FD_SBPF_ELF_ERR_FAILED_TO_READ_RELOCATION_INFO       (-18)
      58           3 : #define FD_SBPF_ELF_ERR_WRONG_TYPE                           (-19)
      59          17 : #define FD_SBPF_ELF_ERR_UNKNOWN_SYMBOL                       (-20)
      60         197 : #define FD_SBPF_ELF_ERR_VALUE_OUT_OF_BOUNDS                  (-21)
      61         374 : #define FD_SBPF_ELF_ERR_UNSUPPORTED_SBPF_VERSION             (-22)
      62          10 : #define FD_SBPF_ELF_ERR_INVALID_PROGRAM_HEADER               (-23)
      63             : 
      64             : /* https://github.com/anza-xyz/sbpf/blob/v0.12.2/src/program.rs */
      65        7178 : #define FD_SBPF_VERSION_COUNT (5U)
      66        6888 : #define FD_SBPF_V0            (0U)
      67     2454678 : #define FD_SBPF_V1            (1U)
      68     3720477 : #define FD_SBPF_V2            (2U)
      69      473518 : #define FD_SBPF_V3            (3U)
      70             : #define FD_SBPF_V4            (4U)
      71         373 : #define FD_SBPF_RESERVED      (FD_SBPF_VERSION_COUNT)
      72             : 
      73             : /* Hardcoded constant for the murmur3_32 hash of the entrypoint. */
      74     1644474 : #define FD_SBPF_ENTRYPOINT_PC   (0xb00c380U)
      75        4875 : #define FD_SBPF_ENTRYPOINT_HASH (0x71e3cf81U) /* fd_pchash( FD_SBPF_ENTRYPOINT_PC ) */
      76             : 
      77             : #define E_FLAGS_SBPF_V2         (0x20U)
      78             : 
      79             : /* Program struct *****************************************************/
      80             : 
      81             : /* fd_sbpf_calldests is a bit vector of valid call destinations.
      82             :    Should be configured to fit any possible program counter.  The max
      83             :    program counter is <size of ELF binary> divided by 8. */
      84             : 
      85             : #define SET_NAME fd_sbpf_calldests
      86             : #include "../../util/tmpl/fd_set_dynamic.c"
      87             : 
      88             : /* The sbpf program footprint is large when stricter elf headers are
      89             :    not enabled due to the calldests bitmap being included.  So, the
      90             :    total footprint of the sbpf_program is the size of the sbpf_program
      91             :    struct plus the calldests bitmap.
      92             : 
      93             :    The calldests bitmap is variable with the text_cnt.  A loose bound on
      94             :    the textcnt is the max size of an account / 8.  So, the max possible
      95             :    text_cnt is 1310720.  So the footprint of the sbpf_calldests is as
      96             :    follows:
      97             :    sizeof(SET_(private_t))-sizeof(SET_(t)) + sizeof(SET_(t))*SET_(private_word_cnt)( max )
      98             :    private_word_cnt(1310720) = 20480
      99             :    sizeof(SET_(t)) = 8 (ulong)
     100             :    sizeof(SET_(private_t)) = 32
     101             :    */
     102           0 : #define FD_SBPF_TEXT_CNT_MAX (FD_RUNTIME_ACC_SZ_MAX / 8UL)
     103             : #define FD_SBPF_CALLDESTS_PRIVATE_WORD_CNT ( (FD_SBPF_TEXT_CNT_MAX +63UL)>>6 )
     104             : #define FD_SBPF_PROGRAM_FOOTPRINT                                      \
     105             :   FD_LAYOUT_FINI( FD_LAYOUT_APPEND( FD_LAYOUT_APPEND( FD_LAYOUT_INIT,  \
     106             :     alignof(fd_sbpf_program_t), sizeof(fd_sbpf_program_t) ),           \
     107             :     alignof(fd_sbpf_calldests_private_t),                              \
     108             :     sizeof(fd_sbpf_calldests_private_t)-sizeof(ulong) + sizeof(ulong)*FD_SBPF_CALLDESTS_PRIVATE_WORD_CNT ), \
     109             :     alignof(fd_sbpf_program_t) )
     110             : 
     111             : /* fd_sbpf_syscall_func_t is a callback implementing an sBPF syscall.
     112             :    vm is a handle to the running VM.  Returns 0 on success or an integer
     113             :    error code on failure.
     114             : 
     115             :    IMPORTANT SAFETY TIP!  See notes in
     116             :    flamenco/vm/syscall/fd_vm_syscall.h on what a syscall should expect
     117             :    to see and expect to return. */
     118             : 
     119             : /* FIXME: THIS BELONGS IN FLAMENCO/VM */
     120             : 
     121             : typedef int
     122             : (*fd_sbpf_syscall_func_t)( void *  vm,
     123             :                            ulong   arg0,
     124             :                            ulong   arg1,
     125             :                            ulong   arg2,
     126             :                            ulong   arg3,
     127             :                            ulong   arg4 );
     128             : 
     129             : /* fd_sbpf_syscalls_t maps syscall IDs => a name and a VM specific
     130             :    context.  FIXME: THIS ALSO PROBABLY BELONGS IN FLAMENCO/VM */
     131             : 
     132     7824563 : #define FD_SBPF_SYSCALLS_LG_SLOT_CNT (7)
     133             : #define FD_SBPF_SYSCALLS_SLOT_CNT    (1UL<<FD_SBPF_SYSCALLS_LG_SLOT_CNT)
     134             : 
     135             : /* The syscalls map keys should technically be of type uint since they are
     136             :    just murmur32 hashes. However, Agave's BTree allows the full range to be
     137             :    used as a key [0, UINT_MAX]. So we need to define a wider key type to
     138             :    allow for a NULL value that is outside this range. We use ulong here. */
     139             : 
     140             : struct fd_sbpf_syscalls {
     141             :   ulong                  key;  /* Murmur3-32 hash of function name */
     142             :   fd_sbpf_syscall_func_t func; /* Function pointer */
     143             :   char const *           name; /* Infinite lifetime pointer to function name */
     144             : };
     145             : 
     146             : typedef struct fd_sbpf_syscalls fd_sbpf_syscalls_t;
     147             : 
     148             : #define MAP_NAME              fd_sbpf_syscalls
     149     1579497 : #define MAP_T                 fd_sbpf_syscalls_t
     150     1561802 : #define MAP_HASH_T            ulong
     151     4564558 : #define MAP_KEY_NULL          ULONG_MAX         /* Any number greater than UINT_MAX works */
     152     2502179 : #define MAP_KEY_INVAL(k)      ( k > UINT_MAX )  /* Force keys to uint size */
     153     1527351 : #define MAP_KEY_EQUAL(k0,k1)  (k0)==(k1)
     154             : #define MAP_KEY_EQUAL_IS_SLOW 0
     155     1562417 : #define MAP_KEY_HASH(k)       (k)
     156             : #define MAP_MEMOIZE           0
     157     7824563 : #define MAP_LG_SLOT_CNT       FD_SBPF_SYSCALLS_LG_SLOT_CNT
     158             : #include "../../util/tmpl/fd_map.c"
     159             : 
     160             : #define FD_SBPF_SYSCALLS_FOOTPRINT (sizeof(fd_sbpf_syscalls_t) * (1UL<<FD_SBPF_SYSCALLS_LG_SLOT_CNT))
     161             : #define FD_SBPF_SYSCALLS_ALIGN     alignof(fd_sbpf_syscalls_t)
     162             : 
     163             : /* fd_sbpf_elf_info_t contains basic information extracted from an ELF
     164             :    binary. Indicates how much scratch memory and buffer size is required
     165             :    to fully load the program. */
     166             : 
     167             : struct fd_sbpf_elf_info {
     168             :   ulong bin_sz;   /* size of ELF binary */
     169             : 
     170             :   ulong calldests_max;  /* Size of calldests set */
     171             :   uint  text_off;       /* File offset of .text section (overlaps rodata segment) */
     172             :   uint  text_cnt;       /* Instruction count */
     173             :   ulong text_sz;        /* size of text segment. Guaranteed to be <= bin_sz. */
     174             : 
     175             :   /* Size of the buffer the loader assembles the program into, computed at
     176             :      peek.  This is exactly the buffer the program cache must allocate:
     177             :        - strict (v3+):       rodata + text segments (text_off + text_sz)
     178             :        - lenient fast path:  the assembled rodata image (highest ro section
     179             :                              end) -- exact size, no scratch buffer needed.
     180             :                              Selected only when the read-only sections already
     181             :                              sit at their file offsets (section address ==
     182             :                              file offset), so the image needs no section
     183             :                              repositioning, only zeroing of the gaps between
     184             :                              and around the read-only slices.
     185             :        - lenient legacy path: bin_sz -- the loader relocates in place over the
     186             :                              full ELF image (and may read the unused account
     187             :                              tail), so it needs the whole binary plus scratch
     188             :      fd_sbpf_loader_is_legacy_lenient() (load_buf_sz==bin_sz) identifies the
     189             :      last case -- the only one that requires a scratch buffer. */
     190             :   ulong load_buf_sz;
     191             : 
     192             :   /* Known section indices
     193             :      In [-1,USHORT_MAX) where -1 means "not found" */
     194             :   int shndx_text;
     195             :   int shndx_symtab;
     196             :   int shndx_strtab;
     197             :   int shndx_dyn;
     198             :   int shndx_dynstr;
     199             :   int shndx_dynsymtab; /* Section header index of the dynamic symbol table */
     200             : 
     201             :   /* Known program header indices (like shndx_*) */
     202             :   int phndx_dyn;
     203             : 
     204             :   /* Dynamic relocation table entries */
     205             :   uint dt_rel_off; /* File offset of dynamic relocation table */
     206             :   uint dt_rel_sz;  /* Number of dynamic relocation table entries */
     207             : 
     208             :   /* SBPF version, SIMD-0161 */
     209             :   ulong sbpf_version;
     210             : };
     211             : typedef struct fd_sbpf_elf_info fd_sbpf_elf_info_t;
     212             : 
     213             : /* fd_sbpf_loader_is_legacy_lenient returns 1 iff the program must be loaded via
     214             :    the legacy lenient path (relocate in place over the full ELF image using a
     215             :    scratch buffer).  This is exactly the case load_buf_sz==bin_sz: strict (v3+)
     216             :    and lenient-fast loads assemble a smaller, exact-size buffer with no scratch,
     217             :    while the legacy path needs the whole binary (load_buf_sz==bin_sz) + scratch. */
     218             : FD_FN_PURE static inline int
     219        4155 : fd_sbpf_loader_is_legacy_lenient( fd_sbpf_elf_info_t const * info ) {
     220        4155 :   return info->load_buf_sz==info->bin_sz;
     221        4155 : }
     222             : 
     223             : /* fd_sbpf_program_t describes a loaded program in memory.
     224             : 
     225             :    [rodata,rodata+bin_sz) is an externally allocated buffer holding
     226             :    the read-only segment to be loaded into the VM.  WARNING: The rodata
     227             :    area required doing load (bin_sz) is larger than the area mapped into
     228             :    the VM (rodata_sz).
     229             : 
     230             :    [text,text+8*text_cnt) is a sub-region of the read-only segment
     231             :    containing executable code.
     232             : 
     233             :    We need to maintain a separate value tracking the entrypoint calldest
     234             :    because we lay out our calldests in a set instead of a map (like
     235             :    Agave does), which is more performant but comes with a few footguns.
     236             :    Since we only store the target PC and not a keypair of <hash, target
     237             :    PC>, we need to make sure we unregister the correct target PC from
     238             :    the map. For all other cases besides the b"entrypoint" string, we can
     239             :    simply check for membership within the calldests set because the
     240             :    32-bit murmur3 hash function is bijective, implying key collision iff
     241             :    value collision. However, the b"entrypoint" string is a special case
     242             :    because the key is the hardcoded hash of the b"entrypoint" string,
     243             :    but the value can correspond to any target PC. This means that
     244             :    someone could register several different target PCs with the same
     245             :    entrypoint PC, and we cannot figure out which target PC we must
     246             :    unregister. Additionally, we would not be able to check for
     247             :    collisions for multiple registered b"entrypoint" strings with
     248             :    different target PCs.
     249             : 
     250             :    Once entry_pc is set, any future calls to set the entry_pc within the
     251             :    loader will error out with FD_SBPF_ELF_ERR_SYMBOL_HASH_COLLISION. */
     252             : 
     253             : struct __attribute__((aligned(32UL))) fd_sbpf_program {
     254             :   fd_sbpf_elf_info_t info;
     255             : 
     256             :   /* rodata segment to be mapped into VM memory */
     257             :   void * rodata;     /* rodata segment data */
     258             :   ulong  rodata_sz;  /* size of read-only data */
     259             : 
     260             :   /* text section within rodata segment */
     261             :   ulong * text;
     262             :   ulong   entry_pc;  /* entrypoint PC (at text[ entry_pc ]). ULONG_MAX if not set. */
     263             : 
     264             :   /* Bit vector of valid call destinations (bit count is text_cnt). */
     265             :   void * calldests_shmem;
     266             :   /* Local join to bit vector of valid call destinations (target PCs) */
     267             :   fd_sbpf_calldests_t * calldests;
     268             : };
     269             : typedef struct fd_sbpf_program fd_sbpf_program_t;
     270             : 
     271             : struct fd_sbpf_loader_config {
     272             :   union {
     273             :    int elf_deploy_checks;
     274             :    int reject_broken_elfs;
     275             :   };
     276             :   uint sbpf_min_version;
     277             :   uint sbpf_max_version;
     278             : };
     279             : typedef struct fd_sbpf_loader_config fd_sbpf_loader_config_t;
     280             : 
     281             : /* Prototypes *********************************************************/
     282             : 
     283             : FD_PROTOTYPES_BEGIN
     284             : 
     285             : /* fd_sbpf_elf_peek partially parses the given ELF file in memory region
     286             :    [bin,bin+bin_sz)  Populates `info`.  Returns FD_SBPF_ELF_SUCCESS (0)
     287             :    on success.  On failure, returns a negative FD_SBPF_ELF_ERR_* error
     288             :    code, and the contents of `info` are unspecified.
     289             : 
     290             :    elf_deploy_checks: The Agave ELF loader introduced additional checks
     291             :    that would fail on (certain) existing mainnet programs. Since it is
     292             :    impossible to retroactively enforce these checks on already deployed programs,
     293             :    a guard flag is used to enable these checks only when deploying programs.
     294             : 
     295             :    sbpf_min_version, sbpf_max_version: determine the min, max SBPF version
     296             :    allowed, version is retrieved from the ELF header. See SIMD-0161. */
     297             : 
     298             : int
     299             : fd_sbpf_elf_peek( fd_sbpf_elf_info_t *            info,
     300             :                   void const *                    bin,
     301             :                   ulong                           bin_sz,
     302             :                   fd_sbpf_loader_config_t const * config );
     303             : 
     304             : /* fd_sbpf_program_{align,footprint} return the alignment and size
     305             :    requirements of the memory region backing the fd_sbpf_program_t
     306             :    object. */
     307             : 
     308             : FD_FN_CONST ulong
     309             : fd_sbpf_program_align( void );
     310             : 
     311             : FD_FN_PURE ulong
     312             : fd_sbpf_program_footprint( fd_sbpf_elf_info_t const * info );
     313             : 
     314             : /* fd_sbpf_program_new formats prog_mem to hold an fd_sbpf_program_t.
     315             :    prog_mem must match footprint requirements of the given elf_info.
     316             :    elf_info may be deallocated on return.
     317             : 
     318             :    rodata is the read-only segment buffer that the program is configured
     319             :    against and must be valid for the lifetime of the program object. It
     320             :    should also meet the alignment requirements of the program object.
     321             :    */
     322             : 
     323             : fd_sbpf_program_t *
     324             : fd_sbpf_program_new( void *                     prog_mem,
     325             :                      fd_sbpf_elf_info_t const * elf_info,
     326             :                      void *                     rodata );
     327             : 
     328             : /* fd_sbpf_program_load loads an eBPF program for execution.
     329             : 
     330             :    prog is a program object allocated with fd_sbpf_program_new and must
     331             :    match the footprint requirements of this ELF file.
     332             : 
     333             :    Initializes and populates the program struct with information about
     334             :    the program and prepares the read-only segment provided in
     335             :    fd_sbpf_program_new. This includes performing relocations in the
     336             :    ELF file and zeroing gaps between rodata sections.
     337             : 
     338             :    Memory region [bin,bin+bin_sz) contains the ELF file to be loaded.
     339             : 
     340             :    syscalls should be a pointer to a map of registered syscalls and
     341             :    will be checked against when registering calldests for potential
     342             :    symbol collisions.
     343             : 
     344             :    scratch should be a pointer to a scratch area with size scratch_sz,
     345             :    used to allocate a temporary buffer for the parsed rodata sections
     346             :    before copying it back into the rodata.  recommended size is bin_sz.
     347             : 
     348             :    On success, returns FD_SBPF_ELF_SUCCESS (0).
     349             :    On error, returns a negative FD_SBPF_ELF_ERR_* code.
     350             : 
     351             :    ### Compliance
     352             : 
     353             :    As of writing, this loader is conformant with Solana SBPF v0.12.2,
     354             :    SBPF versions V0, V1, and V2.
     355             :    */
     356             : 
     357             : int
     358             : fd_sbpf_program_load( fd_sbpf_program_t *             prog,
     359             :                       void const *                    bin,
     360             :                       ulong                           bin_sz,
     361             :                       fd_sbpf_syscalls_t *            syscalls,
     362             :                       fd_sbpf_loader_config_t const * config,
     363             :                       void *                          scratch,
     364             :                       ulong                           scratch_sz );
     365             : 
     366             : /* fd_sbpf_program_delete destroys the program object and unformats the
     367             :    memory regions holding it. */
     368             : 
     369             : void *
     370             : fd_sbpf_program_delete( fd_sbpf_program_t * program );
     371             : 
     372             : /* SBPF versions and features. This should stay in sync with the macro
     373             :    definitions in fd_vm_private.h until they are removed (once Agave
     374             :    cleans up the jump table).
     375             :    https://github.com/anza-xyz/sbpf/blob/v0.12.2/src/program.rs#L28 */
     376             : 
     377        1853 : #define FD_VM_SBPF_DYNAMIC_STACK_FRAMES_ALIGN (64U)
     378             : 
     379             : /* SIMD-0166 */
     380             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L32-L34 */
     381         769 : static inline int fd_sbpf_manual_stack_frame_bump_enabled            ( ulong v ) { return v==FD_SBPF_V1 || v==FD_SBPF_V2; }
     382             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L36-L38 */
     383           0 : static inline int fd_sbpf_stack_frame_gaps_enabled                   ( ulong v ) { return v==FD_SBPF_V0; }
     384             : 
     385             : /* SIMD-0174 */
     386             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L41-L43 */
     387           0 : static inline int fd_sbpf_enable_pqr_enabled                         ( ulong v ) { return v==FD_SBPF_V2; }
     388             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L45-L47 */
     389           0 : static inline int fd_sbpf_explicit_sign_extension_of_results_enabled ( ulong v ) { return v==FD_SBPF_V2; }
     390             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L49-L51 */
     391           0 : static inline int fd_sbpf_swap_sub_reg_imm_operands_enabled          ( ulong v ) { return v==FD_SBPF_V2; }
     392             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L53-L55 */
     393           0 : static inline int fd_sbpf_disable_neg_enabled                        ( ulong v ) { return v==FD_SBPF_V2; }
     394             : 
     395             : /* SIMD-0173 */
     396             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L58-L60 */
     397        1368 : static inline int fd_sbpf_callx_uses_src_reg_enabled                 ( ulong v ) { return v==FD_SBPF_V2; }
     398             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L62-L64 */
     399           0 : static inline int fd_sbpf_disable_lddw_enabled                       ( ulong v ) { return v==FD_SBPF_V2; }
     400             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L66-L68 */
     401           0 : static inline int fd_sbpf_disable_le_enabled                         ( ulong v ) { return v==FD_SBPF_V2; }
     402             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L70-L72 */
     403           0 : static inline int fd_sbpf_move_memory_ix_classes_enabled             ( ulong v ) { return v==FD_SBPF_V2; }
     404             : 
     405             : /* SIMD-0178 */
     406             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L75-L77 */
     407           0 : static inline int fd_sbpf_static_syscalls_enabled                    ( ulong v ) { return v>=FD_SBPF_V3; }
     408             : 
     409             : /* SIMD-0189 */
     410             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L79-L81 */
     411       30274 : static inline int fd_sbpf_enable_stricter_elf_headers_enabled        ( ulong v ) { return v>=FD_SBPF_V3; }
     412             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L83-L85 */
     413           0 : static inline int fd_sbpf_enable_lower_rodata_vaddr_enabled          ( ulong v ) { return v>=FD_SBPF_V3; }
     414             : 
     415             : /* SIMD-0377 */
     416             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L87-L89 */
     417           0 : static inline int fd_sbpf_enable_jmp32_enabled                       ( ulong v ) { return v>=FD_SBPF_V3; }
     418             : /* https://github.com/anza-xyz/sbpf/blob/v0.14.4/src/program.rs#L91-L93 */
     419        1355 : static inline int fd_sbpf_callx_uses_dst_reg_enabled                 ( ulong v ) { return v>=FD_SBPF_V3; }
     420             : 
     421             : FD_PROTOTYPES_END
     422             : 
     423             : #endif /* HEADER_fd_src_ballet_sbpf_fd_sbpf_loader_h */

Generated by: LCOV version 1.14