libc_emcc_wrapper.c 14 KB

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