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

Namespaces

namespace  detail
 
namespace  LLVMJIT
 

Classes

class  code_cache_async
 
class  code_cache_base
 
struct  code_cache_header
 
class  code_cache_sync
 
struct  code_compilation_result_message
 
struct  code_descriptor
 
struct  code_offset
 
struct  code_tuple
 
struct  compilation_result_toofull
 
struct  compilation_result_unknownfailure
 
struct  compile_monitor
 
struct  compile_monitor_session
 
struct  compile_monitor_trampoline
 
struct  compile_wasm_message
 
struct  config
 
struct  evict_wasms_message
 
struct  execution_stack
 
class  executor
 
struct  executor_signal_init
 
struct  initalize_response_message
 
struct  initialize_message
 
struct  instantiated_code
 
struct  intrinsic
 
struct  intrinsic_entry
 
struct  intrinsic_ordinal
 
class  memory
 
struct  no_offset
 
struct  wasm_compilation_result_message
 
class  wrapped_fd
 

Typedefs

using allocator_t = bip::rbtree_best_fit<bip::null_mutex_family, bip::offset_ptr<void>, alignof(std::max_align_t)>
 
using intrinsic_map_t = std::map<std::string, intrinsic_entry>
 
using wasm_compilation_result
 
using eosvmoc_message
 
using control_block = eos_vm_oc_control_block
 
using eosvmoc_optional_offset_or_import_t = std::variant<no_offset, code_offset, intrinsic_ordinal>
 

Enumerations

enum  eosvmoc_exitcode : int { SYSVMOC_EXIT_CLEAN_EXIT = 1 , SYSVMOC_EXIT_CHECKTIME_FAIL , SYSVMOC_EXIT_SEGV , SYSVMOC_EXIT_EXCEPTION }
 

Functions

wrapped_fd get_connection_to_compile_monitor (int cache_fd)
 
void run_compile_trampoline (int fd)
 
const intrinsic_map_tget_intrinsic_map ()
 
constexpr auto get_intrinsic_table ()
 
constexpr std::size_t find_intrinsic_index (std::string_view hf)
 
constexpr std::size_t intrinsic_table_size ()
 
std::tuple< bool, eosvmoc_message, std::vector< wrapped_fd > > read_message_with_fds (boost::asio::local::datagram_protocol::socket &s)
 
std::tuple< bool, eosvmoc_message, std::vector< wrapped_fd > > read_message_with_fds (int fd)
 
bool write_message_with_fds (boost::asio::local::datagram_protocol::socket &s, const eosvmoc_message &message, const std::vector< wrapped_fd > &fds=std::vector< wrapped_fd >())
 
bool write_message_with_fds (int fd_to_send_to, const eosvmoc_message &message, const std::vector< wrapped_fd > &fds=std::vector< wrapped_fd >())
 
template<typename T >
wrapped_fd memfd_for_bytearray (const T &bytes)
 
std::vector< uint8_tvector_for_memfd (const wrapped_fd &memfd)
 
void eosvmoc_switch_stack (void *stack, void(*fn)(void *), void *data)
 
struct sysio::chain::eosvmoc::code_cache_header __attribute__ ((packed))
 
void launch_compile_monitor (int nodeop_fd)
 
int __real_main (int, char *[])
 
int __wrap_main (int argc, char *argv[])
 
void run_compile (wrapped_fd &&response_sock, wrapped_fd &&wasm_code) noexcept
 
 DEFINE_SYSVMOC_TRAP_INTRINSIC (eosvmoc_internal, depth_assert)
 
 DEFINE_SYSVMOC_TRAP_INTRINSIC (eosvmoc_internal, div0_or_overflow)
 
 DEFINE_SYSVMOC_TRAP_INTRINSIC (eosvmoc_internal, indirect_call_mismatch)
 
 DEFINE_SYSVMOC_TRAP_INTRINSIC (eosvmoc_internal, indirect_call_oob)
 
 DEFINE_SYSVMOC_TRAP_INTRINSIC (eosvmoc_internal, unreachable)
 

Typedef Documentation

◆ allocator_t

using sysio::chain::eosvmoc::allocator_t = bip::rbtree_best_fit<bip::null_mutex_family, bip::offset_ptr<void>, alignof(std::max_align_t)>

Definition at line 35 of file code_cache.hpp.

◆ control_block

◆ eosvmoc_message

Initial value:
std::variant<initialize_message,
initalize_response_message,
compile_wasm_message,
evict_wasms_message,
code_compilation_result_message,
wasm_compilation_result_message>

Definition at line 54 of file ipc_protocol.hpp.

◆ eosvmoc_optional_offset_or_import_t

◆ intrinsic_map_t

Definition at line 24 of file intrinsic.hpp.

◆ wasm_compilation_result

Initial value:
std::variant<code_descriptor,
compilation_result_unknownfailure,
compilation_result_toofull>

Definition at line 44 of file ipc_protocol.hpp.

Enumeration Type Documentation

◆ eosvmoc_exitcode

