asmjit 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/asmjit.gemspec +1 -1
  4. data/ext/asmjit/asmjit/.editorconfig +10 -0
  5. data/ext/asmjit/asmjit/.github/FUNDING.yml +1 -0
  6. data/ext/asmjit/asmjit/.github/workflows/build-config.json +47 -0
  7. data/ext/asmjit/asmjit/.github/workflows/build.yml +156 -0
  8. data/ext/asmjit/asmjit/.gitignore +6 -0
  9. data/ext/asmjit/asmjit/CMakeLists.txt +611 -0
  10. data/ext/asmjit/asmjit/LICENSE.md +17 -0
  11. data/ext/asmjit/asmjit/README.md +69 -0
  12. data/ext/asmjit/asmjit/src/asmjit/a64.h +62 -0
  13. data/ext/asmjit/asmjit/src/asmjit/arm/a64archtraits_p.h +81 -0
  14. data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.cpp +5115 -0
  15. data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.h +72 -0
  16. data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.cpp +51 -0
  17. data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.h +57 -0
  18. data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.cpp +60 -0
  19. data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.h +247 -0
  20. data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper.cpp +464 -0
  21. data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper_p.h +50 -0
  22. data/ext/asmjit/asmjit/src/asmjit/arm/a64emitter.h +1228 -0
  23. data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter.cpp +298 -0
  24. data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter_p.h +59 -0
  25. data/ext/asmjit/asmjit/src/asmjit/arm/a64func.cpp +189 -0
  26. data/ext/asmjit/asmjit/src/asmjit/arm/a64func_p.h +33 -0
  27. data/ext/asmjit/asmjit/src/asmjit/arm/a64globals.h +1894 -0
  28. data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi.cpp +278 -0
  29. data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi_p.h +41 -0
  30. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.cpp +1957 -0
  31. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.h +74 -0
  32. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb_p.h +876 -0
  33. data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.cpp +85 -0
  34. data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.h +312 -0
  35. data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass.cpp +852 -0
  36. data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass_p.h +105 -0
  37. data/ext/asmjit/asmjit/src/asmjit/arm/a64utils.h +179 -0
  38. data/ext/asmjit/asmjit/src/asmjit/arm/armformatter.cpp +143 -0
  39. data/ext/asmjit/asmjit/src/asmjit/arm/armformatter_p.h +44 -0
  40. data/ext/asmjit/asmjit/src/asmjit/arm/armglobals.h +21 -0
  41. data/ext/asmjit/asmjit/src/asmjit/arm/armoperand.h +621 -0
  42. data/ext/asmjit/asmjit/src/asmjit/arm.h +62 -0
  43. data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-begin.h +17 -0
  44. data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-end.h +9 -0
  45. data/ext/asmjit/asmjit/src/asmjit/asmjit.h +33 -0
  46. data/ext/asmjit/asmjit/src/asmjit/core/api-build_p.h +55 -0
  47. data/ext/asmjit/asmjit/src/asmjit/core/api-config.h +613 -0
  48. data/ext/asmjit/asmjit/src/asmjit/core/archcommons.h +229 -0
  49. data/ext/asmjit/asmjit/src/asmjit/core/archtraits.cpp +160 -0
  50. data/ext/asmjit/asmjit/src/asmjit/core/archtraits.h +290 -0
  51. data/ext/asmjit/asmjit/src/asmjit/core/assembler.cpp +406 -0
  52. data/ext/asmjit/asmjit/src/asmjit/core/assembler.h +129 -0
  53. data/ext/asmjit/asmjit/src/asmjit/core/builder.cpp +889 -0
  54. data/ext/asmjit/asmjit/src/asmjit/core/builder.h +1391 -0
  55. data/ext/asmjit/asmjit/src/asmjit/core/codebuffer.h +113 -0
  56. data/ext/asmjit/asmjit/src/asmjit/core/codeholder.cpp +1149 -0
  57. data/ext/asmjit/asmjit/src/asmjit/core/codeholder.h +1035 -0
  58. data/ext/asmjit/asmjit/src/asmjit/core/codewriter.cpp +175 -0
  59. data/ext/asmjit/asmjit/src/asmjit/core/codewriter_p.h +179 -0
  60. data/ext/asmjit/asmjit/src/asmjit/core/compiler.cpp +582 -0
  61. data/ext/asmjit/asmjit/src/asmjit/core/compiler.h +737 -0
  62. data/ext/asmjit/asmjit/src/asmjit/core/compilerdefs.h +173 -0
  63. data/ext/asmjit/asmjit/src/asmjit/core/constpool.cpp +363 -0
  64. data/ext/asmjit/asmjit/src/asmjit/core/constpool.h +250 -0
  65. data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.cpp +1162 -0
  66. data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.h +813 -0
  67. data/ext/asmjit/asmjit/src/asmjit/core/emithelper.cpp +323 -0
  68. data/ext/asmjit/asmjit/src/asmjit/core/emithelper_p.h +58 -0
  69. data/ext/asmjit/asmjit/src/asmjit/core/emitter.cpp +333 -0
  70. data/ext/asmjit/asmjit/src/asmjit/core/emitter.h +741 -0
  71. data/ext/asmjit/asmjit/src/asmjit/core/emitterutils.cpp +129 -0
  72. data/ext/asmjit/asmjit/src/asmjit/core/emitterutils_p.h +89 -0
  73. data/ext/asmjit/asmjit/src/asmjit/core/environment.cpp +46 -0
  74. data/ext/asmjit/asmjit/src/asmjit/core/environment.h +508 -0
  75. data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.cpp +14 -0
  76. data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.h +228 -0
  77. data/ext/asmjit/asmjit/src/asmjit/core/formatter.cpp +584 -0
  78. data/ext/asmjit/asmjit/src/asmjit/core/formatter.h +247 -0
  79. data/ext/asmjit/asmjit/src/asmjit/core/formatter_p.h +34 -0
  80. data/ext/asmjit/asmjit/src/asmjit/core/func.cpp +286 -0
  81. data/ext/asmjit/asmjit/src/asmjit/core/func.h +1445 -0
  82. data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext.cpp +293 -0
  83. data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext_p.h +199 -0
  84. data/ext/asmjit/asmjit/src/asmjit/core/globals.cpp +133 -0
  85. data/ext/asmjit/asmjit/src/asmjit/core/globals.h +393 -0
  86. data/ext/asmjit/asmjit/src/asmjit/core/inst.cpp +113 -0
  87. data/ext/asmjit/asmjit/src/asmjit/core/inst.h +772 -0
  88. data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.cpp +1242 -0
  89. data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.h +261 -0
  90. data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.cpp +80 -0
  91. data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.h +89 -0
  92. data/ext/asmjit/asmjit/src/asmjit/core/logger.cpp +69 -0
  93. data/ext/asmjit/asmjit/src/asmjit/core/logger.h +198 -0
  94. data/ext/asmjit/asmjit/src/asmjit/core/misc_p.h +33 -0
  95. data/ext/asmjit/asmjit/src/asmjit/core/operand.cpp +132 -0
  96. data/ext/asmjit/asmjit/src/asmjit/core/operand.h +1611 -0
  97. data/ext/asmjit/asmjit/src/asmjit/core/osutils.cpp +84 -0
  98. data/ext/asmjit/asmjit/src/asmjit/core/osutils.h +61 -0
  99. data/ext/asmjit/asmjit/src/asmjit/core/osutils_p.h +68 -0
  100. data/ext/asmjit/asmjit/src/asmjit/core/raassignment_p.h +418 -0
  101. data/ext/asmjit/asmjit/src/asmjit/core/rabuilders_p.h +612 -0
  102. data/ext/asmjit/asmjit/src/asmjit/core/radefs_p.h +1204 -0
  103. data/ext/asmjit/asmjit/src/asmjit/core/ralocal.cpp +1166 -0
  104. data/ext/asmjit/asmjit/src/asmjit/core/ralocal_p.h +254 -0
  105. data/ext/asmjit/asmjit/src/asmjit/core/rapass.cpp +1969 -0
  106. data/ext/asmjit/asmjit/src/asmjit/core/rapass_p.h +1183 -0
  107. data/ext/asmjit/asmjit/src/asmjit/core/rastack.cpp +184 -0
  108. data/ext/asmjit/asmjit/src/asmjit/core/rastack_p.h +171 -0
  109. data/ext/asmjit/asmjit/src/asmjit/core/string.cpp +559 -0
  110. data/ext/asmjit/asmjit/src/asmjit/core/string.h +372 -0
  111. data/ext/asmjit/asmjit/src/asmjit/core/support.cpp +494 -0
  112. data/ext/asmjit/asmjit/src/asmjit/core/support.h +1773 -0
  113. data/ext/asmjit/asmjit/src/asmjit/core/target.cpp +14 -0
  114. data/ext/asmjit/asmjit/src/asmjit/core/target.h +53 -0
  115. data/ext/asmjit/asmjit/src/asmjit/core/type.cpp +74 -0
  116. data/ext/asmjit/asmjit/src/asmjit/core/type.h +419 -0
  117. data/ext/asmjit/asmjit/src/asmjit/core/virtmem.cpp +722 -0
  118. data/ext/asmjit/asmjit/src/asmjit/core/virtmem.h +242 -0
  119. data/ext/asmjit/asmjit/src/asmjit/core/zone.cpp +353 -0
  120. data/ext/asmjit/asmjit/src/asmjit/core/zone.h +615 -0
  121. data/ext/asmjit/asmjit/src/asmjit/core/zonehash.cpp +309 -0
  122. data/ext/asmjit/asmjit/src/asmjit/core/zonehash.h +186 -0
  123. data/ext/asmjit/asmjit/src/asmjit/core/zonelist.cpp +163 -0
  124. data/ext/asmjit/asmjit/src/asmjit/core/zonelist.h +209 -0
  125. data/ext/asmjit/asmjit/src/asmjit/core/zonestack.cpp +176 -0
  126. data/ext/asmjit/asmjit/src/asmjit/core/zonestack.h +239 -0
  127. data/ext/asmjit/asmjit/src/asmjit/core/zonestring.h +120 -0
  128. data/ext/asmjit/asmjit/src/asmjit/core/zonetree.cpp +99 -0
  129. data/ext/asmjit/asmjit/src/asmjit/core/zonetree.h +380 -0
  130. data/ext/asmjit/asmjit/src/asmjit/core/zonevector.cpp +356 -0
  131. data/ext/asmjit/asmjit/src/asmjit/core/zonevector.h +690 -0
  132. data/ext/asmjit/asmjit/src/asmjit/core.h +1861 -0
  133. data/ext/asmjit/asmjit/src/asmjit/x86/x86archtraits_p.h +148 -0
  134. data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.cpp +5110 -0
  135. data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.h +685 -0
  136. data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.cpp +52 -0
  137. data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.h +351 -0
  138. data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.cpp +61 -0
  139. data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.h +721 -0
  140. data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper.cpp +619 -0
  141. data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper_p.h +60 -0
  142. data/ext/asmjit/asmjit/src/asmjit/x86/x86emitter.h +4315 -0
  143. data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter.cpp +944 -0
  144. data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter_p.h +58 -0
  145. data/ext/asmjit/asmjit/src/asmjit/x86/x86func.cpp +503 -0
  146. data/ext/asmjit/asmjit/src/asmjit/x86/x86func_p.h +33 -0
  147. data/ext/asmjit/asmjit/src/asmjit/x86/x86globals.h +2169 -0
  148. data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi.cpp +1732 -0
  149. data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi_p.h +41 -0
  150. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.cpp +4427 -0
  151. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.h +563 -0
  152. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb_p.h +311 -0
  153. data/ext/asmjit/asmjit/src/asmjit/x86/x86opcode_p.h +436 -0
  154. data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.cpp +231 -0
  155. data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.h +1085 -0
  156. data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass.cpp +1509 -0
  157. data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass_p.h +94 -0
  158. data/ext/asmjit/asmjit/src/asmjit/x86.h +93 -0
  159. data/ext/asmjit/asmjit/src/asmjit.natvis +245 -0
  160. data/ext/asmjit/asmjit/test/asmjit_test_assembler.cpp +84 -0
  161. data/ext/asmjit/asmjit/test/asmjit_test_assembler.h +85 -0
  162. data/ext/asmjit/asmjit/test/asmjit_test_assembler_a64.cpp +4006 -0
  163. data/ext/asmjit/asmjit/test/asmjit_test_assembler_x64.cpp +17833 -0
  164. data/ext/asmjit/asmjit/test/asmjit_test_assembler_x86.cpp +8300 -0
  165. data/ext/asmjit/asmjit/test/asmjit_test_compiler.cpp +253 -0
  166. data/ext/asmjit/asmjit/test/asmjit_test_compiler.h +73 -0
  167. data/ext/asmjit/asmjit/test/asmjit_test_compiler_a64.cpp +690 -0
  168. data/ext/asmjit/asmjit/test/asmjit_test_compiler_x86.cpp +4317 -0
  169. data/ext/asmjit/asmjit/test/asmjit_test_emitters.cpp +197 -0
  170. data/ext/asmjit/asmjit/test/asmjit_test_instinfo.cpp +181 -0
  171. data/ext/asmjit/asmjit/test/asmjit_test_misc.h +257 -0
  172. data/ext/asmjit/asmjit/test/asmjit_test_perf.cpp +62 -0
  173. data/ext/asmjit/asmjit/test/asmjit_test_perf.h +61 -0
  174. data/ext/asmjit/asmjit/test/asmjit_test_perf_a64.cpp +699 -0
  175. data/ext/asmjit/asmjit/test/asmjit_test_perf_x86.cpp +5032 -0
  176. data/ext/asmjit/asmjit/test/asmjit_test_unit.cpp +172 -0
  177. data/ext/asmjit/asmjit/test/asmjit_test_x86_sections.cpp +172 -0
  178. data/ext/asmjit/asmjit/test/asmjitutils.h +38 -0
  179. data/ext/asmjit/asmjit/test/broken.cpp +312 -0
  180. data/ext/asmjit/asmjit/test/broken.h +148 -0
  181. data/ext/asmjit/asmjit/test/cmdline.h +61 -0
  182. data/ext/asmjit/asmjit/test/performancetimer.h +41 -0
  183. data/ext/asmjit/asmjit/tools/configure-makefiles.sh +13 -0
  184. data/ext/asmjit/asmjit/tools/configure-ninja.sh +13 -0
  185. data/ext/asmjit/asmjit/tools/configure-sanitizers.sh +13 -0
  186. data/ext/asmjit/asmjit/tools/configure-vs2019-x64.bat +2 -0
  187. data/ext/asmjit/asmjit/tools/configure-vs2019-x86.bat +2 -0
  188. data/ext/asmjit/asmjit/tools/configure-vs2022-x64.bat +2 -0
  189. data/ext/asmjit/asmjit/tools/configure-vs2022-x86.bat +2 -0
  190. data/ext/asmjit/asmjit/tools/configure-xcode.sh +8 -0
  191. data/ext/asmjit/asmjit/tools/enumgen.js +417 -0
  192. data/ext/asmjit/asmjit/tools/enumgen.sh +3 -0
  193. data/ext/asmjit/asmjit/tools/tablegen-arm.js +365 -0
  194. data/ext/asmjit/asmjit/tools/tablegen-arm.sh +3 -0
  195. data/ext/asmjit/asmjit/tools/tablegen-x86.js +2638 -0
  196. data/ext/asmjit/asmjit/tools/tablegen-x86.sh +3 -0
  197. data/ext/asmjit/asmjit/tools/tablegen.js +947 -0
  198. data/ext/asmjit/asmjit/tools/tablegen.sh +4 -0
  199. data/ext/asmjit/asmjit.cc +18 -0
  200. data/lib/asmjit/version.rb +1 -1
  201. metadata +197 -2
