libc_wrapper.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "wasm_native.h"
  17. #include "wasm_export.h"
  18. #include "wasm_log.h"
  19. #include "wasm_platform_log.h"
  20. void
  21. wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception);
  22. uint32
  23. wasm_runtime_get_temp_ret(wasm_module_inst_t module);
  24. void
  25. wasm_runtime_set_temp_ret(wasm_module_inst_t module, uint32 temp_ret);
  26. uint32
  27. wasm_runtime_get_llvm_stack(wasm_module_inst_t module);
  28. void
  29. wasm_runtime_set_llvm_stack(wasm_module_inst_t module, uint32 llvm_stack);
  30. #define get_module_inst() \
  31. wasm_runtime_get_current_module_inst()
  32. #define validate_app_addr(offset, size) \
  33. wasm_runtime_validate_app_addr(module_inst, offset, size)
  34. #define addr_app_to_native(offset) \
  35. wasm_runtime_addr_app_to_native(module_inst, offset)
  36. #define addr_native_to_app(ptr) \
  37. wasm_runtime_addr_native_to_app(module_inst, ptr)
  38. #define module_malloc(size) \
  39. wasm_runtime_module_malloc(module_inst, size)
  40. #define module_free(offset) \
  41. wasm_runtime_module_free(module_inst, offset)
  42. typedef int (*out_func_t)(int c, void *ctx);
  43. enum pad_type {
  44. PAD_NONE,
  45. PAD_ZERO_BEFORE,
  46. PAD_SPACE_BEFORE,
  47. PAD_SPACE_AFTER,
  48. };
  49. typedef char *_va_list;
  50. #define _INTSIZEOF(n) \
  51. ((sizeof(n) + 3) & ~3)
  52. #define _va_arg(ap,t) \
  53. (*(t*)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)))
  54. /**
  55. * @brief Output an unsigned int in hex format
  56. *
  57. * Output an unsigned int on output installed by platform at init time. Should
  58. * be able to handle an unsigned int of any size, 32 or 64 bit.
  59. * @param num Number to output
  60. *
  61. * @return N/A
  62. */
  63. static void
  64. _printf_hex_uint(out_func_t out, void *ctx,
  65. const uint64 num, bool is_u64,
  66. enum pad_type padding,
  67. int min_width)
  68. {
  69. int size = sizeof(num) * (is_u64 ? 2 : 1);
  70. int found_largest_digit = 0;
  71. int remaining = 8; /* 8 digits max */
  72. int digits = 0;
  73. for (; size; size--) {
  74. char nibble = (num >> ((size - 1) << 2) & 0xf);
  75. if (nibble || found_largest_digit || size == 1) {
  76. found_largest_digit = 1;
  77. nibble += nibble > 9 ? 87 : 48;
  78. out((int) nibble, ctx);
  79. digits++;
  80. continue;
  81. }
  82. if (remaining-- <= min_width) {
  83. if (padding == PAD_ZERO_BEFORE) {
  84. out('0', ctx);
  85. } else if (padding == PAD_SPACE_BEFORE) {
  86. out(' ', ctx);
  87. }
  88. }
  89. }
  90. if (padding == PAD_SPACE_AFTER) {
  91. remaining = min_width * 2 - digits;
  92. while (remaining-- > 0) {
  93. out(' ', ctx);
  94. }
  95. }
  96. }
  97. /**
  98. * @brief Output an unsigned int in decimal format
  99. *
  100. * Output an unsigned int on output installed by platform at init time. Only
  101. * works with 32-bit values.
  102. * @param num Number to output
  103. *
  104. * @return N/A
  105. */
  106. static void
  107. _printf_dec_uint(out_func_t out, void *ctx,
  108. const uint32 num,
  109. enum pad_type padding,
  110. int min_width)
  111. {
  112. uint32 pos = 999999999;
  113. uint32 remainder = num;
  114. int found_largest_digit = 0;
  115. int remaining = 10; /* 10 digits max */
  116. int digits = 1;
  117. /* make sure we don't skip if value is zero */
  118. if (min_width <= 0) {
  119. min_width = 1;
  120. }
  121. while (pos >= 9) {
  122. if (found_largest_digit || remainder > pos) {
  123. found_largest_digit = 1;
  124. out((int) ((remainder / (pos + 1)) + 48), ctx);
  125. digits++;
  126. } else if (remaining <= min_width && padding < PAD_SPACE_AFTER) {
  127. out((int) (padding == PAD_ZERO_BEFORE ? '0' : ' '), ctx);
  128. digits++;
  129. }
  130. remaining--;
  131. remainder %= (pos + 1);
  132. pos /= 10;
  133. }
  134. out((int) (remainder + 48), ctx);
  135. if (padding == PAD_SPACE_AFTER) {
  136. remaining = min_width - digits;
  137. while (remaining-- > 0) {
  138. out(' ', ctx);
  139. }
  140. }
  141. }
  142. static void
  143. print_err(out_func_t out, void *ctx)
  144. {
  145. out('E', ctx);
  146. out('R', ctx);
  147. out('R', ctx);
  148. }
  149. static void
  150. _vprintf(out_func_t out, void *ctx, const char *fmt, _va_list ap,
  151. wasm_module_inst_t module_inst)
  152. {
  153. int might_format = 0; /* 1 if encountered a '%' */
  154. enum pad_type padding = PAD_NONE;
  155. int min_width = -1;
  156. int long_ctr = 0;
  157. /* fmt has already been adjusted if needed */
  158. while (*fmt) {
  159. if (!might_format) {
  160. if (*fmt != '%') {
  161. out((int) *fmt, ctx);
  162. }
  163. else {
  164. might_format = 1;
  165. min_width = -1;
  166. padding = PAD_NONE;
  167. long_ctr = 0;
  168. }
  169. }
  170. else {
  171. switch (*fmt) {
  172. case '-':
  173. padding = PAD_SPACE_AFTER;
  174. goto still_might_format;
  175. case '0':
  176. if (min_width < 0 && padding == PAD_NONE) {
  177. padding = PAD_ZERO_BEFORE;
  178. goto still_might_format;
  179. }
  180. /* Fall through */
  181. case '1' ... '9':
  182. if (min_width < 0) {
  183. min_width = *fmt - '0';
  184. } else {
  185. min_width = 10 * min_width + *fmt - '0';
  186. }
  187. if (padding == PAD_NONE) {
  188. padding = PAD_SPACE_BEFORE;
  189. }
  190. goto still_might_format;
  191. case 'l':
  192. long_ctr++;
  193. /* Fall through */
  194. case 'z':
  195. case 'h':
  196. /* FIXME: do nothing for these modifiers */
  197. goto still_might_format;
  198. case 'd':
  199. case 'i': {
  200. int32 d;
  201. if (long_ctr < 2) {
  202. d = _va_arg(ap, int32);
  203. }
  204. else {
  205. int64 lld = _va_arg(ap, int64);
  206. if (lld > INT32_MAX || lld < INT32_MIN) {
  207. print_err(out, ctx);
  208. break;
  209. }
  210. d = (int32)lld;
  211. }
  212. if (d < 0) {
  213. out((int)'-', ctx);
  214. d = -d;
  215. min_width--;
  216. }
  217. _printf_dec_uint(out, ctx, d, padding, min_width);
  218. break;
  219. }
  220. case 'u': {
  221. uint32 u;
  222. if (long_ctr < 2) {
  223. u = _va_arg(ap, uint32);
  224. }
  225. else {
  226. uint64 llu = _va_arg(ap, uint64);
  227. if (llu > INT32_MAX) {
  228. print_err(out, ctx);
  229. break;
  230. }
  231. u = (uint32)llu;
  232. }
  233. _printf_dec_uint(out, ctx, u, padding, min_width);
  234. break;
  235. }
  236. case 'p':
  237. out('0', ctx);
  238. out('x', ctx);
  239. /* left-pad pointers with zeros */
  240. padding = PAD_ZERO_BEFORE;
  241. min_width = 8;
  242. /* Fall through */
  243. case 'x':
  244. case 'X': {
  245. uint64 x;
  246. bool is_ptr = (*fmt == 'p') ? true : false;
  247. if (long_ctr < 2) {
  248. x = _va_arg(ap, uint32);
  249. } else {
  250. x = _va_arg(ap, uint64);
  251. }
  252. _printf_hex_uint(out, ctx, x, !is_ptr, padding, min_width);
  253. break;
  254. }
  255. case 's': {
  256. char *s;
  257. char *start;
  258. int32 s_offset = _va_arg(ap, uint32);
  259. if (!validate_app_addr(s_offset, 1)) {
  260. wasm_runtime_set_exception(module_inst, "out of bounds memory access");
  261. return;
  262. }
  263. s = start = addr_app_to_native(s_offset);
  264. while (*s)
  265. out((int) (*s++), ctx);
  266. if (padding == PAD_SPACE_AFTER) {
  267. int remaining = min_width - (s - start);
  268. while (remaining-- > 0) {
  269. out(' ', ctx);
  270. }
  271. }
  272. break;
  273. }
  274. case 'c': {
  275. int c = _va_arg(ap, int);
  276. out(c, ctx);
  277. break;
  278. }
  279. case '%': {
  280. out((int) '%', ctx);
  281. break;
  282. }
  283. default:
  284. out((int) '%', ctx);
  285. out((int) *fmt, ctx);
  286. break;
  287. }
  288. might_format = 0;
  289. }
  290. still_might_format:
  291. ++fmt;
  292. }
  293. }
  294. struct str_context {
  295. char *str;
  296. int max;
  297. int count;
  298. };
  299. static int
  300. sprintf_out(int c, struct str_context *ctx)
  301. {
  302. if (!ctx->str || ctx->count >= ctx->max) {
  303. ctx->count++;
  304. return c;
  305. }
  306. if (ctx->count == ctx->max - 1) {
  307. ctx->str[ctx->count++] = '\0';
  308. } else {
  309. ctx->str[ctx->count++] = c;
  310. }
  311. return c;
  312. }
  313. static int
  314. printf_out(int c, struct str_context *ctx)
  315. {
  316. printf("%c", c);
  317. ctx->count++;
  318. return c;
  319. }
  320. static inline _va_list
  321. get_va_list(uint32 *args)
  322. {
  323. union {
  324. uint32 u;
  325. _va_list v;
  326. } u;
  327. u.u = args[0];
  328. return u.v;
  329. }
  330. static bool
  331. parse_printf_args(wasm_module_inst_t module_inst, int32 fmt_offset,
  332. int32 va_list_offset, const char **p_fmt,
  333. _va_list *p_va_args)
  334. {
  335. const char *fmt;
  336. union {
  337. uintptr_t u;
  338. _va_list v;
  339. } u;
  340. if (!validate_app_addr(fmt_offset, 1)
  341. || !validate_app_addr(va_list_offset, sizeof(int32)))
  342. return false;
  343. fmt = (const char*) addr_app_to_native(fmt_offset);
  344. u.u = (uintptr_t) addr_app_to_native(va_list_offset);
  345. *p_fmt = fmt;
  346. *p_va_args = u.v;
  347. return true;
  348. }
  349. static int
  350. _printf_wrapper(int32 fmt_offset, int32 va_list_offset)
  351. {
  352. wasm_module_inst_t module_inst = get_module_inst();
  353. struct str_context ctx = { NULL, 0, 0 };
  354. const char *fmt;
  355. _va_list va_args;
  356. if (!parse_printf_args(module_inst, fmt_offset, va_list_offset, &fmt, &va_args))
  357. return 0;
  358. _vprintf((out_func_t) printf_out, &ctx, fmt, va_args, module_inst);
  359. return ctx.count;
  360. }
  361. static int
  362. _sprintf_wrapper(int32 str_offset, int32 fmt_offset, int32 va_list_offset)
  363. {
  364. wasm_module_inst_t module_inst = get_module_inst();
  365. struct str_context ctx;
  366. char *str;
  367. const char *fmt;
  368. _va_list va_args;
  369. if (!validate_app_addr(str_offset, 1))
  370. return 0;
  371. str = addr_app_to_native(str_offset);
  372. if (!parse_printf_args(module_inst, fmt_offset, va_list_offset, &fmt, &va_args))
  373. return 0;
  374. ctx.str = str;
  375. ctx.max = INT_MAX;
  376. ctx.count = 0;
  377. _vprintf((out_func_t) sprintf_out, &ctx, fmt, va_args, module_inst);
  378. if (ctx.count < ctx.max) {
  379. str[ctx.count] = '\0';
  380. }
  381. return ctx.count;
  382. }
  383. static int
  384. _snprintf_wrapper(int32 str_offset, int32 size, int32 fmt_offset,
  385. int32 va_list_offset)
  386. {
  387. wasm_module_inst_t module_inst = get_module_inst();
  388. struct str_context ctx;
  389. char *str;
  390. const char *fmt;
  391. _va_list va_args;
  392. if (!validate_app_addr(str_offset, size))
  393. return 0;
  394. str = addr_app_to_native(str_offset);
  395. if (!parse_printf_args(module_inst, fmt_offset, va_list_offset, &fmt, &va_args))
  396. return 0;
  397. ctx.str = str;
  398. ctx.max = size;
  399. ctx.count = 0;
  400. _vprintf((out_func_t) sprintf_out, &ctx, fmt, va_args, module_inst);
  401. if (ctx.count < ctx.max) {
  402. str[ctx.count] = '\0';
  403. }
  404. return ctx.count;
  405. }
  406. static int
  407. _puts_wrapper(int32 str_offset)
  408. {
  409. wasm_module_inst_t module_inst = get_module_inst();
  410. const char *str;
  411. if (!validate_app_addr(str_offset, 1))
  412. return 0;
  413. str = addr_app_to_native(str_offset);
  414. return printf("%s\n", str);
  415. }
  416. static int
  417. _putchar_wrapper(int c)
  418. {
  419. printf("%c", c);
  420. return 1;
  421. }
  422. static int32
  423. _strdup_wrapper(int32 str_offset)
  424. {
  425. wasm_module_inst_t module_inst = get_module_inst();
  426. char *str, *str_ret;
  427. uint32 len;
  428. int32 str_ret_offset = 0;
  429. if (!validate_app_addr(str_offset, 1))
  430. return 0;
  431. str = addr_app_to_native(str_offset);
  432. if (str) {
  433. len = strlen(str) + 1;
  434. str_ret_offset = module_malloc(len);
  435. if (str_ret_offset) {
  436. str_ret = addr_app_to_native(str_ret_offset);
  437. memcpy(str_ret, str, len);
  438. }
  439. }
  440. return str_ret_offset;
  441. }
  442. static int32
  443. _memcmp_wrapper(int32 s1_offset, int32 s2_offset, int32 size)
  444. {
  445. wasm_module_inst_t module_inst = get_module_inst();
  446. void *s1, *s2;
  447. if (!validate_app_addr(s1_offset, size)
  448. || !validate_app_addr(s2_offset, size))
  449. return 0;
  450. s1 = addr_app_to_native(s1_offset);
  451. s2 = addr_app_to_native(s2_offset);
  452. return memcmp(s1, s2, size);
  453. }
  454. static int32
  455. _memcpy_wrapper(int32 dst_offset, int32 src_offset, int32 size)
  456. {
  457. wasm_module_inst_t module_inst = get_module_inst();
  458. void *dst, *src;
  459. if (size == 0)
  460. return dst_offset;
  461. if (!validate_app_addr(dst_offset, size)
  462. || !validate_app_addr(src_offset, size))
  463. return dst_offset;
  464. dst = addr_app_to_native(dst_offset);
  465. src = addr_app_to_native(src_offset);
  466. memcpy(dst, src, size);
  467. return dst_offset;
  468. }
  469. static int32
  470. _memmove_wrapper(int32 dst_offset, int32 src_offset, int32 size)
  471. {
  472. wasm_module_inst_t module_inst = get_module_inst();
  473. void *dst, *src;
  474. if (!validate_app_addr(dst_offset, size)
  475. || !validate_app_addr(src_offset, size))
  476. return dst_offset;
  477. dst = addr_app_to_native(dst_offset);
  478. src = addr_app_to_native(src_offset);
  479. memmove(dst, src, size);
  480. return dst_offset;
  481. }
  482. static int32
  483. _memset_wrapper(int32 s_offset, int32 c, int32 size)
  484. {
  485. wasm_module_inst_t module_inst = get_module_inst();
  486. void *s;
  487. if (!validate_app_addr(s_offset, size))
  488. return s_offset;
  489. s = addr_app_to_native(s_offset);
  490. memset(s, c, size);
  491. return s_offset;
  492. }
  493. static int32
  494. _strchr_wrapper(int32 s_offset, int32 c)
  495. {
  496. wasm_module_inst_t module_inst = get_module_inst();
  497. const char *s;
  498. char *ret;
  499. if (!validate_app_addr(s_offset, 1))
  500. return s_offset;
  501. s = addr_app_to_native(s_offset);
  502. ret = strchr(s, c);
  503. return ret ? addr_native_to_app(ret) : 0;
  504. }
  505. static int32
  506. _strcmp_wrapper(int32 s1_offset, int32 s2_offset)
  507. {
  508. wasm_module_inst_t module_inst = get_module_inst();
  509. void *s1, *s2;
  510. if (!validate_app_addr(s1_offset, 1)
  511. || !validate_app_addr(s2_offset, 1))
  512. return 0;
  513. s1 = addr_app_to_native(s1_offset);
  514. s2 = addr_app_to_native(s2_offset);
  515. return strcmp(s1, s2);
  516. }
  517. static int32
  518. _strncmp_wrapper(int32 s1_offset, int32 s2_offset, uint32 size)
  519. {
  520. wasm_module_inst_t module_inst = get_module_inst();
  521. void *s1, *s2;
  522. if (!validate_app_addr(s1_offset, size)
  523. || !validate_app_addr(s2_offset, size))
  524. return 0;
  525. s1 = addr_app_to_native(s1_offset);
  526. s2 = addr_app_to_native(s2_offset);
  527. return strncmp(s1, s2, size);
  528. }
  529. static int32
  530. _strcpy_wrapper(int32 dst_offset, int32 src_offset)
  531. {
  532. wasm_module_inst_t module_inst = get_module_inst();
  533. char *dst, *src;
  534. if (!validate_app_addr(dst_offset, 1)
  535. || !validate_app_addr(src_offset, 1))
  536. return 0;
  537. dst = addr_app_to_native(dst_offset);
  538. src = addr_app_to_native(src_offset);
  539. strcpy(dst, src);
  540. return dst_offset;
  541. }
  542. static int32
  543. _strncpy_wrapper(int32 dst_offset, int32 src_offset, uint32 size)
  544. {
  545. wasm_module_inst_t module_inst = get_module_inst();
  546. char *dst, *src;
  547. if (!validate_app_addr(dst_offset, size)
  548. || !validate_app_addr(src_offset, size))
  549. return 0;
  550. dst = addr_app_to_native(dst_offset);
  551. src = addr_app_to_native(src_offset);
  552. strncpy(dst, src, size);
  553. return dst_offset;
  554. }
  555. static uint32
  556. _strlen_wrapper(int32 s_offset)
  557. {
  558. wasm_module_inst_t module_inst = get_module_inst();
  559. char *s;
  560. if (!validate_app_addr(s_offset, 1))
  561. return 0;
  562. s = addr_app_to_native(s_offset);
  563. return strlen(s);
  564. }
  565. static int32
  566. _malloc_wrapper(uint32 size)
  567. {
  568. wasm_module_inst_t module_inst = get_module_inst();
  569. return module_malloc(size);
  570. }
  571. static int32
  572. _calloc_wrapper(uint32 nmemb, uint32 size)
  573. {
  574. uint64 total_size = (uint64) nmemb * (uint64) size;
  575. wasm_module_inst_t module_inst = get_module_inst();
  576. uint32 ret_offset = 0;
  577. uint8 *ret_ptr;
  578. if (total_size > UINT32_MAX)
  579. total_size = UINT32_MAX;
  580. ret_offset = module_malloc((uint32 )total_size);
  581. if (ret_offset) {
  582. ret_ptr = addr_app_to_native(ret_offset);
  583. memset(ret_ptr, 0, (uint32) total_size);
  584. }
  585. return ret_offset;
  586. }
  587. static void
  588. _free_wrapper(int32 ptr_offset)
  589. {
  590. wasm_module_inst_t module_inst = get_module_inst();
  591. if (!validate_app_addr(ptr_offset, 4))
  592. return;
  593. return module_free(ptr_offset);
  594. }
  595. static void
  596. setTempRet0_wrapper(uint32 temp_ret)
  597. {
  598. wasm_module_inst_t module_inst = get_module_inst();
  599. wasm_runtime_set_temp_ret(module_inst, temp_ret);
  600. }
  601. static uint32
  602. getTempRet0_wrapper()
  603. {
  604. wasm_module_inst_t module_inst = get_module_inst();
  605. return wasm_runtime_get_temp_ret(module_inst);
  606. }
  607. static uint32
  608. _llvm_bswap_i16_wrapper(uint32 data)
  609. {
  610. return (data & 0xFFFF0000)
  611. | ((data & 0xFF) << 8)
  612. | ((data & 0xFF00) >> 8);
  613. }
  614. static uint32
  615. _llvm_bswap_i32_wrapper(uint32 data)
  616. {
  617. return ((data & 0xFF) << 24)
  618. | ((data & 0xFF00) << 8)
  619. | ((data & 0xFF0000) >> 8)
  620. | ((data & 0xFF000000) >> 24);
  621. }
  622. static uint32
  623. _bitshift64Lshr_wrapper(uint32 uint64_part0, uint32 uint64_part1,
  624. uint32 bits)
  625. {
  626. wasm_module_inst_t module_inst = get_module_inst();
  627. union {
  628. uint64 value;
  629. uint32 parts[2];
  630. } u;
  631. u.parts[0] = uint64_part0;
  632. u.parts[1] = uint64_part1;
  633. u.value >>= bits;
  634. /* return low 32bit and save high 32bit to temp ret */
  635. wasm_runtime_set_temp_ret(module_inst, (uint32) (u.value >> 32));
  636. return (uint32) u.value;
  637. }
  638. static uint32
  639. _bitshift64Shl_wrapper(uint32 int64_part0, uint32 int64_part1,
  640. uint32 bits)
  641. {
  642. wasm_module_inst_t module_inst = get_module_inst();
  643. union {
  644. int64 value;
  645. uint32 parts[2];
  646. } u;
  647. u.parts[0] = int64_part0;
  648. u.parts[1] = int64_part1;
  649. u.value <<= bits;
  650. /* return low 32bit and save high 32bit to temp ret */
  651. wasm_runtime_set_temp_ret(module_inst, (uint32) (u.value >> 32));
  652. return (uint32) u.value;
  653. }
  654. static void
  655. _llvm_stackrestore_wrapper(uint32 llvm_stack)
  656. {
  657. wasm_module_inst_t module_inst = get_module_inst();
  658. printf("_llvm_stackrestore called!\n");
  659. wasm_runtime_set_llvm_stack(module_inst, llvm_stack);
  660. }
  661. static uint32
  662. _llvm_stacksave_wrapper()
  663. {
  664. wasm_module_inst_t module_inst = get_module_inst();
  665. printf("_llvm_stacksave called!\n");
  666. return wasm_runtime_get_llvm_stack(module_inst);
  667. }
  668. static int32
  669. _emscripten_memcpy_big_wrapper(int32 dst_offset, int32 src_offset,
  670. uint32 size)
  671. {
  672. wasm_module_inst_t module_inst = get_module_inst();
  673. void *dst, *src;
  674. if (!validate_app_addr(dst_offset, size)
  675. || !validate_app_addr(src_offset, size))
  676. return dst_offset;
  677. dst = addr_app_to_native(dst_offset);
  678. src = addr_app_to_native(src_offset);
  679. memcpy(dst, src, size);
  680. return dst_offset;
  681. }
  682. static void
  683. abort_wrapper(int32 code)
  684. {
  685. wasm_module_inst_t module_inst = get_module_inst();
  686. char buf[32];
  687. snprintf(buf, sizeof(buf), "env.abort(%i)", code);
  688. wasm_runtime_set_exception(module_inst, buf);
  689. }
  690. static void
  691. abortStackOverflow_wrapper(int32 code)
  692. {
  693. wasm_module_inst_t module_inst = get_module_inst();
  694. char buf[32];
  695. snprintf(buf, sizeof(buf), "env.abortStackOverflow(%i)", code);
  696. wasm_runtime_set_exception(module_inst, buf);
  697. }
  698. static void
  699. nullFunc_X_wrapper(int32 code)
  700. {
  701. wasm_module_inst_t module_inst = get_module_inst();
  702. char buf[32];
  703. snprintf(buf, sizeof(buf), "env.nullFunc_X(%i)", code);
  704. wasm_runtime_set_exception(module_inst, buf);
  705. }
  706. /* TODO: add function parameter/result types check */
  707. #define REG_NATIVE_FUNC(module_name, func_name) \
  708. { #module_name, #func_name, func_name##_wrapper }
  709. typedef struct WASMNativeFuncDef {
  710. const char *module_name;
  711. const char *func_name;
  712. void *func_ptr;
  713. } WASMNativeFuncDef;
  714. static WASMNativeFuncDef native_func_defs[] = {
  715. REG_NATIVE_FUNC(env, _printf),
  716. REG_NATIVE_FUNC(env, _sprintf),
  717. REG_NATIVE_FUNC(env, _snprintf),
  718. REG_NATIVE_FUNC(env, _puts),
  719. REG_NATIVE_FUNC(env, _putchar),
  720. REG_NATIVE_FUNC(env, _memcmp),
  721. REG_NATIVE_FUNC(env, _memcpy),
  722. REG_NATIVE_FUNC(env, _memmove),
  723. REG_NATIVE_FUNC(env, _memset),
  724. REG_NATIVE_FUNC(env, _strchr),
  725. REG_NATIVE_FUNC(env, _strcmp),
  726. REG_NATIVE_FUNC(env, _strcpy),
  727. REG_NATIVE_FUNC(env, _strlen),
  728. REG_NATIVE_FUNC(env, _strncmp),
  729. REG_NATIVE_FUNC(env, _strncpy),
  730. REG_NATIVE_FUNC(env, _malloc),
  731. REG_NATIVE_FUNC(env, _calloc),
  732. REG_NATIVE_FUNC(env, _strdup),
  733. REG_NATIVE_FUNC(env, _free),
  734. REG_NATIVE_FUNC(env, setTempRet0),
  735. REG_NATIVE_FUNC(env, getTempRet0),
  736. REG_NATIVE_FUNC(env, _llvm_bswap_i16),
  737. REG_NATIVE_FUNC(env, _llvm_bswap_i32),
  738. REG_NATIVE_FUNC(env, _bitshift64Lshr),
  739. REG_NATIVE_FUNC(env, _bitshift64Shl),
  740. REG_NATIVE_FUNC(env, _llvm_stackrestore),
  741. REG_NATIVE_FUNC(env, _llvm_stacksave),
  742. REG_NATIVE_FUNC(env, _emscripten_memcpy_big),
  743. REG_NATIVE_FUNC(env, abort),
  744. REG_NATIVE_FUNC(env, abortStackOverflow),
  745. REG_NATIVE_FUNC(env, nullFunc_X)
  746. };
  747. void*
  748. wasm_native_func_lookup(const char *module_name, const char *func_name)
  749. {
  750. uint32 size = sizeof(native_func_defs) / sizeof(WASMNativeFuncDef);
  751. WASMNativeFuncDef *func_def = native_func_defs;
  752. WASMNativeFuncDef *func_def_end = func_def + size;
  753. void *ret;
  754. if (!module_name || !func_name)
  755. return NULL;
  756. while (func_def < func_def_end) {
  757. if (!strcmp(func_def->module_name, module_name)
  758. && (!strcmp(func_def->func_name, func_name)
  759. || (func_def->func_name[0] == '_'
  760. && !strcmp(func_def->func_name + 1, func_name))))
  761. return (void*) (uintptr_t) func_def->func_ptr;
  762. func_def++;
  763. }
  764. if ((ret = wasm_platform_native_func_lookup(module_name, func_name)))
  765. return ret;
  766. return NULL;
  767. }
  768. /*************************************
  769. * Global Variables *
  770. *************************************/
  771. typedef struct WASMNativeGlobalDef {
  772. const char *module_name;
  773. const char *global_name;
  774. WASMValue global_data;
  775. } WASMNativeGlobalDef;
  776. static WASMNativeGlobalDef native_global_defs[] = {
  777. { "env", "STACKTOP", .global_data.u32 = 0 },
  778. { "env", "STACK_MAX", .global_data.u32 = 0 },
  779. { "env", "ABORT", .global_data.u32 = 0 },
  780. { "env", "memoryBase", .global_data.u32 = 0 },
  781. { "env", "__memory_base", .global_data.u32 = 0 },
  782. { "env", "tableBase", .global_data.u32 = 0 },
  783. { "env", "__table_base", .global_data.u32 = 0 },
  784. { "env", "DYNAMICTOP_PTR", .global_data.addr = 0 },
  785. { "env", "tempDoublePtr", .global_data.addr = 0 },
  786. { "global", "NaN", .global_data.u64 = 0x7FF8000000000000LL },
  787. { "global", "Infinity", .global_data.u64 = 0x7FF0000000000000LL }
  788. };
  789. bool
  790. wasm_native_global_lookup(const char *module_name, const char *global_name,
  791. WASMGlobalImport *global)
  792. {
  793. uint32 size = sizeof(native_global_defs) / sizeof(WASMNativeGlobalDef);
  794. WASMNativeGlobalDef *global_def = native_global_defs;
  795. WASMNativeGlobalDef *global_def_end = global_def + size;
  796. if (!module_name || !global_name || !global)
  797. return false;
  798. /* Lookup constant globals which can be defined by table */
  799. while (global_def < global_def_end) {
  800. if (!strcmp(global_def->module_name, module_name)
  801. && !strcmp(global_def->global_name, global_name)) {
  802. global->global_data_linked = global_def->global_data;
  803. return true;
  804. }
  805. global_def++;
  806. }
  807. /* Lookup non-constant globals which cannot be defined by table */
  808. if (!strcmp(module_name, "env")) {
  809. if (!strcmp(global_name, "_stdin")) {
  810. global->global_data_linked.addr = (uintptr_t)stdin;
  811. global->is_addr = true;
  812. return true;
  813. } else if (!strcmp(global_name, "_stdout")) {
  814. global->global_data_linked.addr = (uintptr_t)stdout;
  815. global->is_addr = true;
  816. return true;
  817. } else if (!strcmp(global_name, "_stderr")) {
  818. global->global_data_linked.addr = (uintptr_t)stderr;
  819. global->is_addr = true;
  820. return true;
  821. }
  822. }
  823. return false;
  824. }
  825. bool
  826. wasm_native_init()
  827. {
  828. /* TODO: qsort the function defs and global defs. */
  829. return true;
  830. }