libc_builtin_wrapper.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185
  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. uint64
  16. wasm_runtime_module_realloc(wasm_module_inst_t module, uint64 ptr, uint64 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((uint64)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. #ifndef BUILTIN_LIBC_BUFFERED_PRINTF
  270. #define BUILTIN_LIBC_BUFFERED_PRINTF 0
  271. #endif
  272. #ifndef BUILTIN_LIBC_BUFFERED_PRINT_SIZE
  273. #define BUILTIN_LIBC_BUFFERED_PRINT_SIZE 128
  274. #endif
  275. struct str_context {
  276. char *str;
  277. uint32 max;
  278. uint32 count;
  279. #if BUILTIN_LIBC_BUFFERED_PRINTF != 0
  280. char print_buf[BUILTIN_LIBC_BUFFERED_PRINT_SIZE];
  281. uint32 print_buf_size;
  282. #endif
  283. };
  284. static int
  285. sprintf_out(int c, struct str_context *ctx)
  286. {
  287. if (!ctx->str || ctx->count >= ctx->max) {
  288. ctx->count++;
  289. return c;
  290. }
  291. if (ctx->count == ctx->max - 1) {
  292. ctx->str[ctx->count++] = '\0';
  293. }
  294. else {
  295. ctx->str[ctx->count++] = (char)c;
  296. }
  297. return c;
  298. }
  299. #if BUILTIN_LIBC_BUFFERED_PRINTF != 0
  300. static int
  301. printf_out(int c, struct str_context *ctx)
  302. {
  303. if (c == '\n') {
  304. ctx->print_buf[ctx->print_buf_size] = '\0';
  305. os_printf("%s\n", ctx->print_buf);
  306. ctx->print_buf_size = 0;
  307. }
  308. else if (ctx->print_buf_size >= sizeof(ctx->print_buf) - 2) {
  309. ctx->print_buf[ctx->print_buf_size++] = (char)c;
  310. ctx->print_buf[ctx->print_buf_size] = '\0';
  311. os_printf("%s\n", ctx->print_buf);
  312. ctx->print_buf_size = 0;
  313. }
  314. else {
  315. ctx->print_buf[ctx->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 = { 0 };
  334. memset(&ctx, 0, sizeof(ctx));
  335. /* format has been checked by runtime */
  336. if (!validate_native_addr(va_args, (uint64)sizeof(int32)))
  337. return 0;
  338. if (!_vprintf_wa((out_func_t)printf_out, &ctx, format, va_args,
  339. module_inst))
  340. return 0;
  341. #if BUILTIN_LIBC_BUFFERED_PRINTF != 0
  342. if (ctx.print_buf_size > 0)
  343. os_printf("%s", ctx.print_buf);
  344. #endif
  345. return (int)ctx.count;
  346. }
  347. static int
  348. sprintf_wrapper(wasm_exec_env_t exec_env, char *str, const char *format,
  349. _va_list va_args)
  350. {
  351. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  352. uint8 *native_end_offset;
  353. struct str_context ctx;
  354. /* str and format have been checked by runtime */
  355. if (!validate_native_addr(va_args, (uint64)sizeof(uint32)))
  356. return 0;
  357. if (!wasm_runtime_get_native_addr_range(module_inst, (uint8 *)str, NULL,
  358. &native_end_offset)) {
  359. wasm_runtime_set_exception(module_inst, "out of bounds memory access");
  360. return 0;
  361. }
  362. ctx.str = str;
  363. ctx.max = (uint32)(native_end_offset - (uint8 *)str);
  364. ctx.count = 0;
  365. if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args,
  366. module_inst))
  367. return 0;
  368. if (ctx.count < ctx.max) {
  369. str[ctx.count] = '\0';
  370. }
  371. return (int)ctx.count;
  372. }
  373. static int
  374. snprintf_wrapper(wasm_exec_env_t exec_env, char *str, uint32 size,
  375. const char *format, _va_list va_args)
  376. {
  377. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  378. struct str_context ctx;
  379. /* str and format have been checked by runtime */
  380. if (!validate_native_addr(va_args, (uint64)sizeof(uint32)))
  381. return 0;
  382. ctx.str = str;
  383. ctx.max = size;
  384. ctx.count = 0;
  385. if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args,
  386. module_inst))
  387. return 0;
  388. if (ctx.count < ctx.max) {
  389. str[ctx.count] = '\0';
  390. }
  391. return (int)ctx.count;
  392. }
  393. static int
  394. puts_wrapper(wasm_exec_env_t exec_env, const char *str)
  395. {
  396. (void)exec_env;
  397. return os_printf("%s\n", str);
  398. }
  399. static int
  400. putchar_wrapper(wasm_exec_env_t exec_env, int c)
  401. {
  402. (void)exec_env;
  403. os_printf("%c", c);
  404. return 1;
  405. }
  406. static uint32
  407. strdup_wrapper(wasm_exec_env_t exec_env, const char *str)
  408. {
  409. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  410. char *str_ret;
  411. uint32 len;
  412. uint32 str_ret_offset = 0;
  413. /* str has been checked by runtime */
  414. if (str) {
  415. len = (uint32)strlen(str) + 1;
  416. str_ret_offset = (uint32)module_malloc((uint64)len, (void **)&str_ret);
  417. if (str_ret_offset) {
  418. bh_memcpy_s(str_ret, len, str, len);
  419. }
  420. }
  421. return str_ret_offset;
  422. }
  423. static uint32
  424. _strdup_wrapper(wasm_exec_env_t exec_env, const char *str)
  425. {
  426. return strdup_wrapper(exec_env, str);
  427. }
  428. static int32
  429. memcmp_wrapper(wasm_exec_env_t exec_env, const void *s1, const void *s2,
  430. uint32 size)
  431. {
  432. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  433. /* s2 has been checked by runtime */
  434. if (!validate_native_addr((void *)s1, (uint64)size))
  435. return 0;
  436. return memcmp(s1, s2, size);
  437. }
  438. static uint32
  439. memcpy_wrapper(wasm_exec_env_t exec_env, void *dst, const void *src,
  440. uint32 size)
  441. {
  442. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  443. uint32 dst_offset = (uint32)addr_native_to_app(dst);
  444. if (size == 0)
  445. return dst_offset;
  446. /* src has been checked by runtime */
  447. if (!validate_native_addr(dst, (uint64)size))
  448. return dst_offset;
  449. bh_memcpy_s(dst, size, src, size);
  450. return dst_offset;
  451. }
  452. static uint32
  453. memmove_wrapper(wasm_exec_env_t exec_env, void *dst, void *src, uint32 size)
  454. {
  455. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  456. uint32 dst_offset = (uint32)addr_native_to_app(dst);
  457. if (size == 0)
  458. return dst_offset;
  459. /* src has been checked by runtime */
  460. if (!validate_native_addr(dst, (uint64)size))
  461. return dst_offset;
  462. memmove(dst, src, size);
  463. return dst_offset;
  464. }
  465. static uint32
  466. memset_wrapper(wasm_exec_env_t exec_env, void *s, int32 c, uint32 size)
  467. {
  468. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  469. uint32 s_offset = (uint32)addr_native_to_app(s);
  470. if (!validate_native_addr(s, (uint64)size))
  471. return s_offset;
  472. memset(s, c, size);
  473. return s_offset;
  474. }
  475. static uint32
  476. strchr_wrapper(wasm_exec_env_t exec_env, const char *s, int32 c)
  477. {
  478. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  479. char *ret;
  480. /* s has been checked by runtime */
  481. ret = strchr(s, c);
  482. return ret ? (uint32)addr_native_to_app(ret) : 0;
  483. }
  484. static int32
  485. strcmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2)
  486. {
  487. (void)exec_env;
  488. /* s1 and s2 have been checked by runtime */
  489. return strcmp(s1, s2);
  490. }
  491. static int32
  492. strncmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2,
  493. uint32 size)
  494. {
  495. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  496. /* s2 has been checked by runtime */
  497. if (!validate_native_addr((void *)s1, (uint64)size))
  498. return 0;
  499. return strncmp(s1, s2, size);
  500. }
  501. static uint32
  502. strcpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src)
  503. {
  504. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  505. uint32 len = (uint32)strlen(src) + 1;
  506. /* src has been checked by runtime */
  507. if (!validate_native_addr(dst, (uint64)len))
  508. return 0;
  509. #ifndef BH_PLATFORM_WINDOWS
  510. strncpy(dst, src, len);
  511. #else
  512. strncpy_s(dst, len, src, len);
  513. #endif
  514. return (uint32)addr_native_to_app(dst);
  515. }
  516. static uint32
  517. strncpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src,
  518. uint32 size)
  519. {
  520. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  521. /* src has been checked by runtime */
  522. if (!validate_native_addr(dst, (uint64)size))
  523. return 0;
  524. #ifndef BH_PLATFORM_WINDOWS
  525. strncpy(dst, src, size);
  526. #else
  527. strncpy_s(dst, size, src, size);
  528. #endif
  529. return (uint32)addr_native_to_app(dst);
  530. }
  531. static uint32
  532. strlen_wrapper(wasm_exec_env_t exec_env, const char *s)
  533. {
  534. (void)exec_env;
  535. /* s has been checked by runtime */
  536. return (uint32)strlen(s);
  537. }
  538. static uint32
  539. malloc_wrapper(wasm_exec_env_t exec_env, uint32 size)
  540. {
  541. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  542. return (uint32)module_malloc((uint64)size, NULL);
  543. }
  544. static uint32
  545. calloc_wrapper(wasm_exec_env_t exec_env, uint32 nmemb, uint32 size)
  546. {
  547. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  548. uint64 total_size = (uint64)nmemb * (uint64)size;
  549. uint32 ret_offset = 0;
  550. uint8 *ret_ptr;
  551. if (total_size >= UINT32_MAX)
  552. return 0;
  553. ret_offset = (uint32)module_malloc(total_size, (void **)&ret_ptr);
  554. if (ret_offset) {
  555. memset(ret_ptr, 0, (uint32)total_size);
  556. }
  557. return ret_offset;
  558. }
  559. static uint32
  560. realloc_wrapper(wasm_exec_env_t exec_env, uint32 ptr, uint32 new_size)
  561. {
  562. uint64 ret_offset = 0;
  563. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  564. ret_offset = wasm_runtime_module_realloc(module_inst, ptr, new_size, NULL);
  565. bh_assert(ret_offset < UINT32_MAX);
  566. return (uint32)ret_offset;
  567. }
  568. static void
  569. free_wrapper(wasm_exec_env_t exec_env, void *ptr)
  570. {
  571. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  572. if (!validate_native_addr(ptr, (uint64)sizeof(uint32)))
  573. return;
  574. module_free(addr_native_to_app(ptr));
  575. }
  576. static int32
  577. atoi_wrapper(wasm_exec_env_t exec_env, const char *s)
  578. {
  579. (void)exec_env;
  580. /* s has been checked by runtime */
  581. return atoi(s);
  582. }
  583. static void
  584. exit_wrapper(wasm_exec_env_t exec_env, int32 status)
  585. {
  586. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  587. char buf[32];
  588. snprintf(buf, sizeof(buf), "env.exit(%" PRId32 ")", status);
  589. wasm_runtime_set_exception(module_inst, buf);
  590. }
  591. static int32
  592. strtol_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. int32 num = 0;
  597. /* nptr has been checked by runtime */
  598. if (!validate_native_addr(endptr, (uint64)sizeof(uint32)))
  599. return 0;
  600. num = (int32)strtol(nptr, endptr, base);
  601. *(uint32 *)endptr = (uint32)addr_native_to_app(*endptr);
  602. return num;
  603. }
  604. static uint32
  605. strtoul_wrapper(wasm_exec_env_t exec_env, const char *nptr, char **endptr,
  606. int32 base)
  607. {
  608. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  609. uint32 num = 0;
  610. /* nptr has been checked by runtime */
  611. if (!validate_native_addr(endptr, (uint64)sizeof(uint32)))
  612. return 0;
  613. num = (uint32)strtoul(nptr, endptr, base);
  614. *(uint32 *)endptr = (uint32)addr_native_to_app(*endptr);
  615. return num;
  616. }
  617. static uint32
  618. memchr_wrapper(wasm_exec_env_t exec_env, const void *s, int32 c, uint32 n)
  619. {
  620. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  621. void *res;
  622. if (!validate_native_addr((void *)s, (uint64)n))
  623. return 0;
  624. res = memchr(s, c, n);
  625. return (uint32)addr_native_to_app(res);
  626. }
  627. static int32
  628. strncasecmp_wrapper(wasm_exec_env_t exec_env, const char *s1, const char *s2,
  629. uint32 n)
  630. {
  631. (void)exec_env;
  632. /* s1 and s2 have been checked by runtime */
  633. return strncasecmp(s1, s2, n);
  634. }
  635. static uint32
  636. strspn_wrapper(wasm_exec_env_t exec_env, const char *s, const char *accept)
  637. {
  638. (void)exec_env;
  639. /* s and accept have been checked by runtime */
  640. return (uint32)strspn(s, accept);
  641. }
  642. static uint32
  643. strcspn_wrapper(wasm_exec_env_t exec_env, const char *s, const char *reject)
  644. {
  645. (void)exec_env;
  646. /* s and reject have been checked by runtime */
  647. return (uint32)strcspn(s, reject);
  648. }
  649. static uint32
  650. strstr_wrapper(wasm_exec_env_t exec_env, const char *s, const char *find)
  651. {
  652. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  653. /* s and find have been checked by runtime */
  654. char *res = strstr(s, find);
  655. return (uint32)addr_native_to_app(res);
  656. }
  657. static int32
  658. isupper_wrapper(wasm_exec_env_t exec_env, int32 c)
  659. {
  660. (void)exec_env;
  661. return isupper(c);
  662. }
  663. static int32
  664. isalpha_wrapper(wasm_exec_env_t exec_env, int32 c)
  665. {
  666. (void)exec_env;
  667. return isalpha(c);
  668. }
  669. static int32
  670. isspace_wrapper(wasm_exec_env_t exec_env, int32 c)
  671. {
  672. (void)exec_env;
  673. return isspace(c);
  674. }
  675. static int32
  676. isgraph_wrapper(wasm_exec_env_t exec_env, int32 c)
  677. {
  678. (void)exec_env;
  679. return isgraph(c);
  680. }
  681. static int32
  682. isprint_wrapper(wasm_exec_env_t exec_env, int32 c)
  683. {
  684. (void)exec_env;
  685. return isprint(c);
  686. }
  687. static int32
  688. isdigit_wrapper(wasm_exec_env_t exec_env, int32 c)
  689. {
  690. (void)exec_env;
  691. return isdigit(c);
  692. }
  693. static int32
  694. isxdigit_wrapper(wasm_exec_env_t exec_env, int32 c)
  695. {
  696. (void)exec_env;
  697. return isxdigit(c);
  698. }
  699. static int32
  700. tolower_wrapper(wasm_exec_env_t exec_env, int32 c)
  701. {
  702. (void)exec_env;
  703. return tolower(c);
  704. }
  705. static int32
  706. toupper_wrapper(wasm_exec_env_t exec_env, int32 c)
  707. {
  708. (void)exec_env;
  709. return toupper(c);
  710. }
  711. static int32
  712. isalnum_wrapper(wasm_exec_env_t exec_env, int32 c)
  713. {
  714. (void)exec_env;
  715. return isalnum(c);
  716. }
  717. static uint32
  718. emscripten_memcpy_big_wrapper(wasm_exec_env_t exec_env, void *dst,
  719. const void *src, uint32 size)
  720. {
  721. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  722. uint32 dst_offset = (uint32)addr_native_to_app(dst);
  723. /* src has been checked by runtime */
  724. if (!validate_native_addr(dst, (uint64)size))
  725. return dst_offset;
  726. bh_memcpy_s(dst, size, src, size);
  727. return dst_offset;
  728. }
  729. static void
  730. abort_wrapper(wasm_exec_env_t exec_env, int32 code)
  731. {
  732. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  733. char buf[32];
  734. snprintf(buf, sizeof(buf), "env.abort(%" PRId32 ")", code);
  735. wasm_runtime_set_exception(module_inst, buf);
  736. }
  737. static void
  738. abortStackOverflow_wrapper(wasm_exec_env_t exec_env, int32 code)
  739. {
  740. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  741. char buf[32];
  742. snprintf(buf, sizeof(buf), "env.abortStackOverflow(%" PRId32 ")", code);
  743. wasm_runtime_set_exception(module_inst, buf);
  744. }
  745. static void
  746. nullFunc_X_wrapper(wasm_exec_env_t exec_env, int32 code)
  747. {
  748. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  749. char buf[32];
  750. snprintf(buf, sizeof(buf), "env.nullFunc_X(%" PRId32 ")", code);
  751. wasm_runtime_set_exception(module_inst, buf);
  752. }
  753. static uint32
  754. __cxa_allocate_exception_wrapper(wasm_exec_env_t exec_env, uint32 thrown_size)
  755. {
  756. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  757. uint32 exception = (uint32)module_malloc((uint64)thrown_size, NULL);
  758. if (!exception)
  759. return 0;
  760. return exception;
  761. }
  762. static void
  763. __cxa_begin_catch_wrapper(wasm_exec_env_t exec_env, void *exception_object)
  764. {
  765. (void)exec_env;
  766. (void)exception_object;
  767. }
  768. static void
  769. __cxa_throw_wrapper(wasm_exec_env_t exec_env, void *thrown_exception,
  770. void *tinfo, uint32 table_elem_idx)
  771. {
  772. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  773. char buf[32];
  774. (void)thrown_exception;
  775. (void)tinfo;
  776. (void)table_elem_idx;
  777. snprintf(buf, sizeof(buf), "%s", "exception thrown by stdc++");
  778. wasm_runtime_set_exception(module_inst, buf);
  779. }
  780. struct timespec_app {
  781. int64 tv_sec;
  782. int32 tv_nsec;
  783. };
  784. static uint32
  785. clock_gettime_wrapper(wasm_exec_env_t exec_env, uint32 clk_id,
  786. struct timespec_app *ts_app)
  787. {
  788. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  789. uint64 time;
  790. (void)clk_id;
  791. if (!validate_native_addr(ts_app, (uint64)sizeof(struct timespec_app)))
  792. return (uint32)-1;
  793. time = os_time_get_boot_us();
  794. ts_app->tv_sec = time / 1000000;
  795. ts_app->tv_nsec = (time % 1000000) * 1000;
  796. return (uint32)0;
  797. }
  798. static uint64
  799. clock_wrapper(wasm_exec_env_t exec_env)
  800. {
  801. (void)exec_env;
  802. /* Convert to nano seconds as CLOCKS_PER_SEC in wasi-sdk */
  803. return os_time_get_boot_us() * 1000;
  804. }
  805. #if WASM_ENABLE_SPEC_TEST != 0
  806. static void
  807. print_wrapper(wasm_exec_env_t exec_env)
  808. {
  809. os_printf("in specttest.print()\n");
  810. }
  811. static void
  812. print_i32_wrapper(wasm_exec_env_t exec_env, int32 i32)
  813. {
  814. os_printf("in specttest.print_i32(%" PRId32 ")\n", i32);
  815. }
  816. static void
  817. print_i64_wrapper(wasm_exec_env_t exec_env, int64 i64)
  818. {
  819. os_printf("in specttest.print_i64(%" PRId64 ")\n", i64);
  820. }
  821. static void
  822. print_i32_f32_wrapper(wasm_exec_env_t exec_env, int32 i32, float f32)
  823. {
  824. os_printf("in specttest.print_i32_f32(%" PRId32 ", %f)\n", i32, f32);
  825. }
  826. static void
  827. print_f64_f64_wrapper(wasm_exec_env_t exec_env, double f64_1, double f64_2)
  828. {
  829. os_printf("in specttest.print_f64_f64(%f, %f)\n", f64_1, f64_2);
  830. }
  831. static void
  832. print_f32_wrapper(wasm_exec_env_t exec_env, float f32)
  833. {
  834. os_printf("in specttest.print_f32(%f)\n", f32);
  835. }
  836. static void
  837. print_f64_wrapper(wasm_exec_env_t exec_env, double f64)
  838. {
  839. os_printf("in specttest.print_f64(%f)\n", f64);
  840. }
  841. #endif /* WASM_ENABLE_SPEC_TEST */
  842. /* clang-format off */
  843. #define REG_NATIVE_FUNC(func_name, signature) \
  844. { #func_name, func_name##_wrapper, signature, NULL }
  845. /* clang-format on */
  846. static NativeSymbol native_symbols_libc_builtin[] = {
  847. REG_NATIVE_FUNC(printf, "($*)i"),
  848. REG_NATIVE_FUNC(sprintf, "($$*)i"),
  849. REG_NATIVE_FUNC(snprintf, "(*~$*)i"),
  850. { "vprintf", printf_wrapper, "($*)i", NULL },
  851. { "vsprintf", sprintf_wrapper, "($$*)i", NULL },
  852. { "vsnprintf", snprintf_wrapper, "(*~$*)i", NULL },
  853. REG_NATIVE_FUNC(puts, "($)i"),
  854. REG_NATIVE_FUNC(putchar, "(i)i"),
  855. REG_NATIVE_FUNC(memcmp, "(**~)i"),
  856. REG_NATIVE_FUNC(memcpy, "(**~)i"),
  857. REG_NATIVE_FUNC(memmove, "(**~)i"),
  858. REG_NATIVE_FUNC(memset, "(*ii)i"),
  859. REG_NATIVE_FUNC(strchr, "($i)i"),
  860. REG_NATIVE_FUNC(strcmp, "($$)i"),
  861. REG_NATIVE_FUNC(strcpy, "(*$)i"),
  862. REG_NATIVE_FUNC(strlen, "($)i"),
  863. REG_NATIVE_FUNC(strncmp, "(**~)i"),
  864. REG_NATIVE_FUNC(strncpy, "(**~)i"),
  865. REG_NATIVE_FUNC(malloc, "(i)i"),
  866. REG_NATIVE_FUNC(realloc, "(ii)i"),
  867. REG_NATIVE_FUNC(calloc, "(ii)i"),
  868. REG_NATIVE_FUNC(strdup, "($)i"),
  869. /* clang may introduce __strdup */
  870. REG_NATIVE_FUNC(_strdup, "($)i"),
  871. REG_NATIVE_FUNC(free, "(*)"),
  872. REG_NATIVE_FUNC(atoi, "($)i"),
  873. REG_NATIVE_FUNC(exit, "(i)"),
  874. REG_NATIVE_FUNC(strtol, "($*i)i"),
  875. REG_NATIVE_FUNC(strtoul, "($*i)i"),
  876. REG_NATIVE_FUNC(memchr, "(*ii)i"),
  877. REG_NATIVE_FUNC(strncasecmp, "($$i)i"),
  878. REG_NATIVE_FUNC(strspn, "($$)i"),
  879. REG_NATIVE_FUNC(strcspn, "($$)i"),
  880. REG_NATIVE_FUNC(strstr, "($$)i"),
  881. REG_NATIVE_FUNC(isupper, "(i)i"),
  882. REG_NATIVE_FUNC(isalpha, "(i)i"),
  883. REG_NATIVE_FUNC(isspace, "(i)i"),
  884. REG_NATIVE_FUNC(isgraph, "(i)i"),
  885. REG_NATIVE_FUNC(isprint, "(i)i"),
  886. REG_NATIVE_FUNC(isdigit, "(i)i"),
  887. REG_NATIVE_FUNC(isxdigit, "(i)i"),
  888. REG_NATIVE_FUNC(tolower, "(i)i"),
  889. REG_NATIVE_FUNC(toupper, "(i)i"),
  890. REG_NATIVE_FUNC(isalnum, "(i)i"),
  891. REG_NATIVE_FUNC(emscripten_memcpy_big, "(**~)i"),
  892. REG_NATIVE_FUNC(abort, "(i)"),
  893. REG_NATIVE_FUNC(abortStackOverflow, "(i)"),
  894. REG_NATIVE_FUNC(nullFunc_X, "(i)"),
  895. REG_NATIVE_FUNC(__cxa_allocate_exception, "(i)i"),
  896. REG_NATIVE_FUNC(__cxa_begin_catch, "(*)"),
  897. REG_NATIVE_FUNC(__cxa_throw, "(**i)"),
  898. REG_NATIVE_FUNC(clock_gettime, "(i*)i"),
  899. REG_NATIVE_FUNC(clock, "()I"),
  900. };
  901. #if WASM_ENABLE_SPEC_TEST != 0
  902. static NativeSymbol native_symbols_spectest[] = {
  903. REG_NATIVE_FUNC(print, "()"),
  904. REG_NATIVE_FUNC(print_i32, "(i)"),
  905. REG_NATIVE_FUNC(print_i64, "(I)"),
  906. REG_NATIVE_FUNC(print_i32_f32, "(if)"),
  907. REG_NATIVE_FUNC(print_f64_f64, "(FF)"),
  908. REG_NATIVE_FUNC(print_f32, "(f)"),
  909. REG_NATIVE_FUNC(print_f64, "(F)")
  910. };
  911. #endif
  912. uint32
  913. get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis)
  914. {
  915. *p_libc_builtin_apis = native_symbols_libc_builtin;
  916. return sizeof(native_symbols_libc_builtin) / sizeof(NativeSymbol);
  917. }
  918. #if WASM_ENABLE_SPEC_TEST != 0
  919. uint32
  920. get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis)
  921. {
  922. *p_libc_builtin_apis = native_symbols_spectest;
  923. return sizeof(native_symbols_spectest) / sizeof(NativeSymbol);
  924. }
  925. #endif
  926. /*************************************
  927. * Global Variables *
  928. *************************************/
  929. typedef struct WASMNativeGlobalDef {
  930. const char *module_name;
  931. const char *global_name;
  932. uint8 type;
  933. bool is_mutable;
  934. WASMValue value;
  935. } WASMNativeGlobalDef;
  936. static WASMNativeGlobalDef native_global_defs[] = {
  937. #if WASM_ENABLE_SPEC_TEST != 0
  938. { "spectest", "global_i32", VALUE_TYPE_I32, false, .value.i32 = 666 },
  939. { "spectest", "global_i64", VALUE_TYPE_I64, false, .value.i64 = 666 },
  940. { "spectest", "global_f32", VALUE_TYPE_F32, false, .value.f32 = 666.6 },
  941. { "spectest", "global_f64", VALUE_TYPE_F64, false, .value.f64 = 666.6 },
  942. { "test", "global-i32", VALUE_TYPE_I32, false, .value.i32 = 0 },
  943. { "test", "global-f32", VALUE_TYPE_F32, false, .value.f32 = 0 },
  944. { "test", "global-mut-i32", VALUE_TYPE_I32, true, .value.i32 = 0 },
  945. { "test", "global-mut-i64", VALUE_TYPE_I64, true, .value.i64 = 0 },
  946. { "test", "g", VALUE_TYPE_I32, true, .value.i32 = 0 },
  947. #if WASM_ENABLE_GC != 0
  948. { "G", "g", VALUE_TYPE_I32, false, .value.i32 = 4 },
  949. { "M", "g", REF_TYPE_HT_NON_NULLABLE, false, .value.gc_obj = 0 },
  950. #endif
  951. #endif
  952. { "global", "NaN", VALUE_TYPE_F64, .value.u64 = 0x7FF8000000000000LL },
  953. { "global", "Infinity", VALUE_TYPE_F64, .value.u64 = 0x7FF0000000000000LL }
  954. };
  955. bool
  956. wasm_native_lookup_libc_builtin_global(const char *module_name,
  957. const char *global_name,
  958. WASMGlobalImport *global)
  959. {
  960. uint32 size = sizeof(native_global_defs) / sizeof(WASMNativeGlobalDef);
  961. WASMNativeGlobalDef *global_def = native_global_defs;
  962. WASMNativeGlobalDef *global_def_end = global_def + size;
  963. if (!module_name || !global_name || !global)
  964. return false;
  965. /* Lookup constant globals which can be defined by table */
  966. while (global_def < global_def_end) {
  967. if (!strcmp(global_def->module_name, module_name)
  968. && !strcmp(global_def->global_name, global_name)) {
  969. global->type.val_type = global_def->type;
  970. global->type.is_mutable = global_def->is_mutable;
  971. global->global_data_linked = global_def->value;
  972. return true;
  973. }
  974. global_def++;
  975. }
  976. return false;
  977. }