libc_builtin_wrapper.c 30 KB

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