libc_emcc_wrapper.c 15 KB

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