Line data Source code
1 : #include "fd_vm_syscall.h"
2 :
3 : #include "../../../ballet/base64/fd_base64.h"
4 : #include "../../../ballet/utf8/fd_utf8.h"
5 :
6 : int
7 : fd_vm_syscall_abort( /**/ void * _vm,
8 : FD_PARAM_UNUSED ulong r1,
9 : FD_PARAM_UNUSED ulong r2,
10 : FD_PARAM_UNUSED ulong r3,
11 : FD_PARAM_UNUSED ulong r4,
12 : FD_PARAM_UNUSED ulong r5,
13 0 : FD_PARAM_UNUSED ulong * _ret ) {
14 : /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/mod.rs#L630 */
15 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
16 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_ABORT );
17 0 : return FD_VM_SYSCALL_ERR_ABORT;
18 0 : }
19 :
20 : /* FD_TRANSLATE_STRING returns a read only pointer to the host address of
21 : a valid utf8 string, or it errors.
22 :
23 : Analogous of Agave's translate_string_and_do().
24 : https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/mod.rs#L601
25 :
26 : As of v0.2.6, the only two usages are in syscall panic and syscall log. */
27 9 : #define FD_TRANSLATE_STRING( vm, vaddr, msg_sz ) (__extension__({ \
28 9 : char const * msg = FD_VM_MEM_SLICE_HADDR_LD( vm, vaddr, FD_VM_ALIGN_RUST_U8, msg_sz ); \
29 9 : if( FD_UNLIKELY( !fd_utf8_verify( msg, msg_sz ) ) ) { \
30 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_INVALID_STRING ); \
31 0 : return FD_VM_SYSCALL_ERR_INVALID_STRING; \
32 0 : } \
33 9 : msg; \
34 9 : }))
35 :
36 : int
37 : fd_vm_syscall_sol_panic( /**/ void * _vm,
38 : /**/ ulong file_vaddr,
39 : /**/ ulong file_sz,
40 : /**/ ulong line,
41 : /**/ ulong column,
42 : FD_PARAM_UNUSED ulong r5,
43 0 : FD_PARAM_UNUSED ulong * _ret ) {
44 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
45 :
46 : /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/mod.rs#L637
47 :
48 : Note: this syscall is not used by the Rust SDK, only by the C SDK.
49 : Rust transforms `panic!()` into a log, followed by an abort.
50 : It's unclear if this syscall actually makes any sense... */
51 0 : FD_VM_CU_UPDATE( vm, file_sz );
52 :
53 : /* Validate string */
54 0 : FD_TRANSLATE_STRING( vm, file_vaddr, file_sz );
55 :
56 : /* Note: we truncate the log, ignoring file, line, column.
57 : As mentioned above, it's unclear if anyone is even using this syscall,
58 : so dealing with the complexity of Agave's log is a waste of time. */
59 0 : (void)line;
60 0 : (void)column;
61 :
62 0 : FD_VM_ERR_FOR_LOG_SYSCALL( vm, FD_VM_SYSCALL_ERR_PANIC );
63 0 : return FD_VM_SYSCALL_ERR_PANIC;
64 0 : }
65 :
66 : int
67 : fd_vm_syscall_sol_log( /**/ void * _vm,
68 : /**/ ulong msg_vaddr,
69 : /**/ ulong msg_sz,
70 : FD_PARAM_UNUSED ulong r3,
71 : FD_PARAM_UNUSED ulong r4,
72 : FD_PARAM_UNUSED ulong r5,
73 9 : /**/ ulong * _ret ) {
74 9 : fd_vm_t * vm = (fd_vm_t *)_vm;
75 :
76 : /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L5 */
77 :
78 9 : FD_VM_CU_UPDATE( vm, fd_ulong_max( msg_sz, FD_VM_SYSCALL_BASE_COST ) );
79 :
80 : /* Note: when msg_sz==0, msg can be undefined.
81 : fd_log_collector_program_log() handles it. */
82 9 : const char * buf = FD_TRANSLATE_STRING( vm, msg_vaddr, msg_sz );
83 0 : fd_log_collector_program_log( vm->instr_ctx, buf, msg_sz );
84 :
85 9 : *_ret = 0UL;
86 9 : return FD_VM_SUCCESS;
87 18 : }
88 :
89 : int
90 : fd_vm_syscall_sol_log_64( void * _vm,
91 : ulong r1,
92 : ulong r2,
93 : ulong r3,
94 : ulong r4,
95 : ulong r5,
96 3 : ulong * _ret ) {
97 3 : fd_vm_t * vm = (fd_vm_t *)_vm;
98 :
99 : /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L37 */
100 :
101 3 : FD_VM_CU_UPDATE( vm, FD_VM_LOG_64_UNITS );
102 :
103 : /* Max msg_sz: 46 - 15 + 16*5 = 111 < 127 => we can use printf */
104 0 : fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
105 3 : "Program log: 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx", r1, r2, r3, r4, r5 );
106 :
107 3 : *_ret = 0UL;
108 3 : return FD_VM_SUCCESS;
109 3 : }
110 :
111 : int
112 : fd_vm_syscall_sol_log_compute_units( /**/ void * _vm,
113 : FD_PARAM_UNUSED ulong r1,
114 : FD_PARAM_UNUSED ulong r2,
115 : FD_PARAM_UNUSED ulong r3,
116 : FD_PARAM_UNUSED ulong r4,
117 : FD_PARAM_UNUSED ulong r5,
118 0 : /**/ ulong * _ret ) {
119 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
120 :
121 : /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L60 */
122 :
123 0 : FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
124 :
125 : /* Max msg_sz: 40 - 3 + 20 = 57 < 127 => we can use printf */
126 0 : fd_log_collector_printf_dangerous_max_127( vm->instr_ctx,
127 0 : "Program consumption: %lu units remaining", vm->cu );
128 :
129 0 : *_ret = 0UL;
130 0 : return FD_VM_SUCCESS;
131 0 : }
132 :
133 : int
134 : fd_vm_syscall_sol_log_pubkey( /**/ void * _vm,
135 : /**/ ulong pubkey_vaddr,
136 : FD_PARAM_UNUSED ulong r2,
137 : FD_PARAM_UNUSED ulong r3,
138 : FD_PARAM_UNUSED ulong r4,
139 : FD_PARAM_UNUSED ulong r5,
140 0 : /**/ ulong * _ret ) {
141 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
142 :
143 : /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L84 */
144 :
145 0 : FD_VM_CU_UPDATE( vm, FD_VM_LOG_PUBKEY_UNITS );
146 :
147 0 : void const * pubkey = FD_VM_MEM_HADDR_LD( vm, pubkey_vaddr, FD_VM_ALIGN_RUST_PUBKEY, sizeof(fd_pubkey_t) );
148 :
149 0 : char msg[ FD_BASE58_ENCODED_32_SZ ]; ulong msg_sz;
150 0 : if( FD_UNLIKELY( fd_base58_encode_32( pubkey, &msg_sz, msg )==NULL ) ) {
151 0 : return FD_VM_SYSCALL_ERR_INVALID_STRING;
152 0 : }
153 :
154 0 : fd_log_collector_program_log( vm->instr_ctx, msg, msg_sz );
155 :
156 0 : *_ret = 0UL;
157 0 : return FD_VM_SUCCESS;
158 0 : }
159 :
160 : int
161 : fd_vm_syscall_sol_log_data( /**/ void * _vm,
162 : /**/ ulong slice_vaddr,
163 : /**/ ulong slice_cnt,
164 : FD_PARAM_UNUSED ulong r3,
165 : FD_PARAM_UNUSED ulong r4,
166 : FD_PARAM_UNUSED ulong r5,
167 3 : /**/ ulong * _ret ) {
168 3 : fd_vm_t * vm = (fd_vm_t *)_vm;
169 :
170 : /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L109
171 :
172 : Note: this is implemented following Agave's perverse behavior.
173 : We need to loop the slice multiple times to match the exact error,
174 : first compute budget, then memory mapping.
175 : And finally, we can loop to log. */
176 :
177 : /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L121 */
178 :
179 3 : FD_VM_CU_UPDATE( vm, FD_VM_SYSCALL_BASE_COST );
180 :
181 : /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L123-L128 */
182 :
183 6 : fd_vm_vec_t const * slice = (fd_vm_vec_t const *)FD_VM_MEM_SLICE_HADDR_LD( vm, slice_vaddr, FD_VM_ALIGN_RUST_SLICE_U8_REF,
184 6 : fd_ulong_sat_mul( slice_cnt, sizeof(fd_vm_vec_t) ) );
185 :
186 : /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L130-L135 */
187 :
188 3 : FD_VM_CU_UPDATE( vm, fd_ulong_sat_mul( FD_VM_SYSCALL_BASE_COST, slice_cnt ) );
189 :
190 : /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L136-L141 */
191 :
192 18 : for( ulong i=0UL; i<slice_cnt; i++ ) {
193 15 : FD_VM_CU_UPDATE( vm, slice[i].len );
194 15 : }
195 :
196 : /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L145-L152 */
197 :
198 3 : ulong msg_sz = 14UL; /* "Program data: ", with space */
199 18 : for( ulong i=0UL; i<slice_cnt; i++ ) {
200 15 : ulong cur_len = slice[i].len;
201 : /* This fails the syscall in case of memory mapping issues */
202 30 : FD_VM_MEM_SLICE_HADDR_LD( vm, slice[i].addr, FD_VM_ALIGN_RUST_U8, cur_len );
203 : /* Every buffer will be base64 encoded + space separated */
204 0 : msg_sz += (slice[i].len + 2)/3*4 + (i > 0);
205 30 : }
206 :
207 : /* https://github.com/anza-xyz/agave/blob/v2.0.6/programs/bpf_loader/src/syscalls/logging.rs#L156 */
208 :
209 3 : char msg[ FD_LOG_COLLECTOR_MAX ];
210 3 : ulong bytes_written = fd_log_collector_check_and_truncate( &vm->instr_ctx->txn_ctx->log_collector, msg_sz );
211 3 : if( FD_LIKELY( bytes_written < ULONG_MAX ) ) {
212 3 : fd_memcpy( msg, "Program data: ", 14 );
213 3 : char * buf = msg + 14;
214 :
215 18 : for( ulong i=0UL; i<slice_cnt; i++ ) {
216 15 : ulong cur_len = slice[i].len;
217 30 : void const * bytes = FD_VM_MEM_SLICE_HADDR_LD( vm, slice[i].addr, FD_VM_ALIGN_RUST_U8, cur_len );
218 :
219 15 : if( i ) { *buf = ' '; ++buf; } /* skip first */
220 30 : buf += fd_base64_encode( buf, bytes, cur_len );
221 30 : }
222 3 : FD_TEST( (ulong)(buf-msg)==msg_sz );
223 :
224 3 : fd_log_collector_msg( vm->instr_ctx, msg, msg_sz );
225 3 : }
226 :
227 3 : *_ret = 0;
228 3 : return FD_VM_SUCCESS;
229 3 : }
230 :
231 : int
232 : fd_vm_syscall_sol_alloc_free( /**/ void * _vm,
233 : /**/ ulong sz,
234 : /**/ ulong free_vaddr,
235 : FD_PARAM_UNUSED ulong r3,
236 : FD_PARAM_UNUSED ulong r4,
237 : FD_PARAM_UNUSED ulong r5,
238 0 : /**/ ulong * _ret ) {
239 0 : fd_vm_t * vm = (fd_vm_t *)_vm;
240 :
241 : /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L666 */
242 :
243 : /* This syscall is ... uh ... problematic. But the community has
244 : already recognized this and deprecated it:
245 :
246 : https://github.com/solana-labs/solana/blob/v1.17.23/sdk/src/feature_set.rs#L846
247 :
248 : Unfortunately, old code never dies so, practically, this will need
249 : to be supported until the heat death of the universe.
250 :
251 : The most serious issue is that there is nothing to stop VM code
252 : making a decision based on the _location_ of the returned
253 : allocation. If different validator implementations use different
254 : allocator algorithms, though each implementation would behave
255 : functionally correct in isolation, the VM code that uses it would
256 : actually break consensus.
257 :
258 : As a result, every validator needs to use a bit-for-bit identical
259 : allocation algorithm. Fortunately, Solana is just using a basic
260 : bump allocator:
261 :
262 : https://github.com/solana-labs/solana/blob/v1.17.23/program-runtime/src/invoke_context.rs#L122-L148
263 :
264 : vm->heap_{sz,max} and the below replicate this exactly.
265 :
266 : Another major issue is that this alloc doesn't always conform
267 : typical malloc/free semantics (e.g. C/C++ requires malloc to have
268 : an alignment safe for primitive types ... 8 for the Solana machine
269 : model). This is clearly to support backward compat with older VM
270 : code (though ideally a malloc syscall should have behaved like ...
271 : well ... malloc from day 1). So the alignment behavior below is a
272 : bug-for-bug replication of that:
273 :
274 : https://github.com/solana-labs/solana/blob/v1.17.23/programs/bpf_loader/src/syscalls/mod.rs#L645-L681
275 : https://github.com/solana-labs/solana/blob/v1.17.23/sdk/program/src/entrypoint.rs#L265-L266
276 :
277 : More generally and already ranted about elsewhere, any code that
278 : uses malloc/free style dynamic allocation is inherently broken. So
279 : this syscall should have never existed in the first place ... it
280 : just feeds the trolls. The above is just additional implementation
281 : horror because people consistent think malloc/free is much simpler
282 : than it actually is. This is also an example of how quickly
283 : mistakes fossilize and become a thorn-in-the-side forever.
284 :
285 : IMPORTANT SAFETY TIP! heap_start must be non zero and both
286 : heap_start and heap_end should have an alignment of at least 8.
287 : This existing runtime policies around heap implicitly satisfy this.
288 :
289 : IMPORTANT SAFETY TIP! The specification for Rust's align_offset
290 : doesn't seem to provide a strong guarantee that it will return the
291 : minimal positive offset necessary to align pointers. It is
292 : possible for a "conforming" Rust compiler to break consensus by
293 : using a different align_offset implementation that aligned pointer
294 : between different compilations of the Solana validator and the
295 : below. */
296 :
297 : /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L676-L680 */
298 :
299 0 : ulong align = fd_vm_is_check_align_enabled( vm ) ? 8UL : FD_VM_ALIGN_RUST_U8;
300 :
301 : /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L681-L683
302 : Nothing to do. This section can't error, see:
303 : https://doc.rust-lang.org/1.81.0/src/core/alloc/layout.rs.html#70
304 : https://doc.rust-lang.org/1.81.0/src/core/alloc/layout.rs.html#100 */
305 :
306 :
307 : /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L684
308 : Nothing to do.
309 : TODO: unclear if it throw InstructionError::CallDepth
310 : https://github.com/anza-xyz/agave/blob/v2.0.8/program-runtime/src/invoke_context.rs#L662 */
311 :
312 : /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mod.rs#L685-L693 */
313 :
314 : /* Non-zero free address implies that this is a free() call. Since
315 : this is a bump allocator, free is a no-op. */
316 0 : if( FD_UNLIKELY( free_vaddr ) ) {
317 0 : *_ret = 0UL;
318 0 : return FD_VM_SUCCESS;
319 0 : }
320 :
321 :
322 0 : ulong heap_sz = fd_ulong_align_up( vm->heap_sz, align );
323 0 : ulong heap_vaddr = fd_ulong_sat_add ( heap_sz, FD_VM_MEM_MAP_HEAP_REGION_START );
324 0 : /**/ heap_sz = fd_ulong_sat_add ( heap_sz, sz );
325 :
326 0 : if( FD_UNLIKELY( heap_sz > vm->heap_max ) ) { /* Not enough free memory */
327 0 : *_ret = 0UL;
328 0 : return FD_VM_SUCCESS;
329 0 : }
330 :
331 0 : vm->heap_sz = heap_sz;
332 :
333 0 : *_ret = heap_vaddr;
334 0 : return FD_VM_SUCCESS;
335 0 : }
336 :
337 : /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mem_ops.rs#L145 */
338 : int
339 : fd_vm_memmove( fd_vm_t * vm,
340 : ulong dst_vaddr,
341 : ulong src_vaddr,
342 66 : ulong sz ) {
343 66 : if( FD_UNLIKELY( !sz ) ) {
344 0 : return FD_VM_SUCCESS;
345 0 : }
346 :
347 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mem_ops.rs#L188-L192 */
348 66 : fd_vm_haddr_query_t dst_ref_mut_query = {
349 66 : .vaddr = dst_vaddr,
350 66 : .align = FD_VM_ALIGN_RUST_U8,
351 66 : .sz = sz,
352 66 : .is_slice = 1,
353 66 : };
354 :
355 66 : fd_vm_haddr_query_t * queries[] = { &dst_ref_mut_query };
356 66 : FD_VM_TRANSLATE_MUT( vm, queries );
357 :
358 45 : void const * src = FD_VM_MEM_HADDR_LD( vm, src_vaddr, FD_VM_ALIGN_RUST_U8, sz );
359 0 : memmove( dst_ref_mut_query.haddr, src, sz );
360 :
361 39 : return FD_VM_SUCCESS;
362 84 : }
363 :
364 : /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mem_ops.rs#L41 */
365 : int
366 : fd_vm_syscall_sol_memmove( /**/ void * _vm,
367 : /**/ ulong dst_vaddr,
368 : /**/ ulong src_vaddr,
369 : /**/ ulong sz,
370 : FD_PARAM_UNUSED ulong r4,
371 : FD_PARAM_UNUSED ulong r5,
372 36 : /**/ ulong * _ret ) {
373 36 : fd_vm_t * vm = (fd_vm_t *)_vm;
374 :
375 36 : FD_VM_CU_MEM_OP_UPDATE( vm, sz );
376 :
377 0 : *_ret = 0;
378 :
379 : /* No overlap check for memmove. */
380 36 : return fd_vm_memmove( vm, dst_vaddr, src_vaddr, sz );
381 36 : }
382 :
383 : /* https://github.com/anza-xyz/agave/blob/v2.0.8/programs/bpf_loader/src/syscalls/mem_ops.rs#L18 */
384 : int
385 : fd_vm_syscall_sol_memcpy( /**/ void * _vm,
386 : /**/ ulong dst_vaddr,
387 : /**/ ulong src_vaddr,
388 : /**/ ulong sz,
389 : FD_PARAM_UNUSED ulong r4,
390 : FD_PARAM_UNUSED ulong r5,
391 48 : /**/ ulong * _ret ) {
392 48 : fd_vm_t * vm = (fd_vm_t *)_vm;
393 :
394 48 : FD_VM_CU_MEM_OP_UPDATE( vm, sz );
395 :
396 0 : *_ret = 0;
397 :
398 : /* Exact same as memmove, except also check overlap.
399 : https://github.com/anza-xyz/agave/blob/v2.2.17/programs/bpf_loader/src/syscalls/mem_ops.rs#L45 */
400 48 : FD_VM_MEM_CHECK_NON_OVERLAPPING( vm, src_vaddr, sz, dst_vaddr, sz );
401 :
402 30 : return fd_vm_memmove( vm, dst_vaddr, src_vaddr, sz );
403 48 : }
404 :
405 : int
406 : fd_vm_syscall_sol_memcmp( /**/ void * _vm,
407 : /**/ ulong m0_vaddr,
408 : /**/ ulong m1_vaddr,
409 : /**/ ulong sz,
410 : /**/ ulong out_vaddr,
411 : FD_PARAM_UNUSED ulong r5,
412 15 : /**/ ulong * _ret ) {
413 15 : *_ret = 0;
414 15 : fd_vm_t * vm = (fd_vm_t *)_vm;
415 :
416 : /* https://github.com/anza-xyz/agave/blob/v2.2.17/programs/bpf_loader/src/syscalls/mem_ops.rs#L84 */
417 :
418 15 : FD_VM_CU_MEM_OP_UPDATE( vm, sz );
419 :
420 : /* Note: though this behaves like a normal C-style memcmp, we can't
421 : use the compilers / libc memcmp directly because the specification
422 : doesn't provide strong enough guarantees about the return value (it
423 : only promises the sign). */
424 :
425 30 : uchar const * m0 = (uchar const *)FD_VM_MEM_SLICE_HADDR_LD( vm, m0_vaddr, FD_VM_ALIGN_RUST_U8, sz );
426 30 : uchar const * m1 = (uchar const *)FD_VM_MEM_SLICE_HADDR_LD( vm, m1_vaddr, FD_VM_ALIGN_RUST_U8, sz );
427 :
428 : /* Silly that this doesn't use r0 to return ... slower, more edge
429 : case, different from libc style memcmp, harder to callers to use,
430 : etc ... probably too late to do anything about it now ... sigh */
431 :
432 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mem_ops.rs#L121-L125 */
433 0 : fd_vm_haddr_query_t cmp_result_ref_mut_query = {
434 30 : .vaddr = out_vaddr,
435 30 : .align = FD_VM_ALIGN_RUST_I32,
436 30 : .sz = 4UL,
437 30 : .is_slice = 0,
438 30 : };
439 :
440 30 : fd_vm_haddr_query_t * queries[] = { &cmp_result_ref_mut_query };
441 30 : FD_VM_TRANSLATE_MUT( vm, queries );
442 :
443 12 : int out = 0;
444 108 : for( ulong i=0UL; i<sz; i++ ) {
445 105 : int i0 = (int)m0[i];
446 105 : int i1 = (int)m1[i];
447 105 : if( i0!=i1 ) {
448 9 : out = i0 - i1;
449 9 : break;
450 9 : }
451 105 : }
452 :
453 12 : fd_memcpy( cmp_result_ref_mut_query.haddr, &out, 4UL ); /* Sigh ... see note above (and might be unaligned ... double sigh) */
454 :
455 12 : return FD_VM_SUCCESS;
456 30 : }
457 :
458 : int
459 : fd_vm_syscall_sol_memset( /**/ void * _vm,
460 : /**/ ulong dst_vaddr,
461 : /**/ ulong c,
462 : /**/ ulong sz,
463 : FD_PARAM_UNUSED ulong r4,
464 : FD_PARAM_UNUSED ulong r5,
465 27 : /**/ ulong * _ret ) {
466 27 : fd_vm_t * vm = (fd_vm_t *)_vm;
467 27 : *_ret = 0;
468 :
469 : /* https://github.com/anza-xyz/agave/blob/v2.2.17/programs/bpf_loader/src/syscalls/mem_ops.rs#L142 */
470 :
471 27 : FD_VM_CU_MEM_OP_UPDATE( vm, sz );
472 :
473 27 : if( FD_UNLIKELY( !sz ) ) {
474 0 : return FD_VM_SUCCESS;
475 0 : }
476 :
477 27 : int b = (int)(c & 255UL);
478 :
479 : /* https://github.com/anza-xyz/agave/blob/v2.3.1/programs/bpf_loader/src/syscalls/mem_ops.rs#L155-L159 */
480 27 : fd_vm_haddr_query_t haddr_query = {
481 27 : .vaddr = dst_vaddr,
482 27 : .align = FD_VM_ALIGN_RUST_U8,
483 27 : .sz = sz,
484 27 : .is_slice = 1,
485 27 : };
486 :
487 27 : fd_vm_haddr_query_t * queries[] = { &haddr_query };
488 27 : FD_VM_TRANSLATE_MUT( vm, queries );
489 12 : fd_memset( haddr_query.haddr, b, sz );
490 :
491 12 : return FD_VM_SUCCESS;
492 27 : }
|