Enumerator
SYSVMOC_EXIT_CLEAN_EXIT 
SYSVMOC_EXIT_CHECKTIME_FAIL 
SYSVMOC_EXIT_SEGV 
SYSVMOC_EXIT_EXCEPTION 

Definition at line 46 of file sys-vm-oc.hpp.

Function Documentation

◆ __attribute__()

struct sysio::chain::eosvmoc::code_cache_header sysio::chain::eosvmoc::__attribute__ ( (packed) )

◆ __real_main()

int sysio::chain::eosvmoc::__real_main ( int ,
char * [] )

◆ __wrap_main()

int sysio::chain::eosvmoc::__wrap_main ( int argc,
char * argv[] )

Definition at line 299 of file compile_monitor.cpp.

299 {
300
301
302 the_compile_monitor_trampoline.start();
303 return __real_main(argc, argv);
304}
int __real_main(int, char *[])
char ** argv
Here is the call graph for this function:
Here is the caller graph for this function:

◆ DEFINE_SYSVMOC_TRAP_INTRINSIC() [1/5]

sysio::chain::eosvmoc::DEFINE_SYSVMOC_TRAP_INTRINSIC ( eosvmoc_internal ,
depth_assert  )

Definition at line 102 of file executor.cpp.

102 {
103 throw_internal_exception("Exceeded call depth maximum");
104}

◆ DEFINE_SYSVMOC_TRAP_INTRINSIC() [2/5]

sysio::chain::eosvmoc::DEFINE_SYSVMOC_TRAP_INTRINSIC ( eosvmoc_internal ,
div0_or_overflow  )

Definition at line 106 of file executor.cpp.

106 {
107 throw_internal_exception("Division by 0 or integer overflow trapped");
108}

◆ DEFINE_SYSVMOC_TRAP_INTRINSIC() [3/5]

sysio::chain::eosvmoc::DEFINE_SYSVMOC_TRAP_INTRINSIC ( eosvmoc_internal ,
indirect_call_mismatch  )

Definition at line 110 of file executor.cpp.

110 {
111 throw_internal_exception("Indirect call function type mismatch");
112}

◆ DEFINE_SYSVMOC_TRAP_INTRINSIC() [4/5]

sysio::chain::eosvmoc::DEFINE_SYSVMOC_TRAP_INTRINSIC ( eosvmoc_internal ,
indirect_call_oob  )

Definition at line 114 of file executor.cpp.

114 {
115 throw_internal_exception("Indirect call index out of bounds");
116}

◆ DEFINE_SYSVMOC_TRAP_INTRINSIC() [5/5]

sysio::chain::eosvmoc::DEFINE_SYSVMOC_TRAP_INTRINSIC ( eosvmoc_internal ,
unreachable  )

Definition at line 118 of file executor.cpp.

118 {
119 throw_internal_exception("Unreachable reached");
120}

◆ eosvmoc_switch_stack()

void sysio::chain::eosvmoc::eosvmoc_switch_stack ( void * stack,
void(* fn )(void *),
void * data )
Here is the caller graph for this function:

◆ find_intrinsic_index()

std::size_t sysio::chain::eosvmoc::find_intrinsic_index ( std::string_view hf)
inlineconstexpr

Definition at line 273 of file intrinsic_mapping.hpp.

273 {
274 constexpr auto hosts = get_intrinsic_table();
275 for ( std::size_t i = 0; i < hosts.size(); ++i )
276 if ( hosts[i] == hf )
277 return i;
278 return std::numeric_limits<std::size_t>::max();
279}
constexpr auto get_intrinsic_table()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_connection_to_compile_monitor()

wrapped_fd sysio::chain::eosvmoc::get_connection_to_compile_monitor ( int cache_fd)

Definition at line 306 of file compile_monitor.cpp.

306 {
307 FC_ASSERT(the_compile_monitor_trampoline.compile_manager_pid >= 0, "SYS VM oop connection doesn't look active");
308
309 int socks[2]; //0: our socket to compile_manager_session, 1: socket we'll give to compile_maanger_session
310 socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, socks);
311 wrapped_fd socket_to_monitor_session(socks[0]);
312 wrapped_fd socket_to_hand_to_monitor_session(socks[1]);
313
314 //we don't own cache_fd, so try to be extra careful not to accidentally close it: don't stick it in a wrapped_fd
315 // to hand off to write_message_with_fds even temporarily. make a copy of it.
316 int dup_of_cache_fd = dup(cache_fd);
317 FC_ASSERT(dup_of_cache_fd != -1, "failed to dup cache_fd");
318 wrapped_fd dup_cache_fd(dup_of_cache_fd);
319
320 std::vector<wrapped_fd> fds_to_pass;
321 fds_to_pass.emplace_back(std::move(socket_to_hand_to_monitor_session));
322 fds_to_pass.emplace_back(std::move(dup_cache_fd));
323 write_message_with_fds(the_compile_monitor_trampoline.compile_manager_fd, initialize_message(), fds_to_pass);
324
325 auto [success, message, fds] = read_message_with_fds(the_compile_monitor_trampoline.compile_manager_fd);
326 SYS_ASSERT(success, misc_exception, "failed to read response from monitor process");
327 SYS_ASSERT(std::holds_alternative<initalize_response_message>(message), misc_exception, "unexpected response from monitor process");
328 SYS_ASSERT(!std::get<initalize_response_message>(message).error_message, misc_exception, "Error message from monitor process: ${e}", ("e", *std::get<initalize_response_message>(message).error_message));
329 return socket_to_monitor_session;
330}
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
Definition exceptions.hpp:7
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
bool write_message_with_fds(boost::asio::local::datagram_protocol::socket &s, const eosvmoc_message &message, const std::vector< wrapped_fd > &fds=std::vector< wrapped_fd >())
std::tuple< bool, eosvmoc_message, std::vector< wrapped_fd > > read_message_with_fds(boost::asio::local::datagram_protocol::socket &s)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_intrinsic_map()

