libc_builtin_wrapper.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134
  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. void
  10. wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception);
  11. uint32
  12. wasm_runtime_get_temp_ret(wasm_module_inst_t module);
  13. void
  14. wasm_runtime_set_temp_ret(wasm_module_inst_t module, uint32 temp_ret);
  15. uint32
  16. wasm_runtime_get_llvm_stack(wasm_module_inst_t module);
  17. void
  18. wasm_runtime_set_llvm_stack(wasm_module_inst_t module, uint32 llvm_stack);
  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. typedef int (*out_func_t)(int c, void *ctx);
  36. enum pad_type {
  37. PAD_NONE,
  38. PAD_ZERO_BEFORE,
  39. PAD_SPACE_BEFORE,
  40. PAD_SPACE_AFTER,
  41. };
  42. typedef char *_va_list;
  43. #define _INTSIZEOF(n) \
  44. (((uint32)sizeof(n) + 3) & (uint32)~3)
  45. #define _va_arg(ap, t) \
  46. (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
  47. #define CHECK_VA_ARG(ap, t) do { \
  48. if ((uint8*)ap + _INTSIZEOF(t) > native_end_addr) \
  49. goto fail; \
  50. } while (0)
  51. /**
  52. * @brief Output an unsigned int in hex format
  53. *
  54. * Output an unsigned int on output installed by platform at init time. Should
  55. * be able to handle an unsigned int of any size, 32 or 64 bit.
  56. * @param num Number to output
  57. *
  58. * @return N/A
  59. */
  60. static void
  61. _printf_hex_uint(out_func_t out, void *ctx,
  62. const uint64 num, bool is_u64,
  63. enum pad_type padding,
  64. int min_width)
  65. {
  66. int shift = sizeof(num) * 8;
  67. int found_largest_digit = 0;
  68. int remaining = 16; /* 16 digits max */
  69. int digits = 0;
  70. char nibble;
  71. while (shift >= 4) {
  72. shift -= 4;
  73. nibble = (num >> shift) & 0xf;
  74. if (nibble || found_largest_digit || shift == 0) {
  75. found_largest_digit = 1;
  76. nibble = (char)(nibble + (nibble > 9 ? 87 : 48));
  77. out((int) nibble, ctx);
  78. digits++;
  79. continue;
  80. }
  81. if (remaining-- <= min_width) {
  82. if (padding == PAD_ZERO_BEFORE) {
  83. out('0', ctx);
  84. } else if (padding == PAD_SPACE_BEFORE) {
  85. out(' ', ctx);
  86. }
  87. }
  88. }
  89. if (padding == PAD_SPACE_AFTER) {
  90. remaining = min_width * 2 - digits;
  91. while (remaining-- > 0) {
  92. out(' ', ctx);
  93. }
  94. }
  95. }
  96. /**
  97. * @brief Output an unsigned int in decimal format
  98. *
  99. * Output an unsigned int on output installed by platform at init time. Only
  100. * works with 32-bit values.
  101. * @param num Number to output
  102. *
  103. * @return N/A
  104. */
  105. static void
  106. _printf_dec_uint(out_func_t out, void *ctx,
  107. const uint32 num,
  108. enum pad_type padding,
  109. int min_width)
  110. {
  111. uint32 pos = 999999999;
  112. uint32 remainder = num;
  113. int found_largest_digit = 0;
  114. int remaining = 10; /* 10 digits max */
  115. int digits = 1;
  116. /* make sure we don't skip if value is zero */
  117. if (min_width <= 0) {
  118. min_width = 1;
  119. }
  120. while (pos >= 9) {
  121. if (found_largest_digit || remainder > pos) {
  122. found_largest_digit = 1;
  123. out((int) ((remainder / (pos + 1)) + 48), ctx);
  124. digits++;
  125. } else if (remaining <= min_width && padding < PAD_SPACE_AFTER) {
  126. out((int) (padding == PAD_ZERO_BEFORE ? '0' : ' '), ctx);
  127. digits++;
  128. }
  129. remaining--;
  130. remainder %= (pos + 1);
  131. pos /= 10;
  132. }
  133. out((int) (remainder + 48), ctx);
  134. if (padding == PAD_SPACE_AFTER) {
  135. remaining = min_width - digits;
  136. while (remaining-- > 0) {
  137. out(' ', ctx);
  138. }
  139. }
  140. }
  141. static void
  142. print_err(out_func_t out, void *ctx)
  143. {
  144. out('E', ctx);
  145. out('R', ctx);
  146. out('R', ctx);
  147. }
  148. static bool
  149. _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap,
  150. wasm_module_inst_t module_inst)
  151. {
  152. int might_format = 0; /* 1 if encountered a '%' */
  153. enum pad_type padding = PAD_NONE;
  154. int min_width = -1;
  155. int long_ctr = 0;
  156. uint8 *native_end_addr;
  157. if (!wasm_runtime_get_native_addr_range(module_inst, (uint8*)ap,
  158. NULL, &native_end_addr))
  159. goto fail;
  160. /* fmt has already been adjusted if needed */
  161. while (*fmt) {
  162. if (!might_format) {
  163. if (*fmt != '%') {
  164. out((int) *fmt, ctx);
  165. }
  166. else {
  167. might_format = 1;
  168. min_width = -1;
  169. padding = PAD_NONE;
  170. long_ctr = 0;
  171. }
  172. }
  173. else {
  174. switch (*fmt) {
  175. case '-':
  176. padding = PAD_SPACE_AFTER;
  177. goto still_might_format;
  178. case '0':
  179. if (min_width < 0 && padding == PAD_NONE) {
  180. padding = PAD_ZERO_BEFORE;
  181. goto still_might_format;
  182. }
  183. /* Fall through */
  184. case '1' ... '9':
  185. if (min_width < 0) {
  186. min_width = *fmt - '0';
  187. } else {
  188. min_width = 10 * min_width + *fmt - '0';
  189. }
  190. if (padding == PAD_NONE) {
  191. padding = PAD_SPACE_BEFORE;
  192. }
  193. goto still_might_format;
  194. case 'l':
  195. long_ctr++;
  196. /* Fall through */
  197. case 'z':
  198. case 'h':
  199. /* FIXME: do nothing for these modifiers */
  200. goto still_might_format;
  201. case 'd':
  202. case 'i': {
  203. int32 d;
  204. if (long_ctr < 2) {
  205. CHECK_VA_ARG(ap, int32);
  206. d = _va_arg(ap, int32);
  207. }
  208. else {
  209. int64 lld;
  210. CHECK_VA_ARG(ap, int64);
  211. lld = _va_arg(ap, int64);
  212. if (lld > INT32_MAX || lld < INT32_MIN) {
  213. print_err(out, ctx);
  214. break;
  215. }
  216. d = (int32)lld;
  217. }
  218. if (d < 0) {
  219. out((int)'-', ctx);
  220. d = -d;
  221. min_width--;
  222. }
  223. _printf_dec_uint(out, ctx, (uint32)d, padding, min_width);
  224. break;
  225. }
  226. case 'u': {
  227. uint32 u;
  228. if (long_ctr < 2) {
  229. CHECK_VA_ARG(ap, uint32);
  230. u = _va_arg(ap, uint32);
  231. }
  232. else {
  233. uint64 llu;
  234. CHECK_VA_ARG(ap, uint64);
  235. llu = _va_arg(ap, uint64);
  236. if (llu > INT32_MAX) {
  237. print_err(out, ctx);
  238. break;
  239. }
  240. u = (uint32)llu;
  241. }
  242. _printf_dec_uint(out, ctx, u, padding, min_width);
  243. break;
  244. }
  245. case 'p':
  246. out('0', ctx);
  247. out('x', ctx);
  248. /* left-pad pointers with zeros */
  249. padding = PAD_ZERO_BEFORE;
  250. min_width = 8;
  251. /* Fall through */
  252. case 'x':
  253. case 'X': {
  254. uint64 x;
  255. bool is_ptr = (*fmt == 'p') ? true : false;
  256. if (long_ctr < 2) {
  257. CHECK_VA_ARG(ap, uint32);
  258. x = _va_arg(ap, uint32);
  259. } else {
  260. CHECK_VA_ARG(ap, uint64);
  261. x = _va_arg(ap, uint64);
  262. }
  263. _printf_hex_uint(out, ctx, x, !is_ptr, padding, min_width);
  264. break;
  265. }
  266. case 's': {
  267. char *s;
  268. char *start;
  269. int32 s_offset;
  270. CHECK_VA_ARG(ap, int32);
  271. s_offset = _va_arg(ap, int32);
  272. if (!validate_app_str_addr(s_offset)) {
  273. return false;
  274. }
  275. s = start = addr_app_to_native(s_offset);
  276. while (*s)
  277. out((int) (*s++), ctx);
  278. if (padding == PAD_SPACE_AFTER) {
  279. int remaining = min_width - (int32)(s - start);
  280. while (remaining-- > 0) {
  281. out(' ', ctx);
  282. }
  283. }
  284. break;
  285. }
  286. case 'c': {
  287. int c;
  288. CHECK_VA_ARG(ap, int);
  289. c = _va_arg(ap, int);
  290. out(c, ctx);
  291. break;
  292. }
  293. case '%': {
  294. out((int) '%', ctx);
  295. break;
  296. }
  297. default:
  298. out((int) '%', ctx);
  299. out((int) *fmt, ctx);
  300. break;
  301. }
  302. might_format = 0;
  303. }
  304. still_might_format:
  305. ++fmt;
  306. }
  307. return true;
  308. fail:
  309. wasm_runtime_set_exception(module_inst, "out of bounds memory access");
  310. return false;
  311. }
  312. struct str_context {
  313. char *str;
  314. uint32 max;
  315. uint32 count;
  316. };
  317. static int
  318. sprintf_out(int c, struct str_context *ctx)
  319. {
  320. if (!ctx->str || ctx->count >= ctx->max) {
  321. ctx->count++;
  322. return c;
  323. }
  324. if (ctx->count == ctx->max - 1) {
  325. ctx->str[ctx->count++] = '\0';
  326. } else {
  327. ctx->str[ctx->count++] = (char)c;
  328. }
  329. return c;
  330. }
  331. static int
  332. printf_out(int c, struct str_context *ctx)
  333. {
  334. os_printf("%c", c);
  335. ctx->count++;
  336. return c;
  337. }
  338. static int
  339. printf_wrapper(wasm_exec_env_t exec_env,
  340. const char * format, _va_list va_args)
  341. {
  342. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  343. struct str_context ctx = { NULL, 0, 0 };
  344. /* format has been checked by runtime */
  345. if (!validate_native_addr(va_args, sizeof(int32)))
  346. return 0;
  347. if (!_vprintf_wa((out_func_t)printf_out, &ctx, format, va_args, module_inst))
  348. return 0;
  349. return (int)ctx.count;
  350. }
  351. static int
  352. sprintf_wrapper(wasm_exec_env_t exec_env,
  353. char *str, const char *format, _va_list va_args)
  354. {
  355. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  356. uint8 *native_end_offset;
  357. struct str_context ctx;
  358. /* str and format have been checked by runtime */
  359. if (!validate_native_addr(va_args, sizeof(uint32)))
  360. return 0;
  361. if (!wasm_runtime_get_native_addr_range(module_inst, (uint8*)str,
  362. NULL, &native_end_offset)) {
  363. wasm_runtime_set_exception(module_inst, "out of bounds memory access");
  364. return false;
  365. }
  366. ctx.str = str;
  367. ctx.max = (uint32)(native_end_offset - (uint8*)str);
  368. ctx.count = 0;
  369. if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args, module_inst))
  370. return 0;
  371. if (ctx.count < ctx.max) {
  372. str[ctx.count] = '\0';
  373. }
  374. return (int)ctx.count;
  375. }
  376. static int
  377. snprintf_wrapper(wasm_exec_env_t exec_env, char *str, uint32 size,
  378. const char *format, _va_list va_args)
  379. {
  380. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  381. struct str_context ctx;
  382. /* str and format have been checked by runtime */
  383. if (!validate_native_addr(va_args, sizeof(uint32)))
  384. return 0;
  385. ctx.str = str;
  386. ctx.max = size;
  387. ctx.count = 0;
  388. if (!_vprintf_wa((out_func_t)sprintf_out, &ctx, format, va_args, module_inst))
  389. return 0;
  390. if (ctx.count < ctx.max) {
  391. str[ctx.count] = '\0';
  392. }
  393. return (int)ctx.count;
  394. }
  395. static int
  396. puts_wrapper(wasm_exec_env_t exec_env, const char *str)
  397. {
  398. return os_printf("%s\n", str);
  399. }
  400. static int
  401. putchar_wrapper(wasm_exec_env_t exec_env, int c)
  402. {
  403. os_printf("%c", c);
  404. return 1;
  405. }
  406. static int32
  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. int32 str_ret_offset = 0;
  413. /* str has been checked by runtime */
  414. if (str) {
  415. len = (uint32)strlen(str) + 1;
  416. str_ret_offset = module_malloc(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 int32
  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,
  430. const void *s1, const void *s2, 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, size))
  435. return 0;
  436. return memcmp(s1, s2, size);
  437. }
  438. static int32
  439. memcpy_wrapper(wasm_exec_env_t exec_env,
  440. void *dst, const void *src, uint32 size)
  441. {
  442. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  443. int32 dst_offset = 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, size))
  448. return dst_offset;
  449. bh_memcpy_s(dst, size, src, size);
  450. return dst_offset;
  451. }
  452. static int32
  453. memmove_wrapper(wasm_exec_env_t exec_env,
  454. void *dst, void *src, uint32 size)
  455. {
  456. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  457. int32 dst_offset = addr_native_to_app(dst);
  458. if (size == 0)
  459. return dst_offset;
  460. /* src has been checked by runtime */
  461. if (!validate_native_addr(dst, size))
  462. return dst_offset;
  463. memmove(dst, src, size);
  464. return dst_offset;
  465. }
  466. static int32
  467. memset_wrapper(wasm_exec_env_t exec_env,
  468. void *s, int32 c, uint32 size)
  469. {
  470. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  471. int32 s_offset = addr_native_to_app(s);
  472. if (!validate_native_addr(s, size))
  473. return s_offset;
  474. memset(s, c, size);
  475. return s_offset;
  476. }
  477. static int32
  478. strchr_wrapper(wasm_exec_env_t exec_env,
  479. const char *s, int32 c)
  480. {
  481. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  482. char *ret;
  483. /* s has been checked by runtime */
  484. ret = strchr(s, c);
  485. return ret ? addr_native_to_app(ret) : 0;
  486. }
  487. static int32
  488. strcmp_wrapper(wasm_exec_env_t exec_env,
  489. const char *s1, const char *s2)
  490. {
  491. /* s1 and s2 have been checked by runtime */
  492. return strcmp(s1, s2);
  493. }
  494. static int32
  495. strncmp_wrapper(wasm_exec_env_t exec_env,
  496. const char *s1, const char *s2, uint32 size)
  497. {
  498. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  499. /* s2 has been checked by runtime */
  500. if (!validate_native_addr((void*)s1, size))
  501. return 0;
  502. return strncmp(s1, s2, size);
  503. }
  504. static int32
  505. strcpy_wrapper(wasm_exec_env_t exec_env, char *dst, const char *src)
  506. {
  507. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  508. uint32 len = strlen(src) + 1;
  509. /* src has been checked by runtime */
  510. if (!validate_native_addr(dst, len))
  511. return 0;
  512. strncpy(dst, src, len);
  513. return addr_native_to_app(dst);
  514. }
  515. static int32
  516. strncpy_wrapper(wasm_exec_env_t exec_env,
  517. char *dst, const char *src, uint32 size)
  518. {
  519. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  520. /* src has been checked by runtime */
  521. if (!validate_native_addr(dst, size))
  522. return 0;
  523. strncpy(dst, src, size);
  524. return addr_native_to_app(dst);
  525. }
  526. static uint32
  527. strlen_wrapper(wasm_exec_env_t exec_env, const char *s)
  528. {
  529. /* s has been checked by runtime */
  530. return (uint32)strlen(s);
  531. }
  532. static int32
  533. malloc_wrapper(wasm_exec_env_t exec_env, uint32 size)
  534. {
  535. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  536. return module_malloc(size, NULL);
  537. }
  538. static int32
  539. calloc_wrapper(wasm_exec_env_t exec_env, uint32 nmemb, uint32 size)
  540. {
  541. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  542. uint64 total_size = (uint64) nmemb * (uint64) size;
  543. int32 ret_offset = 0;
  544. uint8 *ret_ptr;
  545. if (total_size >= UINT32_MAX)
  546. return 0;
  547. ret_offset = module_malloc((uint32)total_size, (void**)&ret_ptr);
  548. if (ret_offset) {
  549. memset(ret_ptr, 0, (uint32) total_size);
  550. }
  551. return ret_offset;
  552. }
  553. static void
  554. free_wrapper(wasm_exec_env_t exec_env, void *ptr)
  555. {
  556. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  557. if (!validate_native_addr(ptr, sizeof(uint32)))
  558. return;
  559. return module_free(addr_native_to_app(ptr));
  560. }
  561. static int32
  562. atoi_wrapper(wasm_exec_env_t exec_env, const char *s)
  563. {
  564. /* s has been checked by runtime */
  565. return atoi(s);
  566. }
  567. static void
  568. exit_wrapper(wasm_exec_env_t exec_env, int32 status)
  569. {
  570. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  571. char buf[32];
  572. snprintf(buf, sizeof(buf), "env.exit(%i)", status);
  573. wasm_runtime_set_exception(module_inst, buf);
  574. }
  575. static int32
  576. strtol_wrapper(wasm_exec_env_t exec_env,
  577. const char *nptr, char **endptr, int32 base)
  578. {
  579. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  580. int32 num = 0;
  581. /* nptr has been checked by runtime */
  582. if (!validate_native_addr(endptr, sizeof(uint32)))
  583. return 0;
  584. num = (int32)strtol(nptr, endptr, base);
  585. *(int32*)endptr = addr_native_to_app(*endptr);
  586. return num;
  587. }
  588. static uint32
  589. strtoul_wrapper(wasm_exec_env_t exec_env,
  590. const char *nptr, char **endptr, int32 base)
  591. {
  592. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  593. uint32 num = 0;
  594. /* nptr has been checked by runtime */
  595. if (!validate_native_addr(endptr, sizeof(uint32)))
  596. return 0;
  597. num = (uint32)strtoul(nptr, endptr, base);
  598. *(int32 *)endptr = addr_native_to_app(*endptr);
  599. return num;
  600. }
  601. static int32
  602. memchr_wrapper(wasm_exec_env_t exec_env,
  603. const void *s, int32 c, uint32 n)
  604. {
  605. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  606. void *res;
  607. if (!validate_native_addr((void*)s, n))
  608. return 0;
  609. res = memchr(s, c, n);
  610. return addr_native_to_app(res);
  611. }
  612. static int32
  613. strncasecmp_wrapper(wasm_exec_env_t exec_env,
  614. const char *s1, const char *s2, int32 n)
  615. {
  616. /* s1 and s2 have been checked by runtime */
  617. return strncasecmp(s1, s2, n);
  618. }
  619. static uint32
  620. strspn_wrapper(wasm_exec_env_t exec_env,
  621. const char *s, const char *accept)
  622. {
  623. /* s and accept have been checked by runtime */
  624. return (uint32)strspn(s, accept);
  625. }
  626. static uint32
  627. strcspn_wrapper(wasm_exec_env_t exec_env,
  628. 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 int32
  634. strstr_wrapper(wasm_exec_env_t exec_env,
  635. const char *s, const char *find)
  636. {
  637. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  638. /* s and find have been checked by runtime */
  639. char *res = strstr(s, find);
  640. return addr_native_to_app(res);
  641. }
  642. static int32
  643. isupper_wrapper(wasm_exec_env_t exec_env, int32 c)
  644. {
  645. return isupper(c);
  646. }
  647. static int32
  648. isalpha_wrapper(wasm_exec_env_t exec_env, int32 c)
  649. {
  650. return isalpha(c);
  651. }
  652. static int32
  653. isspace_wrapper(wasm_exec_env_t exec_env, int32 c)
  654. {
  655. return isspace(c);
  656. }
  657. static int32
  658. isgraph_wrapper(wasm_exec_env_t exec_env, int32 c)
  659. {
  660. return isgraph(c);
  661. }
  662. static int32
  663. isprint_wrapper(wasm_exec_env_t exec_env, int32 c)
  664. {
  665. return isprint(c);
  666. }
  667. static int32
  668. isdigit_wrapper(wasm_exec_env_t exec_env, int32 c)
  669. {
  670. return isdigit(c);
  671. }
  672. static int32
  673. isxdigit_wrapper(wasm_exec_env_t exec_env, int32 c)
  674. {
  675. return isxdigit(c);
  676. }
  677. static int32
  678. tolower_wrapper(wasm_exec_env_t exec_env, int32 c)
  679. {
  680. return tolower(c);
  681. }
  682. static int32
  683. toupper_wrapper(wasm_exec_env_t exec_env, int32 c)
  684. {
  685. return toupper(c);
  686. }
  687. static int32
  688. isalnum_wrapper(wasm_exec_env_t exec_env, int32 c)
  689. {
  690. return isalnum(c);
  691. }
  692. static void
  693. setTempRet0_wrapper(wasm_exec_env_t exec_env, uint32 temp_ret)
  694. {
  695. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  696. wasm_runtime_set_temp_ret(module_inst, temp_ret);
  697. }
  698. static uint32
  699. getTempRet0_wrapper(wasm_exec_env_t exec_env)
  700. {
  701. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  702. return wasm_runtime_get_temp_ret(module_inst);
  703. }
  704. static uint32
  705. llvm_bswap_i16_wrapper(wasm_exec_env_t exec_env, uint32 data)
  706. {
  707. return (data & 0xFFFF0000)
  708. | ((data & 0xFF) << 8)
  709. | ((data & 0xFF00) >> 8);
  710. }
  711. static uint32
  712. llvm_bswap_i32_wrapper(wasm_exec_env_t exec_env, uint32 data)
  713. {
  714. return ((data & 0xFF) << 24)
  715. | ((data & 0xFF00) << 8)
  716. | ((data & 0xFF0000) >> 8)
  717. | ((data & 0xFF000000) >> 24);
  718. }
  719. static uint32
  720. bitshift64Lshr_wrapper(wasm_exec_env_t exec_env,
  721. uint32 uint64_part0, uint32 uint64_part1,
  722. uint32 bits)
  723. {
  724. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  725. union {
  726. uint64 value;
  727. uint32 parts[2];
  728. } u;
  729. u.parts[0] = uint64_part0;
  730. u.parts[1] = uint64_part1;
  731. u.value >>= bits;
  732. /* return low 32bit and save high 32bit to temp ret */
  733. wasm_runtime_set_temp_ret(module_inst, (uint32) (u.value >> 32));
  734. return (uint32) u.value;
  735. }
  736. static uint32
  737. bitshift64Shl_wrapper(wasm_exec_env_t exec_env,
  738. uint32 int64_part0, uint32 int64_part1,
  739. uint32 bits)
  740. {
  741. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  742. union {
  743. int64 value;
  744. uint32 parts[2];
  745. } u;
  746. u.parts[0] = int64_part0;
  747. u.parts[1] = int64_part1;
  748. u.value <<= bits;
  749. /* return low 32bit and save high 32bit to temp ret */
  750. wasm_runtime_set_temp_ret(module_inst, (uint32) (u.value >> 32));
  751. return (uint32) u.value;
  752. }
  753. static void
  754. llvm_stackrestore_wrapper(wasm_exec_env_t exec_env, uint32 llvm_stack)
  755. {
  756. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  757. os_printf("_llvm_stackrestore called!\n");
  758. wasm_runtime_set_llvm_stack(module_inst, llvm_stack);
  759. }
  760. static uint32
  761. llvm_stacksave_wrapper(wasm_exec_env_t exec_env)
  762. {
  763. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  764. os_printf("_llvm_stacksave called!\n");
  765. return wasm_runtime_get_llvm_stack(module_inst);
  766. }
  767. static int32
  768. emscripten_memcpy_big_wrapper(wasm_exec_env_t exec_env,
  769. void *dst, const void *src, uint32 size)
  770. {
  771. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  772. int32 dst_offset = addr_native_to_app(dst);
  773. /* src has been checked by runtime */
  774. if (!validate_native_addr(dst, size))
  775. return dst_offset;
  776. bh_memcpy_s(dst, size, src, size);
  777. return dst_offset;
  778. }
  779. static void
  780. abort_wrapper(wasm_exec_env_t exec_env, int32 code)
  781. {
  782. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  783. char buf[32];
  784. snprintf(buf, sizeof(buf), "env.abort(%i)", code);
  785. wasm_runtime_set_exception(module_inst, buf);
  786. }
  787. static void
  788. abortStackOverflow_wrapper(wasm_exec_env_t exec_env, int32 code)
  789. {
  790. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  791. char buf[32];
  792. snprintf(buf, sizeof(buf), "env.abortStackOverflow(%i)", code);
  793. wasm_runtime_set_exception(module_inst, buf);
  794. }
  795. static void
  796. nullFunc_X_wrapper(wasm_exec_env_t exec_env, int32 code)
  797. {
  798. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  799. char buf[32];
  800. snprintf(buf, sizeof(buf), "env.nullFunc_X(%i)", code);
  801. wasm_runtime_set_exception(module_inst, buf);
  802. }
  803. static int32
  804. __cxa_allocate_exception_wrapper(wasm_exec_env_t exec_env,
  805. uint32 thrown_size)
  806. {
  807. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  808. int32 exception = module_malloc(thrown_size, NULL);
  809. if (!exception)
  810. return 0;
  811. return exception;
  812. }
  813. static void
  814. __cxa_begin_catch_wrapper(wasm_exec_env_t exec_env,
  815. void *exception_object)
  816. {
  817. }
  818. static void
  819. __cxa_throw_wrapper(wasm_exec_env_t exec_env,
  820. void *thrown_exception,
  821. void *tinfo,
  822. uint32 table_elem_idx)
  823. {
  824. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  825. char buf[32];
  826. snprintf(buf, sizeof(buf), "%s", "exception thrown by stdc++");
  827. wasm_runtime_set_exception(module_inst, buf);
  828. }
  829. static void
  830. print_i32_wrapper(wasm_exec_env_t exec_env, int32 i32)
  831. {
  832. os_printf("%d\n", i32);
  833. }
  834. #define REG_NATIVE_FUNC(func_name, signature) \
  835. { #func_name, func_name##_wrapper, signature, NULL }
  836. static NativeSymbol native_symbols_libc_builtin[] = {
  837. REG_NATIVE_FUNC(printf, "($*)i"),
  838. REG_NATIVE_FUNC(sprintf, "($$*)i"),
  839. REG_NATIVE_FUNC(snprintf, "(*~$*)i"),
  840. REG_NATIVE_FUNC(puts, "($)i"),
  841. REG_NATIVE_FUNC(putchar, "(i)i"),
  842. REG_NATIVE_FUNC(memcmp, "(**~)i"),
  843. REG_NATIVE_FUNC(memcpy, "(**~)i"),
  844. REG_NATIVE_FUNC(memmove, "(**~)i"),
  845. REG_NATIVE_FUNC(memset, "(*ii)i"),
  846. REG_NATIVE_FUNC(strchr, "($i)i"),
  847. REG_NATIVE_FUNC(strcmp, "($$)i"),
  848. REG_NATIVE_FUNC(strcpy, "(*$)i"),
  849. REG_NATIVE_FUNC(strlen, "($)i"),
  850. REG_NATIVE_FUNC(strncmp, "(**~)i"),
  851. REG_NATIVE_FUNC(strncpy, "(**~)i"),
  852. REG_NATIVE_FUNC(malloc, "(i)i"),
  853. REG_NATIVE_FUNC(calloc, "(ii)i"),
  854. REG_NATIVE_FUNC(strdup, "($)i"),
  855. /* clang may introduce __strdup */
  856. REG_NATIVE_FUNC(_strdup, "($)i"),
  857. REG_NATIVE_FUNC(free, "(*)"),
  858. REG_NATIVE_FUNC(atoi, "($)i"),
  859. REG_NATIVE_FUNC(exit, "(i)"),
  860. REG_NATIVE_FUNC(strtol, "($*i)i"),
  861. REG_NATIVE_FUNC(strtoul, "($*i)i"),
  862. REG_NATIVE_FUNC(memchr, "(*ii)i"),
  863. REG_NATIVE_FUNC(strncasecmp, "($$i)"),
  864. REG_NATIVE_FUNC(strspn, "($$)i"),
  865. REG_NATIVE_FUNC(strcspn, "($$)i"),
  866. REG_NATIVE_FUNC(strstr, "($$)i"),
  867. REG_NATIVE_FUNC(isupper, "(i)i"),
  868. REG_NATIVE_FUNC(isalpha, "(i)i"),
  869. REG_NATIVE_FUNC(isspace, "(i)i"),
  870. REG_NATIVE_FUNC(isgraph, "(i)i"),
  871. REG_NATIVE_FUNC(isprint, "(i)i"),
  872. REG_NATIVE_FUNC(isdigit, "(i)i"),
  873. REG_NATIVE_FUNC(isxdigit, "(i)i"),
  874. REG_NATIVE_FUNC(tolower, "(i)i"),
  875. REG_NATIVE_FUNC(toupper, "(i)i"),
  876. REG_NATIVE_FUNC(isalnum, "(i)i"),
  877. REG_NATIVE_FUNC(setTempRet0, "(i)"),
  878. REG_NATIVE_FUNC(getTempRet0, "()i"),
  879. REG_NATIVE_FUNC(llvm_bswap_i16, "(i)i"),
  880. REG_NATIVE_FUNC(llvm_bswap_i32, "(i)i"),
  881. REG_NATIVE_FUNC(bitshift64Lshr, "(iii)i"),
  882. REG_NATIVE_FUNC(bitshift64Shl, "(iii)i"),
  883. REG_NATIVE_FUNC(llvm_stackrestore, "(i)"),
  884. REG_NATIVE_FUNC(llvm_stacksave, "()i"),
  885. REG_NATIVE_FUNC(emscripten_memcpy_big, "(**~)i"),
  886. REG_NATIVE_FUNC(abort, "(i)"),
  887. REG_NATIVE_FUNC(abortStackOverflow, "(i)"),
  888. REG_NATIVE_FUNC(nullFunc_X, "(i)"),
  889. REG_NATIVE_FUNC(__cxa_allocate_exception, "(i)i"),
  890. REG_NATIVE_FUNC(__cxa_begin_catch, "(*)"),
  891. REG_NATIVE_FUNC(__cxa_throw, "(**i)")
  892. };
  893. static NativeSymbol native_symbols_spectest[] = {
  894. REG_NATIVE_FUNC(print_i32, "(i)")
  895. };
  896. uint32
  897. get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis)
  898. {
  899. *p_libc_builtin_apis = native_symbols_libc_builtin;
  900. return sizeof(native_symbols_libc_builtin) / sizeof(NativeSymbol);
  901. }
  902. uint32
  903. get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis)
  904. {
  905. *p_libc_builtin_apis = native_symbols_spectest;
  906. return sizeof(native_symbols_spectest) / sizeof(NativeSymbol);
  907. }
  908. /*************************************
  909. * Global Variables *
  910. *************************************/
  911. typedef struct WASMNativeGlobalDef {
  912. const char *module_name;
  913. const char *global_name;
  914. WASMValue global_data;
  915. } WASMNativeGlobalDef;
  916. static WASMNativeGlobalDef native_global_defs[] = {
  917. { "spectest", "global_i32", .global_data.i32 = 666 },
  918. { "spectest", "global_f32", .global_data.f32 = 0 },
  919. { "spectest", "global_f64", .global_data.f64 = 0 },
  920. { "test", "global-i32", .global_data.i32 = 0 },
  921. { "test", "global-f32", .global_data.f32 = 0 },
  922. { "env", "STACKTOP", .global_data.u32 = 0 },
  923. { "env", "STACK_MAX", .global_data.u32 = 0 },
  924. { "env", "ABORT", .global_data.u32 = 0 },
  925. { "env", "memoryBase", .global_data.u32 = 0 },
  926. { "env", "__memory_base", .global_data.u32 = 0 },
  927. { "env", "tableBase", .global_data.u32 = 0 },
  928. { "env", "__table_base", .global_data.u32 = 0 },
  929. { "env", "DYNAMICTOP_PTR", .global_data.addr = 0 },
  930. { "env", "tempDoublePtr", .global_data.addr = 0 },
  931. { "global", "NaN", .global_data.u64 = 0x7FF8000000000000LL },
  932. { "global", "Infinity", .global_data.u64 = 0x7FF0000000000000LL }
  933. };
  934. bool
  935. wasm_native_lookup_libc_builtin_global(const char *module_name,
  936. const char *global_name,
  937. WASMGlobalImport *global)
  938. {
  939. uint32 size = sizeof(native_global_defs) / sizeof(WASMNativeGlobalDef);
  940. WASMNativeGlobalDef *global_def = native_global_defs;
  941. WASMNativeGlobalDef *global_def_end = global_def + size;
  942. if (!module_name || !global_name || !global)
  943. return false;
  944. /* Lookup constant globals which can be defined by table */
  945. while (global_def < global_def_end) {
  946. if (!strcmp(global_def->module_name, module_name)
  947. && !strcmp(global_def->global_name, global_name)) {
  948. global->global_data_linked = global_def->global_data;
  949. return true;
  950. }
  951. global_def++;
  952. }
  953. return false;
  954. }