asmjit 0.2.0 → 0.2.2

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 (204) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/Rakefile +5 -3
  4. data/asmjit.gemspec +1 -3
  5. data/ext/asmjit/asmjit/.editorconfig +10 -0
  6. data/ext/asmjit/asmjit/.github/FUNDING.yml +1 -0
  7. data/ext/asmjit/asmjit/.github/workflows/build-config.json +47 -0
  8. data/ext/asmjit/asmjit/.github/workflows/build.yml +156 -0
  9. data/ext/asmjit/asmjit/.gitignore +6 -0
  10. data/ext/asmjit/asmjit/CMakeLists.txt +611 -0
  11. data/ext/asmjit/asmjit/LICENSE.md +17 -0
  12. data/ext/asmjit/asmjit/README.md +69 -0
  13. data/ext/asmjit/asmjit/src/asmjit/a64.h +62 -0
  14. data/ext/asmjit/asmjit/src/asmjit/arm/a64archtraits_p.h +81 -0
  15. data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.cpp +5115 -0
  16. data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.h +72 -0
  17. data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.cpp +51 -0
  18. data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.h +57 -0
  19. data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.cpp +60 -0
  20. data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.h +247 -0
  21. data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper.cpp +464 -0
  22. data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper_p.h +50 -0
  23. data/ext/asmjit/asmjit/src/asmjit/arm/a64emitter.h +1228 -0
  24. data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter.cpp +298 -0
  25. data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter_p.h +59 -0
  26. data/ext/asmjit/asmjit/src/asmjit/arm/a64func.cpp +189 -0
  27. data/ext/asmjit/asmjit/src/asmjit/arm/a64func_p.h +33 -0
  28. data/ext/asmjit/asmjit/src/asmjit/arm/a64globals.h +1894 -0
  29. data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi.cpp +278 -0
  30. data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi_p.h +41 -0
  31. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.cpp +1957 -0
  32. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.h +74 -0
  33. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb_p.h +876 -0
  34. data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.cpp +85 -0
  35. data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.h +312 -0
  36. data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass.cpp +852 -0
  37. data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass_p.h +105 -0
  38. data/ext/asmjit/asmjit/src/asmjit/arm/a64utils.h +179 -0
  39. data/ext/asmjit/asmjit/src/asmjit/arm/armformatter.cpp +143 -0
  40. data/ext/asmjit/asmjit/src/asmjit/arm/armformatter_p.h +44 -0
  41. data/ext/asmjit/asmjit/src/asmjit/arm/armglobals.h +21 -0
  42. data/ext/asmjit/asmjit/src/asmjit/arm/armoperand.h +621 -0
  43. data/ext/asmjit/asmjit/src/asmjit/arm.h +62 -0
  44. data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-begin.h +17 -0
  45. data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-end.h +9 -0
  46. data/ext/asmjit/asmjit/src/asmjit/asmjit.h +33 -0
  47. data/ext/asmjit/asmjit/src/asmjit/core/api-build_p.h +55 -0
  48. data/ext/asmjit/asmjit/src/asmjit/core/api-config.h +613 -0
  49. data/ext/asmjit/asmjit/src/asmjit/core/archcommons.h +229 -0
  50. data/ext/asmjit/asmjit/src/asmjit/core/archtraits.cpp +160 -0
  51. data/ext/asmjit/asmjit/src/asmjit/core/archtraits.h +290 -0
  52. data/ext/asmjit/asmjit/src/asmjit/core/assembler.cpp +406 -0
  53. data/ext/asmjit/asmjit/src/asmjit/core/assembler.h +129 -0
  54. data/ext/asmjit/asmjit/src/asmjit/core/builder.cpp +889 -0
  55. data/ext/asmjit/asmjit/src/asmjit/core/builder.h +1391 -0
  56. data/ext/asmjit/asmjit/src/asmjit/core/codebuffer.h +113 -0
  57. data/ext/asmjit/asmjit/src/asmjit/core/codeholder.cpp +1149 -0
  58. data/ext/asmjit/asmjit/src/asmjit/core/codeholder.h +1035 -0
  59. data/ext/asmjit/asmjit/src/asmjit/core/codewriter.cpp +175 -0
  60. data/ext/asmjit/asmjit/src/asmjit/core/codewriter_p.h +179 -0
  61. data/ext/asmjit/asmjit/src/asmjit/core/compiler.cpp +582 -0
  62. data/ext/asmjit/asmjit/src/asmjit/core/compiler.h +737 -0
  63. data/ext/asmjit/asmjit/src/asmjit/core/compilerdefs.h +173 -0
  64. data/ext/asmjit/asmjit/src/asmjit/core/constpool.cpp +363 -0
  65. data/ext/asmjit/asmjit/src/asmjit/core/constpool.h +250 -0
  66. data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.cpp +1162 -0
  67. data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.h +813 -0
  68. data/ext/asmjit/asmjit/src/asmjit/core/emithelper.cpp +323 -0
  69. data/ext/asmjit/asmjit/src/asmjit/core/emithelper_p.h +58 -0
  70. data/ext/asmjit/asmjit/src/asmjit/core/emitter.cpp +333 -0
  71. data/ext/asmjit/asmjit/src/asmjit/core/emitter.h +741 -0
  72. data/ext/asmjit/asmjit/src/asmjit/core/emitterutils.cpp +129 -0
  73. data/ext/asmjit/asmjit/src/asmjit/core/emitterutils_p.h +89 -0
  74. data/ext/asmjit/asmjit/src/asmjit/core/environment.cpp +46 -0
  75. data/ext/asmjit/asmjit/src/asmjit/core/environment.h +508 -0
  76. data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.cpp +14 -0
  77. data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.h +228 -0
  78. data/ext/asmjit/asmjit/src/asmjit/core/formatter.cpp +584 -0
  79. data/ext/asmjit/asmjit/src/asmjit/core/formatter.h +247 -0
  80. data/ext/asmjit/asmjit/src/asmjit/core/formatter_p.h +34 -0
  81. data/ext/asmjit/asmjit/src/asmjit/core/func.cpp +286 -0
  82. data/ext/asmjit/asmjit/src/asmjit/core/func.h +1445 -0
  83. data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext.cpp +293 -0
  84. data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext_p.h +199 -0
  85. data/ext/asmjit/asmjit/src/asmjit/core/globals.cpp +133 -0
  86. data/ext/asmjit/asmjit/src/asmjit/core/globals.h +393 -0
  87. data/ext/asmjit/asmjit/src/asmjit/core/inst.cpp +113 -0
  88. data/ext/asmjit/asmjit/src/asmjit/core/inst.h +772 -0
  89. data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.cpp +1242 -0
  90. data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.h +261 -0
  91. data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.cpp +80 -0
  92. data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.h +89 -0
  93. data/ext/asmjit/asmjit/src/asmjit/core/logger.cpp +69 -0
  94. data/ext/asmjit/asmjit/src/asmjit/core/logger.h +198 -0
  95. data/ext/asmjit/asmjit/src/asmjit/core/misc_p.h +33 -0
  96. data/ext/asmjit/asmjit/src/asmjit/core/operand.cpp +132 -0
  97. data/ext/asmjit/asmjit/src/asmjit/core/operand.h +1611 -0
  98. data/ext/asmjit/asmjit/src/asmjit/core/osutils.cpp +84 -0
  99. data/ext/asmjit/asmjit/src/asmjit/core/osutils.h +61 -0
  100. data/ext/asmjit/asmjit/src/asmjit/core/osutils_p.h +68 -0
  101. data/ext/asmjit/asmjit/src/asmjit/core/raassignment_p.h +418 -0
  102. data/ext/asmjit/asmjit/src/asmjit/core/rabuilders_p.h +612 -0
  103. data/ext/asmjit/asmjit/src/asmjit/core/radefs_p.h +1204 -0
  104. data/ext/asmjit/asmjit/src/asmjit/core/ralocal.cpp +1166 -0
  105. data/ext/asmjit/asmjit/src/asmjit/core/ralocal_p.h +254 -0
  106. data/ext/asmjit/asmjit/src/asmjit/core/rapass.cpp +1969 -0
  107. data/ext/asmjit/asmjit/src/asmjit/core/rapass_p.h +1183 -0
  108. data/ext/asmjit/asmjit/src/asmjit/core/rastack.cpp +184 -0
  109. data/ext/asmjit/asmjit/src/asmjit/core/rastack_p.h +171 -0
  110. data/ext/asmjit/asmjit/src/asmjit/core/string.cpp +559 -0
  111. data/ext/asmjit/asmjit/src/asmjit/core/string.h +372 -0
  112. data/ext/asmjit/asmjit/src/asmjit/core/support.cpp +494 -0
  113. data/ext/asmjit/asmjit/src/asmjit/core/support.h +1773 -0
  114. data/ext/asmjit/asmjit/src/asmjit/core/target.cpp +14 -0
  115. data/ext/asmjit/asmjit/src/asmjit/core/target.h +53 -0
  116. data/ext/asmjit/asmjit/src/asmjit/core/type.cpp +74 -0
  117. data/ext/asmjit/asmjit/src/asmjit/core/type.h +419 -0
  118. data/ext/asmjit/asmjit/src/asmjit/core/virtmem.cpp +722 -0
  119. data/ext/asmjit/asmjit/src/asmjit/core/virtmem.h +242 -0
  120. data/ext/asmjit/asmjit/src/asmjit/core/zone.cpp +353 -0
  121. data/ext/asmjit/asmjit/src/asmjit/core/zone.h +615 -0
  122. data/ext/asmjit/asmjit/src/asmjit/core/zonehash.cpp +309 -0
  123. data/ext/asmjit/asmjit/src/asmjit/core/zonehash.h +186 -0
  124. data/ext/asmjit/asmjit/src/asmjit/core/zonelist.cpp +163 -0
  125. data/ext/asmjit/asmjit/src/asmjit/core/zonelist.h +209 -0
  126. data/ext/asmjit/asmjit/src/asmjit/core/zonestack.cpp +176 -0
  127. data/ext/asmjit/asmjit/src/asmjit/core/zonestack.h +239 -0
  128. data/ext/asmjit/asmjit/src/asmjit/core/zonestring.h +120 -0
  129. data/ext/asmjit/asmjit/src/asmjit/core/zonetree.cpp +99 -0
  130. data/ext/asmjit/asmjit/src/asmjit/core/zonetree.h +380 -0
  131. data/ext/asmjit/asmjit/src/asmjit/core/zonevector.cpp +356 -0
  132. data/ext/asmjit/asmjit/src/asmjit/core/zonevector.h +690 -0
  133. data/ext/asmjit/asmjit/src/asmjit/core.h +1861 -0
  134. data/ext/asmjit/asmjit/src/asmjit/x86/x86archtraits_p.h +148 -0
  135. data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.cpp +5110 -0
  136. data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.h +685 -0
  137. data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.cpp +52 -0
  138. data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.h +351 -0
  139. data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.cpp +61 -0
  140. data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.h +721 -0
  141. data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper.cpp +619 -0
  142. data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper_p.h +60 -0
  143. data/ext/asmjit/asmjit/src/asmjit/x86/x86emitter.h +4315 -0
  144. data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter.cpp +944 -0
  145. data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter_p.h +58 -0
  146. data/ext/asmjit/asmjit/src/asmjit/x86/x86func.cpp +503 -0
  147. data/ext/asmjit/asmjit/src/asmjit/x86/x86func_p.h +33 -0
  148. data/ext/asmjit/asmjit/src/asmjit/x86/x86globals.h +2169 -0
  149. data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi.cpp +1732 -0
  150. data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi_p.h +41 -0
  151. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.cpp +4427 -0
  152. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.h +563 -0
  153. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb_p.h +311 -0
  154. data/ext/asmjit/asmjit/src/asmjit/x86/x86opcode_p.h +436 -0
  155. data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.cpp +231 -0
  156. data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.h +1085 -0
  157. data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass.cpp +1509 -0
  158. data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass_p.h +94 -0
  159. data/ext/asmjit/asmjit/src/asmjit/x86.h +93 -0
  160. data/ext/asmjit/asmjit/src/asmjit.natvis +245 -0
  161. data/ext/asmjit/asmjit/test/asmjit_test_assembler.cpp +84 -0
  162. data/ext/asmjit/asmjit/test/asmjit_test_assembler.h +85 -0
  163. data/ext/asmjit/asmjit/test/asmjit_test_assembler_a64.cpp +4006 -0
  164. data/ext/asmjit/asmjit/test/asmjit_test_assembler_x64.cpp +17833 -0
  165. data/ext/asmjit/asmjit/test/asmjit_test_assembler_x86.cpp +8300 -0
  166. data/ext/asmjit/asmjit/test/asmjit_test_compiler.cpp +253 -0
  167. data/ext/asmjit/asmjit/test/asmjit_test_compiler.h +73 -0
  168. data/ext/asmjit/asmjit/test/asmjit_test_compiler_a64.cpp +690 -0
  169. data/ext/asmjit/asmjit/test/asmjit_test_compiler_x86.cpp +4317 -0
  170. data/ext/asmjit/asmjit/test/asmjit_test_emitters.cpp +197 -0
  171. data/ext/asmjit/asmjit/test/asmjit_test_instinfo.cpp +181 -0
  172. data/ext/asmjit/asmjit/test/asmjit_test_misc.h +257 -0
  173. data/ext/asmjit/asmjit/test/asmjit_test_perf.cpp +62 -0
  174. data/ext/asmjit/asmjit/test/asmjit_test_perf.h +61 -0
  175. data/ext/asmjit/asmjit/test/asmjit_test_perf_a64.cpp +699 -0
  176. data/ext/asmjit/asmjit/test/asmjit_test_perf_x86.cpp +5032 -0
  177. data/ext/asmjit/asmjit/test/asmjit_test_unit.cpp +172 -0
  178. data/ext/asmjit/asmjit/test/asmjit_test_x86_sections.cpp +172 -0
  179. data/ext/asmjit/asmjit/test/asmjitutils.h +38 -0
  180. data/ext/asmjit/asmjit/test/broken.cpp +312 -0
  181. data/ext/asmjit/asmjit/test/broken.h +148 -0
  182. data/ext/asmjit/asmjit/test/cmdline.h +61 -0
  183. data/ext/asmjit/asmjit/test/performancetimer.h +41 -0
  184. data/ext/asmjit/asmjit/tools/configure-makefiles.sh +13 -0
  185. data/ext/asmjit/asmjit/tools/configure-ninja.sh +13 -0
  186. data/ext/asmjit/asmjit/tools/configure-sanitizers.sh +13 -0
  187. data/ext/asmjit/asmjit/tools/configure-vs2019-x64.bat +2 -0
  188. data/ext/asmjit/asmjit/tools/configure-vs2019-x86.bat +2 -0
  189. data/ext/asmjit/asmjit/tools/configure-vs2022-x64.bat +2 -0
  190. data/ext/asmjit/asmjit/tools/configure-vs2022-x86.bat +2 -0
  191. data/ext/asmjit/asmjit/tools/configure-xcode.sh +8 -0
  192. data/ext/asmjit/asmjit/tools/enumgen.js +417 -0
  193. data/ext/asmjit/asmjit/tools/enumgen.sh +3 -0
  194. data/ext/asmjit/asmjit/tools/tablegen-arm.js +365 -0
  195. data/ext/asmjit/asmjit/tools/tablegen-arm.sh +3 -0
  196. data/ext/asmjit/asmjit/tools/tablegen-x86.js +2638 -0
  197. data/ext/asmjit/asmjit/tools/tablegen-x86.sh +3 -0
  198. data/ext/asmjit/asmjit/tools/tablegen.js +947 -0
  199. data/ext/asmjit/asmjit/tools/tablegen.sh +4 -0
  200. data/ext/asmjit/asmjit.cc +167 -30
  201. data/ext/asmjit/extconf.rb +9 -9
  202. data/lib/asmjit/version.rb +1 -1
  203. data/lib/asmjit.rb +14 -4
  204. metadata +198 -17