const intrinsic_map_t & sysio::chain::eosvmoc::get_intrinsic_map ( )

Definition at line 10 of file intrinsic.cpp.

10 {
11 return the_intrinsic_map();
12}
Here is the caller graph for this function:

◆ get_intrinsic_table()

auto sysio::chain::eosvmoc::get_intrinsic_table ( )
inlineconstexpr

Definition at line 17 of file intrinsic_mapping.hpp.

17 {
18 return detail::generate_table(
19 "eosvmoc_internal.unreachable",
20 "eosvmoc_internal.grow_memory",
21 "eosvmoc_internal.div0_or_overflow",
22 "eosvmoc_internal.indirect_call_mismatch",
23 "eosvmoc_internal.indirect_call_oob",
24 "eosvmoc_internal.depth_assert",
25 "sysio_injection.call_depth_assert", //now unused; left for purposes of not upsetting existing code mappings
26 "sysio_injection.checktime", //now unused; left for purposes of not upsetting existing code mappings
27 "env.__ashlti3",
28 "env.__ashrti3",
29 "env.__lshlti3",
30 "env.__lshrti3",
31 "env.__divti3",
32 "env.__udivti3",
33 "env.__modti3",
34 "env.__umodti3",
35 "env.__multi3",
36 "env.__addtf3",
37 "env.__subtf3",
38 "env.__multf3",
39 "env.__divtf3",
40 "env.__eqtf2",
41 "env.__netf2",
42 "env.__getf2",
43 "env.__gttf2",
44 "env.__lttf2",
45 "env.__letf2",
46 "env.__cmptf2",
47 "env.__unordtf2",
48 "env.__negtf2",
49 "env.__floatsitf",
50 "env.__floatunsitf",
51 "env.__floatditf",
52 "env.__floatunditf",
53 "env.__floattidf",
54 "env.__floatuntidf",
55 "env.__floatsidf",
56 "env.__extendsftf2",
57 "env.__extenddftf2",
58 "env.__fixtfti",
59 "env.__fixtfdi",
60 "env.__fixtfsi",
61 "env.__fixunstfti",
62 "env.__fixunstfdi",
63 "env.__fixunstfsi",
64 "env.__fixsfti",
65 "env.__fixdfti",
66 "env.__fixunssfti",
67 "env.__fixunsdfti",
68 "env.__trunctfdf2",
69 "env.__trunctfsf2",
70 "env.is_feature_active",
71 "env.activate_feature",
72 "env.get_resource_limits",
73 "env.set_resource_limits",
74 "env.set_proposed_producers",
75 "env.set_proposed_producers_ex",
76 "env.get_blockchain_parameters_packed",
77 "env.set_blockchain_parameters_packed",
78 "env.is_privileged",
79 "env.set_privileged",
80 "env.preactivate_feature",
81 "env.get_active_producers",
82 "env.db_store_i64",
83 "env.db_update_i64",
84 "env.db_remove_i64",
85 "env.db_get_i64",
86 "env.db_next_i64",
87 "env.db_previous_i64",
88 "env.db_find_i64",
89 "env.db_lowerbound_i64",
90 "env.db_upperbound_i64",
91 "env.db_end_i64",
92 "env.db_idx64_store",
93 "env.db_idx64_remove",
94 "env.db_idx64_update",
95 "env.db_idx64_find_primary",
96 "env.db_idx64_find_secondary",
97 "env.db_idx64_lowerbound",
98 "env.db_idx64_upperbound",
99 "env.db_idx64_end",
100 "env.db_idx64_next",
101 "env.db_idx64_previous",
102 "env.db_idx128_store",
103 "env.db_idx128_remove",
104 "env.db_idx128_update",
105 "env.db_idx128_find_primary",
106 "env.db_idx128_find_secondary",
107 "env.db_idx128_lowerbound",
108 "env.db_idx128_upperbound",
109 "env.db_idx128_end",
110 "env.db_idx128_next",
111 "env.db_idx128_previous",
112 "env.db_idx_double_store",
113 "env.db_idx_double_remove",
114 "env.db_idx_double_update",
115 "env.db_idx_double_find_primary",
116 "env.db_idx_double_find_secondary",
117 "env.db_idx_double_lowerbound",
118 "env.db_idx_double_upperbound",
119 "env.db_idx_double_end",
120 "env.db_idx_double_next",
121 "env.db_idx_double_previous",
122 "env.db_idx_long_double_store",
123 "env.db_idx_long_double_remove",
124 "env.db_idx_long_double_update",
125 "env.db_idx_long_double_find_primary",
126 "env.db_idx_long_double_find_secondary",
127 "env.db_idx_long_double_lowerbound",
128 "env.db_idx_long_double_upperbound",
129 "env.db_idx_long_double_end",
130 "env.db_idx_long_double_next",
131 "env.db_idx_long_double_previous",
132 "env.db_idx256_store",
133 "env.db_idx256_remove",
134 "env.db_idx256_update",
135 "env.db_idx256_find_primary",
136 "env.db_idx256_find_secondary",
137 "env.db_idx256_lowerbound",
138 "env.db_idx256_upperbound",
139 "env.db_idx256_end",
140 "env.db_idx256_next",
141 "env.db_idx256_previous",
142 "env.assert_recover_key",
143 "env.recover_key",
144 "env.assert_sha256",
145 "env.assert_sha1",
146 "env.assert_sha512",
147 "env.assert_ripemd160",
148 "env.sha1",
149 "env.sha256",
150 "env.sha512",
151 "env.ripemd160",
152 "env.check_transaction_authorization",
153 "env.check_permission_authorization",
154 "env.get_permission_last_used",
155 "env.get_account_creation_time",
156 "env.current_time",
157 "env.publication_time",
158 "env.is_feature_activated",
159 "env.get_sender",
160 "env.abort",
161 "env.sysio_assert",
162 "env.sysio_assert_message",
163 "env.sysio_assert_code",
164 "env.sysio_exit",
165 "env.read_action_data",
166 "env.action_data_size",
167 "env.current_receiver",
168 "env.require_recipient",
169 "env.require_auth",
170 "env.require_auth2",
171 "env.has_auth",
172 "env.is_account",
173 "env.prints",
174 "env.prints_l",
175 "env.printi",
176 "env.printui",
177 "env.printi128",
178 "env.printui128",
179 "env.printsf",
180 "env.printdf",
181 "env.printqf",
182 "env.printn",
183 "env.printhex",
184 "env.read_transaction",
185 "env.transaction_size",
186 "env.expiration",
187 "env.tapos_block_prefix",
188 "env.tapos_block_num",
189 "env.get_action",
190 "env.send_inline",
191 "env.send_context_free_inline",
192 "env.send_deferred",
193 "env.cancel_deferred",
194 "env.get_context_free_data",
195 "env.memcpy",
196 "env.memmove",
197 "env.memcmp",
198 "env.memset",
199 "sysio_injection._sysio_f32_add",
200 "sysio_injection._sysio_f32_sub",
201 "sysio_injection._sysio_f32_mul",
202 "sysio_injection._sysio_f32_div",
203 "sysio_injection._sysio_f32_min",
204 "sysio_injection._sysio_f32_max",
205 "sysio_injection._sysio_f32_copysign",
206 "sysio_injection._sysio_f32_abs",
207 "sysio_injection._sysio_f32_neg",
208 "sysio_injection._sysio_f32_sqrt",
209 "sysio_injection._sysio_f32_ceil",
210 "sysio_injection._sysio_f32_floor",
211 "sysio_injection._sysio_f32_trunc",
212 "sysio_injection._sysio_f32_nearest",
213 "sysio_injection._sysio_f32_eq",
214 "sysio_injection._sysio_f32_ne",
215 "sysio_injection._sysio_f32_lt",
216 "sysio_injection._sysio_f32_le",
217 "sysio_injection._sysio_f32_gt",
218 "sysio_injection._sysio_f32_ge",
219 "sysio_injection._sysio_f64_add",
220 "sysio_injection._sysio_f64_sub",
221 "sysio_injection._sysio_f64_mul",
222 "sysio_injection._sysio_f64_div",
223 "sysio_injection._sysio_f64_min",
224 "sysio_injection._sysio_f64_max",
225 "sysio_injection._sysio_f64_copysign",
226 "sysio_injection._sysio_f64_abs",
227 "sysio_injection._sysio_f64_neg",
228 "sysio_injection._sysio_f64_sqrt",
229 "sysio_injection._sysio_f64_ceil",
230 "sysio_injection._sysio_f64_floor",
231 "sysio_injection._sysio_f64_trunc",
232 "sysio_injection._sysio_f64_nearest",
233 "sysio_injection._sysio_f64_eq",
234 "sysio_injection._sysio_f64_ne",
235 "sysio_injection._sysio_f64_lt",
236 "sysio_injection._sysio_f64_le",
237 "sysio_injection._sysio_f64_gt",
238 "sysio_injection._sysio_f64_ge",
239 "sysio_injection._sysio_f32_promote",
240 "sysio_injection._sysio_f64_demote",
241 "sysio_injection._sysio_f32_trunc_i32s",
242 "sysio_injection._sysio_f64_trunc_i32s",
243 "sysio_injection._sysio_f32_trunc_i32u",
244 "sysio_injection._sysio_f64_trunc_i32u",
245 "sysio_injection._sysio_f32_trunc_i64s",
246 "sysio_injection._sysio_f64_trunc_i64s",
247 "sysio_injection._sysio_f32_trunc_i64u",
248 "sysio_injection._sysio_f64_trunc_i64u",
249 "sysio_injection._sysio_i32_to_f32",
250 "sysio_injection._sysio_i64_to_f32",
251 "sysio_injection._sysio_ui32_to_f32",
252 "sysio_injection._sysio_ui64_to_f32",
253 "sysio_injection._sysio_i32_to_f64",
254 "sysio_injection._sysio_i64_to_f64",
255 "sysio_injection._sysio_ui32_to_f64",
256 "sysio_injection._sysio_ui64_to_f64",
257 "env.set_action_return_value",
258 "env.get_wasm_parameters_packed",
259 "env.set_wasm_parameters_packed",
260 "env.get_parameters_packed",
261 "env.set_parameters_packed",
262 "env.get_code_hash",
263 "env.alt_bn128_add",
264 "env.alt_bn128_mul",
265 "env.alt_bn128_pair",
266 "env.mod_exp",
267 "env.sha3",
268 "env.blake2_f",
269 "env.k1_recover",
270 "env.get_block_num"
271 );
272}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ intrinsic_table_size()

