wasm_native.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "wasm_native.h"
  6. #include "wasm_runtime_common.h"
  7. #include "bh_log.h"
  8. static NativeSymbolsList g_native_symbols_list = NULL;
  9. static NativeSymbolsList g_native_symbols_list_end = NULL;
  10. uint32
  11. get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis);
  12. #if WASM_ENABLE_SPEC_TEST != 0
  13. uint32
  14. get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis);
  15. #endif
  16. uint32
  17. get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis);
  18. uint32
  19. get_base_lib_export_apis(NativeSymbol **p_base_lib_apis);
  20. uint32
  21. get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis);
  22. #if WASM_ENABLE_LIB_PTHREAD != 0
  23. bool
  24. lib_pthread_init();
  25. void
  26. lib_pthread_destroy();
  27. uint32
  28. get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis);
  29. #endif
  30. static bool
  31. check_symbol_signature(const WASMType *type, const char *signature)
  32. {
  33. const char *p = signature, *p_end;
  34. char sig_map[] = { 'F', 'f', 'I', 'i' }, sig;
  35. uint32 i = 0;
  36. if (!p || strlen(p) < 2)
  37. return false;
  38. p_end = p + strlen(signature);
  39. if (*p++ != '(')
  40. return false;
  41. if ((uint32)(p_end - p) < (uint32)(type->param_count + 1))
  42. /* signatures of parameters, and ')' */
  43. return false;
  44. for (i = 0; i < type->param_count; i++) {
  45. sig = *p++;
  46. if (sig == sig_map[type->types[i] - VALUE_TYPE_F64])
  47. /* normal parameter */
  48. continue;
  49. if (type->types[i] != VALUE_TYPE_I32)
  50. /* pointer and string must be i32 type */
  51. return false;
  52. if (sig == '*') {
  53. /* it is a pointer */
  54. if (i + 1 < type->param_count
  55. && type->types[i + 1] == VALUE_TYPE_I32
  56. && *p == '~') {
  57. /* pointer length followed */
  58. i++;
  59. p++;
  60. }
  61. }
  62. else if (sig == '$') {
  63. /* it is a string */
  64. }
  65. else {
  66. /* invalid signature */
  67. return false;
  68. }
  69. }
  70. if (*p++ != ')')
  71. return false;
  72. if (type->result_count) {
  73. if (p >= p_end)
  74. return false;
  75. if (*p++ != sig_map[type->types[i] - VALUE_TYPE_F64])
  76. return false;
  77. }
  78. if (*p != '\0')
  79. return false;
  80. return true;
  81. }
  82. static void
  83. sort_symbol_ptr(NativeSymbol *native_symbols, uint32 n_native_symbols)
  84. {
  85. uint32 i, j;
  86. NativeSymbol temp;
  87. for (i = 0; i < n_native_symbols - 1; i++) {
  88. for (j = i + 1; j < n_native_symbols; j++) {
  89. if (strcmp(native_symbols[i].symbol,
  90. native_symbols[j].symbol) > 0) {
  91. temp = native_symbols[i];
  92. native_symbols[i] = native_symbols[j];
  93. native_symbols[j] = temp;
  94. }
  95. }
  96. }
  97. }
  98. static void *
  99. lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
  100. const char *symbol, const char **p_signature, void **p_attachment)
  101. {
  102. int low = 0, mid, ret;
  103. int high = n_native_symbols - 1;
  104. while (low <= high) {
  105. mid = (low + high) / 2;
  106. ret = strcmp(symbol, native_symbols[mid].symbol);
  107. if (ret == 0) {
  108. *p_signature = native_symbols[mid].signature;
  109. *p_attachment = native_symbols[mid].attachment;
  110. return native_symbols[mid].func_ptr;
  111. }
  112. else if (ret < 0)
  113. high = mid - 1;
  114. else
  115. low = mid + 1;
  116. }
  117. return NULL;
  118. }
  119. void*
  120. wasm_native_resolve_symbol(const char *module_name, const char *field_name,
  121. const WASMType *func_type, const char **p_signature,
  122. void **p_attachment, bool *p_call_conv_raw)
  123. {
  124. NativeSymbolsNode *node, *node_next;
  125. const char *signature = NULL;
  126. void *func_ptr = NULL, *attachment;
  127. node = g_native_symbols_list;
  128. while (node) {
  129. node_next = node->next;
  130. if (!strcmp(node->module_name, module_name)) {
  131. if ((func_ptr = lookup_symbol(node->native_symbols,
  132. node->n_native_symbols,
  133. field_name, &signature, &attachment))
  134. || (field_name[0] == '_'
  135. && (func_ptr = lookup_symbol(node->native_symbols,
  136. node->n_native_symbols,
  137. field_name + 1,
  138. &signature, &attachment))))
  139. break;
  140. }
  141. node = node_next;
  142. }
  143. if (func_ptr) {
  144. if (signature && signature[0] != '\0') {
  145. /* signature is not empty, check its format */
  146. if (!check_symbol_signature(func_type, signature)) {
  147. #if WASM_ENABLE_WAMR_COMPILER == 0 /* Output warning except running aot compiler */
  148. LOG_WARNING("failed to check signature '%s' and resolve "
  149. "pointer params for import function (%s %s)\n",
  150. signature, module_name, field_name);
  151. #endif
  152. return NULL;
  153. }
  154. else
  155. /* Save signature for runtime to do pointer check and
  156. address conversion */
  157. *p_signature = signature;
  158. }
  159. else
  160. /* signature is empty */
  161. *p_signature = NULL;
  162. *p_attachment = attachment;
  163. *p_call_conv_raw = node->call_conv_raw;
  164. }
  165. return func_ptr;
  166. }
  167. static bool
  168. register_natives(const char *module_name,
  169. NativeSymbol *native_symbols,
  170. uint32 n_native_symbols,
  171. bool call_conv_raw)
  172. {
  173. NativeSymbolsNode *node;
  174. if (!(node = wasm_runtime_malloc(sizeof(NativeSymbolsNode))))
  175. return false;
  176. node->module_name = module_name;
  177. node->native_symbols = native_symbols;
  178. node->n_native_symbols = n_native_symbols;
  179. node->call_conv_raw = call_conv_raw;
  180. node->next = NULL;
  181. if (g_native_symbols_list_end) {
  182. g_native_symbols_list_end->next = node;
  183. g_native_symbols_list_end = node;
  184. }
  185. else {
  186. g_native_symbols_list = g_native_symbols_list_end = node;
  187. }
  188. sort_symbol_ptr(native_symbols, n_native_symbols);
  189. return true;
  190. }
  191. bool
  192. wasm_native_register_natives(const char *module_name,
  193. NativeSymbol *native_symbols,
  194. uint32 n_native_symbols)
  195. {
  196. return register_natives(module_name, native_symbols, n_native_symbols, false);
  197. }
  198. bool
  199. wasm_native_register_natives_raw(const char *module_name,
  200. NativeSymbol *native_symbols,
  201. uint32 n_native_symbols)
  202. {
  203. return register_natives(module_name, native_symbols, n_native_symbols, true);
  204. }
  205. bool
  206. wasm_native_init()
  207. {
  208. NativeSymbol *native_symbols;
  209. uint32 n_native_symbols;
  210. #if WASM_ENABLE_LIBC_BUILTIN != 0
  211. n_native_symbols = get_libc_builtin_export_apis(&native_symbols);
  212. if (!wasm_native_register_natives("env",
  213. native_symbols, n_native_symbols))
  214. return false;
  215. #endif /* WASM_ENABLE_LIBC_BUILTIN */
  216. #if WASM_ENABLE_SPEC_TEST
  217. n_native_symbols = get_spectest_export_apis(&native_symbols);
  218. if (!wasm_native_register_natives("spectest",
  219. native_symbols, n_native_symbols))
  220. return false;
  221. #endif /* WASM_ENABLE_SPEC_TEST */
  222. #if WASM_ENABLE_LIBC_WASI != 0
  223. n_native_symbols = get_libc_wasi_export_apis(&native_symbols);
  224. if (!wasm_native_register_natives("wasi_unstable",
  225. native_symbols, n_native_symbols))
  226. return false;
  227. if (!wasm_native_register_natives("wasi_snapshot_preview1",
  228. native_symbols, n_native_symbols))
  229. return false;
  230. #endif
  231. #if WASM_ENABLE_BASE_LIB != 0
  232. n_native_symbols = get_base_lib_export_apis(&native_symbols);
  233. if (n_native_symbols > 0
  234. && !wasm_native_register_natives("env",
  235. native_symbols, n_native_symbols))
  236. return false;
  237. #endif
  238. #if WASM_ENABLE_APP_FRAMEWORK != 0
  239. n_native_symbols = get_ext_lib_export_apis(&native_symbols);
  240. if (n_native_symbols > 0
  241. && !wasm_native_register_natives("env",
  242. native_symbols, n_native_symbols))
  243. return false;
  244. #endif
  245. #if WASM_ENABLE_LIB_PTHREAD != 0
  246. if (!lib_pthread_init())
  247. return false;
  248. n_native_symbols = get_lib_pthread_export_apis(&native_symbols);
  249. if (n_native_symbols > 0
  250. && !wasm_native_register_natives("env",
  251. native_symbols, n_native_symbols))
  252. return false;
  253. #endif
  254. return true;
  255. }
  256. void
  257. wasm_native_destroy()
  258. {
  259. NativeSymbolsNode *node, *node_next;
  260. #if WASM_ENABLE_LIB_PTHREAD != 0
  261. lib_pthread_destroy();
  262. #endif
  263. node = g_native_symbols_list;
  264. while (node) {
  265. node_next = node->next;
  266. wasm_runtime_free(node);
  267. node = node_next;
  268. }
  269. g_native_symbols_list = g_native_symbols_list_end = NULL;
  270. }