LCOV - code coverage report
Current view: top level - flamenco/vm/syscall - fd_vm_syscall_util.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 116 182 63.7 %
Date: 2025-11-06 04:46:49 Functions: 8 13 61.5 %

          Line data    Source code
       1             : #include "fd_vm_syscall.h"
       2             : 
       3             : #include "../../../ballet/base64/fd_base64.h"
       4             : #include "../../../ballet/utf8/fd_utf8.h"
       5             : 
       6             : int
       7             : fd_vm_syscall_abort( /**/            void *  _vm,
       8             :                      FD_PARAM_UNUSED ulong   r1,
       9             :                      FD_PARAM_UNUSED ulong   r2,
      10             :                      FD_PARAM_UNUSED ulong   r3,
      11             :                      FD_PARAM_UNUSED ulong   r4,
      12             :                      FD_PARAM_UNUSED ulong   r5,
      13           0 :                      FD_PARAM_UNUSED ulong * _ret ) {
      14             :   /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/mod.rs#L630 */
      15           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
      16           0 :   FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_ABORT );
      17           0 :   return FD_VM_SYSCALL_ERR_ABORT;
      18           0 : }
      19             : 
      20             : /* FD_TRANSLATE_STRING returns a read only pointer to the host address of
      21             :    a valid utf8 string, or it errors.
      22             : 
      23             :    Analogous of Agave's translate_string_and_do().
      24             :    https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/mod.rs#L601
      25             : 
      26             :    As of v0.2.6, the only two usages are in syscall panic and syscall log. */
      27           9 : #define FD_TRANSLATE_STRING( vm, vaddr, msg_sz ) (__extension__({                          \
      28           9 :     char const * msg = FD_VM_MEM_SLICE_HADDR_LD( vm, vaddr, FD_VM_ALIGN_RUST_U8, msg_sz ); \
      29           9 :     if( FD_UNLIKELY( !fd_utf8_verify( msg, msg_sz ) ) ) {                                  \
      30           0 :       FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_STRING );                   \
      31           0 :       return FD_VM_SYSCALL_ERR_INVALID_STRING;                                             \
      32           0 :     }                                                                                      \
      33           9 :     msg;                                                                                   \
      34           9 : }))
      35             : 
      36             : int
      37             : fd_vm_syscall_sol_panic( /**/            void *  _vm,
      38             :                          /**/            ulong   file_vaddr,
      39             :                          /**/            ulong   file_sz,
      40             :                          /**/            ulong   line,
      41             :                          /**/            ulong   column,
      42             :                          FD_PARAM_UNUSED ulong   r5,
      43           0 :                          FD_PARAM_UNUSED ulong * _ret ) {
      44           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
      45             : 
      46             :   /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/mod.rs#L637
      47             : 
      48             :      Note: this syscall is not used by the Rust SDK, only by the C SDK.
      49             :      Rust transforms `panic!()` into a log, followed by an abort.
      50             :      It's unclear if this syscall actually makes any sense... */
      51           0 :   FD_VM_CU_UPDATE( vm, file_sz );
      52             : 
      53             :   /* Validate string */
      54           0 :   FD_TRANSLATE_STRING( vm, file_vaddr, file_sz );
      55             : 
      56             :   /* Note: we truncate the log, ignoring file, line, column.
      57             :      As mentioned above, it's unclear if anyone is even using this syscall,
      58             :      so dealing with the complexity of Agave's log is a waste of time. */
      59           0 :   (void)line;
      60           0 :   (void)column;
      61             : 
      62           0 :   FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_PANIC );
      63           0 :   return FD_VM_SYSCALL_ERR_PANIC;
      64           0 : }
      65             : 
      66             : int
      67             : fd_vm_syscall_sol_log( /**/            void *  _vm,
      68             :                        /**/            ulong   msg_vaddr,
      69             :                        /**/            ulong   msg_sz,
      70             :                        FD_PARAM_UNUSED ulong   r3,
      71             :                        FD_PARAM_UNUSED ulong   r4,
      72             :                        FD_PARAM_UNUSED ulong   r5,
      73           9 :                        /**/            ulong * _ret ) {
      74           9 :   fd_vm_t * vm = (fd_vm_t *)_vm;
      75             : 
      76             :   /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L5 */
      77             : 
      78           9 :   FD_VM_CU_UPDATE( vm, fd_ulong_max( msg_sz, FD_VM_SYSCALL_BASE_COST ) );
      79             : 
      80             :   /* Note: when msg_sz==0, msg can be undefined.
      81             :      fd_log_collector_program_log() handles it. */
      82           9 :   const char * buf = FD_TRANSLATE_STRING( vm, msg_vaddr, msg_sz );
      83           0 :   fd_log_collector_program_log( vm->instr_ctx, buf, msg_sz );
      84             : 
      85           9 :   *_ret = 0UL;
      86           9 :   return FD_VM_SUCCESS;
      87          18 : }
      88             : 
      89             : int
      90             : fd_vm_syscall_sol_log_64( void *  _vm,
      91             :                           ulong   r1,
      92             :                           ulong   r2,
      93             :                           ulong   r3,
      94             :                           ulong   r4,
      95             :                           ulong   r5,
      96           3 :                           ulong * _ret ) {
      97           3 :   fd_vm_t * vm = (fd_vm_t *)_vm;
      98             : 
      99             :   /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L37 */
     100             : 
     101           3 :   FD_VM_CU_UPDATE( vm, FD_VM_LOG_64_UNITS );
     102             : 
     103             :   /* Max msg_sz: 46 - 15 + 16*5 = 111 < 127 => we can use printf */
     104           0 :   fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
     105           3 :     "Program log: 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx", r1, r2, r3, r4, r5 );
     106             : 
     107           3 :   *_ret = 0UL;
     108           3 :   return FD_VM_SUCCESS;
     109           3 : }
     110             : 
     111             : int
     112             : fd_vm_syscall_sol_log_compute_units( /**/            void *  _vm,
     113             :                                      FD_PARAM_UNUSED ulong   r1,
     114             :                                      FD_PARAM_UNUSED ulong   r2,
     115             :                                      FD_PARAM_UNUSED ulong   r3,
     116             :                                      FD_PARAM_UNUSED ulong   r4,
     117             :                                      FD_PARAM_UNUSED ulong   r5,
     118           0 :                                      /**/            ulong * _ret ) {
     119           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     120             : 
     121             :   /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L60 */
     122             : 
     123           0 :   FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
     124             : 
     125             :   /* Max msg_sz: 40 - 3 + 20 = 57 < 127 => we can use printf */
     126           0 :   fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
     127           0 :     "Program consumption: %lu units remaining", vm->cu );
     128             : 
     129           0 :   *_ret = 0UL;
     130           0 :   return FD_VM_SUCCESS;
     131           0 : }
     132             : 
     133             : int
     134             : fd_vm_syscall_sol_log_pubkey( /**/            void *  _vm,
     135             :                               /**/            ulong   pubkey_vaddr,
     136             :                               FD_PARAM_UNUSED ulong   r2,
     137             :                               FD_PARAM_UNUSED ulong   r3,
     138             :                               FD_PARAM_UNUSED ulong   r4,
     139             :                               FD_PARAM_UNUSED ulong   r5,
     140           0 :                               /**/            ulong * _ret ) {
     141           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     142             : 
     143             :   /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L84 */
     144             : 
     145           0 :   FD_VM_CU_UPDATE( vm, FD_VM_LOG_PUBKEY_UNITS );
     146             : 
     147           0 :   void const * pubkey = FD_VM_MEM_HADDR_LD( vm, pubkey_vaddr, FD_VM_ALIGN_RUST_PUBKEY, sizeof(fd_pubkey_t) );
     148             : 
     149           0 :   char msg[ FD_BASE58_ENCODED_32_SZ ]; ulong msg_sz;
     150           0 :   if( FD_UNLIKELY( fd_base58_encode_32( pubkey, &msg_sz, msg )==NULL ) ) {
     151           0 :     return FD_VM_SYSCALL_ERR_INVALID_STRING;
     152           0 :   }
     153             : 
     154           0 :   fd_log_collector_program_log( vm->instr_ctx, msg, msg_sz );
     155             : 
     156           0 :   *_ret = 0UL;
     157           0 :   return FD_VM_SUCCESS;
     158           0 : }
     159             : 
     160             : int
     161             : fd_vm_syscall_sol_log_data( /**/            void *  _vm,
     162             :                             /**/            ulong   slice_vaddr,
     163             :                             /**/            ulong   slice_cnt,
     164             :                             FD_PARAM_UNUSED ulong   r3,
     165             :                             FD_PARAM_UNUSED ulong   r4,
     166             :                             FD_PARAM_UNUSED ulong   r5,
     167           3 :                             /**/            ulong * _ret ) {
     168           3 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     169             : 
     170             :   /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L109
     171             : 
     172             :      Note: this is implemented following Agave's perverse behavior.
     173             :      We need to loop the slice multiple times to match the exact error,
     174             :      first compute budget, then memory mapping.
     175             :      And finally, we can loop to log. */
     176             : 
     177             :   /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L121 */
     178             : 
     179           3 :   FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
     180             : 
     181             :   /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L123-L128 */
     182             : 
     183           6 :   fd_vm_vec_t const * slice = (fd_vm_vec_t const *)FD_VM_MEM_SLICE_HADDR_LD( vm, slice_vaddr, FD_VM_ALIGN_RUST_SLICE_U8_REF,
     184           6 :     fd_ulong_sat_mul( slice_cnt, sizeof(fd_vm_vec_t) ) );
     185             : 
     186             :   /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L130-L135 */
     187             : 
     188           3 :   FD_VM_CU_UPDATE( vm, fd_ulong_sat_mul( FD_VM_SYSCALL_BASE_COST, slice_cnt ) );
     189             : 
     190             :   /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L136-L141 */
     191             : 
     192          18 :   for( ulong i=0UL; i<slice_cnt; i++ ) {
     193          15 :     FD_VM_CU_UPDATE( vm, slice[i].len );
     194          15 :   }
     195             : 
     196             :   /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L145-L152 */
     197             : 
     198           3 :   ulong msg_sz = 14UL; /* "Program data: ", with space */
     199          18 :   for( ulong i=0UL; i<slice_cnt; i++ ) {
     200          15 :     ulong cur_len = slice[i].len;
     201             :     /* This fails the syscall in case of memory mapping issues */
     202          30 :     FD_VM_MEM_SLICE_HADDR_LD( vm, slice[i].addr, FD_VM_ALIGN_RUST_U8, cur_len );
     203             :     /* Every buffer will be base64 encoded + space separated */
     204           0 :     msg_sz += (slice[i].len + 2)/3*4 + (i > 0);
     205          30 :   }
     206             : 
     207             :   /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L156 */
     208             : 
     209           3 :   char msg[ FD_LOG_COLLECTOR_MAX ];
     210           3 :   ulong bytes_written = fd_log_collector_check_and_truncate( &vm->instr_ctx->txn_ctx->log_collector, msg_sz );
     211           3 :   if( FD_LIKELY( bytes_written < ULONG_MAX ) ) {
     212           3 :     fd_memcpy( msg, "Program data: ", 14 );
     213           3 :     char * buf = msg + 14;
     214             : 
     215          18 :     for( ulong i=0UL; i<slice_cnt; i++ ) {
     216          15 :       ulong cur_len = slice[i].len;
     217          30 :       void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, slice[i].addr, FD_VM_ALIGN_RUST_U8, cur_len );
     218             : 
     219          15 :       if( i ) { *buf = ' '; ++buf; } /* skip first */
     220          30 :       buf += fd_base64_encode( buf, bytes, cur_len );
     221          30 :     }
     222           3 :     FD_TEST( (ulong)(buf-msg)==msg_sz );
     223             : 
     224           3 :     fd_log_collector_msg( vm->instr_ctx, msg, msg_sz );
     225           3 :   }
     226             : 
     227           3 :   *_ret = 0;
     228           3 :   return FD_VM_SUCCESS;
     229           3 : }
     230             : 
     231             : int
     232             : fd_vm_syscall_sol_alloc_free( /**/            void *  _vm,
     233             :                               /**/            ulong   sz,
     234             :                               /**/            ulong   free_vaddr,
     235             :                               FD_PARAM_UNUSED ulong   r3,
     236             :                               FD_PARAM_UNUSED ulong   r4,
     237             :                               FD_PARAM_UNUSED ulong   r5,
     238           0 :                               /**/            ulong * _ret ) {
     239           0 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     240             : 
     241             :   /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L666 */
     242             : 
     243             :   /* This syscall is ... uh ... problematic.  But the community has
     244             :      already recognized this and deprecated it:
     245             : 
     246             :      https://github.com/solana-labs/solana/blob/v1.17.23/sdk/src/feature_set.rs#L846
     247             : 
     248             :      Unfortunately, old code never dies so, practically, this will need
     249             :      to be supported until the heat death of the universe.
     250             : 
     251             :      The most serious issue is that there is nothing to stop VM code
     252             :      making a decision based on the _location_ of the returned
     253             :      allocation.  If different validator implementations use different
     254             :      allocator algorithms, though each implementation would behave
     255             :      functionally correct in isolation, the VM code that uses it would
     256             :      actually break consensus.
     257             : 
     258             :      As a result, every validator needs to use a bit-for-bit identical
     259             :      allocation algorithm.  Fortunately, Solana is just using a basic
     260             :      bump allocator:
     261             : 
     262             :      https://github.com/solana-labs/solana/blob/v1.17.23/program-runtime/src/invoke_context.rs#L122-L148
     263             : 
     264             :      vm->heap_{sz,max} and the below replicate this exactly.
     265             : 
     266             :      Another major issue is that this alloc doesn't always conform
     267             :      typical malloc/free semantics (e.g. C/C++ requires malloc to have
     268             :      an alignment safe for primitive types ... 8 for the Solana machine
     269             :      model).  This is clearly to support backward compat with older VM
     270             :      code (though ideally a malloc syscall should have behaved like ...
     271             :      well ... malloc from day 1).  So the alignment behavior below is a
     272             :      bug-for-bug replication of that:
     273             : 
     274             :      https://github.com/solana-labs/solana/blob/v1.17.23/programs/bpf_loader/src/syscalls/mod.rs#L645-L681
     275             :      https://github.com/solana-labs/solana/blob/v1.17.23/sdk/program/src/entrypoint.rs#L265-L266
     276             : 
     277             :      More generally and already ranted about elsewhere, any code that
     278             :      uses malloc/free style dynamic allocation is inherently broken.  So
     279             :      this syscall should have never existed in the first place ... it
     280             :      just feeds the trolls.  The above is just additional implementation
     281             :      horror because people consistent think malloc/free is much simpler
     282             :      than it actually is.  This is also an example of how quickly
     283             :      mistakes fossilize and become a thorn-in-the-side forever.
     284             : 
     285             :      IMPORTANT SAFETY TIP!  heap_start must be non zero and both
     286             :      heap_start and heap_end should have an alignment of at least 8.
     287             :      This existing runtime policies around heap implicitly satisfy this.
     288             : 
     289             :      IMPORTANT SAFETY TIP!  The specification for Rust's align_offset
     290             :      doesn't seem to provide a strong guarantee that it will return the
     291             :      minimal positive offset necessary to align pointers.  It is
     292             :      possible for a "conforming" Rust compiler to break consensus by
     293             :      using a different align_offset implementation that aligned pointer
     294             :      between different compilations of the Solana validator and the
     295             :      below. */
     296             : 
     297             :   /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L676-L680 */
     298             : 
     299           0 :   ulong align = fd_vm_is_check_align_enabled( vm ) ? 8UL : FD_VM_ALIGN_RUST_U8;
     300             : 
     301             :   /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L681-L683
     302             :      Nothing to do. This section can't error, see:
     303             :      https://doc.rust-lang.org/1.81.0/src/core/alloc/layout.rs.html#70
     304             :      https://doc.rust-lang.org/1.81.0/src/core/alloc/layout.rs.html#100 */
     305             : 
     306             : 
     307             :   /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L684
     308             :      Nothing to do.
     309             :      TODO: unclear if it throw InstructionError::CallDepth
     310             :      https://github.com/anza-xyz/agave/blob/v2.0.8/program-runtime/src/invoke_context.rs#L662 */
     311             : 
     312             :   /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L685-L693 */
     313             : 
     314             :   /* Non-zero free address implies that this is a free() call.  Since
     315             :      this is a bump allocator, free is a no-op. */
     316           0 :   if( FD_UNLIKELY( free_vaddr ) ) {
     317           0 :     *_ret = 0UL;
     318           0 :     return FD_VM_SUCCESS;
     319           0 :   }
     320             : 
     321             : 
     322           0 :   ulong heap_sz    = fd_ulong_align_up( vm->heap_sz, align                           );
     323           0 :   ulong heap_vaddr = fd_ulong_sat_add ( heap_sz,     FD_VM_MEM_MAP_HEAP_REGION_START );
     324           0 :   /**/  heap_sz    = fd_ulong_sat_add ( heap_sz,     sz                              );
     325             : 
     326           0 :   if( FD_UNLIKELY( heap_sz > vm->heap_max ) ) { /* Not enough free memory */
     327           0 :     *_ret = 0UL;
     328           0 :     return FD_VM_SUCCESS;
     329           0 :   }
     330             : 
     331           0 :   vm->heap_sz = heap_sz;
     332             : 
     333           0 :   *_ret = heap_vaddr;
     334           0 :   return FD_VM_SUCCESS;
     335           0 : }
     336             : 
     337             : /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mem_ops.rs#L145 */
     338             : int
     339             : fd_vm_memmove( fd_vm_t * vm,
     340             :                ulong     dst_vaddr,
     341             :                ulong     src_vaddr,
     342          66 :                ulong     sz ) {
     343          66 :   if( FD_UNLIKELY( !sz ) ) {
     344           0 :     return FD_VM_SUCCESS;
     345           0 :   }
     346             : 
     347             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mem_ops.rs#L188-L192 */
     348          66 :   fd_vm_haddr_query_t dst_ref_mut_query = {
     349          66 :     .vaddr    = dst_vaddr,
     350          66 :     .align    = FD_VM_ALIGN_RUST_U8,
     351          66 :     .sz       = sz,
     352          66 :     .is_slice = 1,
     353          66 :   };
     354             : 
     355          66 :   fd_vm_haddr_query_t * queries[] = { &dst_ref_mut_query };
     356          66 :   FD_VM_TRANSLATE_MUT( vm, queries );
     357             : 
     358          45 :   void const * src = FD_VM_MEM_HADDR_LD( vm, src_vaddr, FD_VM_ALIGN_RUST_U8, sz );
     359           0 :   memmove( dst_ref_mut_query.haddr, src, sz );
     360             : 
     361          39 :   return FD_VM_SUCCESS;
     362          84 : }
     363             : 
     364             : /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mem_ops.rs#L41 */
     365             : int
     366             : fd_vm_syscall_sol_memmove( /**/            void *  _vm,
     367             :                            /**/            ulong   dst_vaddr,
     368             :                            /**/            ulong   src_vaddr,
     369             :                            /**/            ulong   sz,
     370             :                            FD_PARAM_UNUSED ulong   r4,
     371             :                            FD_PARAM_UNUSED ulong   r5,
     372          36 :                            /**/            ulong * _ret ) {
     373          36 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     374             : 
     375          36 :   FD_VM_CU_MEM_OP_UPDATE( vm, sz );
     376             : 
     377           0 :   *_ret = 0;
     378             : 
     379             :   /* No overlap check for memmove. */
     380          36 :   return fd_vm_memmove( vm, dst_vaddr, src_vaddr, sz );
     381          36 : }
     382             : 
     383             : /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mem_ops.rs#L18 */
     384             : int
     385             : fd_vm_syscall_sol_memcpy( /**/            void *  _vm,
     386             :                           /**/            ulong   dst_vaddr,
     387             :                           /**/            ulong   src_vaddr,
     388             :                           /**/            ulong   sz,
     389             :                           FD_PARAM_UNUSED ulong   r4,
     390             :                           FD_PARAM_UNUSED ulong   r5,
     391          48 :                           /**/            ulong * _ret ) {
     392          48 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     393             : 
     394          48 :   FD_VM_CU_MEM_OP_UPDATE( vm, sz );
     395             : 
     396           0 :   *_ret = 0;
     397             : 
     398             :   /* Exact same as memmove, except also check overlap.
     399             :      https://github.com/anza-xyz/agave/blob/v2.2.17/programs/bpf_loader/src/syscalls/mem_ops.rs#L45 */
     400          48 :   FD_VM_MEM_CHECK_NON_OVERLAPPING( vm, src_vaddr, sz, dst_vaddr, sz );
     401             : 
     402          30 :   return fd_vm_memmove( vm, dst_vaddr, src_vaddr, sz );
     403          48 : }
     404             : 
     405             : int
     406             : fd_vm_syscall_sol_memcmp( /**/            void *  _vm,
     407             :                           /**/            ulong   m0_vaddr,
     408             :                           /**/            ulong   m1_vaddr,
     409             :                           /**/            ulong   sz,
     410             :                           /**/            ulong   out_vaddr,
     411             :                           FD_PARAM_UNUSED ulong   r5,
     412          15 :                           /**/            ulong * _ret ) {
     413          15 :   *_ret = 0;
     414          15 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     415             : 
     416             :   /* https://github.com/anza-xyz/agave/blob/v2.2.17/programs/bpf_loader/src/syscalls/mem_ops.rs#L84 */
     417             : 
     418          15 :   FD_VM_CU_MEM_OP_UPDATE( vm, sz );
     419             : 
     420             :   /* Note: though this behaves like a normal C-style memcmp, we can't
     421             :      use the compilers / libc memcmp directly because the specification
     422             :      doesn't provide strong enough guarantees about the return value (it
     423             :      only promises the sign). */
     424             : 
     425          30 :   uchar const * m0 = (uchar const *)FD_VM_MEM_SLICE_HADDR_LD( vm, m0_vaddr, FD_VM_ALIGN_RUST_U8, sz );
     426          30 :   uchar const * m1 = (uchar const *)FD_VM_MEM_SLICE_HADDR_LD( vm, m1_vaddr, FD_VM_ALIGN_RUST_U8, sz );
     427             : 
     428             :   /* Silly that this doesn't use r0 to return ... slower, more edge
     429             :      case, different from libc style memcmp, harder to callers to use,
     430             :      etc ... probably too late to do anything about it now ... sigh */
     431             : 
     432             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mem_ops.rs#L121-L125 */
     433           0 :   fd_vm_haddr_query_t cmp_result_ref_mut_query = {
     434          30 :     .vaddr    = out_vaddr,
     435          30 :     .align    = FD_VM_ALIGN_RUST_I32,
     436          30 :     .sz       = 4UL,
     437          30 :     .is_slice = 0,
     438          30 :   };
     439             : 
     440          30 :   fd_vm_haddr_query_t * queries[] = { &cmp_result_ref_mut_query };
     441          30 :   FD_VM_TRANSLATE_MUT( vm, queries );
     442             : 
     443          12 :   int out = 0;
     444         108 :   for( ulong i=0UL; i<sz; i++ ) {
     445         105 :     int i0 = (int)m0[i];
     446         105 :     int i1 = (int)m1[i];
     447         105 :     if( i0!=i1 ) {
     448           9 :       out = i0 - i1;
     449           9 :       break;
     450           9 :     }
     451         105 :   }
     452             : 
     453          12 :   fd_memcpy( cmp_result_ref_mut_query.haddr, &out, 4UL ); /* Sigh ... see note above (and might be unaligned ... double sigh) */
     454             : 
     455          12 :   return FD_VM_SUCCESS;
     456          30 : }
     457             : 
     458             : int
     459             : fd_vm_syscall_sol_memset( /**/            void *  _vm,
     460             :                           /**/            ulong   dst_vaddr,
     461             :                           /**/            ulong   c,
     462             :                           /**/            ulong   sz,
     463             :                           FD_PARAM_UNUSED ulong   r4,
     464             :                           FD_PARAM_UNUSED ulong   r5,
     465          27 :                           /**/            ulong * _ret ) {
     466          27 :   fd_vm_t * vm = (fd_vm_t *)_vm;
     467          27 :   *_ret = 0;
     468             : 
     469             :   /* https://github.com/anza-xyz/agave/blob/v2.2.17/programs/bpf_loader/src/syscalls/mem_ops.rs#L142 */
     470             : 
     471          27 :   FD_VM_CU_MEM_OP_UPDATE( vm, sz );
     472             : 
     473          27 :   if( FD_UNLIKELY( !sz ) ) {
     474           0 :     return FD_VM_SUCCESS;
     475           0 :   }
     476             : 
     477          27 :   int b = (int)(c & 255UL);
     478             : 
     479             :   /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mem_ops.rs#L155-L159 */
     480          27 :   fd_vm_haddr_query_t haddr_query = {
     481          27 :     .vaddr    = dst_vaddr,
     482          27 :     .align    = FD_VM_ALIGN_RUST_U8,
     483          27 :     .sz       = sz,
     484          27 :     .is_slice = 1,
     485          27 :   };
     486             : 
     487          27 :   fd_vm_haddr_query_t * queries[] = { &haddr_query };
     488          27 :   FD_VM_TRANSLATE_MUT( vm, queries );
     489          12 :   fd_memset( haddr_query.haddr, b, sz );
     490             : 
     491          12 :   return FD_VM_SUCCESS;
     492          27 : }

Generated by: LCOV version 1.14