libc_builtin_wrapper.c 31 KB

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