std::size_t sysio::chain::eosvmoc::intrinsic_table_size ( )
inlineconstexpr

Definition at line 281 of file intrinsic_mapping.hpp.

281 {
282 return std::tuple_size<decltype(get_intrinsic_table())>::value;
283}
#define value
Definition pkcs11.h:157
Here is the call graph for this function:

◆ launch_compile_monitor()

void sysio::chain::eosvmoc::launch_compile_monitor ( int nodeop_fd)

Definition at line 235 of file compile_monitor.cpp.

235 {
236 prctl(PR_SET_NAME, "oc-monitor");
237 prctl(PR_SET_PDEATHSIG, SIGKILL);
238
239 //first off, let's disable shutdown signals to us; we want all shutdown indicators to come from
240 // nodeop shutting us down
241 sigset_t set;
242 sigemptyset(&set);
243 sigaddset(&set, SIGHUP);
244 sigaddset(&set, SIGTERM);
245 sigaddset(&set, SIGPIPE);
246 sigaddset(&set, SIGINT);
247 sigaddset(&set, SIGQUIT);
248 sigprocmask(SIG_BLOCK, &set, nullptr);
249
250 struct sigaction sa;
251 sa.sa_handler = SIG_DFL;
252 sa.sa_flags = SA_NOCLDWAIT;
253 sigaction(SIGCHLD, &sa, nullptr);
254
255 int socks[2]; //0: local trampoline socket, 1: the one we give to trampoline
256 socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, socks);
257 pid_t child = fork();
258 if(child == 0) {
259 close(socks[0]);
260 run_compile_trampoline(socks[1]);
261 }
262 close(socks[1]);
263
264 {
265 boost::asio::io_context ctx;
266 boost::asio::local::datagram_protocol::socket nodeop_socket(ctx);
267 nodeop_socket.assign(boost::asio::local::datagram_protocol(), nodeop_fd);
268 wrapped_fd trampoline_socket(socks[0]);
269 compile_monitor monitor(ctx, std::move(nodeop_socket), std::move(trampoline_socket));
270 ctx.run();
271 if(monitor._compile_sessions.size())
272 std::cerr << "ERROR: SYS VM OC compiler monitor exiting with active sessions" << std::endl;
273 }
274
275 _exit(0);
276}
void close(T *e, websocketpp::connection_hdl hdl)
void monitor()
bool set
Here is the call graph for this function:
Here is the caller graph for this function:

