libc_emcc_wrapper.c 14 KB

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