@@ -0,0 +1,242 @@
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
+ #ifndef ASMJIT_CORE_VIRTMEM_H_INCLUDED
7
+ #define ASMJIT_CORE_VIRTMEM_H_INCLUDED
8
+
9
+ #include "../core/api-config.h"
10
+ #ifndef ASMJIT_NO_JIT
11
+
12
+ #include "../core/globals.h"
13
+
14
+ ASMJIT_BEGIN_NAMESPACE
15
+
16
+ //! \addtogroup asmjit_virtual_memory
17
+ //! \{
18
+
19
+ //! Virtual memory management.
20
+ namespace VirtMem {
21
+
22
+ //! Flushes instruction cache in the given region.
23
+ //!
24
+ //! Only useful on non-x86 architectures, however, it's a good practice to call it on any platform to make your
25
+ //! code more portable.
26
+ ASMJIT_API void flushInstructionCache(void* p, size_t size) noexcept;
27
+
28
+ //! Virtual memory information.
29
+ struct Info {
30
+ //! Virtual memory page size.
31
+ uint32_t pageSize;
32
+ //! Virtual memory page granularity.
33
+ uint32_t pageGranularity;
34
+ };
35
+
36
+ //! Returns virtual memory information, see `VirtMem::Info` for more details.
37
+ ASMJIT_API Info info() noexcept;
38
+
39
+ //! Virtual memory access and mmap-specific flags.
40
+ enum class MemoryFlags : uint32_t {
41
+ //! No flags.
42
+ kNone = 0,
43
+
44
+ //! Memory is readable.
45
+ kAccessRead = 0x00000001u,
46
+
47
+ //! Memory is writable.
48
+ kAccessWrite = 0x00000002u,
49
+
50
+ //! Memory is executable.
51
+ kAccessExecute = 0x00000004u,
52
+
53
+ //! A combination of \ref MemoryFlags::kAccessRead and \ref MemoryFlags::kAccessWrite.
54
+ kAccessReadWrite = kAccessRead | kAccessWrite,
55
+
56
+ //! A combination of \ref MemoryFlags::kAccessRead, \ref MemoryFlags::kAccessWrite.
57
+ kAccessRW = kAccessRead | kAccessWrite,
58
+
59
+ //! A combination of \ref MemoryFlags::kAccessRead and \ref MemoryFlags::kAccessExecute.
60
+ kAccessRX = kAccessRead | kAccessExecute,
61
+
62
+ //! A combination of \ref MemoryFlags::kAccessRead, \ref MemoryFlags::kAccessWrite, and
63
+ //! \ref MemoryFlags::kAccessExecute.
64
+ kAccessRWX = kAccessRead | kAccessWrite | kAccessExecute,
65
+
66
+ //! Use a `MAP_JIT` flag available on Apple platforms (introduced by Mojave), which allows JIT code to be executed
67
+ //! in MAC bundles. This flag is not turned on by default, because when a process uses `fork()` the child process
68
+ //! has no access to the pages mapped with `MAP_JIT`, which could break code that doesn't expect this behavior.
69
+ //!
70
+ //! \note This flag can only be used with \ref VirtMem::alloc().
71
+ kMMapEnableMapJit = 0x00000010u,
72
+
73
+ //! Pass `PROT_MAX(PROT_READ)` to mmap() on platforms that support `PROT_MAX`.
74
+ //!
75
+ //! \note This flag can only be used with \ref VirtMem::alloc().
76
+ kMMapMaxAccessRead = 0x00000020u,
77
+ //! Pass `PROT_MAX(PROT_WRITE)` to mmap() on platforms that support `PROT_MAX`.
78
+ //!
79
+ //! \note This flag can only be used with \ref VirtMem::alloc().
80
+ kMMapMaxAccessWrite = 0x00000040u,
81
+ //! Pass `PROT_MAX(PROT_EXEC)` to mmap() on platforms that support `PROT_MAX`.
82
+ //!
83
+ //! \note This flag can only be used with \ref VirtMem::alloc().
84
+ kMMapMaxAccessExecute = 0x00000080u,
85
+
86
+ //! A combination of \ref MemoryFlags::kMMapMaxAccessRead and \ref MemoryFlags::kMMapMaxAccessWrite.
87
+ kMMapMaxAccessReadWrite = kMMapMaxAccessRead | kMMapMaxAccessWrite,
88
+
89
+ //! A combination of \ref MemoryFlags::kMMapMaxAccessRead and \ref MemoryFlags::kMMapMaxAccessWrite.
90
+ kMMapMaxAccessRW = kMMapMaxAccessRead | kMMapMaxAccessWrite,
91
+
92
+ //! A combination of \ref MemoryFlags::kMMapMaxAccessRead and \ref MemoryFlags::kMMapMaxAccessExecute.
93
+ kMMapMaxAccessRX = kMMapMaxAccessRead | kMMapMaxAccessExecute,
94
+
95
+ //! A combination of \ref MemoryFlags::kMMapMaxAccessRead, \ref MemoryFlags::kMMapMaxAccessWrite, \ref
96
+ //! MemoryFlags::kMMapMaxAccessExecute.
97
+ kMMapMaxAccessRWX = kMMapMaxAccessRead | kMMapMaxAccessWrite | kMMapMaxAccessExecute,
98
+
99
+ //! Not an access flag, only used by `allocDualMapping()` to override the default allocation strategy to always use
100
+ //! a 'tmp' directory instead of "/dev/shm" (on POSIX platforms). Please note that this flag will be ignored if the
101
+ //! operating system allows to allocate an executable memory by a different API than `open()` or `shm_open()`. For
102
+ //! example on Linux `memfd_create()` is preferred and on BSDs `shm_open(SHM_ANON, ...)` is used if SHM_ANON is
103
+ //! defined.
104
+ //!
105
+ //! \note This flag can only be used with \ref VirtMem::alloc().
106
+ kMappingPreferTmp = 0x80000000u
107
+ };
108
+ ASMJIT_DEFINE_ENUM_FLAGS(MemoryFlags)
109
+
110
+ //! Allocates virtual memory by either using `mmap()` (POSIX) or `VirtualAlloc()` (Windows).
111
+ //!
112
+ //! \note `size` should be aligned to page size, use \ref VirtMem::info() to obtain it. Invalid size will not be
113
+ //! corrected by the implementation and the allocation would not succeed in such case.
114
+ ASMJIT_API Error alloc(void** p, size_t size, MemoryFlags flags) noexcept;
115
+
116
+ //! Releases virtual memory previously allocated by \ref VirtMem::alloc().
117
+ //!
118
+ //! \note The size must be the same as used by \ref VirtMem::alloc(). If the size is not the same value the call
119
+ //! will fail on any POSIX system, but pass on Windows, because it's implemented differently.
120
+ ASMJIT_API Error release(void* p, size_t size) noexcept;
121
+
122
+ //! A cross-platform wrapper around `mprotect()` (POSIX) and `VirtualProtect()` (Windows).
123
+ ASMJIT_API Error protect(void* p, size_t size, MemoryFlags flags) noexcept;
124
+
125
+ //! Dual memory mapping used to map an anonymous memory into two memory regions where one region is read-only, but
126
+ //! executable, and the second region is read+write, but not executable. See \ref VirtMem::allocDualMapping() for
127
+ //! more details.
128
+ struct DualMapping {
129
+ //! Pointer to data with 'Read+Execute' access (this memory is not writable).
130
+ void* rx;
131
+ //! Pointer to data with 'Read+Write' access (this memory is not executable).
132
+ void* rw;
133
+ };
134
+
135
+ //! Allocates virtual memory and creates two views of it where the first view has no write access. This is an addition
136
+ //! to the API that should be used in cases in which the operating system either enforces W^X security policy or the
137
+ //! application wants to use this policy by default to improve security and prevent an accidental (or purposed)
138
+ //! self-modifying code.
139
+ //!
140
+ //! The memory returned in the `dm` are two independent mappings of the same shared memory region. You must use
141
+ //! \ref VirtMem::releaseDualMapping() to release it when it's no longer needed. Never use `VirtMem::release()` to
142
+ //! release the memory returned by `allocDualMapping()` as that would fail on Windows.
143
+ //!
144
+ //! \remarks Both pointers in `dm` would be set to `nullptr` if the function fails.
145
+ ASMJIT_API Error allocDualMapping(DualMapping* dm, size_t size, MemoryFlags flags) noexcept;
146
+
147
+ //! Releases virtual memory mapping previously allocated by \ref VirtMem::allocDualMapping().
148
+ //!
149
+ //! \remarks Both pointers in `dm` would be set to `nullptr` if the function succeeds.
150
+ ASMJIT_API Error releaseDualMapping(DualMapping* dm, size_t size) noexcept;
151
+
152
+ //! Hardened runtime flags.
153
+ enum class HardenedRuntimeFlags : uint32_t {
154
+ //! No flags.
155
+ kNone = 0,
156
+
157
+ //! Hardened runtime is enabled - it's not possible to have "Write & Execute" memory protection. The runtime
158
+ //! enforces W^X (either write or execute).
159
+ //!
160
+ //! \note If the runtime is hardened it means that an operating system specific protection is used. For example on
161
+ //! MacOS platform it's possible to allocate memory with MAP_JIT flag and then use `pthread_jit_write_protect_np()`
162
+ //! to temporarily swap access permissions for the current thread. Dual mapping is also a possibility on X86/X64
163
+ //! architecture.
164
+ kEnabled = 0x00000001u,
165
+
166
+ //! Read+Write+Execute can only be allocated with MAP_JIT flag (Apple specific).
167
+ kMapJit = 0x00000002u
168
+ };
169
+ ASMJIT_DEFINE_ENUM_FLAGS(HardenedRuntimeFlags)
170
+
171
+ //! Hardened runtime information.
172
+ struct HardenedRuntimeInfo {
173
+ //! Hardened runtime flags.
174
+ HardenedRuntimeFlags flags;
175
+ };
176
+
177
+ //! Returns runtime features provided by the OS.
178
+ ASMJIT_API HardenedRuntimeInfo hardenedRuntimeInfo() noexcept;
179
+
180
+ //! Values that can be used with `protectJitMemory()` function.
181
+ enum class ProtectJitAccess : uint32_t {
182
+ //! Protect JIT memory with Read+Write permissions.
183
+ kReadWrite = 0,
184
+ //! Protect JIT memory with Read+Execute permissions.
185
+ kReadExecute = 1
186
+ };
187
+
188
+ //! Protects access of memory mapped with MAP_JIT flag for the current thread.
189
+ //!
190
+ //! \note This feature is only available on Apple hardware (AArch64) at the moment and and uses a non-portable
191
+ //! `pthread_jit_write_protect_np()` call when available.
192
+ //!
193
+ //! This function must be called before and after a memory mapped with MAP_JIT flag is modified. Example:
194
+ //!
195
+ //! ```
196
+ //! void* codePtr = ...;
197
+ //! size_t codeSize = ...;
198
+ //!
199
+ //! VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadWrite);
200
+ //! memcpy(codePtr, source, codeSize);
201
+ //! VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadExecute);
202
+ //! VirtMem::flushInstructionCache(codePtr, codeSize);
203
+ //! ```
204
+ //!
205
+ //! See \ref ProtectJitReadWriteScope, which makes it simpler than the code above.
206
+ ASMJIT_API void protectJitMemory(ProtectJitAccess access) noexcept;
207
+
208
+ //! JIT protection scope that prepares the given memory block to be written to in the current thread.
209
+ //!
210
+ //! It calls `VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadWrite)` at construction time and
211
+ //! `VirtMem::protectJitMemory(VirtMem::ProtectJitAccess::kReadExecute)` combined with `flushInstructionCache()`
212
+ //! in destructor. The purpose of this class is to make writing to JIT memory easier.
213
+ class ProtectJitReadWriteScope {
214
+ public:
215
+ void* _rxPtr;
216
+ size_t _size;
217
+
218
+ //! Makes the given memory block RW protected.
219
+ ASMJIT_FORCE_INLINE ProtectJitReadWriteScope(void* rxPtr, size_t size) noexcept
220
+ : _rxPtr(rxPtr),
221
+ _size(size) {
222
+ protectJitMemory(ProtectJitAccess::kReadWrite);
223
+ }
224
+
225
+ // Not copyable.
226
+ ProtectJitReadWriteScope(const ProtectJitReadWriteScope& other) = delete;
227
+
228
+ //! Makes the memory block RX protected again and flushes instruction cache.
229
+ ASMJIT_FORCE_INLINE ~ProtectJitReadWriteScope() noexcept {
230
+ protectJitMemory(ProtectJitAccess::kReadExecute);
231
+ flushInstructionCache(_rxPtr, _size);
232
+ }
233
+ };
234
+
235
+ } // VirtMem
236
+
237
+ //! \}
238
+
239
+ ASMJIT_END_NAMESPACE
240
+
241
+ #endif
242
+ #endif // ASMJIT_CORE_VIRTMEM_H_INCLUDED
@@ -0,0 +1,353 @@
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
+ #include "../core/support.h"
8
+ #include "../core/zone.h"
9
+
10
+ ASMJIT_BEGIN_NAMESPACE
11
+
12
+ // Zone - Globals
13
+ // ==============
14
+
15
+ // Zero size block used by `Zone` that doesn't have any memory allocated. Should be allocated in read-only memory
16
+ // and should never be modified.
17
+ const Zone::Block Zone::_zeroBlock = { nullptr, nullptr, 0 };
18
+
19
+ // Zone - Init & Reset
20
+ // ===================
21
+
22
+ void Zone::_init(size_t blockSize, size_t blockAlignment, const Support::Temporary* temporary) noexcept {
23
+ ASMJIT_ASSERT(blockSize >= kMinBlockSize);
24
+ ASMJIT_ASSERT(blockSize <= kMaxBlockSize);
25
+ ASMJIT_ASSERT(blockAlignment <= 64);
26
+
27
+ // Just to make the compiler happy...
28
+ constexpr size_t kBlockSizeMask = (Support::allOnes<size_t>() >> 4);
29
+ constexpr size_t kBlockAlignmentShiftMask = 0x7u;
30
+
31
+ _assignZeroBlock();
32
+ _blockSize = blockSize & kBlockSizeMask;
33
+ _isTemporary = temporary != nullptr;
34
+ _blockAlignmentShift = Support::ctz(blockAlignment) & kBlockAlignmentShiftMask;
35
+
36
+ // Setup the first [temporary] block, if necessary.
37
+ if (temporary) {
38
+ Block* block = temporary->data<Block>();
39
+ block->prev = nullptr;
40
+ block->next = nullptr;
41
+
42
+ ASMJIT_ASSERT(temporary->size() >= kBlockSize);
43
+ block->size = temporary->size() - kBlockSize;
44
+
45
+ _assignBlock(block);
46
+ }
47
+ }
48
+
49
+ void Zone::reset(ResetPolicy resetPolicy) noexcept {
50
+ Block* cur = _block;
51
+
52
+ // Can't be altered.
53
+ if (cur == &_zeroBlock)
54
+ return;
55
+
56
+ if (resetPolicy == ResetPolicy::kHard) {
57
+ Block* initial = const_cast<Zone::Block*>(&_zeroBlock);
58
+ _ptr = initial->data();
59
+ _end = initial->data();
60
+ _block = initial;
61
+
62
+ // Since cur can be in the middle of the double-linked list, we have to traverse both directions (`prev` and
63
+ // `next`) separately to visit all.
64
+ Block* next = cur->next;
65
+ do {
66
+ Block* prev = cur->prev;
67
+
68
+ // If this is the first block and this ZoneTmp is temporary then the first block is statically allocated.
69
+ // We cannot free it and it makes sense to keep it even when this is hard reset.
70
+ if (prev == nullptr && _isTemporary) {
71
+ cur->prev = nullptr;
72
+ cur->next = nullptr;
73
+ _assignBlock(cur);
74
+ break;
75
+ }
76
+
77
+ ::free(cur);
78
+ cur = prev;
79
+ } while (cur);
80
+
81
+ cur = next;
82
+ while (cur) {
83
+ next = cur->next;
84
+ ::free(cur);
85
+ cur = next;
86
+ }
87
+ }
88
+ else {
89
+ while (cur->prev)
90
+ cur = cur->prev;
91
+ _assignBlock(cur);
92
+ }
93
+ }
94
+
95
+ // Zone - Alloc
96
+ // ============
97
+
98
+ void* Zone::_alloc(size_t size, size_t alignment) noexcept {
99
+ Block* curBlock = _block;
100
+ Block* next = curBlock->next;
101
+
102
+ size_t rawBlockAlignment = blockAlignment();
103
+ size_t minimumAlignment = Support::max<size_t>(alignment, rawBlockAlignment);
104
+
105
+ // If the `Zone` has been cleared the current block doesn't have to be the last one. Check if there is a block
106
+ // that can be used instead of allocating a new one. If there is a `next` block it's completely unused, we don't
107
+ // have to check for remaining bytes in that case.
108
+ if (next) {
109
+ uint8_t* ptr = Support::alignUp(next->data(), minimumAlignment);
110
+ uint8_t* end = Support::alignDown(next->data() + next->size, rawBlockAlignment);
111
+
112
+ if (size <= (size_t)(end - ptr)) {
113
+ _block = next;
114
+ _ptr = ptr + size;
115
+ _end = Support::alignDown(next->data() + next->size, rawBlockAlignment);
116
+ return static_cast<void*>(ptr);
117
+ }
118
+ }
119
+
120
+ size_t blockAlignmentOverhead = alignment - Support::min<size_t>(alignment, Globals::kAllocAlignment);
121
+ size_t newSize = Support::max(blockSize(), size);
122
+
123
+ // Prevent arithmetic overflow.
124
+ if (ASMJIT_UNLIKELY(newSize > SIZE_MAX - kBlockSize - blockAlignmentOverhead))
125
+ return nullptr;
126
+
127
+ // Allocate new block - we add alignment overhead to `newSize`, which becomes the new block size, and we also add
128
+ // `kBlockOverhead` to the allocator as it includes members of `Zone::Block` structure.
129
+ newSize += blockAlignmentOverhead;
130
+ Block* newBlock = static_cast<Block*>(::malloc(newSize + kBlockSize));
131
+
132
+ if (ASMJIT_UNLIKELY(!newBlock))
133
+ return nullptr;
134
+
135
+ // Align the pointer to `minimumAlignment` and adjust the size of this block accordingly. It's the same as using
136
+ // `minimumAlignment - Support::alignUpDiff()`, just written differently.
137
+ {
138
+ newBlock->prev = nullptr;
139
+ newBlock->next = nullptr;
140
+ newBlock->size = newSize;
141
+
142
+ if (curBlock != &_zeroBlock) {
143
+ newBlock->prev = curBlock;
144
+ curBlock->next = newBlock;
145
+
146
+ // Does only happen if there is a next block, but the requested memory can't fit into it. In this case a new
147
+ // buffer is allocated and inserted between the current block and the next one.
148
+ if (next) {
149
+ newBlock->next = next;
150
+ next->prev = newBlock;
151
+ }
152
+ }
153
+
154
+ uint8_t* ptr = Support::alignUp(newBlock->data(), minimumAlignment);
155
+ uint8_t* end = Support::alignDown(newBlock->data() + newSize, rawBlockAlignment);
156
+
157
+ _ptr = ptr + size;
158
+ _end = end;
159
+ _block = newBlock;
160
+
161
+ ASMJIT_ASSERT(_ptr <= _end);
162
+ return static_cast<void*>(ptr);
163
+ }
164
+ }
165
+
166
+ void* Zone::allocZeroed(size_t size, size_t alignment) noexcept {
167
+ void* p = alloc(size, alignment);
168
+ if (ASMJIT_UNLIKELY(!p))
169
+ return p;
170
+ return memset(p, 0, size);
171
+ }
172
+
173
+ void* Zone::dup(const void* data, size_t size, bool nullTerminate) noexcept {
174
+ if (ASMJIT_UNLIKELY(!data || !size))
175
+ return nullptr;
176
+
177
+ ASMJIT_ASSERT(size != SIZE_MAX);
178
+ uint8_t* m = allocT<uint8_t>(size + nullTerminate);
179
+ if (ASMJIT_UNLIKELY(!m)) return nullptr;
180
+
181
+ memcpy(m, data, size);
182
+ if (nullTerminate) m[size] = '\0';
183
+
184
+ return static_cast<void*>(m);
185
+ }
186
+
187
+ char* Zone::sformat(const char* fmt, ...) noexcept {
188
+ if (ASMJIT_UNLIKELY(!fmt))
189
+ return nullptr;
190
+
191
+ char buf[512];
192
+ size_t size;
193
+ va_list ap;
194
+
195
+ va_start(ap, fmt);
196
+ size = unsigned(vsnprintf(buf, ASMJIT_ARRAY_SIZE(buf) - 1, fmt, ap));
197
+ va_end(ap);
198
+
199
+ buf[size++] = 0;
200
+ return static_cast<char*>(dup(buf, size));
201
+ }
202
+
203
+ // ZoneAllocator - Utilities
204
+ // =========================
205
+
206
+ #if defined(ASMJIT_BUILD_DEBUG)
207
+ static bool ZoneAllocator_hasDynamicBlock(ZoneAllocator* self, ZoneAllocator::DynamicBlock* block) noexcept {
208
+ ZoneAllocator::DynamicBlock* cur = self->_dynamicBlocks;
209
+ while (cur) {
210
+ if (cur == block)
211
+ return true;
212
+ cur = cur->next;
213
+ }
214
+ return false;
215
+ }
216
+ #endif
217
+
218
+ // ZoneAllocator - Init & Reset
219
+ // ============================
220
+
221
+ void ZoneAllocator::reset(Zone* zone) noexcept {
222
+ // Free dynamic blocks.
223
+ DynamicBlock* block = _dynamicBlocks;
224
+ while (block) {
225
+ DynamicBlock* next = block->next;
226
+ ::free(block);
227
+ block = next;
228
+ }
229
+
230
+ // Zero the entire class and initialize to the given `zone`.
231
+ memset(this, 0, sizeof(*this));
232
+ _zone = zone;
233
+ }
234
+
235
+ // asmjit::ZoneAllocator - Alloc & Release
236
+ // =======================================
237
+
238
+ void* ZoneAllocator::_alloc(size_t size, size_t& allocatedSize) noexcept {
239
+ ASMJIT_ASSERT(isInitialized());
240
+
241
+ // Use the memory pool only if the requested block has a reasonable size.
242
+ uint32_t slot;
243
+ if (_getSlotIndex(size, slot, allocatedSize)) {
244
+ // Slot reuse.
245
+ uint8_t* p = reinterpret_cast<uint8_t*>(_slots[slot]);
246
+ size = allocatedSize;
247
+
248
+ if (p) {
249
+ _slots[slot] = reinterpret_cast<Slot*>(p)->next;
250
+ return p;
251
+ }
252
+
253
+ _zone->align(kBlockAlignment);
254
+ p = _zone->ptr();
255
+ size_t remain = (size_t)(_zone->end() - p);
256
+
257
+ if (ASMJIT_LIKELY(remain >= size)) {
258
+ _zone->setPtr(p + size);
259
+ return p;
260
+ }
261
+ else {
262
+ // Distribute the remaining memory to suitable slots, if possible.
263
+ if (remain >= kLoGranularity) {
264
+ do {
265
+ size_t distSize = Support::min<size_t>(remain, kLoMaxSize);
266
+ uint32_t distSlot = uint32_t((distSize - kLoGranularity) / kLoGranularity);
267
+ ASMJIT_ASSERT(distSlot < kLoCount);
268
+
269
+ reinterpret_cast<Slot*>(p)->next = _slots[distSlot];
270
+ _slots[distSlot] = reinterpret_cast<Slot*>(p);
271
+
272
+ p += distSize;
273
+ remain -= distSize;
274
+ } while (remain >= kLoGranularity);
275
+ _zone->setPtr(p);
276
+ }
277
+
278
+ p = static_cast<uint8_t*>(_zone->_alloc(size, kBlockAlignment));
279
+ if (ASMJIT_UNLIKELY(!p)) {
280
+ allocatedSize = 0;
281
+ return nullptr;
282
+ }
283
+
284
+ return p;
285
+ }
286
+ }
287
+ else {
288
+ // Allocate a dynamic block.
289
+ size_t kBlockOverhead = sizeof(DynamicBlock) + sizeof(DynamicBlock*) + kBlockAlignment;
290
+
291
+ // Handle a possible overflow.
292
+ if (ASMJIT_UNLIKELY(kBlockOverhead >= SIZE_MAX - size))
293
+ return nullptr;
294
+
295
+ void* p = ::malloc(size + kBlockOverhead);
296
+ if (ASMJIT_UNLIKELY(!p)) {
297
+ allocatedSize = 0;
298
+ return nullptr;
299
+ }
300
+
301
+ // Link as first in `_dynamicBlocks` double-linked list.
302
+ DynamicBlock* block = static_cast<DynamicBlock*>(p);
303
+ DynamicBlock* next = _dynamicBlocks;
304
+
305
+ if (next)
306
+ next->prev = block;
307
+
308
+ block->prev = nullptr;
309
+ block->next = next;
310
+ _dynamicBlocks = block;
311
+
312
+ // Align the pointer to the guaranteed alignment and store `DynamicBlock`
313
+ // at the beginning of the memory block, so `_releaseDynamic()` can find it.
314
+ p = Support::alignUp(static_cast<uint8_t*>(p) + sizeof(DynamicBlock) + sizeof(DynamicBlock*), kBlockAlignment);
315
+ reinterpret_cast<DynamicBlock**>(p)[-1] = block;
316
+
317
+ allocatedSize = size;
318
+ return p;
319
+ }
320
+ }
321
+
322
+ void* ZoneAllocator::_allocZeroed(size_t size, size_t& allocatedSize) noexcept {
323
+ ASMJIT_ASSERT(isInitialized());
324
+
325
+ void* p = _alloc(size, allocatedSize);
326
+ if (ASMJIT_UNLIKELY(!p)) return p;
327
+ return memset(p, 0, allocatedSize);
328
+ }
329
+
330
+ void ZoneAllocator::_releaseDynamic(void* p, size_t size) noexcept {
331
+ DebugUtils::unused(size);
332
+ ASMJIT_ASSERT(isInitialized());
333
+
334
+ // Pointer to `DynamicBlock` is stored at [-1].
335
+ DynamicBlock* block = reinterpret_cast<DynamicBlock**>(p)[-1];
336
+ ASMJIT_ASSERT(ZoneAllocator_hasDynamicBlock(this, block));
337
+
338
+ // Unlink and free.
339
+ DynamicBlock* prev = block->prev;
340
+ DynamicBlock* next = block->next;
341
+
342
+ if (prev)
343
+ prev->next = next;
344
+ else
345
+ _dynamicBlocks = next;
346
+
347
+ if (next)
348
+ next->prev = prev;
349
+
350
+ ::free(block);
351
+ }
352
+
353
+ ASMJIT_END_NAMESPACE