Line data Source code
1 : #include "fd_progcache.h"
2 : #include "../vm/fd_vm.h" /* fd_vm_syscall_register_slot, fd_vm_validate */
3 : #include "../../util/alloc/fd_alloc.h"
4 :
5 : void *
6 : fd_progcache_val_alloc( fd_progcache_rec_t * rec,
7 : fd_progcache_join_t * join,
8 : ulong val_align,
9 10112 : ulong val_footprint ) {
10 10112 : if( rec->data_gaddr ) fd_progcache_val_free( rec, join );
11 10112 : ulong val_max = 0UL;
12 10112 : void * mem = fd_alloc_malloc_at_least( join->alloc, val_align, val_footprint, &val_max );
13 10112 : if( FD_UNLIKELY( !mem ) ) return NULL;
14 10112 : FD_CRIT( val_max<=UINT_MAX, "massive" ); /* unreachable */
15 10112 : rec->data_gaddr = fd_wksp_gaddr_fast( join->wksp, mem );
16 10112 : rec->data_max = (uint)val_max;
17 10112 : return mem;
18 10112 : }
19 :
20 : void
21 : fd_progcache_val_free( fd_progcache_rec_t * rec,
22 29983 : fd_progcache_join_t * join ) {
23 29983 : if( !rec->data_gaddr ) return;
24 10285 : void * mem = fd_wksp_laddr_fast( join->wksp, rec->data_gaddr );
25 :
26 : /* Illegal to call val_free on a spill-allocated buffer */
27 10285 : FD_TEST( !( (ulong)mem >= (ulong)join->shmem->spill.spad &&
28 10285 : (ulong)mem < (ulong)join->shmem->spill.spad+FD_PROGCACHE_SPAD_MAX ) );
29 :
30 10285 : fd_alloc_free( join->alloc, mem );
31 10285 : rec->data_gaddr = 0UL;
32 10285 : rec->data_max = 0U;
33 10285 : rec->rodata_off = 0U;
34 10285 : rec->rodata_sz = 0U;
35 10285 : }
36 :
37 : FD_FN_PURE ulong
38 20302 : fd_progcache_val_footprint( fd_sbpf_elf_info_t const * elf_info ) {
39 20302 : int has_calldests = !fd_sbpf_enable_stricter_elf_headers_enabled( elf_info->sbpf_version );
40 20302 : ulong pc_max = fd_ulong_max( 1UL, elf_info->text_cnt );
41 :
42 20302 : ulong l = FD_LAYOUT_INIT;
43 20303 : if( has_calldests ) {
44 20303 : l = FD_LAYOUT_APPEND( l, fd_sbpf_calldests_align(), fd_sbpf_calldests_footprint( pc_max ) );
45 20303 : }
46 20302 : l = FD_LAYOUT_APPEND( l, 8UL, elf_info->bin_sz );
47 20302 : return FD_LAYOUT_FINI( l, fd_progcache_val_align() );
48 20302 : }
49 :
50 : fd_progcache_rec_t *
51 : fd_progcache_rec_load( fd_progcache_rec_t * rec,
52 : fd_wksp_t * wksp,
53 : fd_sbpf_elf_info_t const * elf_info,
54 : fd_sbpf_loader_config_t const * config,
55 : ulong load_slot,
56 : fd_features_t const * features,
57 : void const * progdata,
58 : ulong progdata_sz,
59 : void * scratch,
60 10285 : ulong scratch_sz ) {
61 :
62 : /* Format object */
63 :
64 10285 : int has_calldests = !fd_sbpf_enable_stricter_elf_headers_enabled( elf_info->sbpf_version );
65 :
66 10285 : void * val = fd_wksp_laddr_fast( wksp, rec->data_gaddr );
67 10285 : FD_SCRATCH_ALLOC_INIT( l, val );
68 10285 : void * calldests_mem = NULL;
69 10285 : if( has_calldests ) {
70 10285 : /* */calldests_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_sbpf_calldests_align(), fd_sbpf_calldests_footprint( fd_ulong_max( 1UL, elf_info->text_cnt ) ) );
71 10285 : }
72 10285 : void * rodata_mem = FD_SCRATCH_ALLOC_APPEND( l, 8UL, elf_info->bin_sz );
73 10285 : FD_SCRATCH_ALLOC_FINI( l, fd_progcache_val_align() );
74 10285 : FD_TEST( _l-(ulong)val == fd_progcache_val_footprint( elf_info ) );
75 :
76 10285 : rec->calldests_off = has_calldests ? (uint)( (ulong)calldests_mem - (ulong)val ) : 0U;
77 10285 : rec->rodata_off = (uint)( (ulong)rodata_mem - (ulong)val );
78 10285 : rec->entry_pc = 0;
79 10285 : rec->rodata_sz = 0;
80 10285 : rec->executable = 0;
81 :
82 10285 : rec->text_cnt = elf_info->text_cnt;
83 10285 : rec->text_off = elf_info->text_off;
84 10285 : rec->text_sz = (uint)elf_info->text_sz;
85 10285 : rec->sbpf_version = (uchar)elf_info->sbpf_version;
86 :
87 : /* Set up sbpf_loader (redirect writes into progcache_rec object) */
88 :
89 10285 : fd_sbpf_program_t prog[1] = {{
90 10285 : .info = *elf_info,
91 10285 : .rodata = rodata_mem,
92 10285 : .text = (ulong *)((ulong)rodata_mem + elf_info->text_off), /* FIXME: WHAT IF MISALIGNED */
93 10285 : .entry_pc = ULONG_MAX
94 10285 : }};
95 10285 : if( has_calldests && elf_info->text_cnt>0UL ) {
96 10283 : prog->calldests_shmem = calldests_mem;
97 10283 : prog->calldests = fd_sbpf_calldests_join( fd_sbpf_calldests_new( calldests_mem, elf_info->text_cnt ) );
98 10283 : }
99 :
100 : /* Loader requires syscall table */
101 :
102 10285 : fd_sbpf_syscalls_t _syscalls[ FD_SBPF_SYSCALLS_SLOT_CNT ];
103 10285 : fd_sbpf_syscalls_t * syscalls = fd_sbpf_syscalls_join( fd_sbpf_syscalls_new( _syscalls ) );
104 10285 : int syscalls_err = fd_vm_syscall_register_slot( syscalls, load_slot, features, /* is_deploy */ 0 );
105 10285 : if( FD_UNLIKELY( syscalls_err!=FD_VM_SUCCESS ) ) FD_LOG_CRIT(( "fd_vm_syscall_register_slot failed" ));
106 :
107 : /* Run ELF loader */
108 :
109 10285 : if( FD_UNLIKELY( 0!=fd_sbpf_program_load( prog, progdata, progdata_sz, syscalls, config, scratch, scratch_sz ) ) ) {
110 107 : return NULL;
111 107 : }
112 :
113 10178 : rec->entry_pc = (uint)prog->entry_pc;
114 10178 : rec->rodata_sz = (uint)prog->rodata_sz;
115 :
116 : /* Run bytecode validator */
117 :
118 10178 : fd_vm_t _vm[1];
119 10178 : fd_vm_t * vm = fd_vm_join( fd_vm_new( _vm ) );
120 10178 : if( FD_UNLIKELY( !vm ) ) FD_LOG_CRIT(( "fd_vm_new failed" ));
121 10178 : vm = fd_vm_init( vm,
122 10178 : NULL, /* OK since unused in `fd_vm_validate()` */
123 10178 : 0UL,
124 10178 : 0UL,
125 10178 : prog->rodata,
126 10178 : prog->rodata_sz,
127 10178 : prog->text,
128 10178 : prog->info.text_cnt,
129 10178 : prog->info.text_off,
130 10178 : prog->info.text_sz,
131 10178 : prog->entry_pc,
132 10178 : prog->calldests,
133 10178 : elf_info->sbpf_version,
134 10178 : syscalls,
135 10178 : NULL,
136 10178 : NULL,
137 10178 : NULL,
138 10178 : 0U,
139 10178 : NULL,
140 10178 : 0,
141 10178 : FD_FEATURE_ACTIVE( load_slot, features, account_data_direct_mapping ),
142 10178 : FD_FEATURE_ACTIVE( load_slot, features, stricter_abi_and_runtime_constraints ),
143 10178 : 0,
144 10178 : 0UL );
145 10178 : if( FD_UNLIKELY( !vm ) ) FD_LOG_CRIT(( "fd_vm_init failed" ));
146 :
147 10178 : if( FD_UNLIKELY( fd_vm_validate( vm )!=FD_VM_SUCCESS ) ) return NULL;
148 :
149 10112 : rec->executable = 1;
150 10112 : return rec;
151 10178 : }
152 :
153 : fd_progcache_rec_t *
154 19696 : fd_progcache_rec_nx( fd_progcache_rec_t * rec ) {
155 19696 : rec->data_gaddr = 0UL;
156 19696 : rec->data_max = 0U;
157 19696 : rec->entry_pc = 0;
158 19696 : rec->text_cnt = 0;
159 19696 : rec->text_off = 0;
160 19696 : rec->text_sz = 0;
161 19696 : rec->rodata_sz = 0;
162 19696 : rec->calldests_off = 0;
163 19696 : rec->rodata_off = 0;
164 19696 : rec->sbpf_version = 0;
165 19696 : rec->executable = 0;
166 19696 : rec->invalidate = 0;
167 19696 : return rec;
168 19696 : }
|