libc_emcc_wrapper.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. /*
  2. * Copyright (C) 2020 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(__linux__)
  10. #include <linux/version.h>
  11. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
  12. #define HAVE_SYSCALL_GETRANDOM
  13. #include <sys/syscall.h>
  14. #endif
  15. #endif
  16. /* clang-format off */
  17. #define get_module_inst(exec_env) \
  18. wasm_runtime_get_module_inst(exec_env)
  19. #define validate_app_addr(offset, size) \
  20. wasm_runtime_validate_app_addr(module_inst, offset, size)
  21. #define validate_app_str_addr(offset) \
  22. wasm_runtime_validate_app_str_addr(module_inst, offset)
  23. #define validate_native_addr(addr, size) \
  24. wasm_runtime_validate_native_addr(module_inst, addr, size)
  25. #define addr_app_to_native(offset) \
  26. wasm_runtime_addr_app_to_native(module_inst, offset)
  27. #define addr_native_to_app(ptr) \
  28. wasm_runtime_addr_native_to_app(module_inst, ptr)
  29. #define module_malloc(size, p_native_addr) \
  30. wasm_runtime_module_malloc(module_inst, size, p_native_addr)
  31. #define module_free(offset) \
  32. wasm_runtime_module_free(module_inst, offset)
  33. /* clang-format on */
  34. static void
  35. invoke_viiii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0,
  36. int arg1, int arg2, int arg3)
  37. {
  38. uint32 argv[4];
  39. bool ret;
  40. argv[0] = arg0;
  41. argv[1] = arg1;
  42. argv[2] = arg2;
  43. argv[3] = arg3;
  44. ret = wasm_runtime_call_indirect(exec_env, elem_idx, 4, argv);
  45. (void)ret;
  46. }
  47. static void
  48. invoke_viii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0,
  49. int arg1, int arg2)
  50. {
  51. uint32 argv[4];
  52. bool ret;
  53. argv[0] = arg0;
  54. argv[1] = arg1;
  55. argv[2] = arg2;
  56. ret = wasm_runtime_call_indirect(exec_env, elem_idx, 3, argv);
  57. (void)ret;
  58. }
  59. static void
  60. invoke_vii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0,
  61. int arg1)
  62. {
  63. uint32 argv[4];
  64. bool ret;
  65. argv[0] = arg0;
  66. argv[1] = arg1;
  67. ret = wasm_runtime_call_indirect(exec_env, elem_idx, 2, argv);
  68. (void)ret;
  69. }
  70. static void
  71. invoke_vi_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0)
  72. {
  73. uint32 argv[4];
  74. bool ret;
  75. argv[0] = arg0;
  76. ret = wasm_runtime_call_indirect(exec_env, elem_idx, 1, argv);
  77. (void)ret;
  78. }
  79. static int
  80. invoke_iii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0,
  81. int arg1)
  82. {
  83. uint32 argv[4];
  84. bool ret;
  85. argv[0] = arg0;
  86. argv[1] = arg1;
  87. ret = wasm_runtime_call_indirect(exec_env, elem_idx, 2, argv);
  88. return ret ? argv[0] : 0;
  89. }
  90. static int
  91. invoke_ii_wrapper(wasm_exec_env_t exec_env, uint32 elem_idx, int arg0)
  92. {
  93. uint32 argv[4];
  94. bool ret;
  95. argv[0] = arg0;
  96. ret = wasm_runtime_call_indirect(exec_env, elem_idx, 1, argv);
  97. return ret ? argv[0] : 0;
  98. }
  99. struct timespec_emcc {
  100. int tv_sec;
  101. int tv_nsec;
  102. };
  103. struct stat_emcc {
  104. unsigned st_dev;
  105. int __st_dev_padding;
  106. unsigned __st_ino_truncated;
  107. unsigned st_mode;
  108. unsigned st_nlink;
  109. unsigned st_uid;
  110. unsigned st_gid;
  111. unsigned st_rdev;
  112. int __st_rdev_padding;
  113. int64 st_size;
  114. int st_blksize;
  115. int st_blocks;
  116. struct timespec_emcc st_atim;
  117. struct timespec_emcc st_mtim;
  118. struct timespec_emcc st_ctim;
  119. int64 st_ino;
  120. };
  121. static int
  122. open_wrapper(wasm_exec_env_t exec_env, const char *pathname, int flags,
  123. int mode)
  124. {
  125. if (pathname == NULL)
  126. return -1;
  127. return open(pathname, flags, mode);
  128. }
  129. static int
  130. __sys_read_wrapper(wasm_exec_env_t exec_env, int fd, void *buf, uint32 count)
  131. {
  132. return read(fd, buf, count);
  133. }
  134. static void
  135. statbuf_native2app(const struct stat *statbuf_native,
  136. struct stat_emcc *statbuf_app)
  137. {
  138. statbuf_app->st_dev = (unsigned)statbuf_native->st_dev;
  139. statbuf_app->__st_ino_truncated = (unsigned)statbuf_native->st_ino;
  140. statbuf_app->st_mode = (unsigned)statbuf_native->st_mode;
  141. statbuf_app->st_nlink = (unsigned)statbuf_native->st_nlink;
  142. statbuf_app->st_uid = (unsigned)statbuf_native->st_uid;
  143. statbuf_app->st_gid = (unsigned)statbuf_native->st_gid;
  144. statbuf_app->st_rdev = (unsigned)statbuf_native->st_rdev;
  145. statbuf_app->st_size = (int64)statbuf_native->st_size;
  146. statbuf_app->st_blksize = (unsigned)statbuf_native->st_blksize;
  147. statbuf_app->st_blocks = (unsigned)statbuf_native->st_blocks;
  148. statbuf_app->st_ino = (int64)statbuf_native->st_ino;
  149. #if defined(__APPLE__)
  150. statbuf_app->st_atim.tv_sec = (int)statbuf_native->st_atimespec.tv_sec;
  151. statbuf_app->st_atim.tv_nsec = (int)statbuf_native->st_atimespec.tv_nsec;
  152. statbuf_app->st_mtim.tv_sec = (int)statbuf_native->st_mtimespec.tv_sec;
  153. statbuf_app->st_mtim.tv_nsec = (int)statbuf_native->st_mtimespec.tv_nsec;
  154. statbuf_app->st_ctim.tv_sec = (int)statbuf_native->st_ctimespec.tv_sec;
  155. statbuf_app->st_ctim.tv_nsec = (int)statbuf_native->st_ctimespec.tv_nsec;
  156. #else
  157. statbuf_app->st_atim.tv_sec = (int)statbuf_native->st_atim.tv_sec;
  158. statbuf_app->st_atim.tv_nsec = (int)statbuf_native->st_atim.tv_nsec;
  159. statbuf_app->st_mtim.tv_sec = (int)statbuf_native->st_mtim.tv_sec;
  160. statbuf_app->st_mtim.tv_nsec = (int)statbuf_native->st_mtim.tv_nsec;
  161. statbuf_app->st_ctim.tv_sec = (int)statbuf_native->st_ctim.tv_sec;
  162. statbuf_app->st_ctim.tv_nsec = (int)statbuf_native->st_ctim.tv_nsec;
  163. #endif
  164. }
  165. static int
  166. __sys_stat64_wrapper(wasm_exec_env_t exec_env, const char *pathname,
  167. struct stat_emcc *statbuf_app)
  168. {
  169. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  170. int ret;
  171. struct stat statbuf;
  172. if (!validate_native_addr((void *)statbuf_app,
  173. (uint64)sizeof(struct stat_emcc)))
  174. return -1;
  175. if (pathname == NULL)
  176. return -1;
  177. ret = stat(pathname, &statbuf);
  178. if (ret == 0)
  179. statbuf_native2app(&statbuf, statbuf_app);
  180. return ret;
  181. }
  182. static int
  183. __sys_fstat64_wrapper(wasm_exec_env_t exec_env, int fd,
  184. struct stat_emcc *statbuf_app)
  185. {
  186. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  187. int ret;
  188. struct stat statbuf;
  189. if (!validate_native_addr((void *)statbuf_app,
  190. (uint64)sizeof(struct stat_emcc)))
  191. return -1;
  192. if (fd <= 0)
  193. return -1;
  194. ret = fstat(fd, &statbuf);
  195. if (ret == 0)
  196. statbuf_native2app(&statbuf, statbuf_app);
  197. return ret;
  198. }
  199. static int
  200. mmap_wrapper(wasm_exec_env_t exec_env, void *addr, int length, int prot,
  201. int flags, int fd, int64 offset)
  202. {
  203. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  204. uint32 buf_offset;
  205. char *buf;
  206. int size_read;
  207. buf_offset = module_malloc((uint64)length, (void **)&buf);
  208. if (buf_offset == 0)
  209. return -1;
  210. if (fd <= 0)
  211. return -1;
  212. if (lseek(fd, offset, SEEK_SET) == -1)
  213. return -1;
  214. size_read = read(fd, buf, length);
  215. (void)size_read;
  216. return buf_offset;
  217. }
  218. static int
  219. munmap_wrapper(wasm_exec_env_t exec_env, uint32 buf_offset, int length)
  220. {
  221. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  222. module_free((uint64)buf_offset);
  223. return 0;
  224. }
  225. static int
  226. __munmap_wrapper(wasm_exec_env_t exec_env, uint32 buf_offset, int length)
  227. {
  228. return munmap_wrapper(exec_env, buf_offset, length);
  229. }
  230. static int
  231. getentropy_wrapper(wasm_exec_env_t exec_env, void *buffer, uint32 length)
  232. {
  233. if (buffer == NULL)
  234. return -1;
  235. #if defined(HAVE_SYSCALL_GETRANDOM)
  236. return syscall(SYS_getrandom, buffer, length, 0);
  237. #else
  238. return getentropy(buffer, length);
  239. #endif
  240. }
  241. static int
  242. setjmp_wrapper(wasm_exec_env_t exec_env, void *jmp_buf)
  243. {
  244. LOG_DEBUG("setjmp() called\n");
  245. return 0;
  246. }
  247. static void
  248. longjmp_wrapper(wasm_exec_env_t exec_env, void *jmp_buf, int val)
  249. {
  250. LOG_DEBUG("longjmp() called\n");
  251. }
  252. #if !defined(BH_PLATFORM_LINUX_SGX)
  253. static FILE *file_list[32] = { 0 };
  254. static int
  255. get_free_file_slot()
  256. {
  257. unsigned int i;
  258. for (i = 0; i < sizeof(file_list) / sizeof(FILE *); i++) {
  259. if (file_list[i] == NULL)
  260. return (int)i;
  261. }
  262. return -1;
  263. }
  264. static int
  265. fopen_wrapper(wasm_exec_env_t exec_env, const char *pathname, const char *mode)
  266. {
  267. FILE *file;
  268. int file_id;
  269. if (pathname == NULL || mode == NULL)
  270. return 0;
  271. if ((file_id = get_free_file_slot()) == -1)
  272. return 0;
  273. file = fopen(pathname, mode);
  274. if (!file)
  275. return 0;
  276. file_list[file_id] = file;
  277. return file_id + 1;
  278. }
  279. static uint32
  280. fread_wrapper(wasm_exec_env_t exec_env, void *ptr, uint32 size, uint32 nmemb,
  281. int file_id)
  282. {
  283. FILE *file;
  284. file_id = file_id - 1;
  285. if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *)) {
  286. return 0;
  287. }
  288. if ((file = file_list[file_id]) == NULL) {
  289. return 0;
  290. }
  291. return (uint32)fread(ptr, size, nmemb, file);
  292. }
  293. static int
  294. fseeko_wrapper(wasm_exec_env_t exec_env, int file_id, int64 offset, int whence)
  295. {
  296. FILE *file;
  297. file_id = file_id - 1;
  298. if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *)) {
  299. return -1;
  300. }
  301. if ((file = file_list[file_id]) == NULL) {
  302. return -1;
  303. }
  304. return (uint32)fseek(file, offset, whence);
  305. }
  306. static uint32
  307. emcc_fwrite_wrapper(wasm_exec_env_t exec_env, const void *ptr, uint32 size,
  308. uint32 nmemb, int file_id)
  309. {
  310. FILE *file;
  311. file_id = file_id - 1;
  312. if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *)) {
  313. return 0;
  314. }
  315. if ((file = file_list[file_id]) == NULL) {
  316. return 0;
  317. }
  318. return (uint32)fwrite(ptr, size, nmemb, file);
  319. }
  320. static int
  321. feof_wrapper(wasm_exec_env_t exec_env, int file_id)
  322. {
  323. FILE *file;
  324. file_id = file_id - 1;
  325. if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *))
  326. return 1;
  327. if ((file = file_list[file_id]) == NULL)
  328. return 1;
  329. return feof(file);
  330. }
  331. static int
  332. fclose_wrapper(wasm_exec_env_t exec_env, int file_id)
  333. {
  334. FILE *file;
  335. file_id = file_id - 1;
  336. if ((unsigned)file_id >= sizeof(file_list) / sizeof(FILE *))
  337. return -1;
  338. if ((file = file_list[file_id]) == NULL)
  339. return -1;
  340. file_list[file_id] = NULL;
  341. return fclose(file);
  342. }
  343. static int
  344. __sys_mkdir_wrapper(wasm_exec_env_t exec_env, const char *pathname, int mode)
  345. {
  346. if (!pathname)
  347. return -1;
  348. return mkdir(pathname, mode);
  349. }
  350. static int
  351. __sys_rmdir_wrapper(wasm_exec_env_t exec_env, const char *pathname)
  352. {
  353. if (!pathname)
  354. return -1;
  355. return rmdir(pathname);
  356. }
  357. static int
  358. __sys_unlink_wrapper(wasm_exec_env_t exec_env, const char *pathname)
  359. {
  360. if (!pathname)
  361. return -1;
  362. return unlink(pathname);
  363. }
  364. static uint32
  365. __sys_getcwd_wrapper(wasm_exec_env_t exec_env, char *buf, uint32 size)
  366. {
  367. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  368. char *ret;
  369. if (!buf)
  370. return -1;
  371. ret = getcwd(buf, size);
  372. return ret ? (uint32)addr_native_to_app(ret) : 0;
  373. }
  374. #include <sys/utsname.h>
  375. struct utsname_app {
  376. char sysname[64];
  377. char nodename[64];
  378. char release[64];
  379. char version[64];
  380. char machine[64];
  381. char domainname[64];
  382. };
  383. static int
  384. __sys_uname_wrapper(wasm_exec_env_t exec_env, struct utsname_app *uname_app)
  385. {
  386. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  387. struct utsname uname_native = { 0 };
  388. uint32 length;
  389. if (!validate_native_addr(uname_app, (uint64)sizeof(struct utsname_app)))
  390. return -1;
  391. if (uname(&uname_native) != 0) {
  392. return -1;
  393. }
  394. memset(uname_app, 0, sizeof(struct utsname_app));
  395. length = strlen(uname_native.sysname);
  396. if (length > sizeof(uname_app->sysname) - 1)
  397. length = sizeof(uname_app->sysname) - 1;
  398. bh_memcpy_s(uname_app->sysname, sizeof(uname_app->sysname),
  399. uname_native.sysname, length);
  400. length = strlen(uname_native.nodename);
  401. if (length > sizeof(uname_app->nodename) - 1)
  402. length = sizeof(uname_app->nodename) - 1;
  403. bh_memcpy_s(uname_app->nodename, sizeof(uname_app->nodename),
  404. uname_native.nodename, length);
  405. length = strlen(uname_native.release);
  406. if (length > sizeof(uname_app->release) - 1)
  407. length = sizeof(uname_app->release) - 1;
  408. bh_memcpy_s(uname_app->release, sizeof(uname_app->release),
  409. uname_native.release, length);
  410. length = strlen(uname_native.version);
  411. if (length > sizeof(uname_app->version) - 1)
  412. length = sizeof(uname_app->version) - 1;
  413. bh_memcpy_s(uname_app->version, sizeof(uname_app->version),
  414. uname_native.version, length);
  415. #ifdef _GNU_SOURCE
  416. length = strlen(uname_native.domainname);
  417. if (length > sizeof(uname_app->domainname) - 1)
  418. length = sizeof(uname_app->domainname) - 1;
  419. bh_memcpy_s(uname_app->domainname, sizeof(uname_app->domainname),
  420. uname_native.domainname, length);
  421. #endif
  422. return 0;
  423. }
  424. static void
  425. emscripten_notify_memory_growth_wrapper(wasm_exec_env_t exec_env, int i)
  426. {
  427. (void)i;
  428. }
  429. static void
  430. emscripten_sleep_wrapper(wasm_exec_env_t exec_env, int timeout_ms)
  431. {
  432. unsigned int sec;
  433. useconds_t us;
  434. if (timeout_ms <= 0)
  435. return;
  436. sec = timeout_ms / 1000;
  437. us = (timeout_ms % 1000) * 1000;
  438. if (sec > 0)
  439. sleep(sec);
  440. if (us > 0)
  441. usleep(us);
  442. }
  443. static void
  444. emscripten_thread_sleep_wrapper(wasm_exec_env_t exec_env, double timeout_ms)
  445. {
  446. uint64 ms = (uint64)timeout_ms;
  447. uint64 sec = ms / 1000, us = (ms % 1000) * 1000;
  448. if (sec > 0)
  449. sleep(sec);
  450. if (us > 0)
  451. usleep(us);
  452. }
  453. #endif /* end of BH_PLATFORM_LINUX_SGX */
  454. /* clang-format off */
  455. #define REG_NATIVE_FUNC(func_name, signature) \
  456. { #func_name, func_name##_wrapper, signature, NULL }
  457. /* clang-format off */
  458. static NativeSymbol native_symbols_libc_emcc[] = {
  459. REG_NATIVE_FUNC(invoke_viiii, "(iiiii)"),
  460. REG_NATIVE_FUNC(invoke_viii, "(iiii)"),
  461. REG_NATIVE_FUNC(invoke_vii, "(iii)"),
  462. REG_NATIVE_FUNC(invoke_vi, "(ii)"),
  463. REG_NATIVE_FUNC(invoke_iii, "(iii)i"),
  464. REG_NATIVE_FUNC(invoke_ii, "(ii)i"),
  465. REG_NATIVE_FUNC(open, "($ii)i"),
  466. REG_NATIVE_FUNC(__sys_read, "(i*~)i"),
  467. REG_NATIVE_FUNC(__sys_stat64, "($*)i"),
  468. REG_NATIVE_FUNC(__sys_fstat64, "(i*)i"),
  469. REG_NATIVE_FUNC(mmap, "(*iiiiI)i"),
  470. REG_NATIVE_FUNC(munmap, "(ii)i"),
  471. REG_NATIVE_FUNC(__munmap, "(ii)i"),
  472. REG_NATIVE_FUNC(getentropy, "(*~)i"),
  473. REG_NATIVE_FUNC(setjmp, "(*)i"),
  474. REG_NATIVE_FUNC(longjmp, "(*i)"),
  475. #if !defined(BH_PLATFORM_LINUX_SGX)
  476. REG_NATIVE_FUNC(fopen, "($$)i"),
  477. REG_NATIVE_FUNC(fread, "(*iii)i"),
  478. REG_NATIVE_FUNC(fseeko, "(iIi)i"),
  479. REG_NATIVE_FUNC(emcc_fwrite, "(*iii)i"),
  480. REG_NATIVE_FUNC(feof, "(i)i"),
  481. REG_NATIVE_FUNC(fclose, "(i)i"),
  482. REG_NATIVE_FUNC(__sys_mkdir, "($i)i"),
  483. REG_NATIVE_FUNC(__sys_rmdir, "($)i"),
  484. REG_NATIVE_FUNC(__sys_unlink, "($)i"),
  485. REG_NATIVE_FUNC(__sys_getcwd, "(*~)i"),
  486. REG_NATIVE_FUNC(__sys_uname, "(*)i"),
  487. REG_NATIVE_FUNC(emscripten_notify_memory_growth, "(i)"),
  488. REG_NATIVE_FUNC(emscripten_sleep, "(i)"),
  489. REG_NATIVE_FUNC(emscripten_thread_sleep, "(F)"),
  490. #endif /* end of BH_PLATFORM_LINUX_SGX */
  491. };
  492. uint32
  493. get_libc_emcc_export_apis(NativeSymbol **p_libc_emcc_apis)
  494. {
  495. *p_libc_emcc_apis = native_symbols_libc_emcc;
  496. return sizeof(native_symbols_libc_emcc) / sizeof(NativeSymbol);
  497. }