main.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "bh_platform.h"
  8. #include "bh_read_file.h"
  9. #include "wasm_export.h"
  10. #if WASM_ENABLE_LIBC_WASI != 0
  11. #include "../common/libc_wasi.c"
  12. #endif
  13. static int app_argc;
  14. static char **app_argv;
  15. #define MODULE_PATH ("--module-path=")
  16. /* clang-format off */
  17. static int
  18. print_help()
  19. {
  20. printf("Usage: iwasm [-options] wasm_file [args...]\n");
  21. printf("options:\n");
  22. printf(" -f|--function name Specify a function name of the module to run rather\n"
  23. " than main\n");
  24. #if WASM_ENABLE_LOG != 0
  25. printf(" -v=n Set log verbose level (0 to 5, default is 2) larger\n"
  26. " level with more log\n");
  27. #endif
  28. #if WASM_ENABLE_INTERP != 0
  29. printf(" --interp Run the wasm app with interpreter mode\n");
  30. #endif
  31. #if WASM_ENABLE_FAST_JIT != 0
  32. printf(" --fast-jit Run the wasm app with fast jit mode\n");
  33. #endif
  34. #if WASM_ENABLE_JIT != 0
  35. printf(" --llvm-jit Run the wasm app with llvm jit mode\n");
  36. #endif
  37. #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
  38. printf(" --multi-tier-jit Run the wasm app with multi-tier jit mode\n");
  39. #endif
  40. printf(" --stack-size=n Set maximum stack size in bytes, default is 64 KB\n");
  41. #if WASM_ENABLE_LIBC_WASI !=0
  42. printf(" --heap-size=n Set maximum heap size in bytes, default is 0 KB when libc wasi is enabled\n");
  43. #else
  44. printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB when libc wasi is diabled\n");
  45. #endif
  46. #if WASM_ENABLE_GC != 0
  47. printf(" --gc-heap-size=n Set maximum gc heap size in bytes,\n");
  48. printf(" default is %u KB\n", GC_HEAP_SIZE_DEFAULT / 1024);
  49. #endif
  50. #if WASM_ENABLE_JIT != 0
  51. printf(" --llvm-jit-size-level=n Set LLVM JIT size level, default is 3\n");
  52. printf(" --llvm-jit-opt-level=n Set LLVM JIT optimization level, default is 3\n");
  53. #endif
  54. printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n"
  55. " that runs commands in the form of `FUNC ARG...`\n");
  56. #if WASM_ENABLE_LIBC_WASI != 0
  57. libc_wasi_print_help();
  58. #endif
  59. #if WASM_ENABLE_MULTI_MODULE != 0
  60. printf(" --module-path=<path> Indicate a module search path. default is current\n"
  61. " directory('./')\n");
  62. #endif
  63. #if WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0
  64. printf(" --max-threads=n Set maximum thread number per cluster, default is 4\n");
  65. #endif
  66. #if WASM_ENABLE_DEBUG_INTERP != 0
  67. printf(" -g=ip:port Set the debug sever address, default is debug disabled\n");
  68. printf(" if port is 0, then a random port will be used\n");
  69. #endif
  70. printf(" --version Show version information\n");
  71. return 1;
  72. }
  73. /* clang-format on */
  74. static const void *
  75. app_instance_main(wasm_module_inst_t module_inst)
  76. {
  77. const char *exception;
  78. wasm_application_execute_main(module_inst, app_argc, app_argv);
  79. exception = wasm_runtime_get_exception(module_inst);
  80. return exception;
  81. }
  82. static const void *
  83. app_instance_func(wasm_module_inst_t module_inst, const char *func_name)
  84. {
  85. wasm_application_execute_func(module_inst, func_name, app_argc - 1,
  86. app_argv + 1);
  87. /* The result of wasm function or exception info was output inside
  88. wasm_application_execute_func(), here we don't output them again. */
  89. return wasm_runtime_get_exception(module_inst);
  90. }
  91. /**
  92. * Split a space separated strings into an array of strings
  93. * Returns NULL on failure
  94. * Memory must be freed by caller
  95. * Based on: http://stackoverflow.com/a/11198630/471795
  96. */
  97. static char **
  98. split_string(char *str, int *count)
  99. {
  100. char **res = NULL, **res1;
  101. char *p, *next_token;
  102. int idx = 0;
  103. /* split string and append tokens to 'res' */
  104. do {
  105. p = strtok_s(str, " ", &next_token);
  106. str = NULL;
  107. res1 = res;
  108. res = (char **)realloc(res1, sizeof(char *) * (uint32)(idx + 1));
  109. if (res == NULL) {
  110. free(res1);
  111. return NULL;
  112. }
  113. res[idx++] = p;
  114. } while (p);
  115. /**
  116. * Due to the function name,
  117. * res[0] might contain a '\' to indicate a space
  118. * func\name -> func name
  119. */
  120. p = strchr(res[0], '\\');
  121. while (p) {
  122. *p = ' ';
  123. p = strchr(p, '\\');
  124. }
  125. if (count) {
  126. *count = idx - 1;
  127. }
  128. return res;
  129. }
  130. static void *
  131. app_instance_repl(wasm_module_inst_t module_inst)
  132. {
  133. char buffer[4096];
  134. char *cmd;
  135. size_t n;
  136. while ((printf("webassembly> "), fflush(stdout),
  137. cmd = fgets(buffer, sizeof(buffer), stdin))
  138. != NULL) {
  139. bh_assert(cmd);
  140. n = strlen(cmd);
  141. if (cmd[n - 1] == '\n') {
  142. if (n == 1)
  143. continue;
  144. else
  145. cmd[n - 1] = '\0';
  146. }
  147. if (!strcmp(cmd, "__exit__")) {
  148. printf("exit repl mode\n");
  149. break;
  150. }
  151. app_argv = split_string(cmd, &app_argc);
  152. if (app_argv == NULL) {
  153. LOG_ERROR("Wasm prepare param failed: split string failed.\n");
  154. break;
  155. }
  156. if (app_argc != 0) {
  157. const char *exception;
  158. wasm_application_execute_func(module_inst, app_argv[0],
  159. app_argc - 1, app_argv + 1);
  160. if ((exception = wasm_runtime_get_exception(module_inst)))
  161. printf("%s\n", exception);
  162. }
  163. free(app_argv);
  164. }
  165. return NULL;
  166. }
  167. #if WASM_ENABLE_GLOBAL_HEAP_POOL != 0
  168. static char global_heap_buf[WASM_GLOBAL_HEAP_SIZE] = { 0 };
  169. #else
  170. static void *
  171. malloc_func(
  172. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  173. void *user_data,
  174. #endif
  175. unsigned int size)
  176. {
  177. return malloc(size);
  178. }
  179. static void *
  180. realloc_func(
  181. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  182. void *user_data,
  183. #endif
  184. void *ptr, unsigned int size)
  185. {
  186. return realloc(ptr, size);
  187. }
  188. static void
  189. free_func(
  190. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  191. void *user_data,
  192. #endif
  193. void *ptr)
  194. {
  195. free(ptr);
  196. }
  197. #endif /* end of WASM_ENABLE_GLOBAL_HEAP_POOL */
  198. #if WASM_ENABLE_MULTI_MODULE != 0
  199. static char *
  200. handle_module_path(const char *module_path)
  201. {
  202. /* next character after '=' */
  203. return (strchr(module_path, '=')) + 1;
  204. }
  205. static char *module_search_path = ".";
  206. static bool
  207. module_reader_callback(package_type_t module_type, const char *module_name,
  208. uint8 **p_buffer, uint32 *p_size)
  209. {
  210. char *file_format = NULL;
  211. #if WASM_ENABLE_INTERP != 0
  212. if (module_type == Wasm_Module_Bytecode)
  213. file_format = ".wasm";
  214. #endif
  215. #if WASM_ENABLE_AOT != 0
  216. if (module_type == Wasm_Module_AoT)
  217. file_format = ".aot";
  218. #endif
  219. bh_assert(file_format);
  220. const char *format = "%s/%s%s";
  221. int sz = strlen(module_search_path) + strlen("/") + strlen(module_name)
  222. + strlen(file_format) + 1;
  223. char *wasm_file_name = wasm_runtime_malloc(sz);
  224. if (!wasm_file_name) {
  225. return false;
  226. }
  227. snprintf(wasm_file_name, sz, format, module_search_path, module_name,
  228. file_format);
  229. *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size);
  230. wasm_runtime_free(wasm_file_name);
  231. return *p_buffer != NULL;
  232. }
  233. static void
  234. module_destroyer_callback(uint8 *buffer, uint32 size)
  235. {
  236. if (!buffer) {
  237. return;
  238. }
  239. wasm_runtime_free(buffer);
  240. buffer = NULL;
  241. }
  242. #endif /* WASM_ENABLE_MULTI_MODULE */
  243. int
  244. main(int argc, char *argv[])
  245. {
  246. int32 ret = -1;
  247. char *wasm_file = NULL;
  248. const char *func_name = NULL;
  249. uint8 *wasm_file_buf = NULL;
  250. uint32 wasm_file_size;
  251. uint32 stack_size = 64 * 1024;
  252. #if WASM_ENABLE_LIBC_WASI != 0
  253. uint32 heap_size = 0;
  254. #else
  255. uint32 heap_size = 16 * 1024;
  256. #endif
  257. #if WASM_ENABLE_GC != 0
  258. uint32 gc_heap_size = GC_HEAP_SIZE_DEFAULT;
  259. #endif
  260. #if WASM_ENABLE_JIT != 0
  261. uint32 llvm_jit_size_level = 3;
  262. uint32 llvm_jit_opt_level = 3;
  263. #endif
  264. wasm_module_t wasm_module = NULL;
  265. wasm_module_inst_t wasm_module_inst = NULL;
  266. RunningMode running_mode = 0;
  267. RuntimeInitArgs init_args;
  268. char error_buf[128] = { 0 };
  269. #if WASM_ENABLE_LOG != 0
  270. int log_verbose_level = 2;
  271. #endif
  272. bool is_repl_mode = false;
  273. bool is_xip_file = false;
  274. #if WASM_ENABLE_LIBC_WASI != 0
  275. libc_wasi_parse_context_t wasi_parse_ctx;
  276. #endif
  277. #if WASM_ENABLE_DEBUG_INTERP != 0
  278. char *ip_addr = NULL;
  279. int instance_port = 0;
  280. #endif
  281. #if WASM_ENABLE_LIBC_WASI != 0
  282. memset(&wasi_parse_ctx, 0, sizeof(wasi_parse_ctx));
  283. #endif
  284. /* Process options. */
  285. for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
  286. if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--function")) {
  287. argc--, argv++;
  288. if (argc < 2) {
  289. return print_help();
  290. }
  291. func_name = argv[0];
  292. }
  293. #if WASM_ENABLE_INTERP != 0
  294. else if (!strcmp(argv[0], "--interp")) {
  295. running_mode = Mode_Interp;
  296. }
  297. #endif
  298. #if WASM_ENABLE_FAST_JIT != 0
  299. else if (!strcmp(argv[0], "--fast-jit")) {
  300. running_mode = Mode_Fast_JIT;
  301. }
  302. #endif
  303. #if WASM_ENABLE_JIT != 0
  304. else if (!strcmp(argv[0], "--llvm-jit")) {
  305. running_mode = Mode_LLVM_JIT;
  306. }
  307. #endif
  308. #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0
  309. else if (!strcmp(argv[0], "--multi-tier-jit")) {
  310. running_mode = Mode_Multi_Tier_JIT;
  311. }
  312. #endif
  313. #if WASM_ENABLE_LOG != 0
  314. else if (!strncmp(argv[0], "-v=", 3)) {
  315. log_verbose_level = atoi(argv[0] + 3);
  316. if (log_verbose_level < 0 || log_verbose_level > 5)
  317. return print_help();
  318. }
  319. #endif
  320. else if (!strcmp(argv[0], "--repl")) {
  321. is_repl_mode = true;
  322. }
  323. else if (!strncmp(argv[0], "--stack-size=", 13)) {
  324. if (argv[0][13] == '\0')
  325. return print_help();
  326. stack_size = atoi(argv[0] + 13);
  327. }
  328. else if (!strncmp(argv[0], "--heap-size=", 12)) {
  329. if (argv[0][12] == '\0')
  330. return print_help();
  331. heap_size = atoi(argv[0] + 12);
  332. }
  333. #if WASM_ENABLE_GC != 0
  334. else if (!strncmp(argv[0], "--gc-heap-size=", 15)) {
  335. if (argv[0][15] == '\0')
  336. return print_help();
  337. gc_heap_size = atoi(argv[0] + 15);
  338. }
  339. #endif
  340. #if WASM_ENABLE_JIT != 0
  341. else if (!strncmp(argv[0], "--llvm-jit-size-level=", 22)) {
  342. if (argv[0][22] == '\0')
  343. return print_help();
  344. llvm_jit_size_level = atoi(argv[0] + 22);
  345. if (llvm_jit_size_level < 1) {
  346. printf("LLVM JIT size level shouldn't be smaller than 1, "
  347. "setting it to 1\n");
  348. llvm_jit_size_level = 1;
  349. }
  350. else if (llvm_jit_size_level > 3) {
  351. printf("LLVM JIT size level shouldn't be greater than 3, "
  352. "setting it to 3\n");
  353. llvm_jit_size_level = 3;
  354. }
  355. }
  356. else if (!strncmp(argv[0], "--llvm-jit-opt-level=", 21)) {
  357. if (argv[0][21] == '\0')
  358. return print_help();
  359. llvm_jit_opt_level = atoi(argv[0] + 21);
  360. if (llvm_jit_opt_level < 1) {
  361. printf("LLVM JIT opt level shouldn't be smaller than 1, "
  362. "setting it to 1\n");
  363. llvm_jit_opt_level = 1;
  364. }
  365. else if (llvm_jit_opt_level > 3) {
  366. printf("LLVM JIT opt level shouldn't be greater than 3, "
  367. "setting it to 3\n");
  368. llvm_jit_opt_level = 3;
  369. }
  370. }
  371. #endif
  372. #if WASM_ENABLE_MULTI_MODULE != 0
  373. else if (!strncmp(argv[0], MODULE_PATH, strlen(MODULE_PATH))) {
  374. module_search_path = handle_module_path(argv[0]);
  375. if (!strlen(module_search_path)) {
  376. return print_help();
  377. }
  378. }
  379. #endif
  380. #if WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0
  381. else if (!strncmp(argv[0], "--max-threads=", 14)) {
  382. if (argv[0][14] == '\0')
  383. return print_help();
  384. wasm_runtime_set_max_thread_num(atoi(argv[0] + 14));
  385. }
  386. #endif
  387. #if WASM_ENABLE_DEBUG_INTERP != 0
  388. else if (!strncmp(argv[0], "-g=", 3)) {
  389. char *port_str = strchr(argv[0] + 3, ':');
  390. char *port_end;
  391. if (port_str == NULL)
  392. return print_help();
  393. *port_str = '\0';
  394. instance_port = strtoul(port_str + 1, &port_end, 10);
  395. if (port_str[1] == '\0' || *port_end != '\0')
  396. return print_help();
  397. ip_addr = argv[0] + 3;
  398. }
  399. #endif
  400. else if (!strcmp(argv[0], "--version")) {
  401. uint32 major, minor, patch;
  402. wasm_runtime_get_version(&major, &minor, &patch);
  403. printf("iwasm %" PRIu32 ".%" PRIu32 ".%" PRIu32 "\n", major, minor,
  404. patch);
  405. return 0;
  406. }
  407. else {
  408. #if WASM_ENABLE_LIBC_WASI != 0
  409. libc_wasi_parse_result_t result =
  410. libc_wasi_parse(argv[0], &wasi_parse_ctx);
  411. switch (result) {
  412. case LIBC_WASI_PARSE_RESULT_OK:
  413. continue;
  414. case LIBC_WASI_PARSE_RESULT_NEED_HELP:
  415. return print_help();
  416. case LIBC_WASI_PARSE_RESULT_BAD_PARAM:
  417. return 1;
  418. }
  419. #else
  420. return print_help();
  421. #endif
  422. }
  423. }
  424. if (argc == 0)
  425. return print_help();
  426. wasm_file = argv[0];
  427. app_argc = argc;
  428. app_argv = argv;
  429. memset(&init_args, 0, sizeof(RuntimeInitArgs));
  430. init_args.running_mode = running_mode;
  431. #if WASM_ENABLE_GLOBAL_HEAP_POOL != 0
  432. init_args.mem_alloc_type = Alloc_With_Pool;
  433. init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
  434. init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
  435. #else
  436. init_args.mem_alloc_type = Alloc_With_Allocator;
  437. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  438. /* Set user data for the allocator is needed */
  439. /* init_args.mem_alloc_option.allocator.user_data = user_data; */
  440. #endif
  441. init_args.mem_alloc_option.allocator.malloc_func = malloc_func;
  442. init_args.mem_alloc_option.allocator.realloc_func = realloc_func;
  443. init_args.mem_alloc_option.allocator.free_func = free_func;
  444. #endif
  445. #if WASM_ENABLE_GC != 0
  446. init_args.gc_heap_size = gc_heap_size;
  447. #endif
  448. #if WASM_ENABLE_JIT != 0
  449. init_args.llvm_jit_size_level = llvm_jit_size_level;
  450. init_args.llvm_jit_opt_level = llvm_jit_opt_level;
  451. #endif
  452. #if WASM_ENABLE_DEBUG_INTERP != 0
  453. init_args.instance_port = instance_port;
  454. if (ip_addr)
  455. /* ensure that init_args.ip_addr is null terminated */
  456. strncpy_s(init_args.ip_addr, sizeof(init_args.ip_addr) - 1, ip_addr,
  457. strlen(ip_addr));
  458. #endif
  459. /* initialize runtime environment */
  460. if (!wasm_runtime_full_init(&init_args)) {
  461. printf("Init runtime environment failed.\n");
  462. return -1;
  463. }
  464. #if WASM_ENABLE_LOG != 0
  465. bh_log_set_verbose_level(log_verbose_level);
  466. #endif
  467. /* load WASM byte buffer from WASM bin file */
  468. if (!(wasm_file_buf =
  469. (uint8 *)bh_read_file_to_buffer(wasm_file, &wasm_file_size)))
  470. goto fail1;
  471. #if WASM_ENABLE_AOT != 0
  472. if (wasm_runtime_is_xip_file(wasm_file_buf, wasm_file_size)) {
  473. uint8 *wasm_file_mapped;
  474. int map_prot = MMAP_PROT_READ | MMAP_PROT_WRITE | MMAP_PROT_EXEC;
  475. int map_flags = MMAP_MAP_32BIT;
  476. if (!(wasm_file_mapped = os_mmap(NULL, (uint32)wasm_file_size, map_prot,
  477. map_flags, os_get_invalid_handle()))) {
  478. printf("mmap memory failed\n");
  479. wasm_runtime_free(wasm_file_buf);
  480. goto fail1;
  481. }
  482. bh_memcpy_s(wasm_file_mapped, wasm_file_size, wasm_file_buf,
  483. wasm_file_size);
  484. wasm_runtime_free(wasm_file_buf);
  485. wasm_file_buf = wasm_file_mapped;
  486. is_xip_file = true;
  487. }
  488. #endif
  489. #if WASM_ENABLE_MULTI_MODULE != 0
  490. wasm_runtime_set_module_reader(module_reader_callback,
  491. module_destroyer_callback);
  492. #endif
  493. /* load WASM module */
  494. if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size,
  495. error_buf, sizeof(error_buf)))) {
  496. printf("%s\n", error_buf);
  497. goto fail2;
  498. }
  499. #if WASM_ENABLE_LIBC_WASI != 0
  500. libc_wasi_init(wasm_module, argc, argv, &wasi_parse_ctx);
  501. #endif
  502. /* instantiate the module */
  503. if (!(wasm_module_inst =
  504. wasm_runtime_instantiate(wasm_module, stack_size, heap_size,
  505. error_buf, sizeof(error_buf)))) {
  506. printf("%s\n", error_buf);
  507. goto fail3;
  508. }
  509. #if WASM_ENABLE_DEBUG_INTERP != 0
  510. if (ip_addr != NULL) {
  511. wasm_exec_env_t exec_env =
  512. wasm_runtime_get_exec_env_singleton(wasm_module_inst);
  513. uint32_t debug_port;
  514. if (exec_env == NULL) {
  515. printf("%s\n", wasm_runtime_get_exception(wasm_module_inst));
  516. goto fail4;
  517. }
  518. debug_port = wasm_runtime_start_debug_instance(exec_env);
  519. if (debug_port == 0) {
  520. printf("Failed to start debug instance\n");
  521. goto fail4;
  522. }
  523. }
  524. #endif
  525. ret = 0;
  526. const char *exception = NULL;
  527. if (is_repl_mode) {
  528. app_instance_repl(wasm_module_inst);
  529. }
  530. else if (func_name) {
  531. exception = app_instance_func(wasm_module_inst, func_name);
  532. if (exception) {
  533. /* got an exception */
  534. ret = 1;
  535. }
  536. }
  537. else {
  538. exception = app_instance_main(wasm_module_inst);
  539. if (exception) {
  540. /* got an exception */
  541. ret = 1;
  542. }
  543. }
  544. #if WASM_ENABLE_LIBC_WASI != 0
  545. if (ret == 0) {
  546. /* propagate wasi exit code. */
  547. ret = wasm_runtime_get_wasi_exit_code(wasm_module_inst);
  548. }
  549. #endif
  550. if (exception)
  551. printf("%s\n", exception);
  552. #if WASM_ENABLE_DEBUG_INTERP != 0
  553. fail4:
  554. #endif
  555. /* destroy the module instance */
  556. wasm_runtime_deinstantiate(wasm_module_inst);
  557. fail3:
  558. /* unload the module */
  559. wasm_runtime_unload(wasm_module);
  560. fail2:
  561. /* free the file buffer */
  562. if (!is_xip_file)
  563. wasm_runtime_free(wasm_file_buf);
  564. else
  565. os_munmap(wasm_file_buf, wasm_file_size);
  566. fail1:
  567. /* destroy runtime environment */
  568. wasm_runtime_destroy();
  569. return ret;
  570. }