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,1149 @@
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/assembler.h"
8
+ #include "../core/codewriter_p.h"
9
+ #include "../core/logger.h"
10
+ #include "../core/support.h"
11
+
12
+ #include <algorithm>
13
+ #include <tuple>
14
+
15
+ ASMJIT_BEGIN_NAMESPACE
16
+
17
+ // Globals
18
+ // =======
19
+
20
+ static const char CodeHolder_addrTabName[] = ".addrtab";
21
+
22
+ //! Encode MOD byte.
23
+ static inline uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) noexcept {
24
+ return (m << 6) | (o << 3) | rm;
25
+ }
26
+
27
+ // LabelLinkIterator
28
+ // =================
29
+
30
+ class LabelLinkIterator {
31
+ public:
32
+ inline LabelLinkIterator(LabelEntry* le) noexcept { reset(le); }
33
+
34
+ inline explicit operator bool() const noexcept { return isValid(); }
35
+ inline bool isValid() const noexcept { return _link != nullptr; }
36
+
37
+ inline LabelLink* link() const noexcept { return _link; }
38
+ inline LabelLink* operator->() const noexcept { return _link; }
39
+
40
+ inline void reset(LabelEntry* le) noexcept {
41
+ _pPrev = &le->_links;
42
+ _link = *_pPrev;
43
+ }
44
+
45
+ inline void next() noexcept {
46
+ _pPrev = &_link->next;
47
+ _link = *_pPrev;
48
+ }
49
+
50
+ inline void resolveAndNext(CodeHolder* code) noexcept {
51
+ LabelLink* linkToDelete = _link;
52
+
53
+ _link = _link->next;
54
+ *_pPrev = _link;
55
+
56
+ code->_unresolvedLinkCount--;
57
+ code->_allocator.release(linkToDelete, sizeof(LabelLink));
58
+ }
59
+
60
+ LabelLink** _pPrev;
61
+ LabelLink* _link;
62
+ };
63
+
64
+ // CodeHolder - Utilities
65
+ // ======================
66
+
67
+ static void CodeHolder_resetInternal(CodeHolder* self, ResetPolicy resetPolicy) noexcept {
68
+ uint32_t i;
69
+ const ZoneVector<BaseEmitter*>& emitters = self->emitters();
70
+
71
+ i = emitters.size();
72
+ while (i)
73
+ self->detach(emitters[--i]);
74
+
75
+ // Reset everything into its construction state.
76
+ self->_environment.reset();
77
+ self->_baseAddress = Globals::kNoBaseAddress;
78
+ self->_logger = nullptr;
79
+ self->_errorHandler = nullptr;
80
+
81
+ // Reset all sections.
82
+ uint32_t numSections = self->_sections.size();
83
+ for (i = 0; i < numSections; i++) {
84
+ Section* section = self->_sections[i];
85
+ if (section->_buffer.data() && !section->_buffer.isExternal())
86
+ ::free(section->_buffer._data);
87
+ section->_buffer._data = nullptr;
88
+ section->_buffer._capacity = 0;
89
+ }
90
+
91
+ // Reset zone allocator and all containers using it.
92
+ ZoneAllocator* allocator = self->allocator();
93
+
94
+ self->_emitters.reset();
95
+ self->_namedLabels.reset();
96
+ self->_relocations.reset();
97
+ self->_labelEntries.reset();
98
+ self->_sections.reset();
99
+ self->_sectionsByOrder.reset();
100
+
101
+ self->_unresolvedLinkCount = 0;
102
+ self->_addressTableSection = nullptr;
103
+ self->_addressTableEntries.reset();
104
+
105
+ allocator->reset(&self->_zone);
106
+ self->_zone.reset(resetPolicy);
107
+ }
108
+
109
+ static void CodeHolder_onSettingsUpdated(CodeHolder* self) noexcept {
110
+ // Notify all attached emitters about a settings update.
111
+ for (BaseEmitter* emitter : self->emitters()) {
112
+ emitter->onSettingsUpdated();
113
+ }
114
+ }
115
+
116
+ // CodeHolder - Construction & Destruction
117
+ // =======================================
118
+
119
+ CodeHolder::CodeHolder(const Support::Temporary* temporary) noexcept
120
+ : _environment(),
121
+ _baseAddress(Globals::kNoBaseAddress),
122
+ _logger(nullptr),
123
+ _errorHandler(nullptr),
124
+ _zone(16384 - Zone::kBlockOverhead, 1, temporary),
125
+ _allocator(&_zone),
126
+ _unresolvedLinkCount(0),
127
+ _addressTableSection(nullptr) {}
128
+
129
+ CodeHolder::~CodeHolder() noexcept {
130
+ CodeHolder_resetInternal(this, ResetPolicy::kHard);
131
+ }
132
+
133
+ // CodeHolder - Init & Reset
134
+ // =========================
135
+
136
+ inline void CodeHolder_setSectionDefaultName(
137
+ Section* section,
138
+ char c0 = 0, char c1 = 0, char c2 = 0, char c3 = 0,
139
+ char c4 = 0, char c5 = 0, char c6 = 0, char c7 = 0) noexcept {
140
+
141
+ section->_name.u32[0] = Support::bytepack32_4x8(uint8_t(c0), uint8_t(c1), uint8_t(c2), uint8_t(c3));
142
+ section->_name.u32[1] = Support::bytepack32_4x8(uint8_t(c4), uint8_t(c5), uint8_t(c6), uint8_t(c7));
143
+ }
144
+
145
+ Error CodeHolder::init(const Environment& environment, uint64_t baseAddress) noexcept {
146
+ // Cannot reinitialize if it's locked or there is one or more emitter attached.
147
+ if (isInitialized())
148
+ return DebugUtils::errored(kErrorAlreadyInitialized);
149
+
150
+ // If we are just initializing there should be no emitters attached.
151
+ ASMJIT_ASSERT(_emitters.empty());
152
+
153
+ // Create a default section and insert it to the `_sections` array.
154
+ Error err = _sections.willGrow(&_allocator) |
155
+ _sectionsByOrder.willGrow(&_allocator);
156
+ if (err == kErrorOk) {
157
+ Section* section = _allocator.allocZeroedT<Section>();
158
+ if (ASMJIT_LIKELY(section)) {
159
+ section->_flags = SectionFlags::kExecutable | SectionFlags::kReadOnly;
160
+ CodeHolder_setSectionDefaultName(section, '.', 't', 'e', 'x', 't');
161
+ _sections.appendUnsafe(section);
162
+ _sectionsByOrder.appendUnsafe(section);
163
+ }
164
+ else {
165
+ err = DebugUtils::errored(kErrorOutOfMemory);
166
+ }
167
+ }
168
+
169
+ if (ASMJIT_UNLIKELY(err)) {
170
+ _zone.reset();
171
+ return err;
172
+ }
173
+ else {
174
+ _environment = environment;
175
+ _baseAddress = baseAddress;
176
+ return kErrorOk;
177
+ }
178
+ }
179
+
180
+ void CodeHolder::reset(ResetPolicy resetPolicy) noexcept {
181
+ CodeHolder_resetInternal(this, resetPolicy);
182
+ }
183
+
184
+ // CodeHolder - Attach / Detach
185
+ // ============================
186
+
187
+ Error CodeHolder::attach(BaseEmitter* emitter) noexcept {
188
+ // Catch a possible misuse of the API.
189
+ if (ASMJIT_UNLIKELY(!emitter))
190
+ return DebugUtils::errored(kErrorInvalidArgument);
191
+
192
+ // Invalid emitter, this should not be possible.
193
+ EmitterType type = emitter->emitterType();
194
+ if (ASMJIT_UNLIKELY(type == EmitterType::kNone || uint32_t(type) > uint32_t(EmitterType::kMaxValue)))
195
+ return DebugUtils::errored(kErrorInvalidState);
196
+
197
+ uint64_t archMask = emitter->_archMask;
198
+ if (ASMJIT_UNLIKELY(!(archMask & (uint64_t(1) << uint32_t(arch())))))
199
+ return DebugUtils::errored(kErrorInvalidArch);
200
+
201
+ // This is suspicious, but don't fail if `emitter` is already attached
202
+ // to this code holder. This is not error, but it's not recommended.
203
+ if (emitter->_code != nullptr) {
204
+ if (emitter->_code == this)
205
+ return kErrorOk;
206
+ return DebugUtils::errored(kErrorInvalidState);
207
+ }
208
+
209
+ // Reserve the space now as we cannot fail after `onAttach()` succeeded.
210
+ ASMJIT_PROPAGATE(_emitters.willGrow(&_allocator, 1));
211
+ ASMJIT_PROPAGATE(emitter->onAttach(this));
212
+
213
+ // Connect CodeHolder <-> BaseEmitter.
214
+ ASMJIT_ASSERT(emitter->_code == this);
215
+ _emitters.appendUnsafe(emitter);
216
+
217
+ return kErrorOk;
218
+ }
219
+
220
+ Error CodeHolder::detach(BaseEmitter* emitter) noexcept {
221
+ if (ASMJIT_UNLIKELY(!emitter))
222
+ return DebugUtils::errored(kErrorInvalidArgument);
223
+
224
+ if (ASMJIT_UNLIKELY(emitter->_code != this))
225
+ return DebugUtils::errored(kErrorInvalidState);
226
+
227
+ // NOTE: We always detach if we were asked to, if error happens during
228
+ // `emitter->onDetach()` we just propagate it, but the BaseEmitter will
229
+ // be detached.
230
+ Error err = kErrorOk;
231
+ if (!emitter->isDestroyed())
232
+ err = emitter->onDetach(this);
233
+
234
+ // Disconnect CodeHolder <-> BaseEmitter.
235
+ uint32_t index = _emitters.indexOf(emitter);
236
+ ASMJIT_ASSERT(index != Globals::kNotFound);
237
+
238
+ _emitters.removeAt(index);
239
+ emitter->_code = nullptr;
240
+
241
+ return err;
242
+ }
243
+
244
+ // CodeHolder - Logging
245
+ // ====================
246
+
247
+ void CodeHolder::setLogger(Logger* logger) noexcept {
248
+ #ifndef ASMJIT_NO_LOGGING
249
+ _logger = logger;
250
+ CodeHolder_onSettingsUpdated(this);
251
+ #else
252
+ DebugUtils::unused(logger);
253
+ #endif
254
+ }
255
+
256
+ // CodeHolder - Error Handling
257
+ // ===========================
258
+
259
+ void CodeHolder::setErrorHandler(ErrorHandler* errorHandler) noexcept {
260
+ _errorHandler = errorHandler;
261
+ CodeHolder_onSettingsUpdated(this);
262
+ }
263
+
264
+ // CodeHolder - Code Buffer
265
+ // ========================
266
+
267
+ static Error CodeHolder_reserveInternal(CodeHolder* self, CodeBuffer* cb, size_t n) noexcept {
268
+ uint8_t* oldData = cb->_data;
269
+ uint8_t* newData;
270
+
271
+ if (oldData && !cb->isExternal())
272
+ newData = static_cast<uint8_t*>(::realloc(oldData, n));
273
+ else
274
+ newData = static_cast<uint8_t*>(::malloc(n));
275
+
276
+ if (ASMJIT_UNLIKELY(!newData))
277
+ return DebugUtils::errored(kErrorOutOfMemory);
278
+
279
+ cb->_data = newData;
280
+ cb->_capacity = n;
281
+
282
+ // Update pointers used by assemblers, if attached.
283
+ for (BaseEmitter* emitter : self->emitters()) {
284
+ if (emitter->isAssembler()) {
285
+ BaseAssembler* a = static_cast<BaseAssembler*>(emitter);
286
+ if (&a->_section->_buffer == cb) {
287
+ size_t offset = a->offset();
288
+
289
+ a->_bufferData = newData;
290
+ a->_bufferEnd = newData + n;
291
+ a->_bufferPtr = newData + offset;
292
+ }
293
+ }
294
+ }
295
+
296
+ return kErrorOk;
297
+ }
298
+
299
+ Error CodeHolder::growBuffer(CodeBuffer* cb, size_t n) noexcept {
300
+ // The size of the section must be valid.
301
+ size_t size = cb->size();
302
+ if (ASMJIT_UNLIKELY(n > std::numeric_limits<uintptr_t>::max() - size))
303
+ return DebugUtils::errored(kErrorOutOfMemory);
304
+
305
+ // We can now check if growing the buffer is really necessary. It's unlikely
306
+ // that this function is called while there is still room for `n` bytes.
307
+ size_t capacity = cb->capacity();
308
+ size_t required = cb->size() + n;
309
+ if (ASMJIT_UNLIKELY(required <= capacity))
310
+ return kErrorOk;
311
+
312
+ if (cb->isFixed())
313
+ return DebugUtils::errored(kErrorTooLarge);
314
+
315
+ size_t kInitialCapacity = 8096;
316
+ if (capacity < kInitialCapacity)
317
+ capacity = kInitialCapacity;
318
+ else
319
+ capacity += Globals::kAllocOverhead;
320
+
321
+ do {
322
+ size_t old = capacity;
323
+ if (capacity < Globals::kGrowThreshold)
324
+ capacity *= 2;
325
+ else
326
+ capacity += Globals::kGrowThreshold;
327
+
328
+ // Overflow.
329
+ if (ASMJIT_UNLIKELY(old > capacity))
330
+ return DebugUtils::errored(kErrorOutOfMemory);
331
+ } while (capacity - Globals::kAllocOverhead < required);
332
+
333
+ return CodeHolder_reserveInternal(this, cb, capacity - Globals::kAllocOverhead);
334
+ }
335
+
336
+ Error CodeHolder::reserveBuffer(CodeBuffer* cb, size_t n) noexcept {
337
+ size_t capacity = cb->capacity();
338
+
339
+ if (n <= capacity)
340
+ return kErrorOk;
341
+
342
+ if (cb->isFixed())
343
+ return DebugUtils::errored(kErrorTooLarge);
344
+
345
+ return CodeHolder_reserveInternal(this, cb, n);
346
+ }
347
+
348
+ // CodeHolder - Sections
349
+ // =====================
350
+
351
+ Error CodeHolder::newSection(Section** sectionOut, const char* name, size_t nameSize, SectionFlags flags, uint32_t alignment, int32_t order) noexcept {
352
+ *sectionOut = nullptr;
353
+
354
+ if (nameSize == SIZE_MAX)
355
+ nameSize = strlen(name);
356
+
357
+ if (alignment == 0)
358
+ alignment = 1;
359
+
360
+ if (ASMJIT_UNLIKELY(!Support::isPowerOf2(alignment)))
361
+ return DebugUtils::errored(kErrorInvalidArgument);
362
+
363
+ if (ASMJIT_UNLIKELY(nameSize > Globals::kMaxSectionNameSize))
364
+ return DebugUtils::errored(kErrorInvalidSectionName);
365
+
366
+ uint32_t sectionId = _sections.size();
367
+ if (ASMJIT_UNLIKELY(sectionId == Globals::kInvalidId))
368
+ return DebugUtils::errored(kErrorTooManySections);
369
+
370
+ ASMJIT_PROPAGATE(_sections.willGrow(&_allocator));
371
+ ASMJIT_PROPAGATE(_sectionsByOrder.willGrow(&_allocator));
372
+
373
+ Section* section = _allocator.allocZeroedT<Section>();
374
+ if (ASMJIT_UNLIKELY(!section))
375
+ return DebugUtils::errored(kErrorOutOfMemory);
376
+
377
+ section->_id = sectionId;
378
+ section->_flags = flags;
379
+ section->_alignment = alignment;
380
+ section->_order = order;
381
+ memcpy(section->_name.str, name, nameSize);
382
+
383
+ Section** insertPosition = std::lower_bound(_sectionsByOrder.begin(), _sectionsByOrder.end(), section, [](const Section* a, const Section* b) {
384
+ return std::make_tuple(a->order(), a->id()) < std::make_tuple(b->order(), b->id());
385
+ });
386
+
387
+ _sections.appendUnsafe(section);
388
+ _sectionsByOrder.insertUnsafe((size_t)(insertPosition - _sectionsByOrder.data()), section);
389
+
390
+ *sectionOut = section;
391
+ return kErrorOk;
392
+ }
393
+
394
+ Section* CodeHolder::sectionByName(const char* name, size_t nameSize) const noexcept {
395
+ if (nameSize == SIZE_MAX)
396
+ nameSize = strlen(name);
397
+
398
+ // This could be also put in a hash-table similarly like we do with labels,
399
+ // however it's questionable as the number of sections should be pretty low
400
+ // in general. Create an issue if this becomes a problem.
401
+ if (nameSize <= Globals::kMaxSectionNameSize) {
402
+ for (Section* section : _sections)
403
+ if (memcmp(section->_name.str, name, nameSize) == 0 && section->_name.str[nameSize] == '\0')
404
+ return section;
405
+ }
406
+
407
+ return nullptr;
408
+ }
409
+
410
+ Section* CodeHolder::ensureAddressTableSection() noexcept {
411
+ if (_addressTableSection)
412
+ return _addressTableSection;
413
+
414
+ newSection(&_addressTableSection,
415
+ CodeHolder_addrTabName,
416
+ sizeof(CodeHolder_addrTabName) - 1,
417
+ SectionFlags::kNone,
418
+ _environment.registerSize(),
419
+ std::numeric_limits<int32_t>::max());
420
+ return _addressTableSection;
421
+ }
422
+
423
+ Error CodeHolder::addAddressToAddressTable(uint64_t address) noexcept {
424
+ AddressTableEntry* entry = _addressTableEntries.get(address);
425
+ if (entry)
426
+ return kErrorOk;
427
+
428
+ Section* section = ensureAddressTableSection();
429
+ if (ASMJIT_UNLIKELY(!section))
430
+ return DebugUtils::errored(kErrorOutOfMemory);
431
+
432
+ entry = _zone.newT<AddressTableEntry>(address);
433
+ if (ASMJIT_UNLIKELY(!entry))
434
+ return DebugUtils::errored(kErrorOutOfMemory);
435
+
436
+ _addressTableEntries.insert(entry);
437
+ section->_virtualSize += _environment.registerSize();
438
+
439
+ return kErrorOk;
440
+ }
441
+
442
+ // CodeHolder - Labels & Symbols
443
+ // =============================
444
+
445
+ //! Only used to lookup a label from `_namedLabels`.
446
+ class LabelByName {
447
+ public:
448
+ inline LabelByName(const char* key, size_t keySize, uint32_t hashCode, uint32_t parentId) noexcept
449
+ : _key(key),
450
+ _keySize(uint32_t(keySize)),
451
+ _hashCode(hashCode),
452
+ _parentId(parentId) {}
453
+
454
+ inline uint32_t hashCode() const noexcept { return _hashCode; }
455
+
456
+ inline bool matches(const LabelEntry* entry) const noexcept {
457
+ return entry->nameSize() == _keySize &&
458
+ entry->parentId() == _parentId &&
459
+ ::memcmp(entry->name(), _key, _keySize) == 0;
460
+ }
461
+
462
+ const char* _key;
463
+ uint32_t _keySize;
464
+ uint32_t _hashCode;
465
+ uint32_t _parentId;
466
+ };
467
+
468
+ // Returns a hash of `name` and fixes `nameSize` if it's `SIZE_MAX`.
469
+ static uint32_t CodeHolder_hashNameAndGetSize(const char* name, size_t& nameSize) noexcept {
470
+ uint32_t hashCode = 0;
471
+ if (nameSize == SIZE_MAX) {
472
+ size_t i = 0;
473
+ for (;;) {
474
+ uint8_t c = uint8_t(name[i]);
475
+ if (!c) break;
476
+ hashCode = Support::hashRound(hashCode, c);
477
+ i++;
478
+ }
479
+ nameSize = i;
480
+ }
481
+ else {
482
+ for (size_t i = 0; i < nameSize; i++) {
483
+ uint8_t c = uint8_t(name[i]);
484
+ if (ASMJIT_UNLIKELY(!c)) return DebugUtils::errored(kErrorInvalidLabelName);
485
+ hashCode = Support::hashRound(hashCode, c);
486
+ }
487
+ }
488
+ return hashCode;
489
+ }
490
+
491
+ LabelLink* CodeHolder::newLabelLink(LabelEntry* le, uint32_t sectionId, size_t offset, intptr_t rel, const OffsetFormat& format) noexcept {
492
+ LabelLink* link = _allocator.allocT<LabelLink>();
493
+ if (ASMJIT_UNLIKELY(!link)) return nullptr;
494
+
495
+ link->next = le->_links;
496
+ le->_links = link;
497
+
498
+ link->sectionId = sectionId;
499
+ link->relocId = Globals::kInvalidId;
500
+ link->offset = offset;
501
+ link->rel = rel;
502
+ link->format = format;
503
+
504
+ _unresolvedLinkCount++;
505
+ return link;
506
+ }
507
+
508
+ Error CodeHolder::newLabelEntry(LabelEntry** entryOut) noexcept {
509
+ *entryOut = nullptr;
510
+
511
+ uint32_t labelId = _labelEntries.size();
512
+ if (ASMJIT_UNLIKELY(labelId == Globals::kInvalidId))
513
+ return DebugUtils::errored(kErrorTooManyLabels);
514
+
515
+ ASMJIT_PROPAGATE(_labelEntries.willGrow(&_allocator));
516
+ LabelEntry* le = _allocator.allocZeroedT<LabelEntry>();
517
+
518
+ if (ASMJIT_UNLIKELY(!le))
519
+ return DebugUtils::errored(kErrorOutOfMemory);
520
+
521
+ le->_setId(labelId);
522
+ le->_parentId = Globals::kInvalidId;
523
+ le->_offset = 0;
524
+ _labelEntries.appendUnsafe(le);
525
+
526
+ *entryOut = le;
527
+ return kErrorOk;
528
+ }
529
+
530
+ Error CodeHolder::newNamedLabelEntry(LabelEntry** entryOut, const char* name, size_t nameSize, LabelType type, uint32_t parentId) noexcept {
531
+ *entryOut = nullptr;
532
+ uint32_t hashCode = CodeHolder_hashNameAndGetSize(name, nameSize);
533
+
534
+ if (ASMJIT_UNLIKELY(nameSize == 0)) {
535
+ if (type == LabelType::kAnonymous)
536
+ return newLabelEntry(entryOut);
537
+ else
538
+ return DebugUtils::errored(kErrorInvalidLabelName);
539
+ }
540
+
541
+ if (ASMJIT_UNLIKELY(nameSize > Globals::kMaxLabelNameSize))
542
+ return DebugUtils::errored(kErrorLabelNameTooLong);
543
+
544
+ switch (type) {
545
+ case LabelType::kAnonymous: {
546
+ // Anonymous labels cannot have a parent (or more specifically, parent is useless here).
547
+ if (ASMJIT_UNLIKELY(parentId != Globals::kInvalidId))
548
+ return DebugUtils::errored(kErrorInvalidParentLabel);
549
+
550
+ uint32_t labelId = _labelEntries.size();
551
+ if (ASMJIT_UNLIKELY(labelId == Globals::kInvalidId))
552
+ return DebugUtils::errored(kErrorTooManyLabels);
553
+
554
+ ASMJIT_PROPAGATE(_labelEntries.willGrow(&_allocator));
555
+ LabelEntry* le = _allocator.allocZeroedT<LabelEntry>();
556
+
557
+ if (ASMJIT_UNLIKELY(!le))
558
+ return DebugUtils::errored(kErrorOutOfMemory);
559
+
560
+ // NOTE: This LabelEntry has a name, but we leave its hashCode as zero as it's anonymous.
561
+ le->_setId(labelId);
562
+ le->_parentId = Globals::kInvalidId;
563
+ le->_offset = 0;
564
+ ASMJIT_PROPAGATE(le->_name.setData(&_zone, name, nameSize));
565
+
566
+ _labelEntries.appendUnsafe(le);
567
+
568
+ *entryOut = le;
569
+ return kErrorOk;
570
+ }
571
+
572
+ case LabelType::kLocal: {
573
+ if (ASMJIT_UNLIKELY(parentId >= _labelEntries.size()))
574
+ return DebugUtils::errored(kErrorInvalidParentLabel);
575
+
576
+ hashCode ^= parentId;
577
+ break;
578
+ }
579
+
580
+ case LabelType::kGlobal:
581
+ case LabelType::kExternal: {
582
+ if (ASMJIT_UNLIKELY(parentId != Globals::kInvalidId))
583
+ return DebugUtils::errored(kErrorInvalidParentLabel);
584
+ break;
585
+ }
586
+
587
+ default: {
588
+ return DebugUtils::errored(kErrorInvalidArgument);
589
+ }
590
+ }
591
+
592
+ // Don't allow to insert duplicates. Local labels allow duplicates that have
593
+ // different id, this is already accomplished by having a different hashes
594
+ // between the same label names having different parent labels.
595
+ LabelEntry* le = _namedLabels.get(LabelByName(name, nameSize, hashCode, parentId));
596
+ if (ASMJIT_UNLIKELY(le))
597
+ return DebugUtils::errored(kErrorLabelAlreadyDefined);
598
+
599
+ Error err = kErrorOk;
600
+ uint32_t labelId = _labelEntries.size();
601
+
602
+ if (ASMJIT_UNLIKELY(labelId == Globals::kInvalidId))
603
+ return DebugUtils::errored(kErrorTooManyLabels);
604
+
605
+ ASMJIT_PROPAGATE(_labelEntries.willGrow(&_allocator));
606
+ le = _allocator.allocZeroedT<LabelEntry>();
607
+
608
+ if (ASMJIT_UNLIKELY(!le))
609
+ return DebugUtils::errored(kErrorOutOfMemory);
610
+
611
+ le->_hashCode = hashCode;
612
+ le->_setId(labelId);
613
+ le->_type = type;
614
+ le->_parentId = parentId;
615
+ le->_offset = 0;
616
+ ASMJIT_PROPAGATE(le->_name.setData(&_zone, name, nameSize));
617
+
618
+ _labelEntries.appendUnsafe(le);
619
+ _namedLabels.insert(allocator(), le);
620
+
621
+ *entryOut = le;
622
+ return err;
623
+ }
624
+
625
+ uint32_t CodeHolder::labelIdByName(const char* name, size_t nameSize, uint32_t parentId) noexcept {
626
+ uint32_t hashCode = CodeHolder_hashNameAndGetSize(name, nameSize);
627
+ if (ASMJIT_UNLIKELY(!nameSize))
628
+ return 0;
629
+
630
+ if (parentId != Globals::kInvalidId)
631
+ hashCode ^= parentId;
632
+
633
+ LabelEntry* le = _namedLabels.get(LabelByName(name, nameSize, hashCode, parentId));
634
+ return le ? le->id() : uint32_t(Globals::kInvalidId);
635
+ }
636
+
637
+ ASMJIT_API Error CodeHolder::resolveUnresolvedLinks() noexcept {
638
+ if (!hasUnresolvedLinks())
639
+ return kErrorOk;
640
+
641
+ Error err = kErrorOk;
642
+ for (LabelEntry* le : labelEntries()) {
643
+ if (!le->isBound())
644
+ continue;
645
+
646
+ LabelLinkIterator link(le);
647
+ if (link) {
648
+ Support::FastUInt8 of = 0;
649
+ Section* toSection = le->section();
650
+ uint64_t toOffset = Support::addOverflow(toSection->offset(), le->offset(), &of);
651
+
652
+ do {
653
+ uint32_t linkSectionId = link->sectionId;
654
+ if (link->relocId == Globals::kInvalidId) {
655
+ Section* fromSection = sectionById(linkSectionId);
656
+ size_t linkOffset = link->offset;
657
+
658
+ CodeBuffer& buf = _sections[linkSectionId]->buffer();
659
+ ASMJIT_ASSERT(linkOffset < buf.size());
660
+
661
+ // Calculate the offset relative to the start of the virtual base.
662
+ Support::FastUInt8 localOF = of;
663
+ uint64_t fromOffset = Support::addOverflow<uint64_t>(fromSection->offset(), linkOffset, &localOF);
664
+ int64_t displacement = int64_t(toOffset - fromOffset + uint64_t(int64_t(link->rel)));
665
+
666
+ if (!localOF) {
667
+ ASMJIT_ASSERT(size_t(linkOffset) < buf.size());
668
+ ASMJIT_ASSERT(buf.size() - size_t(linkOffset) >= link->format.valueSize());
669
+
670
+ // Overwrite a real displacement in the CodeBuffer.
671
+ if (CodeWriterUtils::writeOffset(buf._data + linkOffset, displacement, link->format)) {
672
+ link.resolveAndNext(this);
673
+ continue;
674
+ }
675
+ }
676
+
677
+ err = DebugUtils::errored(kErrorInvalidDisplacement);
678
+ // Falls through to `link.next()`.
679
+ }
680
+
681
+ link.next();
682
+ } while (link);
683
+ }
684
+ }
685
+
686
+ return err;
687
+ }
688
+
689
+ ASMJIT_API Error CodeHolder::bindLabel(const Label& label, uint32_t toSectionId, uint64_t toOffset) noexcept {
690
+ LabelEntry* le = labelEntry(label);
691
+ if (ASMJIT_UNLIKELY(!le))
692
+ return DebugUtils::errored(kErrorInvalidLabel);
693
+
694
+ if (ASMJIT_UNLIKELY(toSectionId > _sections.size()))
695
+ return DebugUtils::errored(kErrorInvalidSection);
696
+
697
+ // Label can be bound only once.
698
+ if (ASMJIT_UNLIKELY(le->isBound()))
699
+ return DebugUtils::errored(kErrorLabelAlreadyBound);
700
+
701
+ // Bind the label.
702
+ Section* section = _sections[toSectionId];
703
+ le->_section = section;
704
+ le->_offset = toOffset;
705
+
706
+ Error err = kErrorOk;
707
+ CodeBuffer& buf = section->buffer();
708
+
709
+ // Fix all links to this label we have collected so far if they are within
710
+ // the same section. We ignore any inter-section links as these have to be
711
+ // fixed later.
712
+ LabelLinkIterator link(le);
713
+ while (link) {
714
+ uint32_t linkSectionId = link->sectionId;
715
+ size_t linkOffset = link->offset;
716
+
717
+ uint32_t relocId = link->relocId;
718
+ if (relocId != Globals::kInvalidId) {
719
+ // Adjust relocation data only.
720
+ RelocEntry* re = _relocations[relocId];
721
+ re->_payload += toOffset;
722
+ re->_targetSectionId = toSectionId;
723
+ }
724
+ else {
725
+ if (linkSectionId != toSectionId) {
726
+ link.next();
727
+ continue;
728
+ }
729
+
730
+ ASMJIT_ASSERT(linkOffset < buf.size());
731
+ int64_t displacement = int64_t(toOffset - uint64_t(linkOffset) + uint64_t(int64_t(link->rel)));
732
+
733
+ // Size of the value we are going to patch. Only BYTE/DWORD is allowed.
734
+ ASMJIT_ASSERT(buf.size() - size_t(linkOffset) >= link->format.regionSize());
735
+
736
+ // Overwrite a real displacement in the CodeBuffer.
737
+ if (!CodeWriterUtils::writeOffset(buf._data + linkOffset, displacement, link->format)) {
738
+ err = DebugUtils::errored(kErrorInvalidDisplacement);
739
+ link.next();
740
+ continue;
741
+ }
742
+ }
743
+
744
+ link.resolveAndNext(this);
745
+ }
746
+
747
+ return err;
748
+ }
749
+
750
+ // CodeHolder - Relocations
751
+ // ========================
752
+
753
+ Error CodeHolder::newRelocEntry(RelocEntry** dst, RelocType relocType) noexcept {
754
+ ASMJIT_PROPAGATE(_relocations.willGrow(&_allocator));
755
+
756
+ uint32_t relocId = _relocations.size();
757
+ if (ASMJIT_UNLIKELY(relocId == Globals::kInvalidId))
758
+ return DebugUtils::errored(kErrorTooManyRelocations);
759
+
760
+ RelocEntry* re = _allocator.allocZeroedT<RelocEntry>();
761
+ if (ASMJIT_UNLIKELY(!re))
762
+ return DebugUtils::errored(kErrorOutOfMemory);
763
+
764
+ re->_id = relocId;
765
+ re->_relocType = relocType;
766
+ re->_sourceSectionId = Globals::kInvalidId;
767
+ re->_targetSectionId = Globals::kInvalidId;
768
+ _relocations.appendUnsafe(re);
769
+
770
+ *dst = re;
771
+ return kErrorOk;
772
+ }
773
+
774
+ // CodeHolder - Expression Evaluation
775
+ // ==================================
776
+
777
+ static Error CodeHolder_evaluateExpression(CodeHolder* self, Expression* exp, uint64_t* out) noexcept {
778
+ uint64_t value[2];
779
+ for (size_t i = 0; i < 2; i++) {
780
+ uint64_t v;
781
+ switch (exp->valueType[i]) {
782
+ case ExpressionValueType::kNone: {
783
+ v = 0;
784
+ break;
785
+ }
786
+
787
+ case ExpressionValueType::kConstant: {
788
+ v = exp->value[i].constant;
789
+ break;
790
+ }
791
+
792
+ case ExpressionValueType::kLabel: {
793
+ LabelEntry* le = exp->value[i].label;
794
+ if (!le->isBound())
795
+ return DebugUtils::errored(kErrorExpressionLabelNotBound);
796
+ v = le->section()->offset() + le->offset();
797
+ break;
798
+ }
799
+
800
+ case ExpressionValueType::kExpression: {
801
+ Expression* nested = exp->value[i].expression;
802
+ ASMJIT_PROPAGATE(CodeHolder_evaluateExpression(self, nested, &v));
803
+ break;
804
+ }
805
+
806
+ default:
807
+ return DebugUtils::errored(kErrorInvalidState);
808
+ }
809
+
810
+ value[i] = v;
811
+ }
812
+
813
+ uint64_t result;
814
+ uint64_t& a = value[0];
815
+ uint64_t& b = value[1];
816
+
817
+ switch (exp->opType) {
818
+ case ExpressionOpType::kAdd:
819
+ result = a + b;
820
+ break;
821
+
822
+ case ExpressionOpType::kSub:
823
+ result = a - b;
824
+ break;
825
+
826
+ case ExpressionOpType::kMul:
827
+ result = a * b;
828
+ break;
829
+
830
+ case ExpressionOpType::kSll:
831
+ result = (b > 63) ? uint64_t(0) : uint64_t(a << b);
832
+ break;
833
+
834
+ case ExpressionOpType::kSrl:
835
+ result = (b > 63) ? uint64_t(0) : uint64_t(a >> b);
836
+ break;
837
+
838
+ case ExpressionOpType::kSra:
839
+ result = Support::sar(a, Support::min<uint64_t>(b, 63));
840
+ break;
841
+
842
+ default:
843
+ return DebugUtils::errored(kErrorInvalidState);
844
+ }
845
+
846
+ *out = result;
847
+ return kErrorOk;
848
+ }
849
+
850
+ // CodeHolder - Utilities
851
+ // ======================
852
+
853
+ Error CodeHolder::flatten() noexcept {
854
+ uint64_t offset = 0;
855
+ for (Section* section : _sectionsByOrder) {
856
+ uint64_t realSize = section->realSize();
857
+ if (realSize) {
858
+ uint64_t alignedOffset = Support::alignUp(offset, section->alignment());
859
+ if (ASMJIT_UNLIKELY(alignedOffset < offset))
860
+ return DebugUtils::errored(kErrorTooLarge);
861
+
862
+ Support::FastUInt8 of = 0;
863
+ offset = Support::addOverflow(alignedOffset, realSize, &of);
864
+
865
+ if (ASMJIT_UNLIKELY(of))
866
+ return DebugUtils::errored(kErrorTooLarge);
867
+ }
868
+ }
869
+
870
+ // Now we know that we can assign offsets of all sections properly.
871
+ Section* prev = nullptr;
872
+ offset = 0;
873
+ for (Section* section : _sectionsByOrder) {
874
+ uint64_t realSize = section->realSize();
875
+ if (realSize)
876
+ offset = Support::alignUp(offset, section->alignment());
877
+ section->_offset = offset;
878
+
879
+ // Make sure the previous section extends a bit to cover the alignment.
880
+ if (prev)
881
+ prev->_virtualSize = offset - prev->_offset;
882
+
883
+ prev = section;
884
+ offset += realSize;
885
+ }
886
+
887
+ return kErrorOk;
888
+ }
889
+
890
+ size_t CodeHolder::codeSize() const noexcept {
891
+ Support::FastUInt8 of = 0;
892
+ uint64_t offset = 0;
893
+
894
+ for (Section* section : _sectionsByOrder) {
895
+ uint64_t realSize = section->realSize();
896
+
897
+ if (realSize) {
898
+ uint64_t alignedOffset = Support::alignUp(offset, section->alignment());
899
+ ASMJIT_ASSERT(alignedOffset >= offset);
900
+ offset = Support::addOverflow(alignedOffset, realSize, &of);
901
+ }
902
+ }
903
+
904
+ if ((sizeof(uint64_t) > sizeof(size_t) && offset > SIZE_MAX) || of)
905
+ return SIZE_MAX;
906
+
907
+ return size_t(offset);
908
+ }
909
+
910
+ Error CodeHolder::relocateToBase(uint64_t baseAddress) noexcept {
911
+ // Base address must be provided.
912
+ if (ASMJIT_UNLIKELY(baseAddress == Globals::kNoBaseAddress))
913
+ return DebugUtils::errored(kErrorInvalidArgument);
914
+
915
+ _baseAddress = baseAddress;
916
+ uint32_t addressSize = _environment.registerSize();
917
+
918
+ Section* addressTableSection = _addressTableSection;
919
+ uint32_t addressTableEntryCount = 0;
920
+ uint8_t* addressTableEntryData = nullptr;
921
+
922
+ if (addressTableSection) {
923
+ ASMJIT_PROPAGATE(
924
+ reserveBuffer(&addressTableSection->_buffer, size_t(addressTableSection->virtualSize())));
925
+ addressTableEntryData = addressTableSection->_buffer.data();
926
+ }
927
+
928
+ // Relocate all recorded locations.
929
+ for (const RelocEntry* re : _relocations) {
930
+ // Possibly deleted or optimized-out entry.
931
+ if (re->relocType() == RelocType::kNone)
932
+ continue;
933
+
934
+ Section* sourceSection = sectionById(re->sourceSectionId());
935
+ Section* targetSection = nullptr;
936
+
937
+ if (re->targetSectionId() != Globals::kInvalidId)
938
+ targetSection = sectionById(re->targetSectionId());
939
+
940
+ uint64_t value = re->payload();
941
+ uint64_t sectionOffset = sourceSection->offset();
942
+ uint64_t sourceOffset = re->sourceOffset();
943
+
944
+ // Make sure that the `RelocEntry` doesn't go out of bounds.
945
+ size_t regionSize = re->format().regionSize();
946
+ if (ASMJIT_UNLIKELY(re->sourceOffset() >= sourceSection->bufferSize() ||
947
+ sourceSection->bufferSize() - size_t(re->sourceOffset()) < regionSize))
948
+ return DebugUtils::errored(kErrorInvalidRelocEntry);
949
+
950
+ uint8_t* buffer = sourceSection->data();
951
+
952
+ switch (re->relocType()) {
953
+ case RelocType::kExpression: {
954
+ Expression* expression = (Expression*)(uintptr_t(value));
955
+ ASMJIT_PROPAGATE(CodeHolder_evaluateExpression(this, expression, &value));
956
+ break;
957
+ }
958
+
959
+ case RelocType::kAbsToAbs: {
960
+ break;
961
+ }
962
+
963
+ case RelocType::kRelToAbs: {
964
+ // Value is currently a relative offset from the start of its section.
965
+ // We have to convert it to an absolute offset (including base address).
966
+ if (ASMJIT_UNLIKELY(!targetSection))
967
+ return DebugUtils::errored(kErrorInvalidRelocEntry);
968
+
969
+ //value += baseAddress + sectionOffset + sourceOffset + regionSize;
970
+ value += baseAddress + targetSection->offset();
971
+ break;
972
+ }
973
+
974
+ case RelocType::kAbsToRel: {
975
+ value -= baseAddress + sectionOffset + sourceOffset + regionSize;
976
+
977
+ // Sign extend as we are not interested in the high 32-bit word in a 32-bit address space.
978
+ if (addressSize <= 4)
979
+ value = uint64_t(int64_t(int32_t(value & 0xFFFFFFFFu)));
980
+ else if (!Support::isInt32(int64_t(value)))
981
+ return DebugUtils::errored(kErrorRelocOffsetOutOfRange);
982
+
983
+ break;
984
+ }
985
+
986
+ case RelocType::kX64AddressEntry: {
987
+ size_t valueOffset = size_t(re->sourceOffset()) + re->format().valueOffset();
988
+ if (re->format().valueSize() != 4 || valueOffset < 2)
989
+ return DebugUtils::errored(kErrorInvalidRelocEntry);
990
+
991
+ // First try whether a relative 32-bit displacement would work.
992
+ value -= baseAddress + sectionOffset + sourceOffset + regionSize;
993
+ if (!Support::isInt32(int64_t(value))) {
994
+ // Relative 32-bit displacement is not possible, use '.addrtab' section.
995
+ AddressTableEntry* atEntry = _addressTableEntries.get(re->payload());
996
+ if (ASMJIT_UNLIKELY(!atEntry))
997
+ return DebugUtils::errored(kErrorInvalidRelocEntry);
998
+
999
+ // Cannot be null as we have just matched the `AddressTableEntry`.
1000
+ ASMJIT_ASSERT(addressTableSection != nullptr);
1001
+
1002
+ if (!atEntry->hasAssignedSlot())
1003
+ atEntry->_slot = addressTableEntryCount++;
1004
+
1005
+ size_t atEntryIndex = size_t(atEntry->slot()) * addressSize;
1006
+ uint64_t addrSrc = sectionOffset + sourceOffset + regionSize;
1007
+ uint64_t addrDst = addressTableSection->offset() + uint64_t(atEntryIndex);
1008
+
1009
+ value = addrDst - addrSrc;
1010
+ if (!Support::isInt32(int64_t(value)))
1011
+ return DebugUtils::errored(kErrorRelocOffsetOutOfRange);
1012
+
1013
+ // Bytes that replace [REX, OPCODE] bytes.
1014
+ uint32_t byte0 = 0xFF;
1015
+ uint32_t byte1 = buffer[valueOffset - 1];
1016
+
1017
+ if (byte1 == 0xE8) {
1018
+ // Patch CALL/MOD byte to FF /2 (-> 0x15).
1019
+ byte1 = x86EncodeMod(0, 2, 5);
1020
+ }
1021
+ else if (byte1 == 0xE9) {
1022
+ // Patch JMP/MOD byte to FF /4 (-> 0x25).
1023
+ byte1 = x86EncodeMod(0, 4, 5);
1024
+ }
1025
+ else {
1026
+ return DebugUtils::errored(kErrorInvalidRelocEntry);
1027
+ }
1028
+
1029
+ // Patch `jmp/call` instruction.
1030
+ buffer[valueOffset - 2] = uint8_t(byte0);
1031
+ buffer[valueOffset - 1] = uint8_t(byte1);
1032
+
1033
+ Support::writeU64uLE(addressTableEntryData + atEntryIndex, re->payload());
1034
+ }
1035
+ break;
1036
+ }
1037
+
1038
+ default:
1039
+ return DebugUtils::errored(kErrorInvalidRelocEntry);
1040
+ }
1041
+
1042
+ if (!CodeWriterUtils::writeOffset(buffer + re->sourceOffset(), int64_t(value), re->format())) {
1043
+ return DebugUtils::errored(kErrorInvalidRelocEntry);
1044
+ }
1045
+ }
1046
+
1047
+ // Fixup the virtual size of the address table if it's the last section.
1048
+ if (_sectionsByOrder.last() == addressTableSection) {
1049
+ ASMJIT_ASSERT(addressTableSection != nullptr);
1050
+
1051
+ size_t addressTableSize = addressTableEntryCount * addressSize;
1052
+ addressTableSection->_buffer._size = addressTableSize;
1053
+ addressTableSection->_virtualSize = addressTableSize;
1054
+ }
1055
+
1056
+ return kErrorOk;
1057
+ }
1058
+
1059
+ Error CodeHolder::copySectionData(void* dst, size_t dstSize, uint32_t sectionId, CopySectionFlags copyFlags) noexcept {
1060
+ if (ASMJIT_UNLIKELY(!isSectionValid(sectionId)))
1061
+ return DebugUtils::errored(kErrorInvalidSection);
1062
+
1063
+ Section* section = sectionById(sectionId);
1064
+ size_t bufferSize = section->bufferSize();
1065
+
1066
+ if (ASMJIT_UNLIKELY(dstSize < bufferSize))
1067
+ return DebugUtils::errored(kErrorInvalidArgument);
1068
+
1069
+ memcpy(dst, section->data(), bufferSize);
1070
+
1071
+ if (bufferSize < dstSize && Support::test(copyFlags, CopySectionFlags::kPadSectionBuffer)) {
1072
+ size_t paddingSize = dstSize - bufferSize;
1073
+ memset(static_cast<uint8_t*>(dst) + bufferSize, 0, paddingSize);
1074
+ }
1075
+
1076
+ return kErrorOk;
1077
+ }
1078
+
1079
+ Error CodeHolder::copyFlattenedData(void* dst, size_t dstSize, CopySectionFlags copyFlags) noexcept {
1080
+ size_t end = 0;
1081
+ for (Section* section : _sectionsByOrder) {
1082
+ if (section->offset() > dstSize)
1083
+ return DebugUtils::errored(kErrorInvalidArgument);
1084
+
1085
+ size_t bufferSize = section->bufferSize();
1086
+ size_t offset = size_t(section->offset());
1087
+
1088
+ if (ASMJIT_UNLIKELY(dstSize - offset < bufferSize))
1089
+ return DebugUtils::errored(kErrorInvalidArgument);
1090
+
1091
+ uint8_t* dstTarget = static_cast<uint8_t*>(dst) + offset;
1092
+ size_t paddingSize = 0;
1093
+ memcpy(dstTarget, section->data(), bufferSize);
1094
+
1095
+ if (Support::test(copyFlags, CopySectionFlags::kPadSectionBuffer) && bufferSize < section->virtualSize()) {
1096
+ paddingSize = Support::min<size_t>(dstSize - offset, size_t(section->virtualSize())) - bufferSize;
1097
+ memset(dstTarget + bufferSize, 0, paddingSize);
1098
+ }
1099
+
1100
+ end = Support::max(end, offset + bufferSize + paddingSize);
1101
+ }
1102
+
1103
+ if (end < dstSize && Support::test(copyFlags, CopySectionFlags::kPadTargetBuffer)) {
1104
+ memset(static_cast<uint8_t*>(dst) + end, 0, dstSize - end);
1105
+ }
1106
+
1107
+ return kErrorOk;
1108
+ }
1109
+
1110
+ // CodeHolder - Tests
1111
+ // ==================
1112
+
1113
+ #if defined(ASMJIT_TEST)
1114
+ UNIT(code_holder) {
1115
+ CodeHolder code;
1116
+
1117
+ INFO("Verifying CodeHolder::init()");
1118
+ Environment env;
1119
+ env.init(Arch::kX86);
1120
+
1121
+ code.init(env);
1122
+ EXPECT(code.arch() == Arch::kX86);
1123
+
1124
+ INFO("Verifying named labels");
1125
+ LabelEntry* le;
1126
+ EXPECT(code.newNamedLabelEntry(&le, "NamedLabel", SIZE_MAX, LabelType::kGlobal) == kErrorOk);
1127
+ EXPECT(strcmp(le->name(), "NamedLabel") == 0);
1128
+ EXPECT(code.labelIdByName("NamedLabel") == le->id());
1129
+
1130
+ INFO("Verifying section ordering");
1131
+ Section* section1;
1132
+ EXPECT(code.newSection(&section1, "high-priority", SIZE_MAX, SectionFlags::kNone, 1, -1) == kErrorOk);
1133
+ EXPECT(code.sections()[1] == section1);
1134
+ EXPECT(code.sectionsByOrder()[0] == section1);
1135
+
1136
+ Section* section0;
1137
+ EXPECT(code.newSection(&section0, "higher-priority", SIZE_MAX, SectionFlags::kNone, 1, -2) == kErrorOk);
1138
+ EXPECT(code.sections()[2] == section0);
1139
+ EXPECT(code.sectionsByOrder()[0] == section0);
1140
+ EXPECT(code.sectionsByOrder()[1] == section1);
1141
+
1142
+ Section* section3;
1143
+ EXPECT(code.newSection(&section3, "low-priority", SIZE_MAX, SectionFlags::kNone, 1, 2) == kErrorOk);
1144
+ EXPECT(code.sections()[3] == section3);
1145
+ EXPECT(code.sectionsByOrder()[3] == section3);
1146
+ }
1147
+ #endif
1148
+
1149
+ ASMJIT_END_NAMESPACE