iwasm.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*
  2. * Copyright (c) 2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  5. */
  6. #include <rtthread.h>
  7. #include "wasm_export.h"
  8. #include "platform_api_vmcore.h"
  9. #include <dfs.h>
  10. #include <dfs_file.h>
  11. #include <dfs_fs.h>
  12. #include <dfs_posix.h>
  13. #ifdef WAMR_ENABLE_RTT_EXPORT
  14. #ifdef WAMR_RTT_EXPORT_VPRINTF
  15. static int
  16. wasm_vprintf(wasm_exec_env_t env, const char *fmt, va_list va)
  17. {
  18. return vprintf(fmt, va);
  19. }
  20. static int
  21. wasm_vsprintf(wasm_exec_env_t env, char *buf, const char *fmt, va_list va)
  22. {
  23. return vsprintf(buf, fmt, va);
  24. }
  25. static int
  26. wasm_vsnprintf(wasm_exec_env_t env, char *buf, int n, const char *fmt,
  27. va_list va)
  28. {
  29. return vsnprintf(buf, n, fmt, va);
  30. }
  31. #endif /* WAMR_RTT_EXPORT_VPRINTF */
  32. #ifdef WAMR_RTT_EXPORT_DEVICE_OPS
  33. static rt_device_t
  34. wasm_rt_device_find(wasm_exec_env_t env, const char *name)
  35. {
  36. return rt_device_find(name);
  37. }
  38. static rt_err_t
  39. wasm_rt_device_open(wasm_exec_env_t env, rt_device_t dev, rt_uint16_t o_flag)
  40. {
  41. return rt_device_open(dev, o_flag);
  42. }
  43. static rt_size_t
  44. wasm_rt_device_write(wasm_exec_env_t env, rt_device_t dev, rt_off_t offset,
  45. const void *buf, rt_size_t size)
  46. {
  47. return rt_device_write(dev, offset, buf, size);
  48. }
  49. static rt_size_t
  50. wasm_rt_device_read(wasm_exec_env_t env, rt_device_t dev, rt_off_t offset,
  51. void *buf, rt_size_t size)
  52. {
  53. return rt_device_read(dev, offset, buf, size);
  54. }
  55. static rt_err_t
  56. wasm_rt_device_close(wasm_exec_env_t env, rt_device_t dev)
  57. {
  58. return rt_device_close(dev);
  59. }
  60. static rt_err_t
  61. wasm_rt_device_control(wasm_exec_env_t env, rt_device_t dev, int cmd, void *arg)
  62. {
  63. return rt_device_control(dev, cmd, arg);
  64. }
  65. #endif /* WAMR_RTT_EXPORT_DEVICE_OPS */
  66. /* clang-format off */
  67. static NativeSymbol native_export_symbols[] = {
  68. #ifdef WAMR_RTT_EXPORT_VPRINTF
  69. {
  70. "vprintf",
  71. wasm_vprintf,
  72. "($*)i"
  73. },
  74. {
  75. "vsprintf",
  76. wasm_vsprintf,
  77. "($$*)i"
  78. },
  79. {
  80. "vsnprintf",
  81. wasm_vsnprintf,
  82. "($i$*)i"
  83. },
  84. #endif /* WAMR_RTT_EXPORT_VPRINTF */
  85. #ifdef WAMR_RTT_EXPORT_DEVICE_OPS
  86. {
  87. "rt_device_find",
  88. wasm_rt_device_find,
  89. "($)i"
  90. },
  91. {
  92. "rt_device_open",
  93. wasm_rt_device_open,
  94. "(ii)i"
  95. },
  96. {
  97. "rt_device_write",
  98. wasm_rt_device_write,
  99. "(ii*~)i"
  100. },
  101. {
  102. "rt_device_read",
  103. wasm_rt_device_read,
  104. "(ii*~)i"
  105. },
  106. {
  107. "rt_device_close",
  108. wasm_rt_device_close,
  109. "(i)i"
  110. },
  111. {
  112. "rt_device_control",
  113. wasm_rt_device_control,
  114. "(ii*)i"
  115. },
  116. #ifdef WAMR_RTT_EXPORT_DEVICE_OPS_CPP
  117. {
  118. "_Z15rt_device_closeP9rt_device",
  119. wasm_rt_device_close,
  120. "(i)i"
  121. },
  122. {
  123. "_Z14rt_device_readP9rt_devicejPvj",
  124. wasm_rt_device_read,
  125. "(ii*~)i"
  126. },
  127. {
  128. "_Z15rt_device_writeP9rt_devicejPKvj",
  129. wasm_rt_device_write,
  130. "(ii*~)i"
  131. },
  132. {
  133. "_Z14rt_device_openP9rt_devicet",
  134. wasm_rt_device_open,
  135. "(ii)i"
  136. },
  137. {
  138. "_Z14rt_device_findPKc",
  139. wasm_rt_device_find,
  140. "($)i"
  141. },
  142. #endif /* WAMR_RTT_EXPORT_DEVICE_OPS_CPP */
  143. #endif /* WAMR_RTT_EXPORT_DEVICE_OPS */
  144. };
  145. /* clang-format on */
  146. #endif /* WAMR_ENABLE_RTT_EXPORT */
  147. /**
  148. * run WASM module instance.
  149. * @param module_inst instance of wasm module
  150. * @param app_argc wasm argument count
  151. * @param app_argv wasm arguments
  152. * @return NULL
  153. */
  154. static void *
  155. app_instance_main(wasm_module_inst_t module_inst, int app_argc, char **app_argv)
  156. {
  157. const char *exception;
  158. wasm_application_execute_main(module_inst, app_argc, app_argv);
  159. if ((exception = wasm_runtime_get_exception(module_inst)))
  160. rt_kprintf("%s\n", exception);
  161. return NULL;
  162. }
  163. rt_uint8_t *
  164. my_read_file_to_buffer(char *filename, rt_uint32_t *size)
  165. {
  166. struct stat f_stat;
  167. dfs_file_stat(filename, &f_stat);
  168. struct dfs_fd fd;
  169. rt_uint8_t *buff = rt_malloc(f_stat.st_size);
  170. *size = 0;
  171. if (!buff) {
  172. rt_set_errno(-ENOMEM);
  173. return RT_NULL;
  174. }
  175. int ret = dfs_file_open(&fd, filename, O_RDONLY);
  176. if (ret) {
  177. rt_free(buff);
  178. rt_set_errno(ret);
  179. return RT_NULL;
  180. }
  181. *size = dfs_file_read(&fd, buff, f_stat.st_size);
  182. dfs_file_close(&fd);
  183. if (*size != f_stat.st_size) {
  184. rt_free(buff);
  185. rt_set_errno(-EBADF);
  186. return RT_NULL;
  187. }
  188. return buff;
  189. }
  190. void
  191. iwasm_help(void)
  192. {
  193. #ifdef WAMR_ENABLE_IWASM_PARAMS
  194. rt_kputs("wrong input: iwasm [-t] [-m] [-s] <*.wasm> <wasm_args ...>\n"
  195. " iwasm [-h]\n");
  196. rt_kputs("\t -h: show this tips.\n");
  197. rt_kputs("\t -t: show time taking to run this app.\n");
  198. rt_kputs("\t -m: show memory taking to run this app\n");
  199. rt_kputs("\t wasm file name and exec params must behind of all vm-param\n");
  200. #else
  201. rt_kputs("wrong input: iwasm <*.wasm> <wasm_args ...>\n");
  202. #endif /* WAMR_ENABLE_PARAMS */
  203. }
  204. int
  205. iwasm(int argc, char **argv)
  206. {
  207. rt_uint8_t *wasm_file_buf = NULL;
  208. rt_uint32_t wasm_file_size;
  209. rt_uint32_t stack_size = 4 * 1024, heap_size = 4 * 1024;
  210. wasm_module_t wasm_module = NULL;
  211. wasm_module_inst_t wasm_module_inst = NULL;
  212. RuntimeInitArgs init_args;
  213. static char error_buf[128] = { 0 };
  214. /* avoid stack overflow */
  215. #ifdef WAMR_ENABLE_IWASM_PARAMS
  216. int i_arg_begin;
  217. bool show_mem = false;
  218. bool show_stack = false;
  219. bool show_time_exec = false;
  220. for (i_arg_begin = 1; i_arg_begin < argc; i_arg_begin++) {
  221. if (argv[i_arg_begin][0] != '-') {
  222. break;
  223. }
  224. if (argv[i_arg_begin][1] == 'm') {
  225. show_mem = true;
  226. }
  227. else if (argv[i_arg_begin][1] == 's') {
  228. show_stack = true;
  229. }
  230. else if (argv[i_arg_begin][1] == 't') {
  231. show_time_exec = true;
  232. }
  233. else if (argv[i_arg_begin][1] == 'h') {
  234. iwasm_help();
  235. return 0;
  236. }
  237. else if (argv[i_arg_begin][1] == 0x00) {
  238. continue;
  239. }
  240. else {
  241. rt_kprintf("[iwasm] unknown param: %s\n", argv[i_arg_begin]);
  242. }
  243. }
  244. #else /* WAMR_ENABLE_PARAMS */
  245. #define i_arg_begin 1
  246. #endif /* WAMR_ENABLE_PARAMS */
  247. if (argc - i_arg_begin < 1) {
  248. iwasm_help();
  249. return -1;
  250. }
  251. rt_memset(&init_args, 0, sizeof(RuntimeInitArgs));
  252. init_args.mem_alloc_type = Alloc_With_Allocator;
  253. init_args.mem_alloc_option.allocator.malloc_func = os_malloc;
  254. init_args.mem_alloc_option.allocator.realloc_func = os_realloc;
  255. init_args.mem_alloc_option.allocator.free_func = os_free;
  256. #ifdef WAMR_ENABLE_RTT_EXPORT
  257. init_args.native_symbols = native_export_symbols;
  258. init_args.n_native_symbols =
  259. sizeof(native_export_symbols) / sizeof(NativeSymbol);
  260. init_args.native_module_name = "env";
  261. #endif /* WAMR_ENABLE_RTT_EXPORT */
  262. #ifdef WAMR_ENABLE_IWASM_PARAMS
  263. #if defined(RT_USING_HEAP) && defined(RT_USING_MEMHEAP_AS_HEAP)
  264. extern long list_memheap(void);
  265. if (show_mem) {
  266. list_memheap();
  267. }
  268. #else
  269. rt_uint32_t total, max, used;
  270. if (show_mem) {
  271. rt_memory_info(&total, &used, &max);
  272. }
  273. #endif
  274. rt_thread_t tid;
  275. if (show_stack) {
  276. tid = rt_thread_self();
  277. printf("thread stack addr: %p, size: %u, sp: %p\n", tid->stack_addr,
  278. tid->stack_size, tid->sp);
  279. }
  280. #endif /* WAMR_ENABLE_PARAMS */
  281. if (wasm_runtime_full_init(&init_args) == false) {
  282. rt_kprintf("Init WASM runtime environment failed.\n");
  283. return -1;
  284. }
  285. wasm_file_buf = my_read_file_to_buffer(argv[i_arg_begin], &wasm_file_size);
  286. if (!wasm_file_buf) {
  287. rt_err_t err = rt_get_errno();
  288. rt_kprintf("WASM load file to RAM failed: %d\n", err);
  289. goto fail1;
  290. }
  291. rt_memset(error_buf, 0x00, sizeof(error_buf));
  292. wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
  293. sizeof(error_buf));
  294. if (!wasm_module) {
  295. rt_kprintf("%s\n", error_buf);
  296. goto fail2;
  297. }
  298. rt_memset(error_buf, 0x00, sizeof(error_buf));
  299. wasm_module_inst = wasm_runtime_instantiate(
  300. wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf));
  301. if (!wasm_module_inst) {
  302. rt_kprintf("%s\n", error_buf);
  303. goto fail3;
  304. }
  305. #ifdef WAMR_ENABLE_IWASM_PARAMS
  306. rt_tick_t ticks_exec;
  307. if (show_time_exec) {
  308. ticks_exec = rt_tick_get();
  309. }
  310. #endif /* WAMR_ENABLE_PARAMS */
  311. app_instance_main(wasm_module_inst, argc - i_arg_begin, &argv[i_arg_begin]);
  312. #ifdef WAMR_ENABLE_IWASM_PARAMS
  313. if (show_time_exec) {
  314. ticks_exec = rt_tick_get() - ticks_exec;
  315. printf("[iwasm] execute ticks took: %u [ticks/s = %u]\n", ticks_exec,
  316. RT_TICK_PER_SECOND);
  317. }
  318. #if defined(RT_USING_HEAP) && defined(RT_USING_MEMHEAP_AS_HEAP)
  319. if (show_mem) {
  320. list_memheap();
  321. }
  322. #else
  323. rt_uint32_t total_after, max_after, used_after;
  324. if (show_mem) {
  325. rt_memory_info(&total_after, &used_after, &max_after);
  326. rt_kprintf("[iwasm] memory took: %u\n", used_after - used);
  327. }
  328. #endif
  329. if (show_stack) {
  330. printf("[iwasm] thread stack addr: %p, size: %u, sp: %p\n",
  331. tid->stack_addr, tid->stack_size, tid->sp);
  332. }
  333. #endif /* WAMR_ENABLE_PARAMS */
  334. /* destroy the module instance */
  335. wasm_runtime_deinstantiate(wasm_module_inst);
  336. fail3:
  337. /* unload the module */
  338. wasm_runtime_unload(wasm_module);
  339. fail2:
  340. /* free the file buffer */
  341. rt_free(wasm_file_buf);
  342. fail1:
  343. /* destroy runtime environment */
  344. wasm_runtime_destroy();
  345. return 0;
  346. }
  347. MSH_CMD_EXPORT(iwasm, Embeded VM of WebAssembly);