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