Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
sysio::chain::eosvmoc::executor Class Reference

#include <executor.hpp>

Public Member Functions

 executor (const code_cache_base &cc)
 
 ~executor ()
 
void execute (const code_descriptor &code, memory &mem, apply_context &context)
 

Detailed Description

Definition at line 24 of file executor.hpp.

Constructor & Destructor Documentation

◆ executor()

sysio::chain::eosvmoc::executor::executor ( const code_cache_base & cc)

Definition at line 136 of file executor.cpp.

136 {
137 //if we're the first executor created, go setup the signal handling. For now we'll just leave this attached forever
138 static executor_signal_init the_executor_signal_init;
139
140 uint64_t current_gs;
141 if(arch_prctl(ARCH_GET_GS, &current_gs) || current_gs)
142 wlog("x86_64 GS register is not set as expected. SYS VM OC may not run correctly on this platform");
143
144 struct stat s;
145 FC_ASSERT(fstat(cc.fd(), &s) == 0, "executor failed to get code cache size");
146 code_mapping = (uint8_t*)mmap(nullptr, s.st_size, PROT_EXEC|PROT_READ, MAP_SHARED, cc.fd(), 0);
147 FC_ASSERT(code_mapping != MAP_FAILED, "failed to map code cache in to executor");
148 code_mapping_size = s.st_size;
149 mapping_is_executable = true;
150}
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
int arch_prctl(int code, unsigned long *addr)
#define wlog(FORMAT,...)
Definition logger.hpp:124
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
char * s
Here is the call graph for this function:

◆ ~executor()

sysio::chain::eosvmoc::executor::~executor ( )

Definition at line 265 of file executor.cpp.

265 {
266 arch_prctl(ARCH_SET_GS, nullptr);
267}
Here is the call graph for this function:

Member Function Documentation

◆ execute()

void sysio::chain::eosvmoc::executor::execute ( const code_descriptor & code,
memory & mem,
apply_context & context )

Definition at line 152 of file executor.cpp.

