asmjit 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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