LCOV - code coverage report
Current view: top level - flamenco/vm - fd_vm_trace.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 125 131 95.4 %
Date: 2026-10-16 04:29:28 Functions: 8 8 100.0 %

          Line data    Source code
       1             : #include "fd_vm.h"
       2             : #include "../../ballet/sbpf/fd_sbpf_instr.h"
       3             : #include "../../ballet/sbpf/fd_sbpf_opcodes.h"
       4             : 
       5             : ulong
       6          30 : fd_vm_trace_align( void ) {
       7          30 :   return 8UL;
       8          30 : }
       9             : 
      10             : ulong
      11          12 : fd_vm_trace_footprint( ulong event_max ) {
      12          12 :   if( FD_UNLIKELY( event_max>(1UL<<60) ) ) return 0UL; /* FIXME: tune these bounds */
      13           6 :   return fd_ulong_align_up( sizeof(fd_vm_trace_t) + event_max, 8UL );
      14          12 : }
      15             : 
      16             : void *
      17             : fd_vm_trace_new( void * shmem,
      18          12 :                  ulong  event_max ) {
      19          12 :   fd_vm_trace_t * trace = (fd_vm_trace_t *)shmem;
      20             : 
      21          12 :   if( FD_UNLIKELY( !trace ) ) {
      22           3 :     FD_LOG_WARNING(( "NULL shmem" ));
      23           3 :     return NULL;
      24           3 :   }
      25             : 
      26           9 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_vm_trace_align() ) ) ) {
      27           3 :     FD_LOG_WARNING(( "misaligned shmem" ));
      28           3 :     return NULL;
      29           3 :   }
      30             : 
      31           6 :   ulong footprint = fd_vm_trace_footprint( event_max );
      32           6 :   if( FD_UNLIKELY( !footprint ) ) {
      33           3 :     FD_LOG_WARNING(( "bad event_max" ));
      34           3 :     return NULL;
      35           3 :   }
      36             : 
      37           3 :   memset( trace, 0, footprint );
      38             : 
      39           3 :   trace->event_max = event_max;
      40           3 :   trace->event_sz  = 0UL;
      41             : 
      42           3 :   FD_COMPILER_MFENCE();
      43           3 :   FD_VOLATILE( trace->magic ) = FD_VM_TRACE_MAGIC;
      44           3 :   FD_COMPILER_MFENCE();
      45             : 
      46           3 :   return trace;
      47           6 : }
      48             : 
      49             : fd_vm_trace_t *
      50          12 : fd_vm_trace_join( void * _trace ) {
      51          12 :   fd_vm_trace_t * trace = (fd_vm_trace_t *)_trace;
      52             : 
      53          12 :   if( FD_UNLIKELY( !trace ) ) {
      54           3 :     FD_LOG_WARNING(( "NULL _trace" ));
      55           3 :     return NULL;
      56           3 :   }
      57             : 
      58           9 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)_trace, fd_vm_trace_align() ) ) ) {
      59           3 :     FD_LOG_WARNING(( "misaligned _trace" ));
      60           3 :     return NULL;
      61           3 :   }
      62             : 
      63           6 :   if( FD_UNLIKELY( trace->magic!=FD_VM_TRACE_MAGIC ) ) {
      64           3 :     FD_LOG_WARNING(( "bad magic" ));
      65           3 :     return NULL;
      66           3 :   }
      67             : 
      68           3 :   return trace;
      69           6 : }
      70             : 
      71             : void *
      72           6 : fd_vm_trace_leave( fd_vm_trace_t * trace ) {
      73             : 
      74           6 :   if( FD_UNLIKELY( !trace ) ) {
      75           3 :     FD_LOG_WARNING(( "NULL trace" ));
      76           3 :     return NULL;
      77           3 :   }
      78             : 
      79           3 :   return (void *)trace;
      80           6 : }
      81             : 
      82             : void *
      83          12 : fd_vm_trace_delete( void * _trace ) {
      84          12 :   fd_vm_trace_t * trace = (fd_vm_trace_t *)_trace;
      85             : 
      86          12 :   if( FD_UNLIKELY( !trace ) ) {
      87           3 :     FD_LOG_WARNING(( "NULL _trace" ));
      88           3 :     return NULL;
      89           3 :   }
      90             : 
      91           9 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)_trace, fd_vm_trace_align() ) ) ) {
      92           3 :     FD_LOG_WARNING(( "misaligned _trace" ));
      93           3 :     return NULL;
      94           3 :   }
      95             : 
      96           6 :   if( FD_UNLIKELY( trace->magic!=FD_VM_TRACE_MAGIC ) ) {
      97           3 :     FD_LOG_WARNING(( "bad magic" ));
      98           3 :     return NULL;
      99           3 :   }
     100             : 
     101           3 :   FD_COMPILER_MFENCE();
     102           3 :   FD_VOLATILE( trace->magic ) = 0UL;
     103           3 :   FD_COMPILER_MFENCE();
     104             : 
     105           3 :   return (void *)trace;
     106           6 : }
     107             : 
     108             : int
     109             : fd_vm_trace_event_exe( fd_vm_trace_t * trace,
     110             :                        ulong           pc,
     111             :                        ulong           ic,
     112             :                        ulong           cu,
     113             :                        ulong           reg[ FD_VM_REG_CNT ],
     114             :                        ulong const *   text,
     115             :                        ulong           text_cnt,
     116             :                        ulong           ic_correction,
     117          27 :                        ulong           frame_cnt ) {
     118             : 
     119             :   /* Acquire event storage */
     120             : 
     121          27 :   if( FD_UNLIKELY( (!trace) | (!reg) | (!text) | (!text_cnt) ) ) return FD_VM_ERR_INVAL;
     122             : 
     123          24 :   ulong text0     = text[0];
     124          24 :   int   multiword = (text_cnt>1UL) & (fd_sbpf_instr( text0 ).opcode.any.op_class==FD_SBPF_OPCODE_CLASS_LD);
     125             : 
     126          24 :   ulong event_footprint = sizeof(fd_vm_trace_event_exe_t) - fd_ulong_if( !multiword, 8UL, 0UL );
     127             : 
     128          24 :   ulong event_sz  = trace->event_sz;
     129          24 :   ulong event_rem = trace->event_max - event_sz;
     130          24 :   if( FD_UNLIKELY( event_footprint > event_rem ) ) return FD_VM_ERR_FULL;
     131             : 
     132          21 :   fd_vm_trace_event_exe_t * event = (fd_vm_trace_event_exe_t *)((ulong)(trace+1) + event_sz);
     133             : 
     134          21 :   trace->event_sz = event_sz + event_footprint;
     135             : 
     136             :   /* Record the event */
     137             : 
     138          21 :   event->multiword = (ulong)multiword;
     139          21 :   event->pc        = pc;
     140          21 :   event->ic        = ic;
     141          21 :   event->cu        = cu;
     142          21 :   memcpy( event->reg, reg, FD_VM_REG_CNT*sizeof(ulong) );
     143          21 :   event->text[0] = text0;
     144          21 :   event->ic_correction = ic_correction;
     145          21 :   event->frame_cnt = frame_cnt;
     146          21 :   if( FD_UNLIKELY( multiword ) ) event->text[1] = text[1];
     147             : 
     148          21 :   return FD_VM_SUCCESS;
     149          24 : }
     150             : 
     151             : 
     152             : 
     153             : #include <stdio.h>
     154             : 
     155             : int
     156             : fd_vm_trace_printf( fd_vm_trace_t const *      trace,
     157           6 :                     fd_sbpf_syscalls_t const * syscalls ) {
     158             : 
     159           6 :   if( FD_UNLIKELY( !trace ) ) {
     160           3 :     FD_LOG_WARNING(( "bad input args" ));
     161           3 :     return FD_VM_ERR_INVAL;
     162           3 :   }
     163             : 
     164           3 :   uchar const * ptr = fd_vm_trace_event   ( trace ); /* Note: this point is 8 byte aligned */
     165           3 :   ulong         rem = fd_vm_trace_event_sz( trace );
     166          24 :   while( rem ) {
     167             : 
     168          21 :     if( FD_UNLIKELY( rem < sizeof( fd_vm_trace_event_exe_t ) - 8UL ) ) {
     169           0 :       FD_LOG_WARNING(( "truncated event (exe)" ));
     170           0 :       return FD_VM_ERR_IO;
     171           0 :     }
     172             : 
     173          21 :     fd_vm_trace_event_exe_t const * event = (fd_vm_trace_event_exe_t const *)ptr;
     174             : 
     175          21 :     int   multiword       = (int)event->multiword;
     176          21 :     ulong event_footprint = sizeof( fd_vm_trace_event_exe_t ) - fd_ulong_if( !multiword, 8UL, 0UL );
     177          21 :     if( FD_UNLIKELY( rem < event_footprint ) ) {
     178           0 :       FD_LOG_WARNING(( "truncated event (exe)" ));
     179           0 :       return FD_VM_ERR_IO;
     180           0 :     }
     181             : 
     182          21 :     ulong event_pc = event->pc;
     183             : 
     184             :     /* Pretty print the architectural state before the instruction */
     185             : 
     186          21 :     printf( "%5lu [%016lX, %016lX, %016lX, %016lX, %016lX, %016lX, %016lX, %016lX, %016lX, %016lX, %016lX] %5lu: ",
     187          21 :             event->ic,
     188          21 :             event->reg[ 0], event->reg[ 1], event->reg[ 2], event->reg[ 3],
     189          21 :             event->reg[ 4], event->reg[ 5], event->reg[ 6], event->reg[ 7],
     190          21 :             event->reg[ 8], event->reg[ 9], event->reg[10], event_pc );
     191             : 
     192             :     /* Print the instruction */
     193             : 
     194          21 :     ulong out_len = 0UL;
     195          21 :     char  out[128];
     196          21 :     out[0] = '\0';
     197          21 :     int err = fd_vm_disasm_instr( event->text, fd_ulong_if( !multiword, 1UL, 2UL ), event_pc, syscalls, out, 128UL, &out_len );
     198          21 :     if( FD_UNLIKELY( err ) ) printf( "disasm failed (%i-%s)", err, fd_vm_strerror( err ) );
     199          21 :     else                     printf( "%s", out );
     200             : 
     201             :     /* Print CUs  */
     202          21 :     printf( " %lu\n", event->cu );
     203          21 :     fflush( stdout );
     204             : 
     205          21 :     ptr += event_footprint;
     206          21 :     rem -= event_footprint;
     207          21 :   }
     208             : 
     209           3 :   return FD_VM_SUCCESS;
     210           3 : }

Generated by: LCOV version 1.14