libc_wrapper.c 21 KB

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