LCOV - code coverage report
Current view: top level - flamenco/vm/syscall - fd_vm_syscall_runtime.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 332 0.0 %
Date: 2025-10-22 04:33:54 Functions: 0 11 0.0 %

          Line data    Source code
       1             : #include "fd_vm_syscall.h"
       2             : #include "../../runtime/program/fd_vote_program.h"
       3             : #include "../../runtime/context/fd_exec_txn_ctx.h"
       4             : #include "../../runtime/context/fd_exec_instr_ctx.h"
       5             : #include "../../runtime/fd_system_ids.h"
       6             : #include "fd_vm_syscall_macros.h"
       7             : 
       8             : /* FIXME: In the original version of this code, there was an FD_TEST
       9             :    to check if the VM was attached to an instruction context (that
      10             :    would have crashed anyway because of pointer chasing).  If the VM
      11             :    is being run outside the Solana runtime, it should never invoke
      12             :    this syscall in the first place.  So we treat this as a SIGCALL in
      13             :    a non-crashing way for the time being. */
      14             : 
      15             : int
      16             : fd_vm_syscall_sol_get_clock_sysvar( /**/            void *  _vm,
      17             :                                     /**/            ulong   out_vaddr,
      18             :                                     FD_PARAM_UNUSED ulong   r2,
      19             :                                     FD_PARAM_UNUSED ulong   r3,
      20             :                                     FD_PARAM_UNUSED ulong   r4,
      21             :                                     FD_PARAM_UNUSED ulong   r5,
      22           0 :                                     /**/            ulong * _ret ) {
      23           0 :   fd_vm_t * vm = _vm;
      24           0 :   fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
      25           0 :   if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
      26             : 
      27           0 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, sizeof(fd_sol_sysvar_clock_t) ) );
      28             : 
      29           0 :   if( FD_UNLIKELY( vm->stricter_abi_and_runtime_constraints && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
      30           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
      31           0 :     return FD_VM_ERR_INVAL;
      32           0 :   }
      33             : 
      34           0 :   fd_vm_haddr_query_t var_query = {
      35           0 :     .vaddr    = out_vaddr,
      36           0 :     .align    = FD_VM_ALIGN_RUST_SYSVAR_CLOCK,
      37           0 :     .sz       = sizeof(fd_sol_sysvar_clock_t),
      38           0 :     .is_slice = 0,
      39           0 :   };
      40             : 
      41           0 :   fd_vm_haddr_query_t * queries[] = { &var_query };
      42           0 :   FD_VM_TRANSLATE_MUT( vm, queries );
      43             : 
      44           0 :   fd_sol_sysvar_clock_t clock = fd_sysvar_cache_clock_read_nofail( instr_ctx->sysvar_cache );
      45           0 :   memcpy( var_query.haddr, &clock, sizeof(fd_sol_sysvar_clock_t) );
      46             : 
      47           0 :   *_ret = 0UL;
      48           0 :   return FD_VM_SUCCESS;
      49           0 : }
      50             : 
      51             : int
      52             : fd_vm_syscall_sol_get_epoch_schedule_sysvar( /**/            void *  _vm,
      53             :                                              /**/            ulong   out_vaddr,
      54             :                                              FD_PARAM_UNUSED ulong   r2,
      55             :                                              FD_PARAM_UNUSED ulong   r3,
      56             :                                              FD_PARAM_UNUSED ulong   r4,
      57             :                                              FD_PARAM_UNUSED ulong   r5,
      58           0 :                                              /**/            ulong * _ret ) {
      59           0 :   fd_vm_t * vm = _vm;
      60           0 :   fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
      61           0 :   if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
      62             : 
      63           0 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, sizeof(fd_epoch_schedule_t) ) );
      64             : 
      65           0 :   if( FD_UNLIKELY( vm->stricter_abi_and_runtime_constraints && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
      66           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
      67           0 :     return FD_VM_ERR_INVAL;
      68           0 :   }
      69             : 
      70           0 :   fd_vm_haddr_query_t var_query = {
      71           0 :     .vaddr    = out_vaddr,
      72           0 :     .align    = FD_VM_ALIGN_RUST_SYSVAR_EPOCH_SCHEDULE,
      73           0 :     .sz       = sizeof(fd_epoch_schedule_t),
      74           0 :     .is_slice = 0,
      75           0 :   };
      76             : 
      77           0 :   fd_vm_haddr_query_t * queries[] = { &var_query };
      78           0 :   FD_VM_TRANSLATE_MUT( vm, queries );
      79             : 
      80           0 :   fd_epoch_schedule_t schedule;
      81           0 :   if( FD_UNLIKELY( !fd_sysvar_cache_epoch_schedule_read( instr_ctx->sysvar_cache, &schedule ) ) ) {
      82           0 :     FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_ctx->instr_err_idx );
      83           0 :     return FD_VM_ERR_INVAL;
      84           0 :   }
      85           0 :   memcpy( var_query.haddr, &schedule, sizeof(fd_epoch_schedule_t) );
      86             : 
      87           0 :   *_ret = 0UL;
      88           0 :   return FD_VM_SUCCESS;
      89           0 : }
      90             : 
      91             : int
      92             : fd_vm_syscall_sol_get_rent_sysvar( /**/            void *  _vm,
      93             :                                    /**/            ulong   out_vaddr,
      94             :                                    FD_PARAM_UNUSED ulong   r2,
      95             :                                    FD_PARAM_UNUSED ulong   r3,
      96             :                                    FD_PARAM_UNUSED ulong   r4,
      97             :                                    FD_PARAM_UNUSED ulong   r5,
      98           0 :                                    /**/            ulong * _ret ) {
      99           0 :   fd_vm_t * vm = _vm;
     100             : 
     101             :   /* Unreachable in a real SVM, used for testing */
     102             : 
     103           0 :   fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
     104           0 :   if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
     105             : 
     106           0 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, sizeof(fd_rent_t) ) );
     107             : 
     108           0 :   if( FD_UNLIKELY( vm->stricter_abi_and_runtime_constraints && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
     109           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
     110           0 :     return FD_VM_ERR_INVAL;
     111           0 :   }
     112             : 
     113           0 :   fd_vm_haddr_query_t var_query = {
     114           0 :     .vaddr    = out_vaddr,
     115           0 :     .align    = FD_VM_ALIGN_RUST_SYSVAR_RENT,
     116           0 :     .sz       = sizeof(fd_rent_t),
     117           0 :     .is_slice = 0,
     118           0 :   };
     119             : 
     120           0 :   fd_vm_haddr_query_t * queries[] = { &var_query };
     121           0 :   FD_VM_TRANSLATE_MUT( vm, queries );
     122             : 
     123           0 :   fd_rent_t rent = fd_sysvar_cache_rent_read_nofail( instr_ctx->sysvar_cache );
     124           0 :   memcpy( var_query.haddr, &rent, sizeof(fd_rent_t) );
     125             : 
     126           0 :   *_ret = 0UL;
     127           0 :   return FD_VM_SUCCESS;
     128           0 : }
     129             : 
     130             : /* https://github.com/anza-xyz/agave/blob/v2.3.2/programs/bpf_loader/src/syscalls/sysvar.rs#L149 */
     131             : int
     132             : fd_vm_syscall_sol_get_last_restart_slot_sysvar( /**/            void *  _vm,
     133             :                                                 /**/            ulong   out_vaddr,
     134             :                                                 FD_PARAM_UNUSED ulong   r2,
     135             :                                                 FD_PARAM_UNUSED ulong   r3,
     136             :                                                 FD_PARAM_UNUSED ulong   r4,
     137             :                                                 FD_PARAM_UNUSED ulong   r5,
     138           0 :                                                 /**/            ulong * _ret ) {
     139           0 :   fd_vm_t * vm = _vm;
     140           0 :   fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
     141           0 :   if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
     142             : 
     143           0 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, sizeof(fd_sol_sysvar_last_restart_slot_t) ) );
     144             : 
     145           0 :   if( FD_UNLIKELY( vm->stricter_abi_and_runtime_constraints && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
     146           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
     147           0 :     return FD_VM_ERR_INVAL;
     148           0 :   }
     149             : 
     150           0 :   fd_vm_haddr_query_t var_query = {
     151           0 :     .vaddr    = out_vaddr,
     152           0 :     .align    = FD_VM_ALIGN_RUST_SYSVAR_LAST_RESTART_SLOT,
     153           0 :     .sz       = sizeof(fd_sol_sysvar_last_restart_slot_t),
     154           0 :     .is_slice = 0,
     155           0 :   };
     156             : 
     157           0 :   fd_vm_haddr_query_t * queries[] = { &var_query };
     158           0 :   FD_VM_TRANSLATE_MUT( vm, queries );
     159             : 
     160           0 :   fd_sol_sysvar_last_restart_slot_t last_restart_slot;
     161           0 :   if( FD_UNLIKELY( !fd_sysvar_cache_last_restart_slot_read( vm->instr_ctx->sysvar_cache, &last_restart_slot ) ) ) {
     162           0 :     FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_ctx->instr_err_idx );
     163           0 :     return FD_VM_ERR_INVAL;
     164           0 :   }
     165             : 
     166           0 :   memcpy( var_query.haddr, &last_restart_slot, sizeof(fd_sol_sysvar_last_restart_slot_t) );
     167             : 
     168           0 :   *_ret = 0UL;
     169           0 :   return FD_VM_SUCCESS;
     170           0 : }
     171             : 
     172             : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L167-L232 */
     173             : int
     174             : fd_vm_syscall_sol_get_sysvar( /**/            void *  _vm,
     175             :                               /**/            ulong   sysvar_id_vaddr,
     176             :                               /**/            ulong   out_vaddr,
     177             :                               /**/            ulong   offset,
     178             :                               /**/            ulong   sz,
     179             :                               FD_PARAM_UNUSED ulong   r5,
     180           0 :                               /**/            ulong * _ret ) {
     181           0 :   fd_vm_t * vm = _vm;
     182           0 :   fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
     183           0 :   if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
     184             : 
     185             :   /* sysvar_id_cost seems to just always be 32 / 250 = 0...
     186             :      https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L190-L197 */
     187           0 :   ulong sysvar_buf_cost = sz / FD_VM_CPI_BYTES_PER_UNIT;
     188           0 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, fd_ulong_max( sysvar_buf_cost, FD_VM_MEM_OP_BASE_COST ) ) );
     189             : 
     190           0 :   if( FD_UNLIKELY( vm->stricter_abi_and_runtime_constraints && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
     191           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
     192           0 :     return FD_VM_ERR_INVAL;
     193           0 :   }
     194             : 
     195             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/sysvar.rs#L207-L211 */
     196           0 :   fd_vm_haddr_query_t var_query = {
     197           0 :     .vaddr    = out_vaddr,
     198           0 :     .align    = FD_VM_ALIGN_RUST_U8,
     199           0 :     .sz       = sz,
     200           0 :     .is_slice = 1,
     201           0 :   };
     202             : 
     203           0 :   fd_vm_haddr_query_t * queries[] = { &var_query };
     204           0 :   FD_VM_TRANSLATE_MUT( vm, queries );
     205             : 
     206             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L199-L200 */
     207           0 :   const fd_pubkey_t * sysvar_id = FD_VM_MEM_HADDR_LD( vm, sysvar_id_vaddr, FD_VM_ALIGN_RUST_PUBKEY, FD_PUBKEY_FOOTPRINT );
     208             : 
     209             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L205-L208 */
     210           0 :   ulong offset_length;
     211           0 :   int err = fd_int_if( __builtin_uaddl_overflow( offset, sz, &offset_length ), FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW, FD_EXECUTOR_INSTR_SUCCESS );
     212           0 :   if( FD_UNLIKELY( err ) ) {
     213           0 :     FD_VM_ERR_FOR_LOG_INSTR( vm, err );
     214           0 :     return FD_VM_SYSCALL_ERR_ABORT;
     215           0 :   }
     216             : 
     217             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L210-L213
     218             :      We don't need this, we already checked we can store in out_vaddr with requested sz. */
     219             : 
     220             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L215-L221 */
     221           0 :   if( FD_UNLIKELY( memcmp( sysvar_id->uc, fd_sysvar_clock_id.uc,             FD_PUBKEY_FOOTPRINT ) &&
     222           0 :                    memcmp( sysvar_id->uc, fd_sysvar_epoch_schedule_id.uc,    FD_PUBKEY_FOOTPRINT ) &&
     223           0 :                    memcmp( sysvar_id->uc, fd_sysvar_epoch_rewards_id.uc,     FD_PUBKEY_FOOTPRINT ) &&
     224           0 :                    memcmp( sysvar_id->uc, fd_sysvar_rent_id.uc,              FD_PUBKEY_FOOTPRINT ) &&
     225           0 :                    memcmp( sysvar_id->uc, fd_sysvar_slot_hashes_id.uc,       FD_PUBKEY_FOOTPRINT ) &&
     226           0 :                    memcmp( sysvar_id->uc, fd_sysvar_stake_history_id.uc,     FD_PUBKEY_FOOTPRINT ) &&
     227           0 :                    memcmp( sysvar_id->uc, fd_sysvar_last_restart_slot_id.uc, FD_PUBKEY_FOOTPRINT ) ) ) {
     228           0 :     *_ret = 2UL;
     229           0 :     return FD_VM_SUCCESS;
     230           0 :   }
     231             : 
     232           0 :   ulong         sysvar_buf_len;
     233           0 :   uchar const * sysvar_buf =
     234           0 :     fd_sysvar_cache_data_query( vm->instr_ctx->sysvar_cache, sysvar_id, &sysvar_buf_len );
     235           0 :   if( FD_UNLIKELY( !sysvar_buf ) ) {
     236           0 :     *_ret = 2UL;
     237           0 :     return FD_VM_SUCCESS;
     238           0 :   }
     239             : 
     240             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/sysvar.rs#L223-L228
     241             :      Note the length check is at the very end to fail after performing sufficient checks. */
     242             : 
     243           0 :   if( FD_UNLIKELY( offset_length>sysvar_buf_len ) ) {
     244           0 :     *_ret = 1UL;
     245           0 :     return FD_VM_SUCCESS;
     246           0 :   }
     247             : 
     248           0 :   if( FD_UNLIKELY( sz==0UL ) ) {
     249           0 :     *_ret = 0UL;
     250           0 :     return FD_VM_SUCCESS;
     251           0 :   }
     252             : 
     253           0 :   fd_memcpy( var_query.haddr, sysvar_buf + offset, sz );
     254           0 :   *_ret = 0;
     255           0 :   return FD_VM_SUCCESS;
     256           0 : }
     257             : 
     258             : /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2043-L2118 */
     259             : int
     260             : fd_vm_syscall_sol_get_epoch_stake( /**/            void *  _vm,
     261             :                                    /**/            ulong   var_addr,
     262             :                                    FD_PARAM_UNUSED ulong   r2,
     263             :                                    FD_PARAM_UNUSED ulong   r3,
     264             :                                    FD_PARAM_UNUSED ulong   r4,
     265             :                                    FD_PARAM_UNUSED ulong   r5,
     266           0 :                                    /**/            ulong * _ret ) {
     267           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     268             : 
     269             :   /* Var addr of 0 returns the total active stake on the cluster.
     270             : 
     271             :      https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2057-L2075 */
     272           0 :   if( FD_UNLIKELY( var_addr==0UL ) ) {
     273             :     /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2065-L2066 */
     274           0 :     FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
     275             : 
     276             :     /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2074 */
     277           0 :     *_ret = fd_bank_total_epoch_stake_get( vm->instr_ctx->txn_ctx->bank );
     278           0 :     return FD_VM_SUCCESS;
     279           0 :   }
     280             : 
     281             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2083-L2091
     282             :      FD_PUBKEY_FOOTPRINT/FD_VM_CPI_BYTES_PER_UNIT is always 32/250 = 0,
     283             :      so we can omit it */
     284             : 
     285           0 :   FD_VM_CU_UPDATE( vm, FD_VM_MEM_OP_BASE_COST + FD_VM_SYSCALL_BASE_COST );
     286             : 
     287             :   /* https://github.com/anza-xyz/agave/blob/v2.1.0/programs/bpf_loader/src/syscalls/mod.rs#L2103-L2104 */
     288           0 :   const fd_pubkey_t * vote_address = FD_VM_MEM_HADDR_LD( vm, var_addr, FD_VM_ALIGN_RUST_PUBKEY, FD_PUBKEY_FOOTPRINT );
     289             : 
     290             :   /* https://github.com/anza-xyz/agave/blob/v2.2.14/runtime/src/bank.rs#L6954 */
     291           0 :   fd_vote_states_t const *    vote_states    = fd_bank_vote_states_prev_locking_query( vm->instr_ctx->txn_ctx->bank );
     292           0 :   fd_vote_state_ele_t const * vote_state_ele = fd_vote_states_query_const( vote_states, vote_address );
     293           0 :   *_ret = vote_state_ele ? vote_state_ele->stake : 0UL;
     294           0 :   fd_bank_vote_states_prev_end_locking_query( vm->instr_ctx->txn_ctx->bank );
     295             : 
     296           0 :   return FD_VM_SUCCESS;
     297           0 : }
     298             : 
     299             : int
     300             : fd_vm_syscall_sol_get_stack_height( /**/            void *  _vm,
     301             :                                     FD_PARAM_UNUSED ulong   r1,
     302             :                                     FD_PARAM_UNUSED ulong   r2,
     303             :                                     FD_PARAM_UNUSED ulong   r3,
     304             :                                     FD_PARAM_UNUSED ulong   r4,
     305             :                                     FD_PARAM_UNUSED ulong   r5,
     306           0 :                                     /**/            ulong * _ret ) {
     307             :   /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L1547 */
     308           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     309             : 
     310           0 :   FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
     311             : 
     312           0 :   *_ret = vm->instr_ctx->txn_ctx->instr_stack_sz;
     313           0 :   return FD_VM_SUCCESS;
     314           0 : }
     315             : 
     316             : int
     317             : fd_vm_syscall_sol_get_return_data( /**/            void *  _vm,
     318             :                                    /**/            ulong   return_data_vaddr,
     319             :                                    /**/            ulong   sz,
     320             :                                    /**/            ulong   program_id_vaddr,
     321             :                                    FD_PARAM_UNUSED ulong   r4,
     322             :                                    FD_PARAM_UNUSED ulong   r5,
     323           0 :                                    /**/            ulong * _ret ) {
     324           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     325             : 
     326             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1465 */
     327           0 :   FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
     328             : 
     329             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1467 */
     330           0 :   fd_txn_return_data_t const * return_data = &vm->instr_ctx->txn_ctx->return_data;
     331             : 
     332             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1468 */
     333           0 :   ulong length = fd_ulong_min( return_data->len, sz );
     334             : 
     335             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1469-L1492 */
     336           0 :   if( FD_LIKELY( length ) ) {
     337             : 
     338             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1470-L1474 */
     339           0 :     FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( length, sizeof(fd_pubkey_t) ) / FD_VM_CPI_BYTES_PER_UNIT );
     340             : 
     341             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1476-L1481 */
     342           0 :     fd_vm_haddr_query_t return_data_query = {
     343           0 :       .vaddr    = return_data_vaddr,
     344           0 :       .align    = FD_VM_ALIGN_RUST_U8,
     345           0 :       .sz       = length,
     346           0 :       .is_slice = 1
     347           0 :     };
     348             : 
     349           0 :     fd_vm_haddr_query_t program_id_query = {
     350           0 :       .vaddr    = program_id_vaddr,
     351           0 :       .align    = FD_VM_ALIGN_RUST_PUBKEY,
     352           0 :       .sz       = sizeof(fd_pubkey_t),
     353           0 :       .is_slice = 0
     354           0 :     };
     355             : 
     356           0 :     fd_vm_haddr_query_t * queries[] = { &return_data_query, &program_id_query };
     357           0 :     FD_VM_TRANSLATE_MUT( vm, queries );
     358             : 
     359             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1490-L1491 */
     360           0 :     memcpy( return_data_query.haddr, return_data->data, length );
     361           0 :     memcpy( program_id_query.haddr, &return_data->program_id, sizeof(fd_pubkey_t) );
     362           0 :   }
     363             : 
     364             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1495 */
     365           0 :   *_ret = return_data->len;
     366           0 :   return FD_VM_SUCCESS;
     367           0 : }
     368             : 
     369             : int
     370             : fd_vm_syscall_sol_set_return_data( /**/            void *  _vm,
     371             :                                    /**/            ulong   src_vaddr,
     372             :                                    /**/            ulong   src_sz,
     373             :                                    FD_PARAM_UNUSED ulong   r3,
     374             :                                    FD_PARAM_UNUSED ulong   r4,
     375             :                                    FD_PARAM_UNUSED ulong   r5,
     376           0 :                                    /**/            ulong * _ret ) {
     377             :   /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L1297 */
     378           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     379             : 
     380             :   /* In the original version of this code, there was an FD_TEST
     381             :      to check if the VM was attached to an instruction context (that
     382             :      would have crashed anyway because of pointer chasing).  If the VM
     383             :      is being run outside the Solana runtime, it should never invoke
     384             :      this syscall in the first place.  So we treat this as a SIGCALL in
     385             :      a non-crashing way for the time being. */
     386           0 :   fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
     387           0 :   if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
     388             : 
     389           0 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSCALL_BASE_COST, src_sz / FD_VM_CPI_BYTES_PER_UNIT ) );
     390             : 
     391             :   /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L1316 */
     392           0 :   if( FD_UNLIKELY( src_sz>FD_VM_RETURN_DATA_MAX ) ) {
     393             :     /* TODO: this is a bit annoying, we may want to unify return codes...
     394             :        - FD_VM_SYSCALL_ERR_RETURN_DATA_TOO_LARGE is Agave's return code,
     395             :          also used for logging */
     396           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_RETURN_DATA_TOO_LARGE );
     397           0 :     return FD_VM_SYSCALL_ERR_RETURN_DATA_TOO_LARGE;
     398           0 :   }
     399             : 
     400             :   /* src_sz == 0 is ok */
     401           0 :   void const * src = FD_VM_MEM_SLICE_HADDR_LD( vm, src_vaddr, FD_VM_ALIGN_RUST_U8, src_sz );
     402             : 
     403             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/programs/bpf_loader/src/syscalls/mod.rs#L1480-L1484 */
     404           0 :   fd_pubkey_t const * program_id = NULL;
     405           0 :   int err = fd_exec_instr_ctx_get_last_program_key( vm->instr_ctx, &program_id );
     406           0 :   if( FD_UNLIKELY( err ) ) {
     407           0 :     FD_VM_ERR_FOR_LOG_INSTR( vm, err );
     408           0 :     return err;
     409           0 :   }
     410             : 
     411           0 :   fd_txn_return_data_t * return_data = &instr_ctx->txn_ctx->return_data;
     412             : 
     413           0 :   return_data->len = src_sz;
     414           0 :   if( FD_LIKELY( src_sz!=0UL ) ) {
     415           0 :     fd_memcpy( return_data->data, src, src_sz );
     416           0 :   }
     417           0 :   return_data->program_id = *program_id;
     418             : 
     419           0 :   *_ret = 0;
     420           0 :   return FD_VM_SUCCESS;
     421           0 : }
     422             : 
     423             : /* Used to query and convey information about the sibling instruction
     424             :    https://github.com/anza-xyz/agave/blob/70089cce5119c9afaeb2986e2ecaa6d4505ec15d/sdk/program/src/instruction.rs#L676
     425             : 
     426             :     */
     427             : struct fd_vm_syscall_processed_sibling_instruction {
     428             :   /* Length of the instruction data */
     429             :   ulong data_len;
     430             :   /* Number of accounts */
     431             :   ulong accounts_len;
     432             : };
     433             : typedef struct fd_vm_syscall_processed_sibling_instruction fd_vm_syscall_processed_sibling_instruction_t;
     434             : 
     435           0 : #define FD_VM_SYSCALL_PROCESSED_SIBLING_INSTRUCTION_SIZE  (16UL)
     436           0 : #define FD_VM_SYSCALL_PROCESSED_SIBLING_INSTRUCTION_ALIGN (8UL )
     437             : 
     438             : /* https://github.com/anza-xyz/agave/blob/70089cce5119c9afaeb2986e2ecaa6d4505ec15d/programs/bpf_loader/src/syscalls/mod.rs#L1402 */
     439             : int
     440             : fd_vm_syscall_sol_get_processed_sibling_instruction(
     441             :     void * _vm,
     442             :     ulong index,
     443             :     ulong result_meta_vaddr,
     444             :     ulong result_program_id_vaddr,
     445             :     ulong result_data_vaddr,
     446             :     ulong result_accounts_vaddr,
     447             :     ulong * _ret
     448           0 : ) {
     449           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     450             : 
     451             :   /* Consume base compute cost
     452             :      https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1513 */
     453           0 :   FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
     454             : 
     455             :   /* Get the current instruction stack height.  This value is 1-indexed
     456             :      (top level instruction has a stack height of 1).
     457             :     https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1517 */
     458           0 :   ulong stack_height = vm->instr_ctx->txn_ctx->instr_stack_sz;
     459             : 
     460             :   /* Reverse iterate through the instruction trace, ignoring anything except instructions on the same level.
     461             :      https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1518-L1522 */
     462           0 :   ulong instruction_trace_length = vm->instr_ctx->txn_ctx->instr_trace_length;
     463           0 :   ulong reverse_index_at_stack_height = 0UL;
     464           0 :   fd_exec_instr_trace_entry_t * found_instruction_context = NULL;
     465           0 :   for( ulong index_in_trace=instruction_trace_length; index_in_trace>0UL; index_in_trace-- ) {
     466             : 
     467             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1524-L1526
     468             :        This error can never happen */
     469             : 
     470             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1527-L1529 */
     471           0 :     fd_exec_instr_trace_entry_t * instruction_context = &vm->instr_ctx->txn_ctx->instr_trace[ index_in_trace-1UL ];
     472           0 :     if( FD_LIKELY( instruction_context->stack_height<stack_height ) ) {
     473           0 :       break;
     474           0 :     }
     475             : 
     476             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1530-L1536 */
     477           0 :     if( FD_UNLIKELY( instruction_context->stack_height==stack_height ) ) {
     478           0 :       if( FD_UNLIKELY( fd_ulong_sat_add( index, 1UL )==reverse_index_at_stack_height ) ) {
     479           0 :         found_instruction_context = instruction_context;
     480           0 :         break;
     481           0 :       }
     482           0 :       reverse_index_at_stack_height = fd_ulong_sat_add( reverse_index_at_stack_height, 1UL );
     483           0 :     }
     484           0 :   }
     485             : 
     486             :   /* If we have found an entry, then copy the instruction into the
     487             :      result addresses.
     488             :      https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1539-L1588
     489             :    */
     490           0 :   if( FD_LIKELY( found_instruction_context != NULL ) ) {
     491           0 :     fd_instr_info_t * instr_info = found_instruction_context->instr_info;
     492             : 
     493           0 :     fd_vm_haddr_query_t result_header_query = {
     494           0 :       .vaddr    = result_meta_vaddr,
     495           0 :       .align    = FD_VM_SYSCALL_PROCESSED_SIBLING_INSTRUCTION_ALIGN,
     496           0 :       .sz       = FD_VM_SYSCALL_PROCESSED_SIBLING_INSTRUCTION_SIZE,
     497           0 :       .is_slice = 0,
     498           0 :     };
     499             : 
     500           0 :     fd_vm_haddr_query_t * queries[] = { &result_header_query };
     501           0 :     FD_VM_TRANSLATE_MUT( vm, queries );
     502             : 
     503           0 :     fd_vm_syscall_processed_sibling_instruction_t * result_header = result_header_query.haddr;
     504             : 
     505             :     /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1546-L1583 */
     506           0 :     if( result_header->data_len==instr_info->data_sz && result_header->accounts_len==instr_info->acct_cnt ) {
     507           0 :       fd_vm_haddr_query_t program_id_query = {
     508           0 :         .vaddr    = result_program_id_vaddr,
     509           0 :         .align    = FD_VM_ALIGN_RUST_PUBKEY,
     510           0 :         .sz       = sizeof(fd_pubkey_t),
     511           0 :         .is_slice = 0,
     512           0 :       };
     513             : 
     514           0 :       fd_vm_haddr_query_t data_query = {
     515           0 :         .vaddr    = result_data_vaddr,
     516           0 :         .align    = FD_VM_ALIGN_RUST_U8,
     517           0 :         .sz       = result_header->data_len,
     518           0 :         .is_slice = 1,
     519           0 :       };
     520             : 
     521           0 :       fd_vm_haddr_query_t accounts_query = {
     522           0 :         .vaddr    = result_accounts_vaddr,
     523           0 :         .align    = FD_VM_RUST_ACCOUNT_META_ALIGN,
     524           0 :         .sz       = fd_ulong_sat_mul( result_header->accounts_len, FD_VM_RUST_ACCOUNT_META_SIZE ),
     525           0 :         .is_slice = 1,
     526           0 :       };
     527             : 
     528           0 :       fd_vm_haddr_query_t * queries[] = { &program_id_query, &data_query, &accounts_query, &result_header_query };
     529           0 :       FD_VM_TRANSLATE_MUT( vm, queries );
     530             : 
     531           0 :       fd_pubkey_t *               program_id = program_id_query.haddr;
     532           0 :       uchar *                     data       = data_query.haddr;
     533           0 :       fd_vm_rust_account_meta_t * accounts   = accounts_query.haddr;
     534             : 
     535             :       /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1561-L1562 */
     536           0 :       fd_pubkey_t const * instr_ctx_program_id = NULL;
     537           0 :       int err = fd_exec_txn_ctx_get_key_of_account_at_index( vm->instr_ctx->txn_ctx,
     538           0 :                                                              instr_info->program_id,
     539           0 :                                                              &instr_ctx_program_id );
     540           0 :       if( FD_UNLIKELY( err ) ) {
     541           0 :         FD_VM_ERR_FOR_LOG_INSTR( vm, err );
     542           0 :         return err;
     543           0 :       }
     544           0 :       fd_memcpy( program_id, instr_ctx_program_id, sizeof(fd_pubkey_t) );
     545             : 
     546             :       /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1563 */
     547           0 :       fd_memcpy( data, instr_info->data, instr_info->data_sz );
     548             : 
     549             :       /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1564-L1581 */
     550           0 :       for( ushort i=0; i<instr_info->acct_cnt; i++ ) {
     551           0 :         fd_pubkey_t const * account_key;
     552           0 :         ushort txn_idx = instr_info->accounts[ i ].index_in_transaction;
     553           0 :         err            = fd_exec_txn_ctx_get_key_of_account_at_index( vm->instr_ctx->txn_ctx, txn_idx, &account_key );
     554           0 :         if( FD_UNLIKELY( err ) ) {
     555           0 :           FD_VM_ERR_FOR_LOG_INSTR( vm, err );
     556           0 :           return err;
     557           0 :         }
     558             : 
     559           0 :         fd_memcpy( accounts[ i ].pubkey, account_key, sizeof(fd_pubkey_t) );
     560           0 :         accounts[ i ].is_signer   = !!(instr_info->accounts[ i ].is_signer );
     561           0 :         accounts[ i ].is_writable = !!(instr_info->accounts[ i ].is_writable );
     562           0 :       }
     563           0 :     } else {
     564             :       /* Copy the actual metadata into the result meta struct
     565             :          https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1584-L1586 */
     566           0 :       result_header->data_len     = instr_info->data_sz;
     567           0 :       result_header->accounts_len = instr_info->acct_cnt;
     568           0 :     }
     569             : 
     570             :     /* Return true as we found a sibling instruction
     571             :        https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1588 */
     572           0 :     *_ret = 1UL;
     573           0 :     return FD_VM_SUCCESS;
     574           0 :   }
     575             : 
     576             :   /* Return false if we didn't find a sibling instruction
     577             :      https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mod.rs#L1590 */
     578           0 :   *_ret = 0UL;
     579           0 :   return FD_VM_SUCCESS;
     580           0 : }
     581             : 
     582             : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/sysvar.rs#L80 */
     583             : int
     584             : fd_vm_syscall_sol_get_epoch_rewards_sysvar( /**/            void *  _vm,
     585             :                                             /**/            ulong   out_vaddr,
     586             :                                             FD_PARAM_UNUSED ulong   r2,
     587             :                                             FD_PARAM_UNUSED ulong   r3,
     588             :                                             FD_PARAM_UNUSED ulong   r4,
     589             :                                             FD_PARAM_UNUSED ulong   r5,
     590           0 :                                             /**/            ulong * _ret ) {
     591           0 :   fd_vm_t * vm = _vm;
     592           0 :   fd_exec_instr_ctx_t const * instr_ctx = vm->instr_ctx;
     593           0 :   if( FD_UNLIKELY( !instr_ctx ) ) return FD_VM_SYSCALL_ERR_OUTSIDE_RUNTIME;
     594             : 
     595           0 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_add( FD_VM_SYSVAR_BASE_COST, sizeof(fd_sysvar_epoch_rewards_t) ) );
     596             : 
     597           0 :   if( FD_UNLIKELY( vm->stricter_abi_and_runtime_constraints && out_vaddr>=FD_VM_MEM_MAP_INPUT_REGION_START ) ) {
     598           0 :     FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_POINTER );
     599           0 :     return FD_VM_ERR_INVAL;
     600           0 :   }
     601             : 
     602           0 :   uchar * out = FD_VM_MEM_HADDR_ST( vm, out_vaddr, FD_VM_ALIGN_RUST_SYSVAR_EPOCH_REWARDS, sizeof(fd_sysvar_epoch_rewards_t) );
     603             : 
     604           0 :   fd_sysvar_epoch_rewards_t epoch_rewards;
     605           0 :   if( FD_UNLIKELY( !fd_sysvar_cache_epoch_rewards_read( instr_ctx->sysvar_cache, &epoch_rewards ) ) ) {
     606           0 :     FD_TXN_ERR_FOR_LOG_INSTR( vm->instr_ctx->txn_ctx, FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR, vm->instr_ctx->txn_ctx->instr_err_idx );
     607           0 :     return FD_VM_ERR_INVAL;
     608           0 :   }
     609           0 :   memcpy( out, &epoch_rewards, sizeof(fd_sysvar_epoch_rewards_t) );
     610           0 :   memset( out+81, 0, 7 ); /* padding */
     611             : 
     612           0 :   *_ret = 0UL;
     613           0 :   return FD_VM_SUCCESS;
     614           0 : }

Generated by: LCOV version 1.14