asmjit 0.2.0 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/Rakefile +5 -3
- data/asmjit.gemspec +1 -3
- data/ext/asmjit/asmjit/.editorconfig +10 -0
- data/ext/asmjit/asmjit/.github/FUNDING.yml +1 -0
- data/ext/asmjit/asmjit/.github/workflows/build-config.json +47 -0
- data/ext/asmjit/asmjit/.github/workflows/build.yml +156 -0
- data/ext/asmjit/asmjit/.gitignore +6 -0
- data/ext/asmjit/asmjit/CMakeLists.txt +611 -0
- data/ext/asmjit/asmjit/LICENSE.md +17 -0
- data/ext/asmjit/asmjit/README.md +69 -0
- data/ext/asmjit/asmjit/src/asmjit/a64.h +62 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64archtraits_p.h +81 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.cpp +5115 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.h +72 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.cpp +51 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.h +57 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.cpp +60 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.h +247 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper.cpp +464 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper_p.h +50 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64emitter.h +1228 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter.cpp +298 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter_p.h +59 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64func.cpp +189 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64func_p.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64globals.h +1894 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi.cpp +278 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi_p.h +41 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.cpp +1957 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.h +74 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb_p.h +876 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.cpp +85 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.h +312 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass.cpp +852 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass_p.h +105 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64utils.h +179 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armformatter.cpp +143 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armformatter_p.h +44 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armglobals.h +21 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armoperand.h +621 -0
- data/ext/asmjit/asmjit/src/asmjit/arm.h +62 -0
- data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-begin.h +17 -0
- data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-end.h +9 -0
- data/ext/asmjit/asmjit/src/asmjit/asmjit.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/core/api-build_p.h +55 -0
- data/ext/asmjit/asmjit/src/asmjit/core/api-config.h +613 -0
- data/ext/asmjit/asmjit/src/asmjit/core/archcommons.h +229 -0
- data/ext/asmjit/asmjit/src/asmjit/core/archtraits.cpp +160 -0
- data/ext/asmjit/asmjit/src/asmjit/core/archtraits.h +290 -0
- data/ext/asmjit/asmjit/src/asmjit/core/assembler.cpp +406 -0
- data/ext/asmjit/asmjit/src/asmjit/core/assembler.h +129 -0
- data/ext/asmjit/asmjit/src/asmjit/core/builder.cpp +889 -0
- data/ext/asmjit/asmjit/src/asmjit/core/builder.h +1391 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codebuffer.h +113 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codeholder.cpp +1149 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codeholder.h +1035 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codewriter.cpp +175 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codewriter_p.h +179 -0
- data/ext/asmjit/asmjit/src/asmjit/core/compiler.cpp +582 -0
- data/ext/asmjit/asmjit/src/asmjit/core/compiler.h +737 -0
- data/ext/asmjit/asmjit/src/asmjit/core/compilerdefs.h +173 -0
- data/ext/asmjit/asmjit/src/asmjit/core/constpool.cpp +363 -0
- data/ext/asmjit/asmjit/src/asmjit/core/constpool.h +250 -0
- data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.cpp +1162 -0
- data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.h +813 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emithelper.cpp +323 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emithelper_p.h +58 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitter.cpp +333 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitter.h +741 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitterutils.cpp +129 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitterutils_p.h +89 -0
- data/ext/asmjit/asmjit/src/asmjit/core/environment.cpp +46 -0
- data/ext/asmjit/asmjit/src/asmjit/core/environment.h +508 -0
- data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.cpp +14 -0
- data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.h +228 -0
- data/ext/asmjit/asmjit/src/asmjit/core/formatter.cpp +584 -0
- data/ext/asmjit/asmjit/src/asmjit/core/formatter.h +247 -0
- data/ext/asmjit/asmjit/src/asmjit/core/formatter_p.h +34 -0
- data/ext/asmjit/asmjit/src/asmjit/core/func.cpp +286 -0
- data/ext/asmjit/asmjit/src/asmjit/core/func.h +1445 -0
- data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext.cpp +293 -0
- data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext_p.h +199 -0
- data/ext/asmjit/asmjit/src/asmjit/core/globals.cpp +133 -0
- data/ext/asmjit/asmjit/src/asmjit/core/globals.h +393 -0
- data/ext/asmjit/asmjit/src/asmjit/core/inst.cpp +113 -0
- data/ext/asmjit/asmjit/src/asmjit/core/inst.h +772 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.cpp +1242 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.h +261 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.cpp +80 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.h +89 -0
- data/ext/asmjit/asmjit/src/asmjit/core/logger.cpp +69 -0
- data/ext/asmjit/asmjit/src/asmjit/core/logger.h +198 -0
- data/ext/asmjit/asmjit/src/asmjit/core/misc_p.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/core/operand.cpp +132 -0
- data/ext/asmjit/asmjit/src/asmjit/core/operand.h +1611 -0
- data/ext/asmjit/asmjit/src/asmjit/core/osutils.cpp +84 -0
- data/ext/asmjit/asmjit/src/asmjit/core/osutils.h +61 -0
- data/ext/asmjit/asmjit/src/asmjit/core/osutils_p.h +68 -0
- data/ext/asmjit/asmjit/src/asmjit/core/raassignment_p.h +418 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rabuilders_p.h +612 -0
- data/ext/asmjit/asmjit/src/asmjit/core/radefs_p.h +1204 -0
- data/ext/asmjit/asmjit/src/asmjit/core/ralocal.cpp +1166 -0
- data/ext/asmjit/asmjit/src/asmjit/core/ralocal_p.h +254 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rapass.cpp +1969 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rapass_p.h +1183 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rastack.cpp +184 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rastack_p.h +171 -0
- data/ext/asmjit/asmjit/src/asmjit/core/string.cpp +559 -0
- data/ext/asmjit/asmjit/src/asmjit/core/string.h +372 -0
- data/ext/asmjit/asmjit/src/asmjit/core/support.cpp +494 -0
- data/ext/asmjit/asmjit/src/asmjit/core/support.h +1773 -0
- data/ext/asmjit/asmjit/src/asmjit/core/target.cpp +14 -0
- data/ext/asmjit/asmjit/src/asmjit/core/target.h +53 -0
- data/ext/asmjit/asmjit/src/asmjit/core/type.cpp +74 -0
- data/ext/asmjit/asmjit/src/asmjit/core/type.h +419 -0
- data/ext/asmjit/asmjit/src/asmjit/core/virtmem.cpp +722 -0
- data/ext/asmjit/asmjit/src/asmjit/core/virtmem.h +242 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zone.cpp +353 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zone.h +615 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonehash.cpp +309 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonehash.h +186 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonelist.cpp +163 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonelist.h +209 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonestack.cpp +176 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonestack.h +239 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonestring.h +120 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonetree.cpp +99 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonetree.h +380 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonevector.cpp +356 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonevector.h +690 -0
- data/ext/asmjit/asmjit/src/asmjit/core.h +1861 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86archtraits_p.h +148 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.cpp +5110 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.h +685 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.cpp +52 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.h +351 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.cpp +61 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.h +721 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper.cpp +619 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper_p.h +60 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86emitter.h +4315 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter.cpp +944 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter_p.h +58 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86func.cpp +503 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86func_p.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86globals.h +2169 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi.cpp +1732 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi_p.h +41 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.cpp +4427 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.h +563 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb_p.h +311 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86opcode_p.h +436 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.cpp +231 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.h +1085 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass.cpp +1509 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass_p.h +94 -0
- data/ext/asmjit/asmjit/src/asmjit/x86.h +93 -0
- data/ext/asmjit/asmjit/src/asmjit.natvis +245 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler.cpp +84 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler.h +85 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler_a64.cpp +4006 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler_x64.cpp +17833 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler_x86.cpp +8300 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler.cpp +253 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler.h +73 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler_a64.cpp +690 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler_x86.cpp +4317 -0
- data/ext/asmjit/asmjit/test/asmjit_test_emitters.cpp +197 -0
- data/ext/asmjit/asmjit/test/asmjit_test_instinfo.cpp +181 -0
- data/ext/asmjit/asmjit/test/asmjit_test_misc.h +257 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf.cpp +62 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf.h +61 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf_a64.cpp +699 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf_x86.cpp +5032 -0
- data/ext/asmjit/asmjit/test/asmjit_test_unit.cpp +172 -0
- data/ext/asmjit/asmjit/test/asmjit_test_x86_sections.cpp +172 -0
- data/ext/asmjit/asmjit/test/asmjitutils.h +38 -0
- data/ext/asmjit/asmjit/test/broken.cpp +312 -0
- data/ext/asmjit/asmjit/test/broken.h +148 -0
- data/ext/asmjit/asmjit/test/cmdline.h +61 -0
- data/ext/asmjit/asmjit/test/performancetimer.h +41 -0
- data/ext/asmjit/asmjit/tools/configure-makefiles.sh +13 -0
- data/ext/asmjit/asmjit/tools/configure-ninja.sh +13 -0
- data/ext/asmjit/asmjit/tools/configure-sanitizers.sh +13 -0
- data/ext/asmjit/asmjit/tools/configure-vs2019-x64.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-vs2019-x86.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-vs2022-x64.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-vs2022-x86.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-xcode.sh +8 -0
- data/ext/asmjit/asmjit/tools/enumgen.js +417 -0
- data/ext/asmjit/asmjit/tools/enumgen.sh +3 -0
- data/ext/asmjit/asmjit/tools/tablegen-arm.js +365 -0
- data/ext/asmjit/asmjit/tools/tablegen-arm.sh +3 -0
- data/ext/asmjit/asmjit/tools/tablegen-x86.js +2638 -0
- data/ext/asmjit/asmjit/tools/tablegen-x86.sh +3 -0
- data/ext/asmjit/asmjit/tools/tablegen.js +947 -0
- data/ext/asmjit/asmjit/tools/tablegen.sh +4 -0
- data/ext/asmjit/asmjit.cc +167 -30
- data/ext/asmjit/extconf.rb +9 -9
- data/lib/asmjit/version.rb +1 -1
- data/lib/asmjit.rb +14 -4
- metadata +198 -17
@@ -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(§ion1, "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(§ion0, "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(§ion3, "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
|