main.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #ifndef _GNU_SOURCE
  6. #define _GNU_SOURCE
  7. #endif
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "bh_platform.h"
  12. #include "bh_read_file.h"
  13. #include "wasm_export.h"
  14. #if BH_HAS_DLFCN
  15. #include <dlfcn.h>
  16. #endif
  17. static int app_argc;
  18. static char **app_argv;
  19. /* clang-format off */
  20. static int
  21. print_help()
  22. {
  23. printf("Usage: iwasm [-options] wasm_file [args...]\n");
  24. printf("options:\n");
  25. printf(" -f|--function name Specify a function name of the module to run rather\n"
  26. " than main\n");
  27. #if WASM_ENABLE_LOG != 0
  28. printf(" -v=n Set log verbose level (0 to 5, default is 2) larger\n"
  29. " level with more log\n");
  30. #endif
  31. #if WASM_ENABLE_INTERP != 0
  32. printf(" --interp Run the wasm app with interpreter mode\n");
  33. #endif
  34. #if WASM_ENABLE_FAST_JIT != 0
  35. printf(" --fast-jit Run the wasm app with fast jit mode\n");
  36. #endif
  37. #if WASM_ENABLE_JIT != 0
  38. printf(" --llvm-jit Run the wasm app with llvm jit mode\n");
  39. #endif
  40. #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
  41. printf(" --multi-tier-jit Run the wasm app with multi-tier jit mode\n");
  42. #endif
  43. printf(" --stack-size=n Set maximum stack size in bytes, default is 64 KB\n");
  44. printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n");
  45. #if WASM_ENABLE_FAST_JIT != 0
  46. printf(" --jit-codecache-size=n Set fast jit maximum code cache size in bytes,\n");
  47. printf(" default is %u KB\n", FAST_JIT_DEFAULT_CODE_CACHE_SIZE / 1024);
  48. #endif
  49. #if WASM_ENABLE_JIT != 0
  50. printf(" --llvm-jit-size-level=n Set LLVM JIT size level, default is 3\n");
  51. printf(" --llvm-jit-opt-level=n Set LLVM JIT optimization level, default is 3\n");
  52. #endif
  53. printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n"
  54. " that runs commands in the form of \"FUNC ARG...\"\n");
  55. #if WASM_ENABLE_LIBC_WASI != 0
  56. printf(" --env=<env> Pass wasi environment variables with \"key=value\"\n");
  57. printf(" to the program, for example:\n");
  58. printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n");
  59. printf(" --dir=<dir> Grant wasi access to the given host directories\n");
  60. printf(" to the program, for example:\n");
  61. printf(" --dir=<dir1> --dir=<dir2>\n");
  62. printf(" --addr-pool=<addrs> Grant wasi access to the given network addresses in\n");
  63. printf(" CIRD notation to the program, seperated with ',',\n");
  64. printf(" for example:\n");
  65. printf(" --addr-pool=1.2.3.4/15,2.3.4.5/16\n");
  66. printf(" --allow-resolve=<domain> Allow the lookup of the specific domain name or domain\n");
  67. printf(" name suffixes using a wildcard, for example:\n");
  68. printf(" --allow-resolve=example.com # allow the lookup of the specific domain\n");
  69. printf(" --allow-resolve=*.example.com # allow the lookup of all subdomains\n");
  70. printf(" --allow-resolve=* # allow any lookup\n");
  71. #endif
  72. #if BH_HAS_DLFCN
  73. printf(" --native-lib=<lib> Register native libraries to the WASM module, which\n");
  74. printf(" are shared object (.so) files, for example:\n");
  75. printf(" --native-lib=test1.so --native-lib=test2.so\n");
  76. #endif
  77. #if WASM_ENABLE_MULTI_MODULE != 0
  78. printf(" --module-path=<path> Indicate a module search path. default is current\n"
  79. " directory('./')\n");
  80. #endif
  81. #if WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0
  82. printf(" --max-threads=n Set maximum thread number per cluster, default is 4\n");
  83. #endif
  84. #if WASM_ENABLE_DEBUG_INTERP != 0
  85. printf(" -g=ip:port Set the debug sever address, default is debug disabled\n");
  86. printf(" if port is 0, then a random port will be used\n");
  87. #endif
  88. printf(" --version Show version information\n");
  89. return 1;
  90. }
  91. /* clang-format on */
  92. static const void *
  93. app_instance_main(wasm_module_inst_t module_inst)
  94. {
  95. const char *exception;
  96. wasm_application_execute_main(module_inst, app_argc, app_argv);
  97. if ((exception = wasm_runtime_get_exception(module_inst)))
  98. printf("%s\n", exception);
  99. return exception;
  100. }
  101. static const void *
  102. app_instance_func(wasm_module_inst_t module_inst, const char *func_name)
  103. {
  104. wasm_application_execute_func(module_inst, func_name, app_argc - 1,
  105. app_argv + 1);
  106. /* The result of wasm function or exception info was output inside
  107. wasm_application_execute_func(), here we don't output them again. */
  108. return wasm_runtime_get_exception(module_inst);
  109. }
  110. /**
  111. * Split a space separated strings into an array of strings
  112. * Returns NULL on failure
  113. * Memory must be freed by caller
  114. * Based on: http://stackoverflow.com/a/11198630/471795
  115. */
  116. static char **
  117. split_string(char *str, int *count)
  118. {
  119. char **res = NULL, **res1;
  120. char *p;
  121. int idx = 0;
  122. /* split string and append tokens to 'res' */
  123. do {
  124. p = strtok(str, " ");
  125. str = NULL;
  126. res1 = res;
  127. res = (char **)realloc(res1, sizeof(char *) * (uint32)(idx + 1));
  128. if (res == NULL) {
  129. free(res1);
  130. return NULL;
  131. }
  132. res[idx++] = p;
  133. } while (p);
  134. /**
  135. * Due to the function name,
  136. * res[0] might contain a '\' to indicate a space
  137. * func\name -> func name
  138. */
  139. p = strchr(res[0], '\\');
  140. while (p) {
  141. *p = ' ';
  142. p = strchr(p, '\\');
  143. }
  144. if (count) {
  145. *count = idx - 1;
  146. }
  147. return res;
  148. }
  149. static void *
  150. app_instance_repl(wasm_module_inst_t module_inst)
  151. {
  152. char *cmd = NULL;
  153. size_t len = 0;
  154. ssize_t n;
  155. while ((printf("webassembly> "), fflush(stdout),
  156. n = getline(&cmd, &len, stdin))
  157. != -1) {
  158. bh_assert(n > 0);
  159. if (cmd[n - 1] == '\n') {
  160. if (n == 1)
  161. continue;
  162. else
  163. cmd[n - 1] = '\0';
  164. }
  165. if (!strcmp(cmd, "__exit__")) {
  166. printf("exit repl mode\n");
  167. break;
  168. }
  169. app_argv = split_string(cmd, &app_argc);
  170. if (app_argv == NULL) {
  171. LOG_ERROR("Wasm prepare param failed: split string failed.\n");
  172. break;
  173. }
  174. if (app_argc != 0) {
  175. wasm_application_execute_func(module_inst, app_argv[0],
  176. app_argc - 1, app_argv + 1);
  177. }
  178. free(app_argv);
  179. }
  180. free(cmd);
  181. return NULL;
  182. }
  183. #if WASM_ENABLE_LIBC_WASI != 0
  184. static bool
  185. validate_env_str(char *env)
  186. {
  187. char *p = env;
  188. int key_len = 0;
  189. while (*p != '\0' && *p != '=') {
  190. key_len++;
  191. p++;
  192. }
  193. if (*p != '=' || key_len == 0)
  194. return false;
  195. return true;
  196. }
  197. #endif
  198. #if BH_HAS_DLFCN
  199. typedef uint32 (*get_native_lib_func)(char **p_module_name,
  200. NativeSymbol **p_native_symbols);
  201. static uint32
  202. load_and_register_native_libs(const char **native_lib_list,
  203. uint32 native_lib_count,
  204. void **native_handle_list)
  205. {
  206. uint32 i, native_handle_count = 0, n_native_symbols;
  207. NativeSymbol *native_symbols;
  208. char *module_name;
  209. void *handle;
  210. for (i = 0; i < native_lib_count; i++) {
  211. /* open the native library */
  212. if (!(handle = dlopen(native_lib_list[i], RTLD_NOW | RTLD_GLOBAL))
  213. && !(handle = dlopen(native_lib_list[i], RTLD_LAZY))) {
  214. LOG_WARNING("warning: failed to load native library %s",
  215. native_lib_list[i]);
  216. continue;
  217. }
  218. /* lookup get_native_lib func */
  219. get_native_lib_func get_native_lib = dlsym(handle, "get_native_lib");
  220. if (!get_native_lib) {
  221. LOG_WARNING("warning: failed to lookup `get_native_lib` function "
  222. "from native lib %s",
  223. native_lib_list[i]);
  224. dlclose(handle);
  225. continue;
  226. }
  227. n_native_symbols = get_native_lib(&module_name, &native_symbols);
  228. /* register native symbols */
  229. if (!(n_native_symbols > 0 && module_name && native_symbols
  230. && wasm_runtime_register_natives(module_name, native_symbols,
  231. n_native_symbols))) {
  232. LOG_WARNING("warning: failed to register native lib %s",
  233. native_lib_list[i]);
  234. dlclose(handle);
  235. continue;
  236. }
  237. native_handle_list[native_handle_count++] = handle;
  238. }
  239. return native_handle_count;
  240. }
  241. static void
  242. unregister_and_unload_native_libs(uint32 native_lib_count,
  243. void **native_handle_list)
  244. {
  245. uint32 i, n_native_symbols;
  246. NativeSymbol *native_symbols;
  247. char *module_name;
  248. void *handle;
  249. for (i = 0; i < native_lib_count; i++) {
  250. handle = native_handle_list[i];
  251. /* lookup get_native_lib func */
  252. get_native_lib_func get_native_lib = dlsym(handle, "get_native_lib");
  253. if (!get_native_lib) {
  254. LOG_WARNING("warning: failed to lookup `get_native_lib` function "
  255. "from native lib %p",
  256. handle);
  257. continue;
  258. }
  259. n_native_symbols = get_native_lib(&module_name, &native_symbols);
  260. if (n_native_symbols == 0 || module_name == NULL
  261. || native_symbols == NULL) {
  262. LOG_WARNING("warning: get_native_lib returned different values for "
  263. "native lib %p",
  264. handle);
  265. continue;
  266. }
  267. /* unregister native symbols */
  268. if (!wasm_runtime_unregister_natives(module_name, native_symbols)) {
  269. LOG_WARNING("warning: failed to unregister native lib %p", handle);
  270. continue;
  271. }
  272. dlclose(handle);
  273. }
  274. }
  275. #endif /* BH_HAS_DLFCN */
  276. #if WASM_ENABLE_MULTI_MODULE != 0
  277. static char *
  278. handle_module_path(const char *module_path)
  279. {
  280. /* next character after = */
  281. return (strchr(module_path, '=')) + 1;
  282. }
  283. static char *module_search_path = ".";
  284. static bool
  285. module_reader_callback(const char *module_name, uint8 **p_buffer,
  286. uint32 *p_size)
  287. {
  288. const char *format = "%s/%s.wasm";
  289. int sz = strlen(module_search_path) + strlen("/") + strlen(module_name)
  290. + strlen(".wasm") + 1;
  291. char *wasm_file_name = BH_MALLOC(sz);
  292. if (!wasm_file_name) {
  293. return false;
  294. }
  295. snprintf(wasm_file_name, sz, format, module_search_path, module_name);
  296. *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size);
  297. wasm_runtime_free(wasm_file_name);
  298. return *p_buffer != NULL;
  299. }
  300. static void
  301. moudle_destroyer(uint8 *buffer, uint32 size)
  302. {
  303. if (!buffer) {
  304. return;
  305. }
  306. wasm_runtime_free(buffer);
  307. buffer = NULL;
  308. }
  309. #endif /* WASM_ENABLE_MULTI_MODULE */
  310. #if WASM_ENABLE_GLOBAL_HEAP_POOL != 0
  311. static char global_heap_buf[WASM_GLOBAL_HEAP_SIZE] = { 0 };
  312. #endif
  313. int
  314. main(int argc, char *argv[])
  315. {
  316. int32 ret = -1;
  317. char *wasm_file = NULL;
  318. const char *func_name = NULL;
  319. uint8 *wasm_file_buf = NULL;
  320. uint32 wasm_file_size;
  321. uint32 stack_size = 64 * 1024, heap_size = 16 * 1024;
  322. #if WASM_ENABLE_FAST_JIT != 0
  323. uint32 jit_code_cache_size = FAST_JIT_DEFAULT_CODE_CACHE_SIZE;
  324. #endif
  325. #if WASM_ENABLE_JIT != 0
  326. uint32 llvm_jit_size_level = 3;
  327. uint32 llvm_jit_opt_level = 3;
  328. #endif
  329. wasm_module_t wasm_module = NULL;
  330. wasm_module_inst_t wasm_module_inst = NULL;
  331. RunningMode running_mode = 0;
  332. RuntimeInitArgs init_args;
  333. char error_buf[128] = { 0 };
  334. #if WASM_ENABLE_LOG != 0
  335. int log_verbose_level = 2;
  336. #endif
  337. bool is_repl_mode = false;
  338. bool is_xip_file = false;
  339. #if WASM_ENABLE_LIBC_WASI != 0
  340. const char *dir_list[8] = { NULL };
  341. uint32 dir_list_size = 0;
  342. const char *env_list[8] = { NULL };
  343. uint32 env_list_size = 0;
  344. const char *addr_pool[8] = { NULL };
  345. uint32 addr_pool_size = 0;
  346. const char *ns_lookup_pool[8] = { NULL };
  347. uint32 ns_lookup_pool_size = 0;
  348. #endif
  349. #if BH_HAS_DLFCN
  350. const char *native_lib_list[8] = { NULL };
  351. uint32 native_lib_count = 0;
  352. void *native_handle_list[8] = { NULL };
  353. uint32 native_handle_count = 0;
  354. #endif
  355. #if WASM_ENABLE_DEBUG_INTERP != 0
  356. char *ip_addr = NULL;
  357. int instance_port = 0;
  358. #endif
  359. /* Process options. */
  360. for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
  361. if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--function")) {
  362. argc--, argv++;
  363. if (argc < 2) {
  364. return print_help();
  365. }
  366. func_name = argv[0];
  367. }
  368. #if WASM_ENABLE_INTERP != 0
  369. else if (!strcmp(argv[0], "--interp")) {
  370. running_mode = Mode_Interp;
  371. }
  372. #endif
  373. #if WASM_ENABLE_FAST_JIT != 0
  374. else if (!strcmp(argv[0], "--fast-jit")) {
  375. running_mode = Mode_Fast_JIT;
  376. }
  377. #endif
  378. #if WASM_ENABLE_JIT != 0
  379. else if (!strcmp(argv[0], "--llvm-jit")) {
  380. running_mode = Mode_LLVM_JIT;
  381. }
  382. #endif
  383. #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \
  384. && WASM_ENABLE_LAZY_JIT != 0
  385. else if (!strcmp(argv[0], "--multi-tier-jit")) {
  386. running_mode = Mode_Multi_Tier_JIT;
  387. }
  388. #endif
  389. #if WASM_ENABLE_LOG != 0
  390. else if (!strncmp(argv[0], "-v=", 3)) {
  391. log_verbose_level = atoi(argv[0] + 3);
  392. if (log_verbose_level < 0 || log_verbose_level > 5)
  393. return print_help();
  394. }
  395. #endif
  396. else if (!strcmp(argv[0], "--repl")) {
  397. is_repl_mode = true;
  398. }
  399. else if (!strncmp(argv[0], "--stack-size=", 13)) {
  400. if (argv[0][13] == '\0')
  401. return print_help();
  402. stack_size = atoi(argv[0] + 13);
  403. }
  404. else if (!strncmp(argv[0], "--heap-size=", 12)) {
  405. if (argv[0][12] == '\0')
  406. return print_help();
  407. heap_size = atoi(argv[0] + 12);
  408. }
  409. #if WASM_ENABLE_FAST_JIT != 0
  410. else if (!strncmp(argv[0], "--jit-codecache-size=", 21)) {
  411. if (argv[0][21] == '\0')
  412. return print_help();
  413. jit_code_cache_size = atoi(argv[0] + 21);
  414. }
  415. #endif
  416. #if WASM_ENABLE_JIT != 0
  417. else if (!strncmp(argv[0], "--llvm-jit-size-level=", 22)) {
  418. if (argv[0][22] == '\0')
  419. return print_help();
  420. llvm_jit_size_level = atoi(argv[0] + 22);
  421. if (llvm_jit_size_level < 1) {
  422. printf("LLVM JIT size level shouldn't be smaller than 1, "
  423. "setting it to 1\n");
  424. llvm_jit_size_level = 1;
  425. }
  426. else if (llvm_jit_size_level > 3) {
  427. printf("LLVM JIT size level shouldn't be greater than 3, "
  428. "setting it to 3\n");
  429. llvm_jit_size_level = 3;
  430. }
  431. }
  432. else if (!strncmp(argv[0], "--llvm-jit-opt-level=", 21)) {
  433. if (argv[0][21] == '\0')
  434. return print_help();
  435. llvm_jit_opt_level = atoi(argv[0] + 21);
  436. if (llvm_jit_opt_level < 1) {
  437. printf("LLVM JIT opt level shouldn't be smaller than 1, "
  438. "setting it to 1\n");
  439. llvm_jit_opt_level = 1;
  440. }
  441. else if (llvm_jit_opt_level > 3) {
  442. printf("LLVM JIT opt level shouldn't be greater than 3, "
  443. "setting it to 3\n");
  444. llvm_jit_opt_level = 3;
  445. }
  446. }
  447. #endif
  448. #if WASM_ENABLE_LIBC_WASI != 0
  449. else if (!strncmp(argv[0], "--dir=", 6)) {
  450. if (argv[0][6] == '\0')
  451. return print_help();
  452. if (dir_list_size >= sizeof(dir_list) / sizeof(char *)) {
  453. printf("Only allow max dir number %d\n",
  454. (int)(sizeof(dir_list) / sizeof(char *)));
  455. return 1;
  456. }
  457. dir_list[dir_list_size++] = argv[0] + 6;
  458. }
  459. else if (!strncmp(argv[0], "--env=", 6)) {
  460. char *tmp_env;
  461. if (argv[0][6] == '\0')
  462. return print_help();
  463. if (env_list_size >= sizeof(env_list) / sizeof(char *)) {
  464. printf("Only allow max env number %d\n",
  465. (int)(sizeof(env_list) / sizeof(char *)));
  466. return 1;
  467. }
  468. tmp_env = argv[0] + 6;
  469. if (validate_env_str(tmp_env))
  470. env_list[env_list_size++] = tmp_env;
  471. else {
  472. printf("Wasm parse env string failed: expect \"key=value\", "
  473. "got \"%s\"\n",
  474. tmp_env);
  475. return print_help();
  476. }
  477. }
  478. /* TODO: parse the configuration file via --addr-pool-file */
  479. else if (!strncmp(argv[0], "--addr-pool=", strlen("--addr-pool="))) {
  480. /* like: --addr-pool=100.200.244.255/30 */
  481. char *token = NULL;
  482. if ('\0' == argv[0][12])
  483. return print_help();
  484. token = strtok(argv[0] + strlen("--addr-pool="), ",");
  485. while (token) {
  486. if (addr_pool_size >= sizeof(addr_pool) / sizeof(char *)) {
  487. printf("Only allow max address number %d\n",
  488. (int)(sizeof(addr_pool) / sizeof(char *)));
  489. return 1;
  490. }
  491. addr_pool[addr_pool_size++] = token;
  492. token = strtok(NULL, ";");
  493. }
  494. }
  495. else if (!strncmp(argv[0], "--allow-resolve=", 16)) {
  496. if (argv[0][16] == '\0')
  497. return print_help();
  498. if (ns_lookup_pool_size
  499. >= sizeof(ns_lookup_pool) / sizeof(ns_lookup_pool[0])) {
  500. printf(
  501. "Only allow max ns lookup number %d\n",
  502. (int)(sizeof(ns_lookup_pool) / sizeof(ns_lookup_pool[0])));
  503. return 1;
  504. }
  505. ns_lookup_pool[ns_lookup_pool_size++] = argv[0] + 16;
  506. }
  507. #endif /* WASM_ENABLE_LIBC_WASI */
  508. #if BH_HAS_DLFCN
  509. else if (!strncmp(argv[0], "--native-lib=", 13)) {
  510. if (argv[0][13] == '\0')
  511. return print_help();
  512. if (native_lib_count >= sizeof(native_lib_list) / sizeof(char *)) {
  513. printf("Only allow max native lib number %d\n",
  514. (int)(sizeof(native_lib_list) / sizeof(char *)));
  515. return 1;
  516. }
  517. native_lib_list[native_lib_count++] = argv[0] + 13;
  518. }
  519. #endif
  520. #if WASM_ENABLE_MULTI_MODULE != 0
  521. else if (!strncmp(argv[0],
  522. "--module-path=", strlen("--module-path="))) {
  523. module_search_path = handle_module_path(argv[0]);
  524. if (!strlen(module_search_path)) {
  525. return print_help();
  526. }
  527. }
  528. #endif
  529. #if WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0
  530. else if (!strncmp(argv[0], "--max-threads=", 14)) {
  531. if (argv[0][14] == '\0')
  532. return print_help();
  533. wasm_runtime_set_max_thread_num(atoi(argv[0] + 14));
  534. }
  535. #endif
  536. #if WASM_ENABLE_DEBUG_INTERP != 0
  537. else if (!strncmp(argv[0], "-g=", 3)) {
  538. char *port_str = strchr(argv[0] + 3, ':');
  539. char *port_end;
  540. if (port_str == NULL)
  541. return print_help();
  542. *port_str = '\0';
  543. instance_port = strtoul(port_str + 1, &port_end, 10);
  544. if (port_str[1] == '\0' || *port_end != '\0')
  545. return print_help();
  546. ip_addr = argv[0] + 3;
  547. }
  548. #endif
  549. else if (!strncmp(argv[0], "--version", 9)) {
  550. uint32 major, minor, patch;
  551. wasm_runtime_get_version(&major, &minor, &patch);
  552. printf("iwasm %" PRIu32 ".%" PRIu32 ".%" PRIu32 "\n", major, minor,
  553. patch);
  554. return 0;
  555. }
  556. else
  557. return print_help();
  558. }
  559. if (argc == 0)
  560. return print_help();
  561. wasm_file = argv[0];
  562. app_argc = argc;
  563. app_argv = argv;
  564. memset(&init_args, 0, sizeof(RuntimeInitArgs));
  565. init_args.running_mode = running_mode;
  566. #if WASM_ENABLE_GLOBAL_HEAP_POOL != 0
  567. init_args.mem_alloc_type = Alloc_With_Pool;
  568. init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
  569. init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
  570. #else
  571. init_args.mem_alloc_type = Alloc_With_Allocator;
  572. init_args.mem_alloc_option.allocator.malloc_func = malloc;
  573. init_args.mem_alloc_option.allocator.realloc_func = realloc;
  574. init_args.mem_alloc_option.allocator.free_func = free;
  575. #endif
  576. #if WASM_ENABLE_FAST_JIT != 0
  577. init_args.fast_jit_code_cache_size = jit_code_cache_size;
  578. #endif
  579. #if WASM_ENABLE_JIT != 0
  580. init_args.llvm_jit_size_level = llvm_jit_size_level;
  581. init_args.llvm_jit_opt_level = llvm_jit_opt_level;
  582. #endif
  583. #if WASM_ENABLE_DEBUG_INTERP != 0
  584. init_args.instance_port = instance_port;
  585. if (ip_addr)
  586. strcpy(init_args.ip_addr, ip_addr);
  587. #endif
  588. /* initialize runtime environment */
  589. if (!wasm_runtime_full_init(&init_args)) {
  590. printf("Init runtime environment failed.\n");
  591. return -1;
  592. }
  593. #if WASM_ENABLE_LOG != 0
  594. bh_log_set_verbose_level(log_verbose_level);
  595. #endif
  596. #if BH_HAS_DLFCN
  597. native_handle_count = load_and_register_native_libs(
  598. native_lib_list, native_lib_count, native_handle_list);
  599. #endif
  600. /* load WASM byte buffer from WASM bin file */
  601. if (!(wasm_file_buf =
  602. (uint8 *)bh_read_file_to_buffer(wasm_file, &wasm_file_size)))
  603. goto fail1;
  604. #if WASM_ENABLE_AOT != 0
  605. if (wasm_runtime_is_xip_file(wasm_file_buf, wasm_file_size)) {
  606. uint8 *wasm_file_mapped;
  607. int map_prot = MMAP_PROT_READ | MMAP_PROT_WRITE | MMAP_PROT_EXEC;
  608. int map_flags = MMAP_MAP_32BIT;
  609. if (!(wasm_file_mapped =
  610. os_mmap(NULL, (uint32)wasm_file_size, map_prot, map_flags))) {
  611. printf("mmap memory failed\n");
  612. wasm_runtime_free(wasm_file_buf);
  613. goto fail1;
  614. }
  615. bh_memcpy_s(wasm_file_mapped, wasm_file_size, wasm_file_buf,
  616. wasm_file_size);
  617. wasm_runtime_free(wasm_file_buf);
  618. wasm_file_buf = wasm_file_mapped;
  619. is_xip_file = true;
  620. }
  621. #endif
  622. #if WASM_ENABLE_MULTI_MODULE != 0
  623. wasm_runtime_set_module_reader(module_reader_callback, moudle_destroyer);
  624. #endif
  625. /* load WASM module */
  626. if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size,
  627. error_buf, sizeof(error_buf)))) {
  628. printf("%s\n", error_buf);
  629. goto fail2;
  630. }
  631. #if WASM_ENABLE_LIBC_WASI != 0
  632. wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0,
  633. env_list, env_list_size, argv, argc);
  634. wasm_runtime_set_wasi_addr_pool(wasm_module, addr_pool, addr_pool_size);
  635. wasm_runtime_set_wasi_ns_lookup_pool(wasm_module, ns_lookup_pool,
  636. ns_lookup_pool_size);
  637. #endif
  638. /* instantiate the module */
  639. if (!(wasm_module_inst =
  640. wasm_runtime_instantiate(wasm_module, stack_size, heap_size,
  641. error_buf, sizeof(error_buf)))) {
  642. printf("%s\n", error_buf);
  643. goto fail3;
  644. }
  645. #if WASM_ENABLE_DEBUG_INTERP != 0
  646. if (ip_addr != NULL) {
  647. wasm_exec_env_t exec_env =
  648. wasm_runtime_get_exec_env_singleton(wasm_module_inst);
  649. uint32_t debug_port;
  650. if (exec_env == NULL) {
  651. printf("%s\n", wasm_runtime_get_exception(wasm_module_inst));
  652. goto fail4;
  653. }
  654. debug_port = wasm_runtime_start_debug_instance(exec_env);
  655. if (debug_port == 0) {
  656. printf("Failed to start debug instance\n");
  657. goto fail4;
  658. }
  659. }
  660. #endif
  661. ret = 0;
  662. if (is_repl_mode) {
  663. app_instance_repl(wasm_module_inst);
  664. }
  665. else if (func_name) {
  666. if (app_instance_func(wasm_module_inst, func_name)) {
  667. /* got an exception */
  668. ret = 1;
  669. }
  670. }
  671. else {
  672. if (app_instance_main(wasm_module_inst)) {
  673. /* got an exception */
  674. ret = 1;
  675. }
  676. }
  677. #if WASM_ENABLE_LIBC_WASI != 0
  678. if (ret == 0) {
  679. /* propagate wasi exit code. */
  680. ret = wasm_runtime_get_wasi_exit_code(wasm_module_inst);
  681. }
  682. #endif
  683. #if WASM_ENABLE_DEBUG_INTERP != 0
  684. fail4:
  685. #endif
  686. /* destroy the module instance */
  687. wasm_runtime_deinstantiate(wasm_module_inst);
  688. fail3:
  689. /* unload the module */
  690. wasm_runtime_unload(wasm_module);
  691. fail2:
  692. /* free the file buffer */
  693. if (!is_xip_file)
  694. wasm_runtime_free(wasm_file_buf);
  695. else
  696. os_munmap(wasm_file_buf, wasm_file_size);
  697. fail1:
  698. #if BH_HAS_DLFCN
  699. /* unload the native libraries */
  700. unregister_and_unload_native_libs(native_handle_count, native_handle_list);
  701. #endif
  702. /* destroy runtime environment */
  703. wasm_runtime_destroy();
  704. return ret;
  705. }