wasm_memory.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "wasm_runtime_common.h"
  6. #include "../interpreter/wasm_runtime.h"
  7. #include "../aot/aot_runtime.h"
  8. #include "bh_platform.h"
  9. #include "mem_alloc.h"
  10. #include "wasm_memory.h"
  11. #if WASM_ENABLE_SHARED_MEMORY != 0
  12. #include "../common/wasm_shared_memory.h"
  13. #endif
  14. typedef enum Memory_Mode {
  15. MEMORY_MODE_UNKNOWN = 0,
  16. MEMORY_MODE_POOL,
  17. MEMORY_MODE_ALLOCATOR,
  18. MEMORY_MODE_SYSTEM_ALLOCATOR
  19. } Memory_Mode;
  20. static Memory_Mode memory_mode = MEMORY_MODE_UNKNOWN;
  21. static mem_allocator_t pool_allocator = NULL;
  22. static enlarge_memory_error_callback_t enlarge_memory_error_cb;
  23. static void *enlarge_memory_error_user_data;
  24. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  25. static void *allocator_user_data = NULL;
  26. static void *(*malloc_func)(void *user_data, unsigned int size) = NULL;
  27. static void *(*realloc_func)(void *user_data, void *ptr,
  28. unsigned int size) = NULL;
  29. static void (*free_func)(void *user_data, void *ptr) = NULL;
  30. #else
  31. static void *(*malloc_func)(unsigned int size) = NULL;
  32. static void *(*realloc_func)(void *ptr, unsigned int size) = NULL;
  33. static void (*free_func)(void *ptr) = NULL;
  34. #endif
  35. static unsigned int global_pool_size;
  36. static uint32
  37. align_as_and_cast(uint64 size, uint64 alignment)
  38. {
  39. uint64 aligned_size = (size + alignment - 1) & ~(alignment - 1);
  40. return aligned_size > UINT32_MAX ? UINT32_MAX : (uint32)aligned_size;
  41. }
  42. static bool
  43. wasm_memory_init_with_pool(void *mem, unsigned int bytes)
  44. {
  45. mem_allocator_t _allocator = mem_allocator_create(mem, bytes);
  46. if (_allocator) {
  47. memory_mode = MEMORY_MODE_POOL;
  48. pool_allocator = _allocator;
  49. global_pool_size = bytes;
  50. return true;
  51. }
  52. LOG_ERROR("Init memory with pool (%p, %u) failed.\n", mem, bytes);
  53. return false;
  54. }
  55. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  56. static bool
  57. wasm_memory_init_with_allocator(void *_user_data, void *_malloc_func,
  58. void *_realloc_func, void *_free_func)
  59. {
  60. if (_malloc_func && _free_func && _malloc_func != _free_func) {
  61. memory_mode = MEMORY_MODE_ALLOCATOR;
  62. allocator_user_data = _user_data;
  63. malloc_func = _malloc_func;
  64. realloc_func = _realloc_func;
  65. free_func = _free_func;
  66. return true;
  67. }
  68. LOG_ERROR("Init memory with allocator (%p, %p, %p, %p) failed.\n",
  69. _user_data, _malloc_func, _realloc_func, _free_func);
  70. return false;
  71. }
  72. #else
  73. static bool
  74. wasm_memory_init_with_allocator(void *_malloc_func, void *_realloc_func,
  75. void *_free_func)
  76. {
  77. if (_malloc_func && _free_func && _malloc_func != _free_func) {
  78. memory_mode = MEMORY_MODE_ALLOCATOR;
  79. malloc_func = _malloc_func;
  80. realloc_func = _realloc_func;
  81. free_func = _free_func;
  82. return true;
  83. }
  84. LOG_ERROR("Init memory with allocator (%p, %p, %p) failed.\n", _malloc_func,
  85. _realloc_func, _free_func);
  86. return false;
  87. }
  88. #endif
  89. static inline bool
  90. is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst)
  91. {
  92. #if WASM_CONFIGURABLE_BOUNDS_CHECKS != 0
  93. return wasm_runtime_is_bounds_checks_enabled(module_inst);
  94. #else
  95. return true;
  96. #endif
  97. }
  98. bool
  99. wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type,
  100. const MemAllocOption *alloc_option)
  101. {
  102. if (mem_alloc_type == Alloc_With_Pool) {
  103. return wasm_memory_init_with_pool(alloc_option->pool.heap_buf,
  104. alloc_option->pool.heap_size);
  105. }
  106. else if (mem_alloc_type == Alloc_With_Allocator) {
  107. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  108. return wasm_memory_init_with_allocator(
  109. alloc_option->allocator.user_data,
  110. alloc_option->allocator.malloc_func,
  111. alloc_option->allocator.realloc_func,
  112. alloc_option->allocator.free_func);
  113. #else
  114. return wasm_memory_init_with_allocator(
  115. alloc_option->allocator.malloc_func,
  116. alloc_option->allocator.realloc_func,
  117. alloc_option->allocator.free_func);
  118. #endif
  119. }
  120. else if (mem_alloc_type == Alloc_With_System_Allocator) {
  121. memory_mode = MEMORY_MODE_SYSTEM_ALLOCATOR;
  122. return true;
  123. }
  124. else {
  125. return false;
  126. }
  127. }
  128. void
  129. wasm_runtime_memory_destroy()
  130. {
  131. if (memory_mode == MEMORY_MODE_POOL) {
  132. #if BH_ENABLE_GC_VERIFY == 0
  133. (void)mem_allocator_destroy(pool_allocator);
  134. #else
  135. int ret = mem_allocator_destroy(pool_allocator);
  136. if (ret != 0) {
  137. /* Memory leak detected */
  138. exit(-1);
  139. }
  140. #endif
  141. }
  142. memory_mode = MEMORY_MODE_UNKNOWN;
  143. }
  144. unsigned
  145. wasm_runtime_memory_pool_size()
  146. {
  147. if (memory_mode == MEMORY_MODE_POOL)
  148. return global_pool_size;
  149. else
  150. return UINT32_MAX;
  151. }
  152. static inline void *
  153. wasm_runtime_malloc_internal(unsigned int size)
  154. {
  155. if (memory_mode == MEMORY_MODE_UNKNOWN) {
  156. LOG_WARNING(
  157. "wasm_runtime_malloc failed: memory hasn't been initialize.\n");
  158. return NULL;
  159. }
  160. else if (memory_mode == MEMORY_MODE_POOL) {
  161. return mem_allocator_malloc(pool_allocator, size);
  162. }
  163. else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
  164. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  165. return malloc_func(allocator_user_data, size);
  166. #else
  167. return malloc_func(size);
  168. #endif
  169. }
  170. else {
  171. return os_malloc(size);
  172. }
  173. }
  174. static inline void *
  175. wasm_runtime_realloc_internal(void *ptr, unsigned int size)
  176. {
  177. if (memory_mode == MEMORY_MODE_UNKNOWN) {
  178. LOG_WARNING(
  179. "wasm_runtime_realloc failed: memory hasn't been initialize.\n");
  180. return NULL;
  181. }
  182. else if (memory_mode == MEMORY_MODE_POOL) {
  183. return mem_allocator_realloc(pool_allocator, ptr, size);
  184. }
  185. else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
  186. if (realloc_func)
  187. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  188. return realloc_func(allocator_user_data, ptr, size);
  189. #else
  190. return realloc_func(ptr, size);
  191. #endif
  192. else
  193. return NULL;
  194. }
  195. else {
  196. return os_realloc(ptr, size);
  197. }
  198. }
  199. static inline void
  200. wasm_runtime_free_internal(void *ptr)
  201. {
  202. if (!ptr) {
  203. LOG_WARNING("warning: wasm_runtime_free with NULL pointer\n");
  204. #if BH_ENABLE_GC_VERIFY != 0
  205. exit(-1);
  206. #endif
  207. return;
  208. }
  209. if (memory_mode == MEMORY_MODE_UNKNOWN) {
  210. LOG_WARNING("warning: wasm_runtime_free failed: "
  211. "memory hasn't been initialize.\n");
  212. }
  213. else if (memory_mode == MEMORY_MODE_POOL) {
  214. mem_allocator_free(pool_allocator, ptr);
  215. }
  216. else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
  217. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  218. free_func(allocator_user_data, ptr);
  219. #else
  220. free_func(ptr);
  221. #endif
  222. }
  223. else {
  224. os_free(ptr);
  225. }
  226. }
  227. void *
  228. wasm_runtime_malloc(unsigned int size)
  229. {
  230. if (size == 0) {
  231. LOG_WARNING("warning: wasm_runtime_malloc with size zero\n");
  232. /* At lease alloc 1 byte to avoid malloc failed */
  233. size = 1;
  234. #if BH_ENABLE_GC_VERIFY != 0
  235. exit(-1);
  236. #endif
  237. }
  238. return wasm_runtime_malloc_internal(size);
  239. }
  240. void *
  241. wasm_runtime_realloc(void *ptr, unsigned int size)
  242. {
  243. return wasm_runtime_realloc_internal(ptr, size);
  244. }
  245. void
  246. wasm_runtime_free(void *ptr)
  247. {
  248. wasm_runtime_free_internal(ptr);
  249. }
  250. bool
  251. wasm_runtime_get_mem_alloc_info(mem_alloc_info_t *mem_alloc_info)
  252. {
  253. if (memory_mode == MEMORY_MODE_POOL) {
  254. return mem_allocator_get_alloc_info(pool_allocator, mem_alloc_info);
  255. }
  256. return false;
  257. }
  258. bool
  259. wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm,
  260. uint32 app_offset, uint32 size)
  261. {
  262. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  263. WASMMemoryInstance *memory_inst;
  264. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  265. || module_inst_comm->module_type == Wasm_Module_AoT);
  266. if (!is_bounds_checks_enabled(module_inst_comm)) {
  267. return true;
  268. }
  269. memory_inst = wasm_get_default_memory(module_inst);
  270. if (!memory_inst) {
  271. goto fail;
  272. }
  273. /* integer overflow check */
  274. if (app_offset > UINT32_MAX - size) {
  275. goto fail;
  276. }
  277. SHARED_MEMORY_LOCK(memory_inst);
  278. if (app_offset + size <= memory_inst->memory_data_size) {
  279. SHARED_MEMORY_UNLOCK(memory_inst);
  280. return true;
  281. }
  282. SHARED_MEMORY_UNLOCK(memory_inst);
  283. fail:
  284. wasm_set_exception(module_inst, "out of bounds memory access");
  285. return false;
  286. }
  287. bool
  288. wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm,
  289. uint32 app_str_offset)
  290. {
  291. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  292. uint32 app_end_offset;
  293. char *str, *str_end;
  294. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  295. || module_inst_comm->module_type == Wasm_Module_AoT);
  296. if (!is_bounds_checks_enabled(module_inst_comm)) {
  297. return true;
  298. }
  299. if (!wasm_runtime_get_app_addr_range(module_inst_comm, app_str_offset, NULL,
  300. &app_end_offset))
  301. goto fail;
  302. str = wasm_runtime_addr_app_to_native(module_inst_comm, app_str_offset);
  303. str_end = str + (app_end_offset - app_str_offset);
  304. while (str < str_end && *str != '\0')
  305. str++;
  306. if (str == str_end)
  307. goto fail;
  308. return true;
  309. fail:
  310. wasm_set_exception(module_inst, "out of bounds memory access");
  311. return false;
  312. }
  313. bool
  314. wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm,
  315. void *native_ptr, uint32 size)
  316. {
  317. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  318. WASMMemoryInstance *memory_inst;
  319. uint8 *addr = (uint8 *)native_ptr;
  320. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  321. || module_inst_comm->module_type == Wasm_Module_AoT);
  322. if (!is_bounds_checks_enabled(module_inst_comm)) {
  323. return true;
  324. }
  325. memory_inst = wasm_get_default_memory(module_inst);
  326. if (!memory_inst) {
  327. goto fail;
  328. }
  329. /* integer overflow check */
  330. if ((uintptr_t)addr > UINTPTR_MAX - size) {
  331. goto fail;
  332. }
  333. SHARED_MEMORY_LOCK(memory_inst);
  334. if (memory_inst->memory_data <= addr
  335. && addr + size <= memory_inst->memory_data_end) {
  336. SHARED_MEMORY_UNLOCK(memory_inst);
  337. return true;
  338. }
  339. SHARED_MEMORY_UNLOCK(memory_inst);
  340. fail:
  341. wasm_set_exception(module_inst, "out of bounds memory access");
  342. return false;
  343. }
  344. void *
  345. wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm,
  346. uint32 app_offset)
  347. {
  348. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  349. WASMMemoryInstance *memory_inst;
  350. uint8 *addr;
  351. bool bounds_checks;
  352. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  353. || module_inst_comm->module_type == Wasm_Module_AoT);
  354. bounds_checks = is_bounds_checks_enabled(module_inst_comm);
  355. memory_inst = wasm_get_default_memory(module_inst);
  356. if (!memory_inst) {
  357. return NULL;
  358. }
  359. SHARED_MEMORY_LOCK(memory_inst);
  360. addr = memory_inst->memory_data + app_offset;
  361. if (bounds_checks) {
  362. if (memory_inst->memory_data <= addr
  363. && addr < memory_inst->memory_data_end) {
  364. SHARED_MEMORY_UNLOCK(memory_inst);
  365. return addr;
  366. }
  367. }
  368. /* If bounds checks is disabled, return the address directly */
  369. else if (app_offset != 0) {
  370. SHARED_MEMORY_UNLOCK(memory_inst);
  371. return addr;
  372. }
  373. SHARED_MEMORY_UNLOCK(memory_inst);
  374. return NULL;
  375. }
  376. uint32
  377. wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm,
  378. void *native_ptr)
  379. {
  380. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  381. WASMMemoryInstance *memory_inst;
  382. uint8 *addr = (uint8 *)native_ptr;
  383. bool bounds_checks;
  384. uint32 ret;
  385. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  386. || module_inst_comm->module_type == Wasm_Module_AoT);
  387. bounds_checks = is_bounds_checks_enabled(module_inst_comm);
  388. memory_inst = wasm_get_default_memory(module_inst);
  389. if (!memory_inst) {
  390. return 0;
  391. }
  392. SHARED_MEMORY_LOCK(memory_inst);
  393. if (bounds_checks) {
  394. if (memory_inst->memory_data <= addr
  395. && addr < memory_inst->memory_data_end) {
  396. ret = (uint32)(addr - memory_inst->memory_data);
  397. SHARED_MEMORY_UNLOCK(memory_inst);
  398. return ret;
  399. }
  400. }
  401. /* If bounds checks is disabled, return the offset directly */
  402. else if (addr != NULL) {
  403. ret = (uint32)(addr - memory_inst->memory_data);
  404. SHARED_MEMORY_UNLOCK(memory_inst);
  405. return ret;
  406. }
  407. SHARED_MEMORY_UNLOCK(memory_inst);
  408. return 0;
  409. }
  410. bool
  411. wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst_comm,
  412. uint32 app_offset, uint32 *p_app_start_offset,
  413. uint32 *p_app_end_offset)
  414. {
  415. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  416. WASMMemoryInstance *memory_inst;
  417. uint32 memory_data_size;
  418. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  419. || module_inst_comm->module_type == Wasm_Module_AoT);
  420. memory_inst = wasm_get_default_memory(module_inst);
  421. if (!memory_inst) {
  422. return false;
  423. }
  424. SHARED_MEMORY_LOCK(memory_inst);
  425. memory_data_size = memory_inst->memory_data_size;
  426. if (app_offset < memory_data_size) {
  427. if (p_app_start_offset)
  428. *p_app_start_offset = 0;
  429. if (p_app_end_offset)
  430. *p_app_end_offset = memory_data_size;
  431. SHARED_MEMORY_UNLOCK(memory_inst);
  432. return true;
  433. }
  434. SHARED_MEMORY_UNLOCK(memory_inst);
  435. return false;
  436. }
  437. bool
  438. wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst_comm,
  439. uint8 *native_ptr,
  440. uint8 **p_native_start_addr,
  441. uint8 **p_native_end_addr)
  442. {
  443. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  444. WASMMemoryInstance *memory_inst;
  445. uint8 *addr = (uint8 *)native_ptr;
  446. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  447. || module_inst_comm->module_type == Wasm_Module_AoT);
  448. memory_inst = wasm_get_default_memory(module_inst);
  449. if (!memory_inst) {
  450. return false;
  451. }
  452. SHARED_MEMORY_LOCK(memory_inst);
  453. if (memory_inst->memory_data <= addr
  454. && addr < memory_inst->memory_data_end) {
  455. if (p_native_start_addr)
  456. *p_native_start_addr = memory_inst->memory_data;
  457. if (p_native_end_addr)
  458. *p_native_end_addr = memory_inst->memory_data_end;
  459. SHARED_MEMORY_UNLOCK(memory_inst);
  460. return true;
  461. }
  462. SHARED_MEMORY_UNLOCK(memory_inst);
  463. return false;
  464. }
  465. bool
  466. wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
  467. uint32 app_buf_addr, uint32 app_buf_size,
  468. void **p_native_addr)
  469. {
  470. WASMMemoryInstance *memory_inst = wasm_get_default_memory(module_inst);
  471. uint8 *native_addr;
  472. bool bounds_checks;
  473. if (!memory_inst) {
  474. wasm_set_exception(module_inst, "out of bounds memory access");
  475. return false;
  476. }
  477. native_addr = memory_inst->memory_data + app_buf_addr;
  478. bounds_checks = is_bounds_checks_enabled((wasm_module_inst_t)module_inst);
  479. if (!bounds_checks) {
  480. if (app_buf_addr == 0) {
  481. native_addr = NULL;
  482. }
  483. goto success;
  484. }
  485. /* No need to check the app_offset and buf_size if memory access
  486. boundary check with hardware trap is enabled */
  487. #ifndef OS_ENABLE_HW_BOUND_CHECK
  488. SHARED_MEMORY_LOCK(memory_inst);
  489. if (app_buf_addr >= memory_inst->memory_data_size) {
  490. goto fail;
  491. }
  492. if (!is_str) {
  493. if (app_buf_size > memory_inst->memory_data_size - app_buf_addr) {
  494. goto fail;
  495. }
  496. }
  497. else {
  498. const char *str, *str_end;
  499. /* The whole string must be in the linear memory */
  500. str = (const char *)native_addr;
  501. str_end = (const char *)memory_inst->memory_data_end;
  502. while (str < str_end && *str != '\0')
  503. str++;
  504. if (str == str_end)
  505. goto fail;
  506. }
  507. SHARED_MEMORY_UNLOCK(memory_inst);
  508. #endif
  509. success:
  510. *p_native_addr = (void *)native_addr;
  511. return true;
  512. #ifndef OS_ENABLE_HW_BOUND_CHECK
  513. fail:
  514. SHARED_MEMORY_UNLOCK(memory_inst);
  515. wasm_set_exception(module_inst, "out of bounds memory access");
  516. return false;
  517. #endif
  518. }
  519. WASMMemoryInstance *
  520. wasm_get_default_memory(WASMModuleInstance *module_inst)
  521. {
  522. if (module_inst->memories)
  523. return module_inst->memories[0];
  524. else
  525. return NULL;
  526. }
  527. void
  528. wasm_runtime_set_mem_bound_check_bytes(WASMMemoryInstance *memory,
  529. uint64 memory_data_size)
  530. {
  531. #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0
  532. #if UINTPTR_MAX == UINT64_MAX
  533. memory->mem_bound_check_1byte.u64 = memory_data_size - 1;
  534. memory->mem_bound_check_2bytes.u64 = memory_data_size - 2;
  535. memory->mem_bound_check_4bytes.u64 = memory_data_size - 4;
  536. memory->mem_bound_check_8bytes.u64 = memory_data_size - 8;
  537. memory->mem_bound_check_16bytes.u64 = memory_data_size - 16;
  538. #else
  539. memory->mem_bound_check_1byte.u32[0] = (uint32)memory_data_size - 1;
  540. memory->mem_bound_check_2bytes.u32[0] = (uint32)memory_data_size - 2;
  541. memory->mem_bound_check_4bytes.u32[0] = (uint32)memory_data_size - 4;
  542. memory->mem_bound_check_8bytes.u32[0] = (uint32)memory_data_size - 8;
  543. memory->mem_bound_check_16bytes.u32[0] = (uint32)memory_data_size - 16;
  544. #endif
  545. #endif
  546. }
  547. static void
  548. wasm_munmap_linear_memory(void *mapped_mem, uint64 commit_size, uint64 map_size)
  549. {
  550. #ifdef BH_PLATFORM_WINDOWS
  551. os_mem_decommit(mapped_mem, commit_size);
  552. #else
  553. (void)commit_size;
  554. #endif
  555. os_munmap(mapped_mem, map_size);
  556. }
  557. static void *
  558. wasm_mremap_linear_memory(void *mapped_mem, uint64 old_size, uint64 new_size,
  559. uint64 commit_size)
  560. {
  561. void *new_mem;
  562. bh_assert(new_size > 0);
  563. bh_assert(new_size > old_size);
  564. if (mapped_mem) {
  565. new_mem = os_mremap(mapped_mem, old_size, new_size);
  566. }
  567. else {
  568. new_mem = os_mmap(NULL, new_size, MMAP_PROT_NONE, MMAP_MAP_NONE,
  569. os_get_invalid_handle());
  570. }
  571. if (!new_mem) {
  572. return NULL;
  573. }
  574. #ifdef BH_PLATFORM_WINDOWS
  575. if (commit_size > 0
  576. && !os_mem_commit(new_mem, commit_size,
  577. MMAP_PROT_READ | MMAP_PROT_WRITE)) {
  578. os_munmap(new_mem, new_size);
  579. return NULL;
  580. }
  581. #endif
  582. if (os_mprotect(new_mem, commit_size, MMAP_PROT_READ | MMAP_PROT_WRITE)
  583. != 0) {
  584. wasm_munmap_linear_memory(new_mem, new_size, new_size);
  585. return NULL;
  586. }
  587. return new_mem;
  588. }
  589. static void *
  590. wasm_mmap_linear_memory(uint64_t map_size, uint64 commit_size)
  591. {
  592. return wasm_mremap_linear_memory(NULL, 0, map_size, commit_size);
  593. }
  594. bool
  595. wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
  596. {
  597. WASMMemoryInstance *memory = wasm_get_default_memory(module);
  598. uint8 *memory_data_old, *memory_data_new, *heap_data_old;
  599. uint32 num_bytes_per_page, heap_size, total_size_old = 0;
  600. uint32 cur_page_count, max_page_count, total_page_count;
  601. uint64 total_size_new;
  602. bool ret = true, full_size_mmaped;
  603. enlarge_memory_error_reason_t failure_reason = INTERNAL_ERROR;
  604. if (!memory) {
  605. ret = false;
  606. goto return_func;
  607. }
  608. #ifdef OS_ENABLE_HW_BOUND_CHECK
  609. full_size_mmaped = true;
  610. #elif WASM_ENABLE_SHARED_MEMORY != 0
  611. full_size_mmaped = shared_memory_is_shared(memory);
  612. #else
  613. full_size_mmaped = false;
  614. #endif
  615. memory_data_old = memory->memory_data;
  616. total_size_old = memory->memory_data_size;
  617. heap_data_old = memory->heap_data;
  618. heap_size = (uint32)(memory->heap_data_end - memory->heap_data);
  619. num_bytes_per_page = memory->num_bytes_per_page;
  620. cur_page_count = memory->cur_page_count;
  621. max_page_count = memory->max_page_count;
  622. total_page_count = inc_page_count + cur_page_count;
  623. total_size_new = num_bytes_per_page * (uint64)total_page_count;
  624. if (inc_page_count <= 0)
  625. /* No need to enlarge memory */
  626. return true;
  627. if (total_page_count < cur_page_count) { /* integer overflow */
  628. ret = false;
  629. goto return_func;
  630. }
  631. if (total_page_count > max_page_count) {
  632. failure_reason = MAX_SIZE_REACHED;
  633. ret = false;
  634. goto return_func;
  635. }
  636. bh_assert(total_size_new <= 4 * (uint64)BH_GB);
  637. if (total_size_new > UINT32_MAX) {
  638. /* Resize to 1 page with size 4G-1 */
  639. num_bytes_per_page = UINT32_MAX;
  640. total_page_count = max_page_count = 1;
  641. total_size_new = UINT32_MAX;
  642. }
  643. if (full_size_mmaped) {
  644. #ifdef BH_PLATFORM_WINDOWS
  645. if (!os_mem_commit(memory->memory_data_end,
  646. (uint32)total_size_new - total_size_old,
  647. MMAP_PROT_READ | MMAP_PROT_WRITE)) {
  648. ret = false;
  649. goto return_func;
  650. }
  651. #endif
  652. if (os_mprotect(memory->memory_data_end,
  653. (uint32)total_size_new - total_size_old,
  654. MMAP_PROT_READ | MMAP_PROT_WRITE)
  655. != 0) {
  656. #ifdef BH_PLATFORM_WINDOWS
  657. os_mem_decommit(memory->memory_data_end,
  658. (uint32)total_size_new - total_size_old);
  659. #endif
  660. ret = false;
  661. goto return_func;
  662. }
  663. }
  664. else {
  665. if (heap_size > 0) {
  666. if (mem_allocator_is_heap_corrupted(memory->heap_handle)) {
  667. wasm_runtime_show_app_heap_corrupted_prompt();
  668. ret = false;
  669. goto return_func;
  670. }
  671. }
  672. if (!(memory_data_new = wasm_mremap_linear_memory(
  673. memory_data_old, total_size_old, (uint32)total_size_new,
  674. (uint32)total_size_new))) {
  675. ret = false;
  676. goto return_func;
  677. }
  678. if (heap_size > 0) {
  679. if (mem_allocator_migrate(memory->heap_handle,
  680. (char *)heap_data_old
  681. + (memory_data_new - memory_data_old),
  682. heap_size)
  683. != 0) {
  684. /* Don't return here as memory->memory_data is obsolete and
  685. must be updated to be correctly used later. */
  686. ret = false;
  687. }
  688. }
  689. memory->heap_data = memory_data_new + (heap_data_old - memory_data_old);
  690. memory->heap_data_end = memory->heap_data + heap_size;
  691. memory->memory_data = memory_data_new;
  692. #if defined(os_writegsbase)
  693. /* write base addr of linear memory to GS segment register */
  694. os_writegsbase(memory_data_new);
  695. #endif
  696. }
  697. memory->num_bytes_per_page = num_bytes_per_page;
  698. memory->cur_page_count = total_page_count;
  699. memory->max_page_count = max_page_count;
  700. SET_LINEAR_MEMORY_SIZE(memory, (uint32)total_size_new);
  701. memory->memory_data_end = memory->memory_data + (uint32)total_size_new;
  702. wasm_runtime_set_mem_bound_check_bytes(memory, total_size_new);
  703. return_func:
  704. if (!ret && enlarge_memory_error_cb) {
  705. WASMExecEnv *exec_env = NULL;
  706. #if WASM_ENABLE_INTERP != 0
  707. if (module->module_type == Wasm_Module_Bytecode)
  708. exec_env =
  709. ((WASMModuleInstanceExtra *)module->e)->common.cur_exec_env;
  710. #endif
  711. #if WASM_ENABLE_AOT != 0
  712. if (module->module_type == Wasm_Module_AoT)
  713. exec_env =
  714. ((AOTModuleInstanceExtra *)module->e)->common.cur_exec_env;
  715. #endif
  716. enlarge_memory_error_cb(inc_page_count, total_size_old, 0,
  717. failure_reason,
  718. (WASMModuleInstanceCommon *)module, exec_env,
  719. enlarge_memory_error_user_data);
  720. }
  721. return ret;
  722. }
  723. void
  724. wasm_runtime_set_enlarge_mem_error_callback(
  725. const enlarge_memory_error_callback_t callback, void *user_data)
  726. {
  727. enlarge_memory_error_cb = callback;
  728. enlarge_memory_error_user_data = user_data;
  729. }
  730. bool
  731. wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
  732. {
  733. bool ret = false;
  734. #if WASM_ENABLE_SHARED_MEMORY != 0
  735. if (module->memory_count > 0)
  736. shared_memory_lock(module->memories[0]);
  737. #endif
  738. ret = wasm_enlarge_memory_internal(module, inc_page_count);
  739. #if WASM_ENABLE_SHARED_MEMORY != 0
  740. if (module->memory_count > 0)
  741. shared_memory_unlock(module->memories[0]);
  742. #endif
  743. return ret;
  744. }
  745. void
  746. wasm_deallocate_linear_memory(WASMMemoryInstance *memory_inst)
  747. {
  748. uint64 map_size;
  749. bh_assert(memory_inst);
  750. bh_assert(memory_inst->memory_data);
  751. #ifndef OS_ENABLE_HW_BOUND_CHECK
  752. #if WASM_ENABLE_SHARED_MEMORY != 0
  753. if (shared_memory_is_shared(memory_inst)) {
  754. map_size = (uint64)memory_inst->num_bytes_per_page
  755. * memory_inst->max_page_count;
  756. }
  757. else
  758. #endif
  759. {
  760. map_size = (uint64)memory_inst->num_bytes_per_page
  761. * memory_inst->cur_page_count;
  762. }
  763. #else
  764. map_size = 8 * (uint64)BH_GB;
  765. #endif
  766. wasm_munmap_linear_memory(memory_inst->memory_data,
  767. memory_inst->memory_data_size, map_size);
  768. memory_inst->memory_data = NULL;
  769. }
  770. int
  771. wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory,
  772. uint64 num_bytes_per_page, uint64 init_page_count,
  773. uint64 max_page_count, uint64 *memory_data_size)
  774. {
  775. uint64 map_size, page_size;
  776. bh_assert(data);
  777. bh_assert(memory_data_size);
  778. #ifndef OS_ENABLE_HW_BOUND_CHECK
  779. #if WASM_ENABLE_SHARED_MEMORY != 0
  780. if (is_shared_memory) {
  781. /* Allocate maximum memory size when memory is shared */
  782. map_size = max_page_count * num_bytes_per_page;
  783. }
  784. else
  785. #endif
  786. {
  787. map_size = init_page_count * num_bytes_per_page;
  788. }
  789. #else /* else of OS_ENABLE_HW_BOUND_CHECK */
  790. /* Totally 8G is mapped, the opcode load/store address range is 0 to 8G:
  791. * ea = i + memarg.offset
  792. * both i and memarg.offset are u32 in range 0 to 4G
  793. * so the range of ea is 0 to 8G
  794. */
  795. map_size = 8 * (uint64)BH_GB;
  796. #endif /* end of OS_ENABLE_HW_BOUND_CHECK */
  797. page_size = os_getpagesize();
  798. *memory_data_size = init_page_count * num_bytes_per_page;
  799. bh_assert(*memory_data_size <= UINT32_MAX);
  800. align_as_and_cast(*memory_data_size, page_size);
  801. if (map_size > 0) {
  802. if (!(*data = wasm_mmap_linear_memory(map_size, *memory_data_size))) {
  803. return BHT_ERROR;
  804. }
  805. }
  806. return BHT_OK;
  807. }