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 : }
|