LCOV - code coverage report
Current view: top level - flamenco/progcache - fd_progcache_rec.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 117 117 100.0 %
Date: 2026-03-19 18:19:27 Functions: 5 5 100.0 %

          Line data    Source code
       1             : #include "fd_progcache.h"
       2             : #include "../vm/fd_vm.h" /* fd_vm_syscall_register_slot, fd_vm_validate */
       3             : #include "../../util/alloc/fd_alloc.h"
       4             : 
       5             : void *
       6             : fd_progcache_val_alloc( fd_progcache_rec_t *  rec,
       7             :                         fd_progcache_join_t * join,
       8             :                         ulong                 val_align,
       9       10112 :                         ulong                 val_footprint ) {
      10       10112 :   if( rec->data_gaddr ) fd_progcache_val_free( rec, join );
      11       10112 :   ulong val_max = 0UL;
      12       10112 :   void * mem = fd_alloc_malloc_at_least( join->alloc, val_align, val_footprint, &val_max );
      13       10112 :   if( FD_UNLIKELY( !mem ) ) return NULL;
      14       10112 :   FD_CRIT( val_max<=UINT_MAX, "massive" ); /* unreachable */
      15       10112 :   rec->data_gaddr = fd_wksp_gaddr_fast( join->wksp, mem );
      16       10112 :   rec->data_max   = (uint)val_max;
      17       10112 :   return mem;
      18       10112 : }
      19             : 
      20             : void
      21             : fd_progcache_val_free( fd_progcache_rec_t *  rec,
      22       29983 :                        fd_progcache_join_t * join ) {
      23       29983 :   if( !rec->data_gaddr ) return;
      24       10285 :   void * mem = fd_wksp_laddr_fast( join->wksp, rec->data_gaddr );
      25             : 
      26             :   /* Illegal to call val_free on a spill-allocated buffer */
      27       10285 :   FD_TEST( !( (ulong)mem >= (ulong)join->shmem->spill.spad &&
      28       10285 :               (ulong)mem <  (ulong)join->shmem->spill.spad+FD_PROGCACHE_SPAD_MAX ) );
      29             : 
      30       10285 :   fd_alloc_free( join->alloc, mem );
      31       10285 :   rec->data_gaddr = 0UL;
      32       10285 :   rec->data_max   = 0U;
      33       10285 :   rec->rodata_off = 0U;
      34       10285 :   rec->rodata_sz  = 0U;
      35       10285 : }
      36             : 
      37             : FD_FN_PURE ulong
      38       20302 : fd_progcache_val_footprint( fd_sbpf_elf_info_t const * elf_info ) {
      39       20302 :   int   has_calldests = !fd_sbpf_enable_stricter_elf_headers_enabled( elf_info->sbpf_version );
      40       20302 :   ulong pc_max        = fd_ulong_max( 1UL, elf_info->text_cnt );
      41             : 
      42       20302 :   ulong l = FD_LAYOUT_INIT;
      43       20303 :   if( has_calldests ) {
      44       20303 :     l = FD_LAYOUT_APPEND( l, fd_sbpf_calldests_align(), fd_sbpf_calldests_footprint( pc_max ) );
      45       20303 :   }
      46       20302 :   l = FD_LAYOUT_APPEND( l, 8UL, elf_info->bin_sz );
      47       20302 :   return FD_LAYOUT_FINI( l, fd_progcache_val_align() );
      48       20302 : }
      49             : 
      50             : fd_progcache_rec_t *
      51             : fd_progcache_rec_load( fd_progcache_rec_t *            rec,
      52             :                        fd_wksp_t *                     wksp,
      53             :                        fd_sbpf_elf_info_t const *      elf_info,
      54             :                        fd_sbpf_loader_config_t const * config,
      55             :                        ulong                           load_slot,
      56             :                        fd_features_t const *           features,
      57             :                        void const *                    progdata,
      58             :                        ulong                           progdata_sz,
      59             :                        void *                          scratch,
      60       10285 :                        ulong                           scratch_sz ) {
      61             : 
      62             :   /* Format object */
      63             : 
      64       10285 :   int has_calldests = !fd_sbpf_enable_stricter_elf_headers_enabled( elf_info->sbpf_version );
      65             : 
      66       10285 :   void * val = fd_wksp_laddr_fast( wksp, rec->data_gaddr );
      67       10285 :   FD_SCRATCH_ALLOC_INIT( l, val );
      68       10285 :   void *               calldests_mem = NULL;
      69       10285 :   if( has_calldests ) {
      70       10285 :     /*               */calldests_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_sbpf_calldests_align(), fd_sbpf_calldests_footprint( fd_ulong_max( 1UL, elf_info->text_cnt ) ) );
      71       10285 :   }
      72       10285 :   void *               rodata_mem    = FD_SCRATCH_ALLOC_APPEND( l, 8UL, elf_info->bin_sz );
      73       10285 :   FD_SCRATCH_ALLOC_FINI( l, fd_progcache_val_align() );
      74       10285 :   FD_TEST( _l-(ulong)val == fd_progcache_val_footprint( elf_info ) );
      75             : 
      76       10285 :   rec->calldests_off = has_calldests ? (uint)( (ulong)calldests_mem - (ulong)val ) : 0U;
      77       10285 :   rec->rodata_off    = (uint)( (ulong)rodata_mem - (ulong)val );
      78       10285 :   rec->entry_pc      = 0;
      79       10285 :   rec->rodata_sz     = 0;
      80       10285 :   rec->executable    = 0;
      81             : 
      82       10285 :   rec->text_cnt      = elf_info->text_cnt;
      83       10285 :   rec->text_off      = elf_info->text_off;
      84       10285 :   rec->text_sz       = (uint)elf_info->text_sz;
      85       10285 :   rec->sbpf_version  = (uchar)elf_info->sbpf_version;
      86             : 
      87             :   /* Set up sbpf_loader (redirect writes into progcache_rec object) */
      88             : 
      89       10285 :   fd_sbpf_program_t prog[1] = {{
      90       10285 :     .info     = *elf_info,
      91       10285 :     .rodata   = rodata_mem,
      92       10285 :     .text     = (ulong *)((ulong)rodata_mem + elf_info->text_off), /* FIXME: WHAT IF MISALIGNED */
      93       10285 :     .entry_pc = ULONG_MAX
      94       10285 :   }};
      95       10285 :   if( has_calldests && elf_info->text_cnt>0UL ) {
      96       10283 :     prog->calldests_shmem = calldests_mem;
      97       10283 :     prog->calldests = fd_sbpf_calldests_join( fd_sbpf_calldests_new( calldests_mem, elf_info->text_cnt ) );
      98       10283 :   }
      99             : 
     100             :   /* Loader requires syscall table */
     101             : 
     102       10285 :   fd_sbpf_syscalls_t _syscalls[ FD_SBPF_SYSCALLS_SLOT_CNT ];
     103       10285 :   fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_join( fd_sbpf_syscalls_new( _syscalls ) );
     104       10285 :   int syscalls_err = fd_vm_syscall_register_slot( syscalls, load_slot, features, /* is_deploy */ 0 );
     105       10285 :   if( FD_UNLIKELY( syscalls_err!=FD_VM_SUCCESS ) ) FD_LOG_CRIT(( "fd_vm_syscall_register_slot failed" ));
     106             : 
     107             :   /* Run ELF loader */
     108             : 
     109       10285 :   if( FD_UNLIKELY( 0!=fd_sbpf_program_load( prog, progdata, progdata_sz, syscalls, config, scratch, scratch_sz ) ) ) {
     110         107 :     return NULL;
     111         107 :   }
     112             : 
     113       10178 :   rec->entry_pc  = (uint)prog->entry_pc;
     114       10178 :   rec->rodata_sz = (uint)prog->rodata_sz;
     115             : 
     116             :   /* Run bytecode validator */
     117             : 
     118       10178 :   fd_vm_t _vm[1];
     119       10178 :   fd_vm_t * vm = fd_vm_join( fd_vm_new( _vm ) );
     120       10178 :   if( FD_UNLIKELY( !vm ) ) FD_LOG_CRIT(( "fd_vm_new failed" ));
     121       10178 :   vm = fd_vm_init( vm,
     122       10178 :                    NULL, /* OK since unused in `fd_vm_validate()` */
     123       10178 :                    0UL,
     124       10178 :                    0UL,
     125       10178 :                    prog->rodata,
     126       10178 :                    prog->rodata_sz,
     127       10178 :                    prog->text,
     128       10178 :                    prog->info.text_cnt,
     129       10178 :                    prog->info.text_off,
     130       10178 :                    prog->info.text_sz,
     131       10178 :                    prog->entry_pc,
     132       10178 :                    prog->calldests,
     133       10178 :                    elf_info->sbpf_version,
     134       10178 :                    syscalls,
     135       10178 :                    NULL,
     136       10178 :                    NULL,
     137       10178 :                    NULL,
     138       10178 :                    0U,
     139       10178 :                    NULL,
     140       10178 :                    0,
     141       10178 :                    FD_FEATURE_ACTIVE( load_slot, features, account_data_direct_mapping ),
     142       10178 :                    FD_FEATURE_ACTIVE( load_slot, features, stricter_abi_and_runtime_constraints ),
     143       10178 :                    0,
     144       10178 :                    0UL );
     145       10178 :   if( FD_UNLIKELY( !vm ) ) FD_LOG_CRIT(( "fd_vm_init failed" ));
     146             : 
     147       10178 :   if( FD_UNLIKELY( fd_vm_validate( vm )!=FD_VM_SUCCESS ) ) return NULL;
     148             : 
     149       10112 :   rec->executable = 1;
     150       10112 :   return rec;
     151       10178 : }
     152             : 
     153             : fd_progcache_rec_t *
     154       19696 : fd_progcache_rec_nx( fd_progcache_rec_t * rec ) {
     155       19696 :   rec->data_gaddr    = 0UL;
     156       19696 :   rec->data_max      = 0U;
     157       19696 :   rec->entry_pc      = 0;
     158       19696 :   rec->text_cnt      = 0;
     159       19696 :   rec->text_off      = 0;
     160       19696 :   rec->text_sz       = 0;
     161       19696 :   rec->rodata_sz     = 0;
     162       19696 :   rec->calldests_off = 0;
     163       19696 :   rec->rodata_off    = 0;
     164       19696 :   rec->sbpf_version  = 0;
     165       19696 :   rec->executable    = 0;
     166       19696 :   rec->invalidate    = 0;
     167       19696 :   return rec;
     168       19696 : }

Generated by: LCOV version 1.14