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