152 {
153 if(mapping_is_executable == false) {
154 mprotect(code_mapping, code_mapping_size, PROT_EXEC|PROT_READ);
155 mapping_is_executable = true;
156 }
157
159 uint64_t max_pages = sysio::chain::wasm_constraints::maximum_linear_memory/sysio::chain::wasm_constraints::wasm_page_size;
160 if(context.control.is_builtin_activated(builtin_protocol_feature_t::configurable_wasm_limits)) {
161 const wasm_config& config = context.control.get_global_properties().wasm_configuration;
162 max_call_depth = config.max_call_depth;
163 max_pages = config.max_pages;
164 }
165 stack.reset(max_call_depth);
166 SYS_ASSERT(code.starting_memory_pages <= (int)max_pages, wasm_execution_error, "Initial memory out of range");
167
168 //prepare initial memory, mutable globals, and table data
169 if(code.starting_memory_pages > 0 ) {
170 uint64_t initial_page_offset = std::min(static_cast<std::size_t>(code.starting_memory_pages), mem.size_of_memory_slice_mapping()/memory::stride - 1);
171 if(initial_page_offset < static_cast<uint64_t>(code.starting_memory_pages)) {
172 mprotect(mem.full_page_memory_base() + initial_page_offset * sysio::chain::wasm_constraints::wasm_page_size,
173 (code.starting_memory_pages - initial_page_offset) * sysio::chain::wasm_constraints::wasm_page_size, PROT_READ | PROT_WRITE);
174 }
175 arch_prctl(ARCH_SET_GS, (unsigned long*)(mem.zero_page_memory_base()+initial_page_offset*memory::stride));
176 memset(mem.full_page_memory_base(), 0, 64u*1024u*code.starting_memory_pages);
177 }
178 else
179 arch_prctl(ARCH_SET_GS, (unsigned long*)mem.zero_page_memory_base());
180
181 void* globals;
182 if(code.initdata_prologue_size > memory::max_prologue_size) {
183 globals_buffer.resize(code.initdata_prologue_size);
184 memcpy(globals_buffer.data(), code_mapping + code.initdata_begin, code.initdata_prologue_size);
185 memcpy(mem.full_page_memory_base() - memory::max_prologue_size,
186 code_mapping + code.initdata_begin + code.initdata_prologue_size - memory::max_prologue_size,
187 code.initdata_size - code.initdata_prologue_size + memory::max_prologue_size);
188 globals = globals_buffer.data() + globals_buffer.size();
189 } else {
190 memcpy(mem.full_page_memory_base() - code.initdata_prologue_size, code_mapping + code.initdata_begin, code.initdata_size);
191 globals = mem.full_page_memory_base();
192 }
193
194 control_block* const cb = mem.get_control_block();
195 cb->magic = signal_sentinel;
196 cb->execution_thread_code_start = (uintptr_t)code_mapping;
197 cb->execution_thread_code_length = code_mapping_size;
198 cb->execution_thread_memory_start = (uintptr_t)mem.start_of_memory_slices();
199 cb->execution_thread_memory_length = mem.size_of_memory_slice_mapping();
200 cb->ctx = &context;
201 executors_exception_ptr = nullptr;
202 cb->eptr = &executors_exception_ptr;
203 cb->current_call_depth_remaining = max_call_depth + 1;
204 cb->current_linear_memory_pages = code.starting_memory_pages;
205 cb->max_linear_memory_pages = max_pages;
206 cb->first_invalid_memory_address = code.starting_memory_pages*64*1024;
207 cb->full_linear_memory_start = (char*)mem.full_page_memory_base();
208 cb->jmp = &executors_sigjmp_buf;
209 cb->bounce_buffers = &executors_bounce_buffers;
210 cb->running_code_base = (uintptr_t)(code_mapping + code.code_begin);
211 cb->is_running = true;
212 cb->globals = globals;
213
214 context.trx_context.transaction_timer.set_expiration_callback([](void* user) {
215 executor* self = (executor*)user;
216 syscall(SYS_mprotect, self->code_mapping, self->code_mapping_size, PROT_NONE);
217 self->mapping_is_executable = false;
218 }, this);
219 context.trx_context.checktime(); //catch any expiration that might have occurred before setting up callback
220
221 auto cleanup = fc::make_scoped_exit([cb, &tt=context.trx_context.transaction_timer, &mem=mem](){
222 cb->is_running = false;
223 cb->bounce_buffers->clear();
224 tt.set_expiration_callback(nullptr, nullptr);
225
226 uint64_t base_pages = mem.size_of_memory_slice_mapping()/memory::stride - 1;
227 if(cb->current_linear_memory_pages > base_pages) {
228 mprotect(mem.full_page_memory_base() + base_pages * sysio::chain::wasm_constraints::wasm_page_size,
229 (cb->current_linear_memory_pages - base_pages) * sysio::chain::wasm_constraints::wasm_page_size, PROT_NONE);
230 }
231 });
232
233 void(*apply_func)(uint64_t, uint64_t, uint64_t) = (void(*)(uint64_t, uint64_t, uint64_t))(cb->running_code_base + code.apply_offset);
234
235 switch(sigsetjmp(*cb->jmp, 0)) {
236 case 0:
237 stack.run([&]{
238 std::visit(overloaded {
239 [&](const no_offset&) {},
240 [&](const intrinsic_ordinal& i) {
241 void(*start_func)() = (void(*)())(*(uintptr_t*)((uintptr_t)mem.zero_page_memory_base() - memory::first_intrinsic_offset - i.ordinal*8));
242 start_func();
243 },
244 [&](const code_offset& offs) {
245 void(*start_func)() = (void(*)())(cb->running_code_base + offs.offset);
246 start_func();
247 }
248 }, code.start);
249 apply_func(context.get_receiver().to_uint64_t(), context.get_action().account.to_uint64_t(), context.get_action().name.to_uint64_t());
250 });
251 break;
252 //case 1: clean sysio_exit
254 context.trx_context.checktime();
255 break;
257 SYS_ASSERT(false, wasm_execution_error, "access violation");
258 break;
259 case SYSVMOC_EXIT_EXCEPTION: //exception
260 std::rethrow_exception(*cb->eptr);
261 break;
262 }
263}
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
Definition exceptions.hpp:7
executor(const code_cache_base &cc)
Definition executor.cpp:136
static constexpr size_t stride
Definition memory.hpp:44
static constexpr uintptr_t first_intrinsic_offset
Definition memory.hpp:49
static constexpr uintptr_t max_prologue_size
Definition memory.hpp:51
scoped_exit< Callback > make_scoped_exit(Callback &&c)
eos_vm_oc_control_block control_block
Definition sys-vm-oc.hpp:21
overloaded(Ts...) -> overloaded< Ts... >
@ self
the connection is to itself
Definition protocol.hpp:48
sysio::client::http::http_context context
Definition main.cpp:200
_W64 unsigned int uintptr_t
Definition stdint.h:165
void reset(std::size_t max_call_depth)
Definition stack.cpp:7
memset(pInfo->slotDescription, ' ', 64)
memcpy((char *) pInfo->slotDescription, s, l)
Here is the call graph for this function:
Here is the caller graph for this function:

The documentation for this class was generated from the following files: