libc_builtin_wrapper.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "bh_common.h"
  6. #include "bh_log.h"
  7. #include "wasm_export.h"
  8. #include "../interpreter/wasm.h"
  9. #if defined(_WIN32) || defined(_WIN32_)
  10. #define strncasecmp _strnicmp
  11. #define strcasecmp _stricmp
  12. #endif
  13. void
  14. wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception);
  15. uint32
  16. wasm_runtime_get_temp_ret(wasm_module_inst_t module);
  17. void
  18. wasm_runtime_set_temp_ret(wasm_module_inst_t module, uint32 temp_ret);
  19. uint32
  20. wasm_runtime_get_llvm_stack(wasm_module_inst_t module);
  21. void
  22. wasm_runtime_set_llvm_stack(wasm_module_inst_t module, uint32 llvm_stack);
  23. uint32
  24. wasm_runtime_module_realloc(wasm_module_inst_t module, uint32 ptr, uint32 size,
  25. void **p_native_addr);
  26. /* clang-format off */
  27. #define get_module_inst(exec_env) \
  28. wasm_runtime_get_module_inst(exec_env)
  29. #define validate_app_addr(offset, size) \
  30. wasm_runtime_validate_app_addr(module_inst, offset, size)
  31. #define validate_app_str_addr(offset) \
  32. wasm_runtime_validate_app_str_addr(module_inst, offset)
  33. #define validate_native_addr(addr, size) \
  34. wasm_runtime_validate_native_addr(module_inst, addr, size)
  35. #define addr_app_to_native(offset) \
  36. wasm_runtime_addr_app_to_native(module_inst, offset)
  37. #define addr_native_to_app(ptr) \
  38. wasm_runtime_addr_native_to_app(module_inst, ptr)
  39. #define module_malloc(size, p_native_addr) \
  40. wasm_runtime_module_malloc(module_inst, size, p_native_addr)
  41. #define module_free(offset) \
  42. wasm_runtime_module_free(module_inst, offset)
  43. /* clang-format on */
  44. typedef int (*out_func_t)(int c, void *ctx);
  45. typedef char *_va_list;
  46. #define _INTSIZEOF(n) (((uint32)sizeof(n) + 3) & (uint32)~3)
  47. #define _va_arg(ap, t) (*(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
  48. #define CHECK_VA_ARG(ap, t) \
  49. do { \
  50. if ((uint8 *)ap + _INTSIZEOF(t) > native_end_addr) { \
  51. if (fmt_buf != temp_fmt) { \
  52. wasm_runtime_free(fmt_buf); \
  53. } \
  54. goto fail; \
  55. } \
  56. } while (0)
  57. /* clang-format off */
  58. #define PREPARE_TEMP_FORMAT() \
  59. char temp_fmt[32], *s, *fmt_buf = temp_fmt; \
  60. uint32 fmt_buf_len = (uint32)sizeof(temp_fmt); \
  61. int32 n; \
  62. \
  63. /* additional 2 bytes: one is the format char, \
  64. the other is `\0` */ \
  65. if ((uint32)(fmt - fmt_start_addr + 2) >= fmt_buf_len) { \
  66. bh_assert((uint32)(fmt - fmt_start_addr) <= \
  67. UINT32_MAX - 2); \
  68. fmt_buf_len = (uint32)(fmt - fmt_start_addr + 2); \
  69. if (!(fmt_buf = wasm_runtime_malloc(fmt_buf_len))) { \
  70. print_err(out, ctx); \
  71. break; \
  72. } \
  73. } \
  74. \
  75. memset(fmt_buf, 0, fmt_buf_len); \
  76. bh_memcpy_s(fmt_buf, fmt_buf_len, fmt_start_addr, \
  77. (uint32)(fmt - fmt_start_addr + 1));
  78. /* clang-format on */
  79. #define OUTPUT_TEMP_FORMAT() \
  80. do { \
  81. if (n > 0) { \
  82. s = buf; \
  83. while (*s) \
  84. out((int)(*s++), ctx); \
  85. } \
  86. \
  87. if (fmt_buf != temp_fmt) { \
  88. wasm_runtime_free(fmt_buf); \
  89. } \
  90. } while (0)
  91. static void
  92. print_err(out_func_t out, void *ctx)
  93. {
  94. out('E', ctx);
  95. out('R', ctx);
  96. out('R', ctx);
  97. }
  98. static bool
  99. _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap,
  100. wasm_module_inst_t module_inst)
  101. {
  102. int might_format = 0; /* 1 if encountered a '%' */
  103. int long_ctr = 0;
  104. uint8 *native_end_addr;
  105. const char *fmt_start_addr = NULL;
  106. if (!wasm_runtime_get_native_addr_range(module_inst, (uint8 *)ap, NULL,
  107. &native_end_addr))
  108. goto fail;
  109. /* fmt has already been adjusted if needed */
  110. while (*fmt) {
  111. if (!might_format) {
  112. if (*fmt != '%') {
  113. out((int)*fmt, ctx);
  114. }
  115. else {
  116. might_format = 1;
  117. long_ctr = 0;
  118. fmt_start_addr = fmt;
  119. }
  120. }
  121. else {
  122. switch (*fmt) {
  123. case '.':
  124. case '+':
  125. case '-':
  126. case ' ':
  127. case '#':
  128. case '0':
  129. case '1':
  130. case '2':
  131. case '3':
  132. case '4':
  133. case '5':
  134. case '6':
  135. case '7':
  136. case '8':
  137. case '9':
  138. goto still_might_format;
  139. case 't': /* ptrdiff_t */
  140. case 'z': /* size_t (32bit on wasm) */
  141. long_ctr = 1;
  142. goto still_might_format;
  143. case 'j':
  144. /* intmax_t/uintmax_t */
  145. long_ctr = 2;
  146. goto still_might_format;
  147. case 'l':
  148. long_ctr++;
  149. /* Fall through */
  150. case 'h':
  151. /* FIXME: do nothing for these modifiers */
  152. goto still_might_format;
  153. case 'o':
  154. case 'd':
  155. case 'i':
  156. case 'u':
  157. case 'p':
  158. case 'x':
  159. case 'X':
  160. case 'c':
  161. {
  162. char buf[64];
  163. PREPARE_TEMP_FORMAT();
  164. if (long_ctr < 2) {
  165. int32 d;
  166. CHECK_VA_ARG(ap, uint32);
  167. d = _va_arg(ap, int32);
  168. if (long_ctr == 1) {
  169. uint32 fmt_end_idx = (uint32)(fmt - fmt_start_addr);
  170. if (fmt_buf[fmt_end_idx - 1] == 'l'
  171. || fmt_buf[fmt_end_idx - 1] == 'z'
  172. || fmt_buf[fmt_end_idx - 1] == 't') {
  173. /* The %ld, %zd and %td should be treated as
  174. * 32bit integer in wasm */
  175. fmt_buf[fmt_end_idx - 1] = fmt_buf[fmt_end_idx];
  176. fmt_buf[fmt_end_idx] = '\0';
  177. }
  178. }
  179. n = snprintf(buf, sizeof(buf), fmt_buf, d);
  180. }
  181. else {
  182. int64 lld;
  183. /* Make 8-byte aligned */
  184. ap = (_va_list)(((uintptr_t)ap + 7) & ~(uintptr_t)7);
  185. CHECK_VA_ARG(ap, uint64);
  186. lld = _va_arg(ap, int64);
  187. n = snprintf(buf, sizeof(buf), fmt_buf, lld);
  188. }
  189. OUTPUT_TEMP_FORMAT();
  190. break;
  191. }
  192. case 's':
  193. {
  194. char buf_tmp[128], *buf = buf_tmp;
  195. char *start;
  196. uint32 s_offset, str_len, buf_len;
  197. PREPARE_TEMP_FORMAT();
  198. CHECK_VA_ARG(ap, int32);
  199. s_offset = _va_arg(ap, uint32);
  200. if (!validate_app_str_addr(s_offset)) {
  201. if (fmt_buf != temp_fmt) {
  202. wasm_runtime_free(fmt_buf);
  203. }
  204. return false;
  205. }
  206. s = start = addr_app_to_native(s_offset);
  207. str_len = (uint32)strlen(start);
  208. if (str_len >= UINT32_MAX - 64) {
  209. print_err(out, ctx);
  210. if (fmt_buf != temp_fmt) {
  211. wasm_runtime_free(fmt_buf);
  212. }
  213. break;
  214. }
  215. /* reserve 64 more bytes as there may be width description
  216. * in the fmt */
  217. buf_len = str_len + 64;
  218. if (buf_len > (uint32)sizeof(buf_tmp)) {
  219. if (!(buf = wasm_runtime_malloc(buf_len))) {
  220. print_err(out, ctx);
  221. if (fmt_buf != temp_fmt) {
  222. wasm_runtime_free(fmt_buf);
  223. }
  224. break;
  225. }
  226. }
  227. n = snprintf(buf, buf_len, fmt_buf,
  228. (s_offset == 0 && str_len == 0) ? NULL
  229. : start);
  230. OUTPUT_TEMP_FORMAT();
  231. if (buf != buf_tmp) {
  232. wasm_runtime_free(buf);
  233. }
  234. break;
  235. }
  236. case '%':
  237. {
  238. out((int)'%', ctx);
  239. break;
  240. }
  241. case 'e':
  242. case 'E':
  243. case 'g':
  244. case 'G':
  245. case 'f':
  246. case 'F':
  247. {
  248. float64 f64;
  249. char buf[64];
  250. PREPARE_TEMP_FORMAT();
  251. /* Make 8-byte aligned */
  252. ap = (_va_list)(((uintptr_t)ap + 7) & ~(uintptr_t)7);
  253. CHECK_VA_ARG(ap, float64);
  254. f64 = _va_arg(ap, float64);
  255. n = snprintf(buf, sizeof(buf), fmt_buf, f64);
  256. OUTPUT_TEMP_FORMAT();
  257. break;
  258. }
  259. case 'n':
  260. /* print nothing */
  261. break;
  262. default:
  263. out((int)'%', ctx);
  264. out((int)*fmt, ctx);
  265. break;
  266. }
  267. might_format = 0;
  268. }
  269. still_might_format:
  270. ++fmt;
  271. }
  272. return true;
  273. fail:
  274. wasm_runtime_set_exception(module_inst, "out of bounds memory access");
  275. return false;
  276. }
  277. struct str_context {
  278. char *str;
  279. uint32 max;
  280. uint32 count;
  281. };
  282. static int
  283. sprintf_out(int c, struct str_context *ctx)
  284. {
  285. if (!ctx->str || ctx->count >= ctx->max) {
  286. ctx->count++;
  287. return c;
  288. }
  289. if (ctx->count == ctx->max - 1) {
  290. ctx->str[ctx->count++] = '\0';
  291. }
  292. else {
  293. ctx->str[ctx->count++] = (char)c;
  294. }
  295. return c;
  296. }
  297. #ifdef BH_PLATFORM_OPENRTOS
  298. PRIVILEGED_DATA static char print_buf[128] = { 0 };
  299. PRIVILEGED_DATA static int print_buf_size = 0;
  300. static int
  301. printf_out(int c, struct str_context *ctx)
  302. {
  303. if (c == '\n') {
  304. print_buf[print_buf_size] = '\0';
  305. os_printf("%s\n", print_buf);
  306. print_buf_size = 0;
  307. }
  308. else if (print_buf_size >= sizeof(print_buf) - 2) {
  309. print_buf[print_buf_size++] = (char)c;
  310. print_buf[print_buf_size] = '\0';
  311. os_printf("%s\n", print_buf);
  312. print_buf_size = 0;
  313. }
  314. else {
  315. print_buf[print_buf_size++] = (char)c;
  316. }
  317. ctx->count++;
  318. return c;
  319. }
  320. #else
  321. static int
  322. printf_out(int c, struct str_context *ctx)
  323. {
  324. os_printf("%c", c);
  325. ctx->count++;
  326. return c;
  327. }
  328. #endif
  329. static int
  330. printf_wrapper(wasm_exec_env_t exec_env, const char *format, _va_list va_args)
  331. {
  332. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  333. struct str_context ctx = { NULL, 0, 0 };
  334. /* format has been checked by runtime */
  335. if (!validate_native_addr(va_args, sizeof(int32)))
  336. return 0;
  337. if (!_vprintf_wa((out_func_t)printf_out, &ctx, format, va_args,
  338. module_inst))
  339. return 0;
  340. return (int)ctx.count;
  341. }
  342. static int
  343. sprintf_wrapper(wasm_exec_env_t exec_env, char *str, const char *format,
  344. _va_list va_args)
  345. {
  346. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  347. uint8 *native_end_offset;
  348. struct str_context ctx;
  349. /* str and format have been checked by runtime */
  350. if (!validate_native_addr(va_args, sizeof(uint32)))
  351. return 0;
  352. if (!wasm_runtime_get_native_addr_range(module_inst, (uint8 *)str, NULL,
  353. &native_end_offset)) {
  354. wasm_runtime_set_exception(module_inst, "out of bounds memory access");
  355. return false;
  356. }
  357. ctx.str = str;
  358. ctx.max = (uint32)(native_end_offset - (uint8 *)str);
  359. ctx.count = 0;
  360. if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args,
  361. module_inst))
  362. return 0;
  363. if (ctx.count < ctx.max) {
  364. str[ctx.count] = '\0';
  365. }
  366. return (int)ctx.count;
  367. }
  368. static int
  369. snprintf_wrapper(wasm_exec_env_t exec_env, char *str, uint32 size,
  370. const char *format, _va_list va_args)
  371. {
  372. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  373. struct str_context ctx;
  374. /* str and format have been checked by runtime */
  375. if (!validate_native_addr(va_args, sizeof(uint32)))
  376. return 0;
  377. ctx.str = str;
  378. ctx.max = size;
  379. ctx.count = 0;
  380. if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args,
  381. module_inst))
  382. return 0;
  383. if (ctx.count < ctx.max) {
  384. str[ctx.count] = '\0';
  385. }
  386. return (int)ctx.count;
  387. }
  388. static int
  389. puts_wrapper(wasm_exec_env_t exec_env, const char *str)
  390. {
  391. return os_printf("%s\n", str);
  392. }
  393. static int
  394. putchar_wrapper(wasm_exec_env_t exec_env, int c)
  395. {
  396. os_printf("%c", c);
  397. return 1;
  398. }
  399. static uint32
  400. strdup_wrapper(wasm_exec_env_t exec_env, const char *str)
  401. {
  402. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  403. char *str_ret;
  404. uint32 len;
  405. uint32 str_ret_offset = 0;
  406. /* str has been checked by runtime */
  407. if (str) {
  408. len = (uint32)strlen(str) + 1;
  409. str_ret_offset = module_malloc(len, (void **)&str_ret);
  410. if (str_ret_offset) {
  411. bh_memcpy_s(str_ret, len, str, len);
  412. }
  413. }
  414. return str_ret_offset;
  415. }
  416. static uint32
  417. _strdup_wrapper(wasm_exec_env_t exec_env, const char *str)
  418. {
  419. return strdup_wrapper(exec_env, str);
  420. }
  421. static int32
  422. memcmp_wrapper(wasm_exec_env_t exec_env, const void *s1, const void *s2,
  423. uint32 size)
  424. {
  425. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  426. /* s2 has been checked by runtime */
  427. if (!validate_native_addr((void *)s1, size))
  428. return 0;
  429. return memcmp(s1, s2, size);
  430. }
  431. static uint32
  432. memcpy_wrapper(wasm_exec_env_t exec_env, void *dst, const void *src,
  433. uint32 size)
  434. {
  435. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  436. uint32 dst_offset = addr_native_to_app(dst);
  437. if (size == 0)
  438. return dst_offset;
  439. /* src has been checked by runtime */
  440. if (!validate_native_addr(dst, size))
  441. return dst_offset;
  442. bh_memcpy_s(dst, size, src, size);
  443. return dst_offset;
  444. }
  445. static uint32
  446. memmove_wrapper(wasm_exec_env_t exec_env, void *dst, void *src, uint32 size)
  447. {
  448. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  449. uint32 dst_offset = addr_native_to_app(dst);
  450. if (size == 0)
  451. return dst_offset;
  452. /* src has been checked by runtime */
  453. if (!validate_native_addr(dst, size))
  454. return dst_offset;
  455. memmove(dst, src, size);
  456. return dst_offset;
  457. }
  458. static uint32
  459. memset_wrapper(wasm_exec_env_t exec_env, void *s, int32 c, uint32 size)
  460. {
  461. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  462. uint32 s_offset = addr_native_to_app(s);
  463. if (!validate_native_addr(s, size))
  464. return s_offset;
  465. memset(s, c, size);
  466. return s_offset;
  467. }
  468. static uint32
  469. strchr_wrapper(wasm_exec_env_t exec_env, const char *s, int32 c)
  470. {
  471. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  472. char *ret;
  473. /* s has been checked by runtime */
  474. ret = strchr(s, c);
  475. return ret ? addr_native_to_app(ret) : 0;
  476. }
  477. static int32
  478. strcmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2)
  479. {
  480. /* s1 and s2 have been checked by runtime */
  481. return strcmp(s1, s2);
  482. }
  483. static int32
  484. strncmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2,
  485. uint32 size)
  486. {
  487. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  488. /* s2 has been checked by runtime */
  489. if (!validate_native_addr((void *)s1, size))
  490. return 0;
  491. return strncmp(s1, s2, size);
  492. }
  493. static uint32
  494. strcpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src)
  495. {
  496. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  497. uint32 len = (uint32)strlen(src) + 1;
  498. /* src has been checked by runtime */
  499. if (!validate_native_addr(dst, len))
  500. return 0;
  501. #ifndef BH_PLATFORM_WINDOWS
  502. strncpy(dst, src, len);
  503. #else
  504. strncpy_s(dst, len, src, len);
  505. #endif
  506. return addr_native_to_app(dst);
  507. }
  508. static uint32
  509. strncpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src,
  510. uint32 size)
  511. {
  512. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  513. /* src has been checked by runtime */
  514. if (!validate_native_addr(dst, size))
  515. return 0;
  516. #ifndef BH_PLATFORM_WINDOWS
  517. strncpy(dst, src, size);
  518. #else
  519. strncpy_s(dst, size, src, size);
  520. #endif
  521. return addr_native_to_app(dst);
  522. }
  523. static uint32
  524. strlen_wrapper(wasm_exec_env_t exec_env, const char *s)
  525. {
  526. /* s has been checked by runtime */
  527. return (uint32)strlen(s);
  528. }
  529. static uint32
  530. malloc_wrapper(wasm_exec_env_t exec_env, uint32 size)
  531. {
  532. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  533. return module_malloc(size, NULL);
  534. }
  535. static uint32
  536. calloc_wrapper(wasm_exec_env_t exec_env, uint32 nmemb, uint32 size)
  537. {
  538. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  539. uint64 total_size = (uint64)nmemb * (uint64)size;
  540. uint32 ret_offset = 0;
  541. uint8 *ret_ptr;
  542. if (total_size >= UINT32_MAX)
  543. return 0;
  544. ret_offset = module_malloc((uint32)total_size, (void **)&ret_ptr);
  545. if (ret_offset) {
  546. memset(ret_ptr, 0, (uint32)total_size);
  547. }
  548. return ret_offset;
  549. }
  550. static uint32
  551. realloc_wrapper(wasm_exec_env_t exec_env, uint32 ptr, uint32 new_size)
  552. {
  553. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  554. return wasm_runtime_module_realloc(module_inst, ptr, new_size, NULL);
  555. }
  556. static void
  557. free_wrapper(wasm_exec_env_t exec_env, void *ptr)
  558. {
  559. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  560. if (!validate_native_addr(ptr, sizeof(uint32)))
  561. return;
  562. module_free(addr_native_to_app(ptr));
  563. }
  564. static int32
  565. atoi_wrapper(wasm_exec_env_t exec_env, const char *s)
  566. {
  567. /* s has been checked by runtime */
  568. return atoi(s);
  569. }
  570. static void
  571. exit_wrapper(wasm_exec_env_t exec_env, int32 status)
  572. {
  573. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  574. char buf[32];
  575. snprintf(buf, sizeof(buf), "env.exit(%" PRId32 ")", status);
  576. wasm_runtime_set_exception(module_inst, buf);
  577. }
  578. static int32
  579. strtol_wrapper(wasm_exec_env_t exec_env, const char *nptr, char **endptr,
  580. int32 base)
  581. {
  582. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  583. int32 num = 0;
  584. /* nptr has been checked by runtime */
  585. if (!validate_native_addr(endptr, sizeof(uint32)))
  586. return 0;
  587. num = (int32)strtol(nptr, endptr, base);
  588. *(uint32 *)endptr = addr_native_to_app(*endptr);
  589. return num;
  590. }
  591. static uint32
  592. strtoul_wrapper(wasm_exec_env_t exec_env, const char *nptr, char **endptr,
  593. int32 base)
  594. {
  595. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  596. uint32 num = 0;
  597. /* nptr has been checked by runtime */
  598. if (!validate_native_addr(endptr, sizeof(uint32)))
  599. return 0;
  600. num = (uint32)strtoul(nptr, endptr, base);
  601. *(uint32 *)endptr = addr_native_to_app(*endptr);
  602. return num;
  603. }
  604. static uint32
  605. memchr_wrapper(wasm_exec_env_t exec_env, const void *s, int32 c, uint32 n)
  606. {
  607. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  608. void *res;
  609. if (!validate_native_addr((void *)s, n))
  610. return 0;
  611. res = memchr(s, c, n);
  612. return addr_native_to_app(res);
  613. }
  614. static int32
  615. strncasecmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2,
  616. uint32 n)
  617. {
  618. /* s1 and s2 have been checked by runtime */
  619. return strncasecmp(s1, s2, n);
  620. }
  621. static uint32
  622. strspn_wrapper(wasm_exec_env_t exec_env, const char *s, const char *accept)
  623. {
  624. /* s and accept have been checked by runtime */
  625. return (uint32)strspn(s, accept);
  626. }
  627. static uint32
  628. strcspn_wrapper(wasm_exec_env_t exec_env, const char *s, const char *reject)
  629. {
  630. /* s and reject have been checked by runtime */
  631. return (uint32)strcspn(s, reject);
  632. }
  633. static uint32
  634. strstr_wrapper(wasm_exec_env_t exec_env, const char *s, const char *find)
  635. {
  636. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  637. /* s and find have been checked by runtime */
  638. char *res = strstr(s, find);
  639. return addr_native_to_app(res);
  640. }
  641. static int32
  642. isupper_wrapper(wasm_exec_env_t exec_env, int32 c)
  643. {
  644. return isupper(c);
  645. }
  646. static int32
  647. isalpha_wrapper(wasm_exec_env_t exec_env, int32 c)
  648. {
  649. return isalpha(c);
  650. }
  651. static int32
  652. isspace_wrapper(wasm_exec_env_t exec_env, int32 c)
  653. {
  654. return isspace(c);
  655. }
  656. static int32
  657. isgraph_wrapper(wasm_exec_env_t exec_env, int32 c)
  658. {
  659. return isgraph(c);
  660. }
  661. static int32
  662. isprint_wrapper(wasm_exec_env_t exec_env, int32 c)
  663. {
  664. return isprint(c);
  665. }
  666. static int32
  667. isdigit_wrapper(wasm_exec_env_t exec_env, int32 c)
  668. {
  669. return isdigit(c);
  670. }
  671. static int32
  672. isxdigit_wrapper(wasm_exec_env_t exec_env, int32 c)
  673. {
  674. return isxdigit(c);
  675. }
  676. static int32
  677. tolower_wrapper(wasm_exec_env_t exec_env, int32 c)
  678. {
  679. return tolower(c);
  680. }
  681. static int32
  682. toupper_wrapper(wasm_exec_env_t exec_env, int32 c)
  683. {
  684. return toupper(c);
  685. }
  686. static int32
  687. isalnum_wrapper(wasm_exec_env_t exec_env, int32 c)
  688. {
  689. return isalnum(c);
  690. }
  691. static void
  692. setTempRet0_wrapper(wasm_exec_env_t exec_env, uint32 temp_ret)
  693. {
  694. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  695. wasm_runtime_set_temp_ret(module_inst, temp_ret);
  696. }
  697. static uint32
  698. getTempRet0_wrapper(wasm_exec_env_t exec_env)
  699. {
  700. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  701. return wasm_runtime_get_temp_ret(module_inst);
  702. }
  703. static uint32
  704. llvm_bswap_i16_wrapper(wasm_exec_env_t exec_env, uint32 data)
  705. {
  706. return (data & 0xFFFF0000) | ((data & 0xFF) << 8) | ((data & 0xFF00) >> 8);
  707. }
  708. static uint32
  709. llvm_bswap_i32_wrapper(wasm_exec_env_t exec_env, uint32 data)
  710. {
  711. return ((data & 0xFF) << 24) | ((data & 0xFF00) << 8)
  712. | ((data & 0xFF0000) >> 8) | ((data & 0xFF000000) >> 24);
  713. }
  714. static uint32
  715. bitshift64Lshr_wrapper(wasm_exec_env_t exec_env, uint32 uint64_part0,
  716. uint32 uint64_part1, uint32 bits)
  717. {
  718. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  719. union {
  720. uint64 value;
  721. uint32 parts[2];
  722. } u;
  723. u.parts[0] = uint64_part0;
  724. u.parts[1] = uint64_part1;
  725. u.value >>= bits;
  726. /* return low 32bit and save high 32bit to temp ret */
  727. wasm_runtime_set_temp_ret(module_inst, (uint32)(u.value >> 32));
  728. return (uint32)u.value;
  729. }
  730. static uint32
  731. bitshift64Shl_wrapper(wasm_exec_env_t exec_env, uint32 int64_part0,
  732. uint32 int64_part1, uint32 bits)
  733. {
  734. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  735. union {
  736. int64 value;
  737. uint32 parts[2];
  738. } u;
  739. u.parts[0] = int64_part0;
  740. u.parts[1] = int64_part1;
  741. u.value <<= bits;
  742. /* return low 32bit and save high 32bit to temp ret */
  743. wasm_runtime_set_temp_ret(module_inst, (uint32)(u.value >> 32));
  744. return (uint32)u.value;
  745. }
  746. static void
  747. llvm_stackrestore_wrapper(wasm_exec_env_t exec_env, uint32 llvm_stack)
  748. {
  749. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  750. os_printf("_llvm_stackrestore called!\n");
  751. wasm_runtime_set_llvm_stack(module_inst, llvm_stack);
  752. }
  753. static uint32
  754. llvm_stacksave_wrapper(wasm_exec_env_t exec_env)
  755. {
  756. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  757. os_printf("_llvm_stacksave called!\n");
  758. return wasm_runtime_get_llvm_stack(module_inst);
  759. }
  760. static uint32
  761. emscripten_memcpy_big_wrapper(wasm_exec_env_t exec_env, void *dst,
  762. const void *src, uint32 size)
  763. {
  764. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  765. uint32 dst_offset = addr_native_to_app(dst);
  766. /* src has been checked by runtime */
  767. if (!validate_native_addr(dst, size))
  768. return dst_offset;
  769. bh_memcpy_s(dst, size, src, size);
  770. return dst_offset;
  771. }
  772. static void
  773. abort_wrapper(wasm_exec_env_t exec_env, int32 code)
  774. {
  775. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  776. char buf[32];
  777. snprintf(buf, sizeof(buf), "env.abort(%" PRId32 ")", code);
  778. wasm_runtime_set_exception(module_inst, buf);
  779. }
  780. static void
  781. abortStackOverflow_wrapper(wasm_exec_env_t exec_env, int32 code)
  782. {
  783. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  784. char buf[32];
  785. snprintf(buf, sizeof(buf), "env.abortStackOverflow(%" PRId32 ")", code);
  786. wasm_runtime_set_exception(module_inst, buf);
  787. }
  788. static void
  789. nullFunc_X_wrapper(wasm_exec_env_t exec_env, int32 code)
  790. {
  791. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  792. char buf[32];
  793. snprintf(buf, sizeof(buf), "env.nullFunc_X(%" PRId32 ")", code);
  794. wasm_runtime_set_exception(module_inst, buf);
  795. }
  796. static uint32
  797. __cxa_allocate_exception_wrapper(wasm_exec_env_t exec_env, uint32 thrown_size)
  798. {
  799. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  800. uint32 exception = module_malloc(thrown_size, NULL);
  801. if (!exception)
  802. return 0;
  803. return exception;
  804. }
  805. static void
  806. __cxa_begin_catch_wrapper(wasm_exec_env_t exec_env, void *exception_object)
  807. {}
  808. static void
  809. __cxa_throw_wrapper(wasm_exec_env_t exec_env, void *thrown_exception,
  810. void *tinfo, uint32 table_elem_idx)
  811. {
  812. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  813. char buf[32];
  814. snprintf(buf, sizeof(buf), "%s", "exception thrown by stdc++");
  815. wasm_runtime_set_exception(module_inst, buf);
  816. }
  817. struct timespec_app {
  818. int64 tv_sec;
  819. int32 tv_nsec;
  820. };
  821. static uint32
  822. clock_gettime_wrapper(wasm_exec_env_t exec_env, uint32 clk_id,
  823. struct timespec_app *ts_app)
  824. {
  825. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  826. uint64 time;
  827. if (!validate_native_addr(ts_app, sizeof(struct timespec_app)))
  828. return (uint32)-1;
  829. time = os_time_get_boot_microsecond();
  830. ts_app->tv_sec = time / 1000000;
  831. ts_app->tv_nsec = (time % 1000000) * 1000;
  832. return (uint32)0;
  833. }
  834. static uint64
  835. clock_wrapper(wasm_exec_env_t exec_env)
  836. {
  837. /* Convert to nano seconds as CLOCKS_PER_SEC in wasi-sdk */
  838. return os_time_get_boot_microsecond() * 1000;
  839. }
  840. #if WASM_ENABLE_SPEC_TEST != 0
  841. static void
  842. print_wrapper(wasm_exec_env_t exec_env)
  843. {
  844. os_printf("in specttest.print()\n");
  845. }
  846. static void
  847. print_i32_wrapper(wasm_exec_env_t exec_env, int32 i32)
  848. {
  849. os_printf("in specttest.print_i32(%d)\n", i32);
  850. }
  851. static void
  852. print_i32_f32_wrapper(wasm_exec_env_t exec_env, int32 i32, float f32)
  853. {
  854. os_printf("in specttest.print_i32_f32(%d, %f)\n", i32, f32);
  855. }
  856. static void
  857. print_f64_f64_wrapper(wasm_exec_env_t exec_env, double f64_1, double f64_2)
  858. {
  859. os_printf("in specttest.print_f64_f64(%f, %f)\n", f64_1, f64_2);
  860. }
  861. static void
  862. print_f32_wrapper(wasm_exec_env_t exec_env, float f32)
  863. {
  864. os_printf("in specttest.print_f32(%f)\n", f32);
  865. }
  866. static void
  867. print_f64_wrapper(wasm_exec_env_t exec_env, double f64)
  868. {
  869. os_printf("in specttest.print_f64(%f)\n", f64);
  870. }
  871. #endif /* WASM_ENABLE_SPEC_TEST */
  872. /* clang-format off */
  873. #define REG_NATIVE_FUNC(func_name, signature) \
  874. { #func_name, func_name##_wrapper, signature, NULL }
  875. /* clang-format on */
  876. static NativeSymbol native_symbols_libc_builtin[] = {
  877. REG_NATIVE_FUNC(printf, "($*)i"),
  878. REG_NATIVE_FUNC(sprintf, "($$*)i"),
  879. REG_NATIVE_FUNC(snprintf, "(*~$*)i"),
  880. { "vprintf", printf_wrapper, "($*)i", NULL },
  881. { "vsprintf", sprintf_wrapper, "($$*)i", NULL },
  882. { "vsnprintf", snprintf_wrapper, "(*~$*)i", NULL },
  883. REG_NATIVE_FUNC(puts, "($)i"),
  884. REG_NATIVE_FUNC(putchar, "(i)i"),
  885. REG_NATIVE_FUNC(memcmp, "(**~)i"),
  886. REG_NATIVE_FUNC(memcpy, "(**~)i"),
  887. REG_NATIVE_FUNC(memmove, "(**~)i"),
  888. REG_NATIVE_FUNC(memset, "(*ii)i"),
  889. REG_NATIVE_FUNC(strchr, "($i)i"),
  890. REG_NATIVE_FUNC(strcmp, "($$)i"),
  891. REG_NATIVE_FUNC(strcpy, "(*$)i"),
  892. REG_NATIVE_FUNC(strlen, "($)i"),
  893. REG_NATIVE_FUNC(strncmp, "(**~)i"),
  894. REG_NATIVE_FUNC(strncpy, "(**~)i"),
  895. REG_NATIVE_FUNC(malloc, "(i)i"),
  896. REG_NATIVE_FUNC(realloc, "(ii)i"),
  897. REG_NATIVE_FUNC(calloc, "(ii)i"),
  898. REG_NATIVE_FUNC(strdup, "($)i"),
  899. /* clang may introduce __strdup */
  900. REG_NATIVE_FUNC(_strdup, "($)i"),
  901. REG_NATIVE_FUNC(free, "(*)"),
  902. REG_NATIVE_FUNC(atoi, "($)i"),
  903. REG_NATIVE_FUNC(exit, "(i)"),
  904. REG_NATIVE_FUNC(strtol, "($*i)i"),
  905. REG_NATIVE_FUNC(strtoul, "($*i)i"),
  906. REG_NATIVE_FUNC(memchr, "(*ii)i"),
  907. REG_NATIVE_FUNC(strncasecmp, "($$i)i"),
  908. REG_NATIVE_FUNC(strspn, "($$)i"),
  909. REG_NATIVE_FUNC(strcspn, "($$)i"),
  910. REG_NATIVE_FUNC(strstr, "($$)i"),
  911. REG_NATIVE_FUNC(isupper, "(i)i"),
  912. REG_NATIVE_FUNC(isalpha, "(i)i"),
  913. REG_NATIVE_FUNC(isspace, "(i)i"),
  914. REG_NATIVE_FUNC(isgraph, "(i)i"),
  915. REG_NATIVE_FUNC(isprint, "(i)i"),
  916. REG_NATIVE_FUNC(isdigit, "(i)i"),
  917. REG_NATIVE_FUNC(isxdigit, "(i)i"),
  918. REG_NATIVE_FUNC(tolower, "(i)i"),
  919. REG_NATIVE_FUNC(toupper, "(i)i"),
  920. REG_NATIVE_FUNC(isalnum, "(i)i"),
  921. REG_NATIVE_FUNC(setTempRet0, "(i)"),
  922. REG_NATIVE_FUNC(getTempRet0, "()i"),
  923. REG_NATIVE_FUNC(llvm_bswap_i16, "(i)i"),
  924. REG_NATIVE_FUNC(llvm_bswap_i32, "(i)i"),
  925. REG_NATIVE_FUNC(bitshift64Lshr, "(iii)i"),
  926. REG_NATIVE_FUNC(bitshift64Shl, "(iii)i"),
  927. REG_NATIVE_FUNC(llvm_stackrestore, "(i)"),
  928. REG_NATIVE_FUNC(llvm_stacksave, "()i"),
  929. REG_NATIVE_FUNC(emscripten_memcpy_big, "(**~)i"),
  930. REG_NATIVE_FUNC(abort, "(i)"),
  931. REG_NATIVE_FUNC(abortStackOverflow, "(i)"),
  932. REG_NATIVE_FUNC(nullFunc_X, "(i)"),
  933. REG_NATIVE_FUNC(__cxa_allocate_exception, "(i)i"),
  934. REG_NATIVE_FUNC(__cxa_begin_catch, "(*)"),
  935. REG_NATIVE_FUNC(__cxa_throw, "(**i)"),
  936. REG_NATIVE_FUNC(clock_gettime, "(i*)i"),
  937. REG_NATIVE_FUNC(clock, "()I"),
  938. };
  939. #if WASM_ENABLE_SPEC_TEST != 0
  940. static NativeSymbol native_symbols_spectest[] = {
  941. REG_NATIVE_FUNC(print, "()"),
  942. REG_NATIVE_FUNC(print_i32, "(i)"),
  943. REG_NATIVE_FUNC(print_i32_f32, "(if)"),
  944. REG_NATIVE_FUNC(print_f64_f64, "(FF)"),
  945. REG_NATIVE_FUNC(print_f32, "(f)"),
  946. REG_NATIVE_FUNC(print_f64, "(F)")
  947. };
  948. #endif
  949. uint32
  950. get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis)
  951. {
  952. *p_libc_builtin_apis = native_symbols_libc_builtin;
  953. return sizeof(native_symbols_libc_builtin) / sizeof(NativeSymbol);
  954. }
  955. #if WASM_ENABLE_SPEC_TEST != 0
  956. uint32
  957. get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis)
  958. {
  959. *p_libc_builtin_apis = native_symbols_spectest;
  960. return sizeof(native_symbols_spectest) / sizeof(NativeSymbol);
  961. }
  962. #endif
  963. /*************************************
  964. * Global Variables *
  965. *************************************/
  966. typedef struct WASMNativeGlobalDef {
  967. const char *module_name;
  968. const char *global_name;
  969. uint8 type;
  970. bool is_mutable;
  971. WASMValue value;
  972. } WASMNativeGlobalDef;
  973. static WASMNativeGlobalDef native_global_defs[] = {
  974. #if WASM_ENABLE_SPEC_TEST != 0
  975. { "spectest", "global_i32", VALUE_TYPE_I32, false, .value.i32 = 666 },
  976. { "spectest", "global_i64", VALUE_TYPE_I64, false, .value.i64 = 666 },
  977. { "spectest", "global_f32", VALUE_TYPE_F32, false, .value.f32 = 666.6 },
  978. { "spectest", "global_f64", VALUE_TYPE_F64, false, .value.f64 = 666.6 },
  979. { "test", "global-i32", VALUE_TYPE_I32, false, .value.i32 = 0 },
  980. { "test", "global-f32", VALUE_TYPE_F32, false, .value.f32 = 0 },
  981. { "test", "global-mut-i32", VALUE_TYPE_I32, true, .value.i32 = 0 },
  982. { "test", "global-mut-i64", VALUE_TYPE_I64, true, .value.i64 = 0 },
  983. #endif
  984. { "global", "NaN", VALUE_TYPE_F64, .value.u64 = 0x7FF8000000000000LL },
  985. { "global", "Infinity", VALUE_TYPE_F64, .value.u64 = 0x7FF0000000000000LL }
  986. };
  987. bool
  988. wasm_native_lookup_libc_builtin_global(const char *module_name,
  989. const char *global_name,
  990. WASMGlobalImport *global)
  991. {
  992. uint32 size = sizeof(native_global_defs) / sizeof(WASMNativeGlobalDef);
  993. WASMNativeGlobalDef *global_def = native_global_defs;
  994. WASMNativeGlobalDef *global_def_end = global_def + size;
  995. if (!module_name || !global_name || !global)
  996. return false;
  997. /* Lookup constant globals which can be defined by table */
  998. while (global_def < global_def_end) {
  999. if (!strcmp(global_def->module_name, module_name)
  1000. && !strcmp(global_def->global_name, global_name)) {
  1001. global->type = global_def->type;
  1002. global->is_mutable = global_def->is_mutable;
  1003. global->global_data_linked = global_def->value;
  1004. return true;
  1005. }
  1006. global_def++;
  1007. }
  1008. return false;
  1009. }