◆ memfd_for_bytearray()

template<typename T >
wrapped_fd sysio::chain::eosvmoc::memfd_for_bytearray ( const T & bytes)

Definition at line 56 of file ipc_helpers.hpp.

56 {
57 int fd = syscall(SYS_memfd_create, "eosvmoc_code", MFD_CLOEXEC);
58 FC_ASSERT(fd >= 0, "Failed to create memfd");
59 FC_ASSERT(ftruncate(fd, bytes.size()) == 0, "failed to grow memfd");
60 if(bytes.size()) {
61 uint8_t* b = (uint8_t*)mmap(nullptr, bytes.size(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
62 FC_ASSERT(b != MAP_FAILED, "failed to mmap memfd");
63 memcpy(b, bytes.data(), bytes.size());
64 munmap(b, bytes.size());
65 }
66 return wrapped_fd(fd);
67}
unsigned char uint8_t
Definition stdint.h:124
memcpy((char *) pInfo->slotDescription, s, l)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_message_with_fds() [1/2]

std::tuple< bool, eosvmoc_message, std::vector< wrapped_fd > > sysio::chain::eosvmoc::read_message_with_fds ( boost::asio::local::datagram_protocol::socket & s)

Definition at line 9 of file ipc_helpers.cpp.

9 {
10 return read_message_with_fds(s.native_handle());
11}
char * s
Here is the call graph for this function:
Here is the caller graph for this function:

◆ read_message_with_fds() [2/2]

std::tuple< bool, eosvmoc_message, std::vector< wrapped_fd > > sysio::chain::eosvmoc::read_message_with_fds ( int fd)

Definition at line 13 of file ipc_helpers.cpp.

13 {
14 char buff[max_message_size];
15
16 struct msghdr msg = {};
17 struct cmsghdr* cmsg;
18
19 eosvmoc_message message;
20 std::vector<wrapped_fd> fds;
21
22 struct iovec io = {
23 .iov_base = buff,
24 .iov_len = sizeof(buff)
25 };
26 union {
27 char buf[CMSG_SPACE(max_num_fds * sizeof(int))];
28 struct cmsghdr align;
29 } u;
30
31 msg.msg_iov = &io;
32 msg.msg_iovlen = 1;
33 msg.msg_control = u.buf;
34 msg.msg_controllen = sizeof(u.buf);
35
36 int red;
37 do {
38 red = recvmsg(fd, &msg, 0);
39 } while(red == -1 && errno == EINTR);
40 if(red < 1 || static_cast<unsigned>(red) >= sizeof(buff))
41 return {false, message, std::move(fds)};
42
43 try {
44 fc::datastream<char*> ds(buff, red);
45 fc::raw::unpack(ds, message);
46 }
47 catch(...) {
48 return {false, message, std::move(fds)};
49 }
50
51 if(msg.msg_controllen) {
52 cmsg = CMSG_FIRSTHDR(&msg);
53 unsigned num_of_fds = (cmsg->cmsg_len - CMSG_LEN(0))/sizeof(int);
54 if(num_of_fds > max_num_fds)
55 return {false, message, std::move(fds)};
56 int* fd_ptr = (int*)CMSG_DATA(cmsg);
57 for(unsigned i = 0; i < num_of_fds; ++i)
58 fds.push_back(*fd_ptr++);
59 }
60
61 return {true, message, std::move(fds)};
62}
static const Segment ds(Segment::ds)
void unpack(Stream &s, std::deque< T > &value)
Definition raw.hpp:540
uint8_t buf[2048]
Here is the call graph for this function:

◆ run_compile()

void sysio::chain::eosvmoc::run_compile ( wrapped_fd && response_sock,
wrapped_fd && wasm_code )
noexcept

Definition at line 20 of file compile_trampoline.cpp.

20 { //noexcept; we'll just blow up if anything tries to cross this boundry
21 std::vector<uint8_t> wasm = vector_for_memfd(wasm_code);
22
23 //ideally we catch exceptions and sent them upstream as strings for easier reporting
24
26 Serialization::MemoryInputStream stream(wasm.data(), wasm.size());
28 WASM::serialize(stream, module);
29 module.userSections.clear();
31 injector.inject();
32
34
36
37 const std::map<unsigned, uintptr_t>& function_to_offsets = code.function_offsets;
38
39 if(module.startFunctionIndex == UINTPTR_MAX)
40 result_message.start = no_offset{};
41 else if(module.startFunctionIndex < module.functions.imports.size()) {
42 const auto& f = module.functions.imports[module.startFunctionIndex];
43 const intrinsic_entry& ie = get_intrinsic_map().at(f.moduleName + "." + f.exportName);
44 result_message.start = intrinsic_ordinal{ie.ordinal};
45 }
46 else
47 result_message.start = code_offset{function_to_offsets.at(module.startFunctionIndex-module.functions.imports.size())};
48
49 for(const Export& exprt : module.exports) {
50 if(exprt.name == "apply")
51 result_message.apply_offset = function_to_offsets.at(exprt.index-module.functions.imports.size());
52 }
53
54 result_message.starting_memory_pages = -1;
55 if(module.memories.size())
56 result_message.starting_memory_pages = module.memories.defs.at(0).type.size.min;
57
58 std::vector<uint8_t> prologue(module.globals.defs.size() * 8); // Large enough to handle all mutable globals
59 std::vector<uint8_t>::iterator prologue_it = prologue.end();
60
61 //set up mutable globals
62 union global_union {
65 float f32;
66 double f64;
67 };
68
69 for(const GlobalDef& global : module.globals.defs) {
70 if(!global.type.isMutable)
71 continue;
72 prologue_it -= 8;
73 global_union* const u = (global_union* const)&*prologue_it;
74
75 switch(global.initializer.type) {
76 case InitializerExpression::Type::i32_const: u->i32 = global.initializer.i32; break;
77 case InitializerExpression::Type::i64_const: u->i64 = global.initializer.i64; break;
78 case InitializerExpression::Type::f32_const: u->f32 = global.initializer.f32; break;
79 case InitializerExpression::Type::f64_const: u->f64 = global.initializer.f64; break;
80 default: break; //impossible
81 }
82 }
83
84 struct table_entry {
86 int64_t func; //>= 0 means offset to code in wasm; < 0 means intrinsic call at offset address
87 };
88
89 for(const TableSegment& table_segment : module.tableSegments) {
90 struct table_entry* table_index_0 = (struct table_entry*)(code.code.data() + code.table_offset);
91
92 if(static_cast<uint64_t>(table_segment.baseOffset.i32) > module.tables.defs[0].type.size.min)
93 return;
94
95 if(static_cast<uint64_t>(table_segment.baseOffset.i32) > module.tables.defs[0].type.size.min)
96 return;
97
98 for(Uptr i = 0; i < table_segment.indices.size(); ++i) {
99 const Uptr function_index = table_segment.indices[i];
100 const uint64_t effective_table_index = table_segment.baseOffset.i32 + i;
101
102 if(effective_table_index >= module.tables.defs[0].type.size.min)
103 return;
104
105 if(function_index < module.functions.imports.size()) {
106 const auto& f = module.functions.imports[function_index];
107 const intrinsic_entry& ie = get_intrinsic_map().at(f.moduleName + "." + f.exportName);
108 table_index_0[effective_table_index].func = ie.ordinal*-8;
109 table_index_0[effective_table_index].type = (uintptr_t)module.types[module.functions.imports[function_index].type.index];
110 }
111 else {
112 table_index_0[effective_table_index].func = function_to_offsets.at(function_index - module.functions.imports.size());
113 table_index_0[effective_table_index].type = (uintptr_t)module.types[module.functions.defs[function_index - module.functions.imports.size()].type.index];
114 }
115 }
116 }
117
118 //this is somewhat copy pasta from wasm_interface_private, with the asserts removed
119 std::vector<uint8_t> initial_mem;
120 for(const DataSegment& data_segment : module.dataSegments) {
121 const U32 base_offset = data_segment.baseOffset.i32;
122
123 if(base_offset + data_segment.data.size() > initial_mem.size())
124 initial_mem.resize(base_offset + data_segment.data.size(), 0x00);
125 memcpy(initial_mem.data() + base_offset, data_segment.data.data(), data_segment.data.size());
126 }
127
128 result_message.initdata_prologue_size = prologue.end() - prologue_it;
129 std::vector<uint8_t> initdata_prep;
130 std::move(prologue_it, prologue.end(), std::back_inserter(initdata_prep));
131 std::move(initial_mem.begin(), initial_mem.end(), std::back_inserter(initdata_prep));
132
133 std::vector<wrapped_fd> fds_to_send;
134 fds_to_send.emplace_back(memfd_for_bytearray(code.code));
135 fds_to_send.emplace_back(memfd_for_bytearray(initdata_prep));
136 write_message_with_fds(response_sock, result_message, fds_to_send);
137}
uint32_t U32
Definition BasicTypes.h:9
PointerIntHelper< sizeof(size_t)>::UnsignedIntType Uptr
Definition BasicTypes.h:22
RUNTIME_API ModuleInstance * instantiateModule(const IR::Module &module, ImportBindings &&imports)
void serialize(Stream &stream, U8 &i)
std::vector< uint8_t > vector_for_memfd(const wrapped_fd &memfd)
const intrinsic_map_t & get_intrinsic_map()
Definition intrinsic.cpp:10
wrapped_fd memfd_for_bytearray(const T &bytes)
_W64 unsigned int uintptr_t
Definition stdint.h:165
signed __int64 int64_t
Definition stdint.h:135
signed int int32_t
Definition stdint.h:123
#define UINTPTR_MAX
Definition stdint.h:227
unsigned __int64 uint64_t
Definition stdint.h:136
std::vector< U8 > data
Definition Module.h:95
InitializerExpression baseOffset
Definition Module.h:94
std::string name
Definition Module.h:85
Uptr index
Definition Module.h:87
std::vector< Uptr > indices
Definition Module.h:103
InitializerExpression baseOffset
Definition Module.h:102
yh_object_type type
Definition yubihsm.h:672
Here is the call graph for this function:
Here is the caller graph for this function:

◆ run_compile_trampoline()

void sysio::chain::eosvmoc::run_compile_trampoline ( int fd)

Definition at line 139 of file compile_trampoline.cpp.

139 {
140 prctl(PR_SET_NAME, "oc-trampoline");
141 prctl(PR_SET_PDEATHSIG, SIGKILL);
142
143 //squelching this for now, but it means we won't have ability to get compile metrics
144 struct sigaction act;
145 sigset_t set;
146 sigemptyset(&set);
147 act.sa_handler = SIG_IGN;
148 act.sa_mask = set;
149 act.sa_flags = SA_NOCLDWAIT;
150 act.sa_sigaction = nullptr;
151 sigaction(SIGCHLD, &act, nullptr);
152
153 while(true) {
154 auto [success, message, fds] = read_message_with_fds(fd);
155 if(!success)
156 break;
157
158 if(!std::holds_alternative<compile_wasm_message>(message) || fds.size() != 2) {
159 std::cerr << "SYS VM OC compile trampoline got unexpected message; ignoring" << std::endl;
160 continue;
161 }
162
163 pid_t pid = fork();
164 if(pid == 0) {
165 prctl(PR_SET_NAME, "oc-compile");
166 prctl(PR_SET_PDEATHSIG, SIGKILL);
167
168 struct rlimit cpu_limits = {20u, 20u};
169 setrlimit(RLIMIT_CPU, &cpu_limits);
170
171 struct rlimit vm_limits = {512u*1024u*1024u, 512u*1024u*1024u};
172 setrlimit(RLIMIT_AS, &vm_limits);
173
174 struct rlimit core_limits = {0u, 0u};
175 setrlimit(RLIMIT_CORE, &core_limits);
176
177 run_compile(std::move(fds[0]), std::move(fds[1]));
178 _exit(0);
179 }
180 else if(pid == -1)
181 std::cerr << "SYS VM OC compile trampoline failed to spawn compile task" << std::endl;
182 }
183
184 _exit(0);
185}
void run_compile(wrapped_fd &&response_sock, wrapped_fd &&wasm_code) noexcept
Here is the call graph for this function:
Here is the caller graph for this function:

◆ vector_for_memfd()

std::vector< uint8_t > sysio::chain::eosvmoc::vector_for_memfd ( const wrapped_fd & memfd)

Definition at line 121 of file ipc_helpers.cpp.

121 {
122 struct stat st;
123 FC_ASSERT(fstat(memfd, &st) == 0, "failed to get memfd size");
124
125 if(st.st_size == 0)
126 return std::vector<uint8_t>();
127
128 uint8_t* p = (uint8_t*)mmap(nullptr, st.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, memfd, 0);
129 FC_ASSERT(p != MAP_FAILED, "failed to map memfd");
130 std::vector<uint8_t> ret(p, p+st.st_size);
131 munmap(p, st.st_size);
132 return ret;
133}
const mie::Vuint & p
Definition bn.cpp:27
CK_RV ret
Here is the caller graph for this function:

◆ write_message_with_fds() [1/2]

bool sysio::chain::eosvmoc::write_message_with_fds ( boost::asio::local::datagram_protocol::socket & s,
const eosvmoc_message & message,
const std::vector< wrapped_fd > & fds = std::vector<wrapped_fd>() )

Definition at line 64 of file ipc_helpers.cpp.

64 {
65 return write_message_with_fds(s.native_handle(), message, fds);
66}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ write_message_with_fds() [2/2]

bool sysio::chain::eosvmoc::write_message_with_fds ( int fd_to_send_to,
const eosvmoc_message & message,
const std::vector< wrapped_fd > & fds = std::vector<wrapped_fd>() )

Definition at line 68 of file ipc_helpers.cpp.

68 {
69 struct msghdr msg = {};
70 struct cmsghdr* cmsg;
71
72 size_t sz = fc::raw::pack_size(message);
73 if(sz > max_message_size)
74 return false;
75 char buff[max_message_size];
76 try {
77 fc::datastream<char*> ds(buff, max_message_size);
78 fc::raw::pack(ds, message);
79 }
80 catch(...) {
81 return false;
82 }
83
84 if(fds.size() > max_num_fds)
85 return false;
86
87 struct iovec io = {
88 .iov_base = buff,
89 .iov_len = sz
90 };
91 union {
92 char buf[CMSG_SPACE(max_num_fds * sizeof(int))];
93 struct cmsghdr align;
94 } u;
95
96 msg.msg_iov = &io;
97 msg.msg_iovlen = 1;
98 if(fds.size()) {
99 msg.msg_control = u.buf;
100 msg.msg_controllen = sizeof(u.buf);
101 cmsg = CMSG_FIRSTHDR(&msg);
102 cmsg->cmsg_level = SOL_SOCKET;
103 cmsg->cmsg_type = SCM_RIGHTS;
104 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fds.size());
105 unsigned char* p = CMSG_DATA(cmsg);
106 for(const wrapped_fd& fd : fds) {
107 int thisfd = fd;
108 memcpy(p, &thisfd, sizeof(thisfd));
109 p += sizeof(thisfd);
110 }
111 }
112
113 int wrote;
114 do {
115 wrote = sendmsg(fd_to_send_to, &msg, 0);
116 } while(wrote == -1 && errno == EINTR);
117
118 return wrote >= 0;
119}
void pack(Stream &s, const std::deque< T > &value)
Definition raw.hpp:531
size_t pack_size(const T &v)
Definition raw.hpp:671
Here is the call graph for this function: