wasm-native.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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 145: /* readv */
  94. case 146: /* writev */
  95. {
  96. /* Implement syscall 54 and syscall 146 to support printf()
  97. for non SIDE_MODULE=1 mode */
  98. uint32 iovcnt = arg3, i;
  99. struct iovec *vec_begin, *vec;
  100. if (!validate_app_addr(arg2, sizeof(struct iovec)))
  101. return 0;
  102. vec_begin = vec = (struct iovec*)addr_app_to_native(arg2);
  103. for (i = 0; i < iovcnt; i++, vec++) {
  104. if (vec->iov_len > 0) {
  105. if (!validate_app_addr((int32)vec->iov_base, 1))
  106. return 0;
  107. vec->iov_base = addr_app_to_native((int32)vec->iov_base);
  108. }
  109. }
  110. if (arg0 == 145)
  111. return syscall(145, arg1, vec_begin, arg3);
  112. else
  113. return syscall(146, arg1, vec_begin, arg3);
  114. }
  115. case 3: /* read*/
  116. case 5: /* open */
  117. case 221: /* fcntl */
  118. /* TODO */
  119. default:
  120. printf("##_syscall3 called, syscall id: %d\n", arg0);
  121. }
  122. return 0;
  123. }
  124. static int32
  125. __syscall4_wrapper(int32 arg0, int32 arg1, int32 arg2,
  126. int32 arg3, int32 arg4)
  127. {
  128. printf("##_syscall4 called, syscall id: %d\n", arg0);
  129. return 0;
  130. }
  131. static int32
  132. __syscall5_wrapper(int32 arg0, int32 arg1, int32 arg2,
  133. int32 arg3, int32 arg4, int32 arg5)
  134. {
  135. switch (arg0) {
  136. case 140: /* llseek */
  137. /* TODO */
  138. default:
  139. printf("##_syscall5 called, args[0]: %d\n", arg0);
  140. }
  141. return 0;
  142. }
  143. #define GET_EMCC_SYSCALL_ARGS() \
  144. WASMModuleInstance *module_inst = get_module_inst(); \
  145. int32 *args; \
  146. if (!validate_app_addr(args_off, 1)) \
  147. return 0; \
  148. args = addr_app_to_native(args_off) \
  149. #define EMCC_SYSCALL_WRAPPER0(id) \
  150. static int32 ___syscall##id##_wrapper(int32 _id) { \
  151. return __syscall0_wrapper(id); \
  152. }
  153. #define EMCC_SYSCALL_WRAPPER1(id) \
  154. static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
  155. GET_EMCC_SYSCALL_ARGS(); \
  156. return __syscall1_wrapper(id, args[0]); \
  157. }
  158. #define EMCC_SYSCALL_WRAPPER2(id) \
  159. static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
  160. GET_EMCC_SYSCALL_ARGS(); \
  161. return __syscall2_wrapper(id, args[0], args[1]); \
  162. }
  163. #define EMCC_SYSCALL_WRAPPER3(id) \
  164. static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
  165. GET_EMCC_SYSCALL_ARGS(); \
  166. return __syscall3_wrapper(id, args[0], args[1], args[2]); \
  167. }
  168. #define EMCC_SYSCALL_WRAPPER4(id) \
  169. static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
  170. GET_EMCC_SYSCALL_ARGS(); \
  171. return __syscall4_wrapper(id, args[0], args[1], args[2], args[3]);\
  172. }
  173. #define EMCC_SYSCALL_WRAPPER5(id) \
  174. static int32 ___syscall##id##_wrapper(int32 _id, int32 args_off) {\
  175. GET_EMCC_SYSCALL_ARGS(); \
  176. return __syscall5_wrapper(id, args[0], args[1], args[2], \
  177. args[3], args[4]); \
  178. }
  179. EMCC_SYSCALL_WRAPPER0(199)
  180. EMCC_SYSCALL_WRAPPER1(6)
  181. EMCC_SYSCALL_WRAPPER2(183)
  182. EMCC_SYSCALL_WRAPPER3(3)
  183. EMCC_SYSCALL_WRAPPER3(5)
  184. EMCC_SYSCALL_WRAPPER3(54)
  185. EMCC_SYSCALL_WRAPPER3(145)
  186. EMCC_SYSCALL_WRAPPER3(146)
  187. EMCC_SYSCALL_WRAPPER3(221)
  188. EMCC_SYSCALL_WRAPPER5(140)
  189. static int32
  190. getTotalMemory_wrapper()
  191. {
  192. WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
  193. WASMMemoryInstance *memory = module_inst->default_memory;
  194. return NumBytesPerPage * memory->cur_page_count;
  195. }
  196. static int32
  197. enlargeMemory_wrapper()
  198. {
  199. bool ret;
  200. WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
  201. WASMMemoryInstance *memory = module_inst->default_memory;
  202. uint32 DYNAMICTOP_PTR_offset = module_inst->DYNAMICTOP_PTR_offset;
  203. uint32 addr_data_offset = *(uint32*)(memory->global_data + DYNAMICTOP_PTR_offset);
  204. uint32 *DYNAMICTOP_PTR = (uint32*)(memory->memory_data + addr_data_offset);
  205. uint32 memory_size_expected = *DYNAMICTOP_PTR;
  206. uint32 total_page_count = (memory_size_expected + NumBytesPerPage - 1) / NumBytesPerPage;
  207. if (total_page_count < memory->cur_page_count) {
  208. return 1;
  209. }
  210. else {
  211. ret = wasm_runtime_enlarge_memory(module_inst, total_page_count -
  212. memory->cur_page_count);
  213. return ret ? 1 : 0;
  214. }
  215. }
  216. static void
  217. _abort_wrapper(int32 code)
  218. {
  219. WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
  220. char buf[32];
  221. snprintf(buf, sizeof(buf), "env.abort(%i)", code);
  222. wasm_runtime_set_exception(module_inst, buf);
  223. }
  224. static void
  225. abortOnCannotGrowMemory_wrapper()
  226. {
  227. WASMModuleInstance *module_inst = wasm_runtime_get_current_module_inst();
  228. wasm_runtime_set_exception(module_inst, "abort on cannot grow memory");
  229. }
  230. static void
  231. ___setErrNo_wrapper(int32 error_no)
  232. {
  233. errno = error_no;
  234. }
  235. /* TODO: add function parameter/result types check */
  236. #define REG_NATIVE_FUNC(module_name, func_name) \
  237. {#module_name, #func_name, func_name##_wrapper}
  238. typedef struct WASMNativeFuncDef {
  239. const char *module_name;
  240. const char *func_name;
  241. void *func_ptr;
  242. } WASMNativeFuncDef;
  243. static WASMNativeFuncDef native_func_defs[] = {
  244. REG_NATIVE_FUNC(env, __syscall0),
  245. REG_NATIVE_FUNC(env, __syscall1),
  246. REG_NATIVE_FUNC(env, __syscall2),
  247. REG_NATIVE_FUNC(env, __syscall3),
  248. REG_NATIVE_FUNC(env, __syscall4),
  249. REG_NATIVE_FUNC(env, __syscall5),
  250. REG_NATIVE_FUNC(env, ___syscall3),
  251. REG_NATIVE_FUNC(env, ___syscall5),
  252. REG_NATIVE_FUNC(env, ___syscall6),
  253. REG_NATIVE_FUNC(env, ___syscall54),
  254. REG_NATIVE_FUNC(env, ___syscall140),
  255. REG_NATIVE_FUNC(env, ___syscall145),
  256. REG_NATIVE_FUNC(env, ___syscall146),
  257. REG_NATIVE_FUNC(env, ___syscall183),
  258. REG_NATIVE_FUNC(env, ___syscall199),
  259. REG_NATIVE_FUNC(env, ___syscall221),
  260. REG_NATIVE_FUNC(env, _abort),
  261. REG_NATIVE_FUNC(env, abortOnCannotGrowMemory),
  262. REG_NATIVE_FUNC(env, enlargeMemory),
  263. REG_NATIVE_FUNC(env, getTotalMemory),
  264. REG_NATIVE_FUNC(env, ___setErrNo),
  265. };
  266. void*
  267. wasm_platform_native_func_lookup(const char *module_name,
  268. const char *func_name)
  269. {
  270. uint32 size = sizeof(native_func_defs) / sizeof(WASMNativeFuncDef);
  271. WASMNativeFuncDef *func_def = native_func_defs;
  272. WASMNativeFuncDef *func_def_end = func_def + size;
  273. if (!module_name || !func_name)
  274. return NULL;
  275. while (func_def < func_def_end) {
  276. if (!strcmp(func_def->module_name, module_name)
  277. && !strcmp(func_def->func_name, func_name))
  278. return (void*)(uintptr_t)func_def->func_ptr;
  279. func_def++;
  280. }
  281. return NULL;
  282. }