wasm-native.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef _GNU_SOURCE
  17. #define _GNU_SOURCE /* for O_DIRECT */
  18. #endif
  19. #include "wasm-native.h"
  20. #include "wasm-runtime.h"
  21. #include "wasm_log.h"
  22. #include "wasm_memory.h"
  23. #include "wasm_platform_log.h"
  24. #include <sys/ioctl.h>
  25. #include <sys/uio.h>
  26. #include <sys/syscall.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <unistd.h>
  30. #include <pwd.h>
  31. #include <fcntl.h>
  32. #include <errno.h>
  33. #define get_module_inst() \
  34. wasm_runtime_get_current_module_inst()
  35. #define validate_app_addr(offset, size) \
  36. wasm_runtime_validate_app_addr(module_inst, offset, size)
  37. #define addr_app_to_native(offset) \
  38. wasm_runtime_addr_app_to_native(module_inst, offset)
  39. #define addr_native_to_app(ptr) \
  40. wasm_runtime_addr_native_to_app(module_inst, ptr)
  41. #define module_malloc(size) \
  42. wasm_runtime_module_malloc(module_inst, size)
  43. #define module_free(offset) \
  44. wasm_runtime_module_free(module_inst, offset)
  45. static int32
  46. __syscall0_wrapper(int32 arg0)
  47. {
  48. switch (arg0) {
  49. case 199: /* getuid */
  50. /* TODO */
  51. default:
  52. printf("##_syscall0 called, syscall id: %d\n", arg0);
  53. }
  54. return 0;
  55. }
  56. static int32
  57. __syscall1_wrapper(int32 arg0, int32 arg1)
  58. {
  59. switch (arg0) {
  60. case 6: /* close */
  61. /* TODO */
  62. default:
  63. printf("##_syscall1 called, syscall id: %d\n", arg0);
  64. }
  65. return 0;
  66. }
  67. static int32
  68. __syscall2_wrapper(int32 arg0, int32 arg1, int32 arg2)
  69. {
  70. switch (arg0) {
  71. case 183: /* getcwd */
  72. /* TODO */
  73. default:
  74. printf("##_syscall2 called, syscall id: %d\n", arg0);
  75. }
  76. return 0;
  77. }
  78. static int32
  79. __syscall3_wrapper(int32 arg0, int32 arg1, int32 arg2, int32 arg3)
  80. {
  81. WASMModuleInstance *module_inst = get_module_inst();
  82. switch (arg0) {
  83. case 54: /* ioctl */
  84. {
  85. /* Implement syscall 54 and syscall 146 to support printf()
  86. for non SIDE_MODULE=1 mode */
  87. struct winsize *wsz;
  88. if (!validate_app_addr(arg3, sizeof(struct winsize)))
  89. return 0;
  90. wsz = (struct winsize*)addr_app_to_native(arg3);
  91. return syscall(54, arg1, arg2, wsz);
  92. }
  93. case 146: /* writev */
  94. {
  95. /* Implement syscall 54 and syscall 146 to support printf()
  96. for non SIDE_MODULE=1 mode */
  97. struct iovec_app {
  98. int32 iov_base_offset;
  99. uint32 iov_len;
  100. } *vec;
  101. int32 vec_offset = arg2, str_offset;
  102. uint32 iov_count = arg3, i;
  103. int32 count = 0;
  104. char *iov_base, *str;
  105. if (!validate_app_addr(vec_offset, sizeof(struct iovec_app)))
  106. return 0;
  107. vec = (struct iovec_app *)addr_app_to_native(vec_offset);
  108. for (i = 0; i < iov_count; i++, vec++) {
  109. if (vec->iov_len > 0) {
  110. if (!validate_app_addr(vec->iov_base_offset, 1))
  111. return 0;
  112. iov_base = (char*)addr_app_to_native(vec->iov_base_offset);
  113. if (!(str_offset = module_malloc(vec->iov_len + 1)))
  114. return 0;
  115. str = addr_app_to_native(str_offset);
  116. memcpy(str, iov_base, vec->iov_len);
  117. str[vec->iov_len] = '\0';
  118. count += wasm_printf("%s", str);
  119. module_free(str_offset);
  120. }
  121. }
  122. return count;
  123. }
  124. case 145: /* readv */
  125. case 3: /* read*/
  126. case 5: /* open */
  127. case 221: /* fcntl */
  128. /* TODO */
  129. default:
  130. printf("##_syscall3 called, syscall id: %d\n", arg0);
  131. }
  132. return 0;
  133. }
  134. static int32
  135. __syscall4_wrapper(int32 arg0, int32 arg1, int32 arg2,
  136. int32 arg3, int32 arg4)
  137. {
  138. printf("##_syscall4 called, syscall id: %d\n", arg0);
  139. return 0;
  140. }
  141. static int32
  142. __syscall5_wrapper(int32 arg0, int32 arg1, int32 arg2,
  143. int32 arg3, int32 arg4, int32 arg5)
  144. {
  145. switch (arg0) {
  146. case 140: /* llseek */
  147. /* TODO */
  148. default:
  149. printf("##_syscall5 called, args[0]: %d\n", arg0);
  150. }
  151. return 0;
  152. }
  153. #define GET_EMCC_SYSCALL_ARGS() \
  154. WASMModuleInstance *module_inst = get_module_inst(); \
  155. int32 *args; \
  156. if (!validate_app_addr(args_off, 1)) \
  157. return 0; \
  158. args = addr_app_to_native(args_off) \
  159. #define EMCC_SYSCALL_WRAPPER0(id) \
  160. static int32 ___syscall##id##_wrapper(int32 _id) { \
  161. return __syscall0_wrapper(id); \
  162. }
  163. #define EMCC_SYSCALL_WRAPPER1(id) \
  164. static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
  165. GET_EMCC_SYSCALL_ARGS(); \
  166. return __syscall1_wrapper(id, args[0]); \
  167. }
  168. #define EMCC_SYSCALL_WRAPPER2(id) \
  169. static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
  170. GET_EMCC_SYSCALL_ARGS(); \
  171. return __syscall2_wrapper(id, args[0], args[1]); \
  172. }
  173. #define EMCC_SYSCALL_WRAPPER3(id) \
  174. static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
  175. GET_EMCC_SYSCALL_ARGS(); \
  176. return __syscall3_wrapper(id, args[0], args[1], args[2]); \
  177. }
  178. #define EMCC_SYSCALL_WRAPPER4(id) \
  179. static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
  180. GET_EMCC_SYSCALL_ARGS(); \
  181. return __syscall4_wrapper(id, args[0], args[1], args[2], args[3]);\
  182. }
  183. #define EMCC_SYSCALL_WRAPPER5(id) \
  184. static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
  185. GET_EMCC_SYSCALL_ARGS(); \
  186. return __syscall5_wrapper(id, args[0], args[1], args[2], \
  187. args[3], args[4]); \
  188. }
  189. EMCC_SYSCALL_WRAPPER0(199)
  190. EMCC_SYSCALL_WRAPPER1(6)
  191. EMCC_SYSCALL_WRAPPER2(183)
  192. EMCC_SYSCALL_WRAPPER3(3)
  193. EMCC_SYSCALL_WRAPPER3(5)
  194. EMCC_SYSCALL_WRAPPER3(54)
  195. EMCC_SYSCALL_WRAPPER3(145)
  196. EMCC_SYSCALL_WRAPPER3(146)
  197. EMCC_SYSCALL_WRAPPER3(221)
  198. EMCC_SYSCALL_WRAPPER5(140)
  199. static int32
  200. getTotalMemory_wrapper()
  201. {
  202. WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
  203. WASMMemoryInstance *memory = module_inst->default_memory;
  204. return NumBytesPerPage * memory->cur_page_count;
  205. }
  206. static int32
  207. enlargeMemory_wrapper()
  208. {
  209. bool ret;
  210. WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
  211. WASMMemoryInstance *memory = module_inst->default_memory;
  212. uint32 DYNAMICTOP_PTR_offset = module_inst->DYNAMICTOP_PTR_offset;
  213. uint32 addr_data_offset = *(uint32*)(memory->global_data + DYNAMICTOP_PTR_offset);
  214. uint32 *DYNAMICTOP_PTR = (uint32*)(memory->memory_data + addr_data_offset);
  215. uint32 memory_size_expected = *DYNAMICTOP_PTR;
  216. uint32 total_page_count = (memory_size_expected + NumBytesPerPage - 1) / NumBytesPerPage;
  217. if (total_page_count < memory->cur_page_count) {
  218. return 1;
  219. }
  220. else {
  221. ret = wasm_runtime_enlarge_memory(module_inst, total_page_count -
  222. memory->cur_page_count);
  223. return ret ? 1 : 0;
  224. }
  225. }
  226. static void
  227. _abort_wrapper(int32 code)
  228. {
  229. WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
  230. char buf[32];
  231. snprintf(buf, sizeof(buf), "env.abort(%i)", code);
  232. wasm_runtime_set_exception(module_inst, buf);
  233. }
  234. static void
  235. abortOnCannotGrowMemory_wrapper()
  236. {
  237. WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
  238. wasm_runtime_set_exception(module_inst, "abort on cannot grow memory");
  239. }
  240. static void
  241. ___setErrNo_wrapper(int32 error_no)
  242. {
  243. errno = error_no;
  244. }
  245. /* TODO: add function parameter/result types check */
  246. #define REG_NATIVE_FUNC(module_name, func_name) \
  247. {#module_name, #func_name, func_name##_wrapper}
  248. typedef struct WASMNativeFuncDef {
  249. const char *module_name;
  250. const char *func_name;
  251. void *func_ptr;
  252. } WASMNativeFuncDef;
  253. static WASMNativeFuncDef native_func_defs[] = {
  254. REG_NATIVE_FUNC(env, __syscall0),
  255. REG_NATIVE_FUNC(env, __syscall1),
  256. REG_NATIVE_FUNC(env, __syscall2),
  257. REG_NATIVE_FUNC(env, __syscall3),
  258. REG_NATIVE_FUNC(env, __syscall4),
  259. REG_NATIVE_FUNC(env, __syscall5),
  260. REG_NATIVE_FUNC(env, ___syscall3),
  261. REG_NATIVE_FUNC(env, ___syscall5),
  262. REG_NATIVE_FUNC(env, ___syscall6),
  263. REG_NATIVE_FUNC(env, ___syscall54),
  264. REG_NATIVE_FUNC(env, ___syscall140),
  265. REG_NATIVE_FUNC(env, ___syscall145),
  266. REG_NATIVE_FUNC(env, ___syscall146),
  267. REG_NATIVE_FUNC(env, ___syscall183),
  268. REG_NATIVE_FUNC(env, ___syscall199),
  269. REG_NATIVE_FUNC(env, ___syscall221),
  270. REG_NATIVE_FUNC(env, _abort),
  271. REG_NATIVE_FUNC(env, abortOnCannotGrowMemory),
  272. REG_NATIVE_FUNC(env, enlargeMemory),
  273. REG_NATIVE_FUNC(env, getTotalMemory),
  274. REG_NATIVE_FUNC(env, ___setErrNo),
  275. };
  276. void*
  277. wasm_platform_native_func_lookup(const char *module_name,
  278. const char *func_name)
  279. {
  280. uint32 size = sizeof(native_func_defs) / sizeof(WASMNativeFuncDef);
  281. WASMNativeFuncDef *func_def = native_func_defs;
  282. WASMNativeFuncDef *func_def_end = func_def + size;
  283. if (!module_name || !func_name)
  284. return NULL;
  285. while (func_def < func_def_end) {
  286. if (!strcmp(func_def->module_name, module_name)
  287. && !strcmp(func_def->func_name, func_name))
  288. return (void*)(uintptr_t)func_def->func_ptr;
  289. func_def++;
  290. }
  291. return NULL;
  292. }