LCOV - code coverage report
Current view: top level - flamenco/vm - fd_vm_trace.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 182 198 91.9 %
Date: 2024-11-13 11:58:15 Functions: 9 9 100.0 %

          Line data    Source code
       1             : #include "fd_vm_private.h"
       2             : 
       3             : ulong
       4           6 : fd_vm_trace_align( void ) {
       5           6 :   return 8UL;
       6           6 : }
       7             : 
       8             : ulong
       9             : fd_vm_trace_footprint( ulong event_max,
      10          24 :                        ulong event_data_max ) {
      11          24 :   if( FD_UNLIKELY( (event_max>(1UL<<60)) | (event_data_max>(1UL<<60)) ) ) return 0UL; /* FIXME: tune these bounds */
      12          12 :   return fd_ulong_align_up( sizeof(fd_vm_trace_t) + event_max, 8UL );
      13          24 : }
      14             : 
      15             : void *
      16             : fd_vm_trace_new( void * shmem,
      17             :                  ulong  event_max,
      18          18 :                  ulong  event_data_max ) {
      19          18 :   fd_vm_trace_t * trace = (fd_vm_trace_t *)shmem;
      20             : 
      21          18 :   if( FD_UNLIKELY( !trace ) ) {
      22           3 :     FD_LOG_WARNING(( "NULL shmem" ));
      23           3 :     return NULL;
      24           3 :   }
      25             : 
      26          15 :   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          12 :   ulong footprint = fd_vm_trace_footprint( event_max, event_data_max );
      32          12 :   if( FD_UNLIKELY( !footprint ) ) {
      33           6 :     FD_LOG_WARNING(( "bad event_max or event_data_max" ));
      34           6 :     return NULL;
      35           6 :   }
      36             : 
      37           6 :   memset( trace, 0, footprint );
      38             : 
      39           6 :   trace->event_max      = event_max;
      40           6 :   trace->event_data_max = event_data_max;
      41           6 :   trace->event_sz       = 0UL;
      42             : 
      43           6 :   FD_COMPILER_MFENCE();
      44           6 :   FD_VOLATILE( trace->magic ) = FD_VM_TRACE_MAGIC;
      45           6 :   FD_COMPILER_MFENCE();
      46             : 
      47           6 :   return trace;
      48          12 : }
      49             : 
      50             : fd_vm_trace_t *
      51          12 : fd_vm_trace_join( void * _trace ) {
      52          12 :   fd_vm_trace_t * trace = (fd_vm_trace_t *)_trace;
      53             : 
      54          12 :   if( FD_UNLIKELY( !trace ) ) {
      55           3 :     FD_LOG_WARNING(( "NULL _trace" ));
      56           3 :     return NULL;
      57           3 :   }
      58             : 
      59           9 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)_trace, fd_vm_trace_align() ) ) ) {
      60           3 :     FD_LOG_WARNING(( "misaligned _trace" ));
      61           3 :     return NULL;
      62           3 :   }
      63             : 
      64           6 :   if( FD_UNLIKELY( trace->magic!=FD_VM_TRACE_MAGIC ) ) {
      65           3 :     FD_LOG_WARNING(( "bad magic" ));
      66           3 :     return NULL;
      67           3 :   }
      68             : 
      69           3 :   return trace;
      70           6 : }
      71             : 
      72             : void *
      73           9 : fd_vm_trace_leave( fd_vm_trace_t * trace ) {
      74             : 
      75           9 :   if( FD_UNLIKELY( !trace ) ) {
      76           3 :     FD_LOG_WARNING(( "NULL trace" ));
      77           3 :     return NULL;
      78           3 :   }
      79             : 
      80           6 :   return (void *)trace;
      81           9 : }
      82             : 
      83             : void *
      84          15 : fd_vm_trace_delete( void * _trace ) {
      85          15 :   fd_vm_trace_t * trace = (fd_vm_trace_t *)_trace;
      86             : 
      87          15 :   if( FD_UNLIKELY( !trace ) ) {
      88           3 :     FD_LOG_WARNING(( "NULL _trace" ));
      89           3 :     return NULL;
      90           3 :   }
      91             : 
      92          12 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)_trace, fd_vm_trace_align() ) ) ) {
      93           3 :     FD_LOG_WARNING(( "misaligned _trace" ));
      94           3 :     return NULL;
      95           3 :   }
      96             : 
      97           9 :   if( FD_UNLIKELY( trace->magic!=FD_VM_TRACE_MAGIC ) ) {
      98           3 :     FD_LOG_WARNING(( "bad magic" ));
      99           3 :     return NULL;
     100           3 :   }
     101             : 
     102           6 :   FD_COMPILER_MFENCE();
     103           6 :   FD_VOLATILE( trace->magic ) = 0UL;
     104           6 :   FD_COMPILER_MFENCE();
     105             : 
     106           6 :   return (void *)trace;
     107           9 : }
     108             : 
     109             : int
     110             : fd_vm_trace_event_exe( fd_vm_trace_t * trace,
     111             :                        ulong           pc,
     112             :                        ulong           ic,
     113             :                        ulong           cu,
     114             :                        ulong           reg[ FD_VM_REG_CNT ],
     115             :                        ulong const *   text,
     116             :                        ulong           text_cnt,
     117             :                        ulong           ic_correction,
     118          24 :                        ulong           frame_cnt ) {
     119             : 
     120             :   /* Acquire event storage */
     121             : 
     122          24 :   if( FD_UNLIKELY( (!trace) | (!reg) | (!text) | (!text_cnt) ) ) return FD_VM_ERR_INVAL;
     123             : 
     124          21 :   ulong text0     = text[0];
     125          21 :   int   multiword = (text_cnt>1UL) & (fd_sbpf_instr( text0 ).opcode.any.op_class==FD_SBPF_OPCODE_CLASS_LD);
     126             : 
     127          21 :   ulong event_footprint = sizeof(fd_vm_trace_event_exe_t) - fd_ulong_if( !multiword, 8UL, 0UL );
     128             : 
     129          21 :   ulong event_sz  = trace->event_sz;
     130          21 :   ulong event_rem = trace->event_max - event_sz;
     131          21 :   if( FD_UNLIKELY( event_footprint > event_rem ) ) return FD_VM_ERR_FULL;
     132             : 
     133          18 :   fd_vm_trace_event_exe_t * event = (fd_vm_trace_event_exe_t *)((ulong)(trace+1) + event_sz);
     134             : 
     135          18 :   trace->event_sz = event_sz + event_footprint;
     136             : 
     137             :   /* Record the event */
     138             : 
     139          18 :   event->info    = fd_vm_trace_event_info( FD_VM_TRACE_EVENT_TYPE_EXE, multiword );
     140          18 :   event->pc      = pc;
     141          18 :   event->ic      = ic;
     142          18 :   event->cu      = cu;
     143          18 :   memcpy( event->reg, reg, FD_VM_REG_CNT*sizeof(ulong) );
     144          18 :   event->text[0] = text0;
     145          18 :   event->ic_correction = ic_correction;
     146          18 :   event->frame_cnt = frame_cnt;
     147          18 :   if( FD_UNLIKELY( multiword ) ) event->text[1] = text[1];
     148             : 
     149          18 :   return FD_VM_SUCCESS;
     150          21 : }
     151             : 
     152             : int
     153             : fd_vm_trace_event_mem( fd_vm_trace_t * trace,
     154             :                        int             write,
     155             :                        ulong           vaddr,
     156             :                        ulong           sz,
     157          15 :                        void *          data ) {
     158             : 
     159             :   /* Acquire event storage */
     160             : 
     161          15 :   if( FD_UNLIKELY( !trace ) ) return FD_VM_ERR_INVAL;
     162             : 
     163          12 :   int   valid           = (!!data) & (!!sz); /* FIXME: ponder sz==0 handling */
     164          12 :   ulong event_data_sz   = fd_ulong_if( valid, fd_ulong_min( sz, trace->event_data_max ), 0UL );
     165          12 :   ulong event_footprint = fd_ulong_align_up( sizeof(fd_vm_trace_event_mem_t) + event_data_sz, 8UL );
     166             : 
     167          12 :   ulong event_sz  = trace->event_sz;
     168          12 :   ulong event_rem = trace->event_max - event_sz;
     169          12 :   if( FD_UNLIKELY( event_footprint > event_rem ) ) return FD_VM_ERR_FULL;
     170             : 
     171          12 :   fd_vm_trace_event_mem_t * event = (fd_vm_trace_event_mem_t *)((ulong)(trace+1) + event_sz);
     172             : 
     173          12 :   trace->event_sz = event_sz + event_footprint;
     174             : 
     175             :   /* Record the event */
     176             : 
     177          12 :   event->info  = fd_vm_trace_event_info( fd_int_if( write, FD_VM_TRACE_EVENT_TYPE_WRITE, FD_VM_TRACE_EVENT_TYPE_READ ), valid );
     178          12 :   event->vaddr = vaddr;
     179          12 :   event->sz    = sz;
     180          12 :   if( FD_LIKELY( valid ) ) memcpy( event+1, data, event_data_sz );
     181             : 
     182          12 :   return FD_VM_SUCCESS;
     183          12 : }
     184             : 
     185             : #include <stdio.h>
     186             : 
     187             : int
     188             : fd_vm_trace_printf( fd_vm_trace_t const *      trace,
     189           6 :                     fd_sbpf_syscalls_t const * syscalls ) {
     190             : 
     191           6 :   if( FD_UNLIKELY( !trace ) ) {
     192           3 :     FD_LOG_WARNING(( "bad input args" ));
     193           3 :     return FD_VM_ERR_INVAL;
     194           3 :   }
     195             : 
     196           3 :   ulong data_max = fd_vm_trace_event_data_max( trace );
     197             : 
     198           3 :   uchar const * ptr = fd_vm_trace_event   ( trace ); /* Note: this point is 8 byte aligned */
     199           3 :   ulong         rem = fd_vm_trace_event_sz( trace );
     200          30 :   while( rem ) {
     201             : 
     202             :     /* Read the event info */
     203             : 
     204          27 :     if( FD_UNLIKELY( rem<7UL ) ) {
     205           0 :       FD_LOG_WARNING(( "truncated event (info)" ));
     206           0 :       return FD_VM_ERR_IO;
     207           0 :     }
     208             : 
     209          27 :     ulong info = *(ulong *)ptr; /* Note: this point is 8 byte aligned */
     210             : 
     211          27 :     ulong event_footprint;
     212             : 
     213          27 :     int event_type = fd_vm_trace_event_info_type( info );
     214          27 :     switch( event_type ) {
     215             : 
     216          15 :     case FD_VM_TRACE_EVENT_TYPE_EXE: {
     217          15 :       int multiword = fd_vm_trace_event_info_valid( info );
     218          15 :       event_footprint = sizeof( fd_vm_trace_event_exe_t ) - fd_ulong_if( !multiword, 8UL, 0UL );
     219          15 :       if( FD_UNLIKELY( rem < event_footprint ) ) {
     220           0 :         FD_LOG_WARNING(( "truncated event (exe)" ));
     221           0 :         return FD_VM_ERR_IO;
     222           0 :       }
     223             : 
     224          15 :       fd_vm_trace_event_exe_t * event = (fd_vm_trace_event_exe_t *)ptr;
     225             : 
     226          15 :       ulong event_pc = event->pc;
     227             : 
     228             :       /* Pretty print the architectural state before the instruction */
     229             : 
     230          15 :       printf( "%5lu [%016lX, %016lX, %016lX, %016lX, %016lX, %016lX, %016lX, %016lX, %016lX, %016lX, %016lX] %5lu: ",
     231          15 :               event->ic,
     232          15 :               event->reg[ 0], event->reg[ 1], event->reg[ 2], event->reg[ 3],
     233          15 :               event->reg[ 4], event->reg[ 5], event->reg[ 6], event->reg[ 7],
     234          15 :               event->reg[ 8], event->reg[ 9], event->reg[10], event_pc );
     235             : 
     236             :       /* Print the instruction */
     237             : 
     238          15 :       ulong out_len = 0UL;
     239          15 :       char  out[128];
     240          15 :       out[0] = '\0';
     241          15 :       int err = fd_vm_disasm_instr( event->text, fd_ulong_if( !multiword, 1UL, 2UL ), event_pc, syscalls, out, 128UL, &out_len );
     242          15 :       if( FD_UNLIKELY( err ) ) printf( "disasm failed (%i-%s)", err, fd_vm_strerror( err ) );
     243          15 :       else                     printf( "%s", out );
     244             : 
     245             :       /* Print CUs  */
     246          15 :       printf( " %lu\n", event->cu );
     247          15 :       fflush( stdout );
     248          15 :       break;
     249          15 :     }
     250             : 
     251          12 :     case FD_VM_TRACE_EVENT_TYPE_READ:
     252          12 :     case FD_VM_TRACE_EVENT_TYPE_WRITE: {
     253             : 
     254          12 :       event_footprint = sizeof(fd_vm_trace_event_mem_t);
     255          12 :       if( FD_UNLIKELY( rem < event_footprint ) ) {
     256           0 :         FD_LOG_WARNING(( "truncated event (mem)" ));
     257           0 :         return FD_VM_ERR_IO;
     258           0 :       }
     259             : 
     260          12 :       fd_vm_trace_event_mem_t * event = (fd_vm_trace_event_mem_t *)ptr;
     261             : 
     262          12 :       int   valid    = fd_vm_trace_event_info_valid( info );
     263          12 :       ulong event_sz = event->sz;
     264          12 :       ulong data_sz  = fd_ulong_if( valid, fd_ulong_min( event_sz, data_max ), 0UL );
     265             : 
     266          12 :       event_footprint = fd_ulong_align_up( event_footprint + data_sz, 8UL );
     267          12 :       if( FD_UNLIKELY( rem < event_footprint ) ) {
     268           0 :         FD_LOG_WARNING(( "truncated event (data)" ));
     269           0 :         return FD_VM_ERR_IO;
     270           0 :       }
     271             : 
     272          12 :       uchar * data = (uchar *)(event+1);
     273             : 
     274          12 :       ulong prev_ic = 0UL; /* FIXME: there was some commented out code originally to find the ic that previously modified */
     275             : 
     276          12 :       printf( "        %s: vm_addr: 0x%016lX, sz: %8lu, prev_ic: %8lu, data: ",
     277          12 :               event_type==FD_VM_TRACE_EVENT_TYPE_READ ? "R" : "W", event->vaddr, event_sz, prev_ic );
     278             : 
     279          12 :       char buf[ 1024UL + 6UL*2048UL ]; /* 1KiB for overhead + 6 bytes for every byte of event_data_max */
     280             : 
     281          12 :       char * p = fd_cstr_init( buf );
     282          12 :       if( !valid ) p = fd_cstr_append_char( p, '-' );
     283          12 :       else {
     284         492 :         for( ulong data_off=0UL; data_off<data_sz; data_off++ ) {
     285         480 :           if( FD_UNLIKELY( (data_off & 0xfUL)==0UL ) ) p = fd_cstr_append_printf( p, "\n                0x%04lX:", data_off );
     286         480 :           if( FD_UNLIKELY( (data_off & 0xfUL)==8UL ) ) p = fd_cstr_append_char( p, ' ' );
     287         480 :           p = fd_cstr_append_printf( p, " %02X", (uint)data[ data_off ] );
     288         480 :         }
     289          12 :         if( FD_UNLIKELY( data_sz < event_sz ) )
     290           0 :           p = fd_cstr_append_printf( p, "\n                ... omitted %lu bytes ...", event_sz - data_sz );
     291          12 :       }
     292          12 :       p = fd_cstr_append_char( p, '\n' );
     293          12 :       fd_cstr_fini( p );
     294             : 
     295          12 :       printf( "%s", buf );
     296          12 :       break;
     297          12 :     }
     298             : 
     299           0 :     default: {
     300           0 :       FD_LOG_WARNING(( "unexpected event type" ));
     301           0 :       return FD_VM_ERR_IO;
     302          12 :     }
     303             : 
     304          27 :     }
     305             : 
     306          27 :     ptr += event_footprint;
     307          27 :     rem -= event_footprint;
     308          27 :   }
     309             : 
     310           3 :   return FD_VM_SUCCESS;
     311           3 : }

Generated by: LCOV version 1.14