@@ -0,0 +1,722 @@
1
+ // This file is part of AsmJit project <https://asmjit.com>
2
+ //
3
+ // See asmjit.h or LICENSE.md for license and copyright information
4
+ // SPDX-License-Identifier: Zlib
5
+
6
+ #include "../core/api-build_p.h"
7
+ #ifndef ASMJIT_NO_JIT
8
+
9
+ #include "../core/osutils.h"
10
+ #include "../core/string.h"
11
+ #include "../core/support.h"
12
+ #include "../core/virtmem.h"
13
+
14
+ #if !defined(_WIN32)
15
+ #include <errno.h>
16
+ #include <fcntl.h>
17
+ #include <sys/mman.h>
18
+ #include <sys/stat.h>
19
+ #include <sys/types.h>
20
+ #include <unistd.h>
21
+
22
+ // Linux has a `memfd_create` syscall that we would like to use, if available.
23
+ #if defined(__linux__)
24
+ #include <sys/syscall.h>
25
+ #endif
26
+
27
+ // Apple recently introduced MAP_JIT flag, which we want to use.
28
+ #if defined(__APPLE__)
29
+ #include <pthread.h>
30
+ #include <TargetConditionals.h>
31
+ #if TARGET_OS_OSX
32
+ #include <sys/utsname.h>
33
+ #include <libkern/OSCacheControl.h> // sys_icache_invalidate().
34
+ #endif
35
+ // Older SDK doesn't define `MAP_JIT`.
36
+ #ifndef MAP_JIT
37
+ #define MAP_JIT 0x800
38
+ #endif
39
+ #endif
40
+
41
+ // BSD/MAC: `MAP_ANONYMOUS` is not defined, `MAP_ANON` is.
42
+ #if !defined(MAP_ANONYMOUS)
43
+ #define MAP_ANONYMOUS MAP_ANON
44
+ #endif
45
+ #endif
46
+
47
+ #include <atomic>
48
+
49
+ #if defined(__APPLE__) || defined(__BIONIC__)
50
+ #define ASMJIT_VM_SHM_DETECT 0
51
+ #else
52
+ #define ASMJIT_VM_SHM_DETECT 1
53
+ #endif
54
+
55
+ // Android NDK doesn't provide `shm_open()` and `shm_unlink()`.
56
+ #if defined(__BIONIC__)
57
+ #define ASMJIT_VM_SHM_AVAILABLE 0
58
+ #else
59
+ #define ASMJIT_VM_SHM_AVAILABLE 1
60
+ #endif
61
+
62
+ #if defined(__APPLE__) && ASMJIT_ARCH_ARM >= 64
63
+ #define ASMJIT_HAS_PTHREAD_JIT_WRITE_PROTECT_NP
64
+ #endif
65
+
66
+ ASMJIT_BEGIN_SUB_NAMESPACE(VirtMem)
67
+
68
+ // Virtual Memory Utilities
69
+ // ========================
70
+
71
+ static const MemoryFlags dualMappingFilter[2] = {
72
+ MemoryFlags::kAccessWrite | MemoryFlags::kMMapMaxAccessWrite,
73
+ MemoryFlags::kAccessExecute | MemoryFlags::kMMapMaxAccessExecute
74
+ };
75
+
76
+ // Virtual Memory [Windows]
77
+ // ========================
78
+
79
+ #if defined(_WIN32)
80
+
81
+ struct ScopedHandle {
82
+ inline ScopedHandle() noexcept
83
+ : value(nullptr) {}
84
+
85
+ inline ~ScopedHandle() noexcept {
86
+ if (value != nullptr)
87
+ ::CloseHandle(value);
88
+ }
89
+
90
+ HANDLE value;
91
+ };
92
+
93
+ static void getVMInfo(Info& vmInfo) noexcept {
94
+ SYSTEM_INFO systemInfo;
95
+
96
+ ::GetSystemInfo(&systemInfo);
97
+ vmInfo.pageSize = Support::alignUpPowerOf2<uint32_t>(systemInfo.dwPageSize);
98
+ vmInfo.pageGranularity = systemInfo.dwAllocationGranularity;
99
+ }
100
+
101
+ // Returns windows-specific protectFlags from \ref MemoryFlags.
102
+ static DWORD protectFlagsFromMemoryFlags(MemoryFlags memoryFlags) noexcept {
103
+ DWORD protectFlags;
104
+
105
+ // READ|WRITE|EXECUTE.
106
+ if (Support::test(memoryFlags, MemoryFlags::kAccessExecute))
107
+ protectFlags = Support::test(memoryFlags, MemoryFlags::kAccessWrite) ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ;
108
+ else if (Support::test(memoryFlags, MemoryFlags::kAccessRW))
109
+ protectFlags = Support::test(memoryFlags, MemoryFlags::kAccessWrite) ? PAGE_READWRITE : PAGE_READONLY;
110
+ else
111
+ protectFlags = PAGE_NOACCESS;
112
+
113
+ // Any other flags to consider?
114
+ return protectFlags;
115
+ }
116
+
117
+ static DWORD desiredAccessFromMemoryFlags(MemoryFlags memoryFlags) noexcept {
118
+ DWORD access = Support::test(memoryFlags, MemoryFlags::kAccessWrite) ? FILE_MAP_WRITE : FILE_MAP_READ;
119
+ if (Support::test(memoryFlags, MemoryFlags::kAccessExecute))
120
+ access |= FILE_MAP_EXECUTE;
121
+ return access;
122
+ }
123
+
124
+ static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept {
125
+ return HardenedRuntimeFlags::kNone;
126
+ }
127
+
128
+ Error alloc(void** p, size_t size, MemoryFlags memoryFlags) noexcept {
129
+ *p = nullptr;
130
+ if (size == 0)
131
+ return DebugUtils::errored(kErrorInvalidArgument);
132
+
133
+ DWORD protectFlags = protectFlagsFromMemoryFlags(memoryFlags);
134
+ void* result = ::VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, protectFlags);
135
+
136
+ if (!result)
137
+ return DebugUtils::errored(kErrorOutOfMemory);
138
+
139
+ *p = result;
140
+ return kErrorOk;
141
+ }
142
+
143
+ Error release(void* p, size_t size) noexcept {
144
+ DebugUtils::unused(size);
145
+ if (ASMJIT_UNLIKELY(!::VirtualFree(p, 0, MEM_RELEASE)))
146
+ return DebugUtils::errored(kErrorInvalidArgument);
147
+ return kErrorOk;
148
+ }
149
+
150
+ Error protect(void* p, size_t size, MemoryFlags memoryFlags) noexcept {
151
+ DWORD protectFlags = protectFlagsFromMemoryFlags(memoryFlags);
152
+ DWORD oldFlags;
153
+
154
+ if (::VirtualProtect(p, size, protectFlags, &oldFlags))
155
+ return kErrorOk;
156
+
157
+ return DebugUtils::errored(kErrorInvalidArgument);
158
+ }
159
+
160
+ Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags memoryFlags) noexcept {
161
+ dm->rx = nullptr;
162
+ dm->rw = nullptr;
163
+
164
+ if (size == 0)
165
+ return DebugUtils::errored(kErrorInvalidArgument);
166
+
167
+ ScopedHandle handle;
168
+ handle.value = ::CreateFileMappingW(
169
+ INVALID_HANDLE_VALUE,
170
+ nullptr,
171
+ PAGE_EXECUTE_READWRITE,
172
+ (DWORD)(uint64_t(size) >> 32),
173
+ (DWORD)(size & 0xFFFFFFFFu),
174
+ nullptr);
175
+
176
+ if (ASMJIT_UNLIKELY(!handle.value))
177
+ return DebugUtils::errored(kErrorOutOfMemory);
178
+
179
+ void* ptr[2];
180
+ for (uint32_t i = 0; i < 2; i++) {
181
+ MemoryFlags accessFlags = memoryFlags & ~dualMappingFilter[i];
182
+ DWORD desiredAccess = desiredAccessFromMemoryFlags(accessFlags);
183
+ ptr[i] = ::MapViewOfFile(handle.value, desiredAccess, 0, 0, size);
184
+
185
+ if (ptr[i] == nullptr) {
186
+ if (i == 0)
187
+ ::UnmapViewOfFile(ptr[0]);
188
+ return DebugUtils::errored(kErrorOutOfMemory);
189
+ }
190
+ }
191
+
192
+ dm->rx = ptr[0];
193
+ dm->rw = ptr[1];
194
+ return kErrorOk;
195
+ }
196
+
197
+ Error releaseDualMapping(DualMapping* dm, size_t size) noexcept {
198
+ DebugUtils::unused(size);
199
+ bool failed = false;
200
+
201
+ if (!::UnmapViewOfFile(dm->rx))
202
+ failed = true;
203
+
204
+ if (dm->rx != dm->rw && !UnmapViewOfFile(dm->rw))
205
+ failed = true;
206
+
207
+ if (failed)
208
+ return DebugUtils::errored(kErrorInvalidArgument);
209
+
210
+ dm->rx = nullptr;
211
+ dm->rw = nullptr;
212
+ return kErrorOk;
213
+ }
214
+
215
+ #endif
216
+
217
+ // Virtual Memory [Posix]
218
+ // ======================
219
+
220
+ #if !defined(_WIN32)
221
+
222
+ static void getVMInfo(Info& vmInfo) noexcept {
223
+ uint32_t pageSize = uint32_t(::getpagesize());
224
+
225
+ vmInfo.pageSize = pageSize;
226
+ vmInfo.pageGranularity = Support::max<uint32_t>(pageSize, 65536);
227
+ }
228
+
229
+ #if !defined(SHM_ANON)
230
+ static const char* getTmpDir() noexcept {
231
+ const char* tmpDir = getenv("TMPDIR");
232
+ return tmpDir ? tmpDir : "/tmp";
233
+ }
234
+ #endif
235
+
236
+ // Translates libc errors specific to VirtualMemory mapping to `asmjit::Error`.
237
+ static Error asmjitErrorFromErrno(int e) noexcept {
238
+ switch (e) {
239
+ case EACCES:
240
+ case EAGAIN:
241
+ case ENODEV:
242
+ case EPERM:
243
+ return kErrorInvalidState;
244
+
245
+ case EFBIG:
246
+ case ENOMEM:
247
+ case EOVERFLOW:
248
+ return kErrorOutOfMemory;
249
+
250
+ case EMFILE:
251
+ case ENFILE:
252
+ return kErrorTooManyHandles;
253
+
254
+ default:
255
+ return kErrorInvalidArgument;
256
+ }
257
+ }
258
+
259
+ // Some operating systems don't allow /dev/shm to be executable. On Linux this happens when /dev/shm is mounted with
260
+ // 'noexec', which is enforced by systemd. Other operating systems like MacOS also restrict executable permissions
261
+ // regarding /dev/shm, so we use a runtime detection before attempting to allocate executable memory. Sometimes we
262
+ // don't need the detection as we know it would always result in `ShmStrategy::kTmpDir`.
263
+ enum class ShmStrategy : uint32_t {
264
+ kUnknown = 0,
265
+ kDevShm = 1,
266
+ kTmpDir = 2
267
+ };
268
+
269
+ class AnonymousMemory {
270
+ public:
271
+ enum FileType : uint32_t {
272
+ kFileTypeNone,
273
+ kFileTypeShm,
274
+ kFileTypeTmp
275
+ };
276
+
277
+ int _fd;
278
+ FileType _fileType;
279
+ StringTmp<128> _tmpName;
280
+
281
+ inline AnonymousMemory() noexcept
282
+ : _fd(-1),
283
+ _fileType(kFileTypeNone),
284
+ _tmpName() {}
285
+
286
+ inline ~AnonymousMemory() noexcept {
287
+ unlink();
288
+ close();
289
+ }
290
+
291
+ inline int fd() const noexcept { return _fd; }
292
+
293
+ Error open(bool preferTmpOverDevShm) noexcept {
294
+ #if defined(__linux__) && defined(__NR_memfd_create)
295
+ // Linux specific 'memfd_create' - if the syscall returns `ENOSYS` it means
296
+ // it's not available and we will never call it again (would be pointless).
297
+
298
+ // Zero initialized, if ever changed to '1' that would mean the syscall is not
299
+ // available and we must use `shm_open()` and `shm_unlink()`.
300
+ static volatile uint32_t memfd_create_not_supported;
301
+
302
+ if (!memfd_create_not_supported) {
303
+ _fd = (int)syscall(__NR_memfd_create, "vmem", 0);
304
+ if (ASMJIT_LIKELY(_fd >= 0))
305
+ return kErrorOk;
306
+
307
+ int e = errno;
308
+ if (e == ENOSYS)
309
+ memfd_create_not_supported = 1;
310
+ else
311
+ return DebugUtils::errored(asmjitErrorFromErrno(e));
312
+ }
313
+ #endif
314
+
315
+ #if defined(SHM_ANON)
316
+ // Originally FreeBSD extension, apparently works in other BSDs too.
317
+ DebugUtils::unused(preferTmpOverDevShm);
318
+ _fd = ::shm_open(SHM_ANON, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
319
+
320
+ if (ASMJIT_LIKELY(_fd >= 0))
321
+ return kErrorOk;
322
+ else
323
+ return DebugUtils::errored(asmjitErrorFromErrno(errno));
324
+ #else
325
+ // POSIX API. We have to generate somehow a unique name. This is nothing cryptographic, just using a bit from
326
+ // the stack address to always have a different base for different threads (as threads have their own stack)
327
+ // and retries for avoiding collisions. We use `shm_open()` with flags that require creation of the file so we
328
+ // never open an existing shared memory.
329
+ static std::atomic<uint32_t> internalCounter;
330
+ const char* kShmFormat = "/shm-id-%016llX";
331
+
332
+ uint32_t kRetryCount = 100;
333
+ uint64_t bits = ((uintptr_t)(void*)this) & 0x55555555u;
334
+
335
+ for (uint32_t i = 0; i < kRetryCount; i++) {
336
+ bits -= uint64_t(OSUtils::getTickCount()) * 773703683;
337
+ bits = ((bits >> 14) ^ (bits << 6)) + uint64_t(++internalCounter) * 10619863;
338
+
339
+ bool useTmp = !ASMJIT_VM_SHM_DETECT || preferTmpOverDevShm;
340
+
341
+ if (useTmp) {
342
+ _tmpName.assign(getTmpDir());
343
+ _tmpName.appendFormat(kShmFormat, (unsigned long long)bits);
344
+ _fd = ::open(_tmpName.data(), O_RDWR | O_CREAT | O_EXCL, 0);
345
+ if (ASMJIT_LIKELY(_fd >= 0)) {
346
+ _fileType = kFileTypeTmp;
347
+ return kErrorOk;
348
+ }
349
+ }
350
+ #if ASMJIT_VM_SHM_AVAILABLE
351
+ else {
352
+ _tmpName.assignFormat(kShmFormat, (unsigned long long)bits);
353
+ _fd = ::shm_open(_tmpName.data(), O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
354
+ if (ASMJIT_LIKELY(_fd >= 0)) {
355
+ _fileType = kFileTypeShm;
356
+ return kErrorOk;
357
+ }
358
+ }
359
+ #endif
360
+
361
+ int e = errno;
362
+ if (e != EEXIST)
363
+ return DebugUtils::errored(asmjitErrorFromErrno(e));
364
+ }
365
+
366
+ return DebugUtils::errored(kErrorFailedToOpenAnonymousMemory);
367
+ #endif
368
+ }
369
+
370
+ void unlink() noexcept {
371
+ FileType type = _fileType;
372
+ _fileType = kFileTypeNone;
373
+
374
+ #if ASMJIT_VM_SHM_AVAILABLE
375
+ if (type == kFileTypeShm) {
376
+ ::shm_unlink(_tmpName.data());
377
+ return;
378
+ }
379
+ #endif
380
+
381
+ if (type == kFileTypeTmp) {
382
+ ::unlink(_tmpName.data());
383
+ return;
384
+ }
385
+ }
386
+
387
+ void close() noexcept {
388
+ if (_fd >= 0) {
389
+ ::close(_fd);
390
+ _fd = -1;
391
+ }
392
+ }
393
+
394
+ Error allocate(size_t size) noexcept {
395
+ // TODO: Improve this by using `posix_fallocate()` when available.
396
+ if (ftruncate(_fd, off_t(size)) != 0)
397
+ return DebugUtils::errored(asmjitErrorFromErrno(errno));
398
+
399
+ return kErrorOk;
400
+ }
401
+ };
402
+
403
+ // Returns `mmap()` protection flags from \ref MemoryFlags.
404
+ static int mmProtFromMemoryFlags(MemoryFlags memoryFlags) noexcept {
405
+ int protection = 0;
406
+ if (Support::test(memoryFlags, MemoryFlags::kAccessRead)) protection |= PROT_READ;
407
+ if (Support::test(memoryFlags, MemoryFlags::kAccessWrite)) protection |= PROT_READ | PROT_WRITE;
408
+ if (Support::test(memoryFlags, MemoryFlags::kAccessExecute)) protection |= PROT_READ | PROT_EXEC;
409
+ return protection;
410
+ }
411
+
412
+ #if defined(__APPLE__)
413
+ // Detects whether the current process is hardened, which means that pages that have WRITE and EXECUTABLE flags cannot
414
+ // be allocated without MAP_JIT flag.
415
+ static inline bool hasHardenedRuntimeMacOS() noexcept {
416
+ #if TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64
417
+ // MacOS on AArch64 has always hardened runtime enabled.
418
+ return true;
419
+ #else
420
+ static std::atomic<uint32_t> globalHardenedFlag;
421
+
422
+ enum HardenedFlag : uint32_t {
423
+ kHardenedFlagUnknown = 0,
424
+ kHardenedFlagDisabled = 1,
425
+ kHardenedFlagEnabled = 2
426
+ };
427
+
428
+ uint32_t flag = globalHardenedFlag.load();
429
+ if (flag == kHardenedFlagUnknown) {
430
+ size_t pageSize = ::getpagesize();
431
+
432
+ void* ptr = mmap(nullptr, pageSize, PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
433
+ if (ptr == MAP_FAILED) {
434
+ flag = kHardenedFlagEnabled;
435
+ }
436
+ else {
437
+ flag = kHardenedFlagDisabled;
438
+ munmap(ptr, pageSize);
439
+ }
440
+ globalHardenedFlag.store(flag);
441
+ }
442
+
443
+ return flag == kHardenedFlagEnabled;
444
+ #endif
445
+ }
446
+
447
+ static inline bool hasMapJitSupportMacOS() noexcept {
448
+ #if TARGET_OS_OSX && ASMJIT_ARCH_ARM >= 64
449
+ // MacOS for 64-bit AArch architecture always uses hardened runtime. Some documentation can be found here:
450
+ // - https://developer.apple.com/documentation/apple_silicon/porting_just-in-time_compilers_to_apple_silicon
451
+ return true;
452
+ #elif TARGET_OS_OSX
453
+ // MAP_JIT flag required to run unsigned JIT code is only supported by kernel version 10.14+ (Mojave) and IOS.
454
+ static std::atomic<uint32_t> globalVersion;
455
+
456
+ int ver = globalVersion.load();
457
+ if (!ver) {
458
+ struct utsname osname {};
459
+ uname(&osname);
460
+ ver = atoi(osname.release);
461
+ globalVersion.store(ver);
462
+ }
463
+ return ver >= 18;
464
+ #else
465
+ // Assume it's available.
466
+ return true;
467
+ #endif
468
+ }
469
+ #endif // __APPLE__
470
+
471
+ // Detects whether the current process is hardened, which means that pages that have WRITE and EXECUTABLE flags
472
+ // cannot be normally allocated. On MacOS such allocation requires MAP_JIT flag.
473
+ static inline bool hasHardenedRuntime() noexcept {
474
+ #if defined(__APPLE__)
475
+ return hasHardenedRuntimeMacOS();
476
+ #else
477
+ return false;
478
+ #endif
479
+ }
480
+
481
+ // Detects whether MAP_JIT is available.
482
+ static inline bool hasMapJitSupport() noexcept {
483
+ #if defined(__APPLE__)
484
+ return hasMapJitSupportMacOS();
485
+ #else
486
+ return false;
487
+ #endif
488
+ }
489
+
490
+ // Returns either MAP_JIT or 0 based on `flags` and the host operating system.
491
+ static inline int mmMapJitFromMemoryFlags(MemoryFlags memoryFlags) noexcept {
492
+ #if defined(__APPLE__)
493
+ // Always use MAP_JIT flag if user asked for it (could be used for testing on non-hardened processes) and detect
494
+ // whether it must be used when the process is actually hardened (in that case it doesn't make sense to rely on
495
+ // user `memoryFlags`).
496
+ bool useMapJit = Support::test(memoryFlags, MemoryFlags::kMMapEnableMapJit) || hasHardenedRuntime();
497
+ if (useMapJit)
498
+ return hasMapJitSupport() ? int(MAP_JIT) : 0;
499
+ else
500
+ return 0;
501
+ #else
502
+ DebugUtils::unused(memoryFlags);
503
+ return 0;
504
+ #endif
505
+ }
506
+
507
+ // Returns BSD-specific `PROT_MAX()` flags.
508
+ static inline int mmMaxProtFromMemoryFlags(MemoryFlags memoryFlags) noexcept {
509
+ #if defined(PROT_MAX)
510
+ static constexpr uint32_t kMaxProtShift = Support::ConstCTZ<uint32_t(MemoryFlags::kMMapMaxAccessRead)>::value;
511
+
512
+ if (Support::test(memoryFlags, MemoryFlags::kMMapMaxAccessReadWrite | MemoryFlags::kMMapMaxAccessExecute))
513
+ return PROT_MAX(mmProtFromMemoryFlags((MemoryFlags)(uint32_t(memoryFlags) >> kMaxProtShift)));
514
+ else
515
+ return 0;
516
+ #else
517
+ DebugUtils::unused(memoryFlags);
518
+ return 0;
519
+ #endif
520
+ }
521
+
522
+ #if ASMJIT_VM_SHM_DETECT
523
+ static Error detectShmStrategy(ShmStrategy* strategyOut) noexcept {
524
+ AnonymousMemory anonMem;
525
+ Info vmInfo = info();
526
+
527
+ ASMJIT_PROPAGATE(anonMem.open(false));
528
+ ASMJIT_PROPAGATE(anonMem.allocate(vmInfo.pageSize));
529
+
530
+ void* ptr = mmap(nullptr, vmInfo.pageSize, PROT_READ | PROT_EXEC, MAP_SHARED, anonMem.fd(), 0);
531
+ if (ptr == MAP_FAILED) {
532
+ int e = errno;
533
+ if (e == EINVAL) {
534
+ *strategyOut = ShmStrategy::kTmpDir;
535
+ return kErrorOk;
536
+ }
537
+ return DebugUtils::errored(asmjitErrorFromErrno(e));
538
+ }
539
+ else {
540
+ munmap(ptr, vmInfo.pageSize);
541
+ *strategyOut = ShmStrategy::kDevShm;
542
+ return kErrorOk;
543
+ }
544
+ }
545
+ #endif
546
+
547
+ static Error getShmStrategy(ShmStrategy* strategyOut) noexcept {
548
+ #if ASMJIT_VM_SHM_DETECT
549
+ // Initially don't assume anything. It has to be tested whether '/dev/shm' was mounted with 'noexec' flag or not.
550
+ static std::atomic<uint32_t> globalShmStrategy;
551
+
552
+ ShmStrategy strategy = static_cast<ShmStrategy>(globalShmStrategy.load());
553
+ if (strategy == ShmStrategy::kUnknown) {
554
+ ASMJIT_PROPAGATE(detectShmStrategy(&strategy));
555
+ globalShmStrategy.store(static_cast<uint32_t>(strategy));
556
+ }
557
+
558
+ *strategyOut = strategy;
559
+ return kErrorOk;
560
+ #else
561
+ *strategyOut = ShmStrategy::kTmpDir;
562
+ return kErrorOk;
563
+ #endif
564
+ }
565
+
566
+ static HardenedRuntimeFlags getHardenedRuntimeFlags() noexcept {
567
+ HardenedRuntimeFlags hrFlags = HardenedRuntimeFlags::kNone;
568
+
569
+ if (hasHardenedRuntime())
570
+ hrFlags |= HardenedRuntimeFlags::kEnabled;
571
+
572
+ if (hasMapJitSupport())
573
+ hrFlags |= HardenedRuntimeFlags::kMapJit;
574
+
575
+ return hrFlags;
576
+ }
577
+
578
+ Error alloc(void** p, size_t size, MemoryFlags memoryFlags) noexcept {
579
+ *p = nullptr;
580
+ if (size == 0)
581
+ return DebugUtils::errored(kErrorInvalidArgument);
582
+
583
+ int protection = mmProtFromMemoryFlags(memoryFlags) | mmMaxProtFromMemoryFlags(memoryFlags);
584
+ int mmFlags = MAP_PRIVATE | MAP_ANONYMOUS | mmMapJitFromMemoryFlags(memoryFlags);
585
+
586
+ void* ptr = mmap(nullptr, size, protection, mmFlags, -1, 0);
587
+ if (ptr == MAP_FAILED)
588
+ return DebugUtils::errored(kErrorOutOfMemory);
589
+
590
+ *p = ptr;
591
+ return kErrorOk;
592
+ }
593
+
594
+ Error release(void* p, size_t size) noexcept {
595
+ if (ASMJIT_UNLIKELY(munmap(p, size) != 0))
596
+ return DebugUtils::errored(kErrorInvalidArgument);
597
+
598
+ return kErrorOk;
599
+ }
600
+
601
+
602
+ Error protect(void* p, size_t size, MemoryFlags memoryFlags) noexcept {
603
+ int protection = mmProtFromMemoryFlags(memoryFlags);
604
+ if (mprotect(p, size, protection) == 0)
605
+ return kErrorOk;
606
+
607
+ return DebugUtils::errored(kErrorInvalidArgument);
608
+ }
609
+
610
+ Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags memoryFlags) noexcept {
611
+ dm->rx = nullptr;
612
+ dm->rw = nullptr;
613
+
614
+ if (off_t(size) <= 0)
615
+ return DebugUtils::errored(size == 0 ? kErrorInvalidArgument : kErrorTooLarge);
616
+
617
+ bool preferTmpOverDevShm = Support::test(memoryFlags, MemoryFlags::kMappingPreferTmp);
618
+ if (!preferTmpOverDevShm) {
619
+ ShmStrategy strategy;
620
+ ASMJIT_PROPAGATE(getShmStrategy(&strategy));
621
+ preferTmpOverDevShm = (strategy == ShmStrategy::kTmpDir);
622
+ }
623
+
624
+ AnonymousMemory anonMem;
625
+ ASMJIT_PROPAGATE(anonMem.open(preferTmpOverDevShm));
626
+ ASMJIT_PROPAGATE(anonMem.allocate(size));
627
+
628
+ void* ptr[2];
629
+ for (uint32_t i = 0; i < 2; i++) {
630
+ MemoryFlags accessFlags = memoryFlags & ~dualMappingFilter[i];
631
+ int protection = mmProtFromMemoryFlags(accessFlags) | mmMaxProtFromMemoryFlags(accessFlags);
632
+
633
+ ptr[i] = mmap(nullptr, size, protection, MAP_SHARED, anonMem.fd(), 0);
634
+ if (ptr[i] == MAP_FAILED) {
635
+ // Get the error now before `munmap()` has a chance to clobber it.
636
+ int e = errno;
637
+ if (i == 1)
638
+ munmap(ptr[0], size);
639
+ return DebugUtils::errored(asmjitErrorFromErrno(e));
640
+ }
641
+ }
642
+
643
+ dm->rx = ptr[0];
644
+ dm->rw = ptr[1];
645
+ return kErrorOk;
646
+ }
647
+
648
+ Error releaseDualMapping(DualMapping* dm, size_t size) noexcept {
649
+ Error err = release(dm->rx, size);
650
+ if (dm->rx != dm->rw)
651
+ err |= release(dm->rw, size);
652
+
653
+ if (err)
654
+ return DebugUtils::errored(kErrorInvalidArgument);
655
+
656
+ dm->rx = nullptr;
657
+ dm->rw = nullptr;
658
+ return kErrorOk;
659
+ }
660
+ #endif
661
+
662
+ // Virtual Memory - Flush Instruction Cache
663
+ // ========================================
664
+
665
+ void flushInstructionCache(void* p, size_t size) noexcept {
666
+ #if ASMJIT_ARCH_X86
667
+ // X86/X86_64 architecture doesn't require to do anything to flush instruction cache.
668
+ DebugUtils::unused(p, size);
669
+ #elif defined(__APPLE__)
670
+ sys_icache_invalidate(p, size);
671
+ #elif defined(_WIN32)
672
+ // Windows has a built-in support in `kernel32.dll`.
673
+ FlushInstructionCache(GetCurrentProcess(), p, size);
674
+ #elif defined(__GNUC__)
675
+ char* start = static_cast<char*>(p);
676
+ char* end = start + size;
677
+ __builtin___clear_cache(start, end);
678
+ #else
679
+ #pragma message("asmjit::VirtMem::flushInstructionCache() doesn't have implementation for the target OS and compiler")
680
+ DebugUtils::unused(p, size);
681
+ #endif
682
+ }
683
+
684
+ // Virtual Memory - Memory Info
685
+ // ============================
686
+
687
+ Info info() noexcept {
688
+ static std::atomic<uint32_t> vmInfoInitialized;
689
+ static Info vmInfo;
690
+
691
+ if (!vmInfoInitialized.load()) {
692
+ Info localMemInfo;
693
+ getVMInfo(localMemInfo);
694
+
695
+ vmInfo = localMemInfo;
696
+ vmInfoInitialized.store(1u);
697
+ }
698
+
699
+ return vmInfo;
700
+ }
701
+
702
+ // Virtual Memory - Hardened Runtime Info
703
+ // ======================================
704
+
705
+ HardenedRuntimeInfo hardenedRuntimeInfo() noexcept {
706
+ return HardenedRuntimeInfo { getHardenedRuntimeFlags() };
707
+ }
708
+
709
+ // Virtual Memory - Project JIT Memory
710
+ // ===================================
711
+
712
+ void protectJitMemory(ProtectJitAccess access) noexcept {
713
+ #if defined(ASMJIT_HAS_PTHREAD_JIT_WRITE_PROTECT_NP)
714
+ pthread_jit_write_protect_np(static_cast<uint32_t>(access));
715
+ #else
716
+ DebugUtils::unused(access);
717
+ #endif
718
+ }
719
+
720
+ ASMJIT_END_SUB_NAMESPACE
721
+
722
+ #endif