1 // AsmJit - Machine code generation for C++
2 //
3 //  * Official AsmJit Home Page: https://asmjit.com
4 //  * Official Github Repository: https://github.com/asmjit/asmjit
5 //
6 // Copyright (c) 2008-2020 The AsmJit Authors
7 //
8 // This software is provided 'as-is', without any express or implied
9 // warranty. In no event will the authors be held liable for any damages
10 // arising from the use of this software.
11 //
12 // Permission is granted to anyone to use this software for any purpose,
13 // including commercial applications, and to alter it and redistribute it
14 // freely, subject to the following restrictions:
15 //
16 // 1. The origin of this software must not be misrepresented; you must not
17 //    claim that you wrote the original software. If you use this software
18 //    in a product, an acknowledgment in the product documentation would be
19 //    appreciated but is not required.
20 // 2. Altered source versions must be plainly marked as such, and must not be
21 //    misrepresented as being the original software.
22 // 3. This notice may not be removed or altered from any source distribution.
23 
24 #include "../core/api-build_p.h"
25 #ifndef ASMJIT_NO_JIT
26 
27 #include "../core/cpuinfo.h"
28 #include "../core/jitruntime.h"
29 
30 ASMJIT_BEGIN_NAMESPACE
31 
32 // ============================================================================
33 // [asmjit::JitRuntime - Utilities]
34 // ============================================================================
35 
36 // Only useful on non-x86 architectures.
JitRuntime_flushInstructionCache(const void * p,size_t size)37 static inline void JitRuntime_flushInstructionCache(const void* p, size_t size) noexcept {
38 #if ASMJIT_ARCH_X86
39   DebugUtils::unused(p, size);
40 #else
41 # if defined(_WIN32)
42   // Windows has a built-in support in `kernel32.dll`.
43   ::FlushInstructionCache(::GetCurrentProcess(), p, size);
44 # elif defined(__GNUC__)
45   char* start = static_cast<char*>(const_cast<void*>(p));
46   char* end = start + size;
47   __builtin___clear_cache(start, end);
48 # else
49   DebugUtils::unused(p, size);
50 # endif
51 #endif
52 }
53 
54 // ============================================================================
55 // [asmjit::JitRuntime - Construction / Destruction]
56 // ============================================================================
57 
JitRuntime(const JitAllocator::CreateParams * params)58 JitRuntime::JitRuntime(const JitAllocator::CreateParams* params) noexcept
59   : _allocator(params) {
60   _environment = hostEnvironment();
61   _environment.setFormat(Environment::kFormatJIT);
62 }
63 
~JitRuntime()64 JitRuntime::~JitRuntime() noexcept {}
65 
66 // ============================================================================
67 // [asmjit::JitRuntime - Interface]
68 // ============================================================================
69 
_add(void ** dst,CodeHolder * code)70 Error JitRuntime::_add(void** dst, CodeHolder* code) noexcept {
71   *dst = nullptr;
72 
73   ASMJIT_PROPAGATE(code->flatten());
74   ASMJIT_PROPAGATE(code->resolveUnresolvedLinks());
75 
76   size_t estimatedCodeSize = code->codeSize();
77   if (ASMJIT_UNLIKELY(estimatedCodeSize == 0))
78     return DebugUtils::errored(kErrorNoCodeGenerated);
79 
80   uint8_t* ro;
81   uint8_t* rw;
82   ASMJIT_PROPAGATE(_allocator.alloc((void**)&ro, (void**)&rw, estimatedCodeSize));
83 
84   // Relocate the code.
85   Error err = code->relocateToBase(uintptr_t((void*)ro));
86   if (ASMJIT_UNLIKELY(err)) {
87     _allocator.release(ro);
88     return err;
89   }
90 
91   // Recalculate the final code size and shrink the memory we allocated for it
92   // in case that some relocations didn't require records in an address table.
93   size_t codeSize = code->codeSize();
94 
95   for (Section* section : code->_sections) {
96     size_t offset = size_t(section->offset());
97     size_t bufferSize = size_t(section->bufferSize());
98     size_t virtualSize = size_t(section->virtualSize());
99 
100     ASMJIT_ASSERT(offset + bufferSize <= codeSize);
101     memcpy(rw + offset, section->data(), bufferSize);
102 
103     if (virtualSize > bufferSize) {
104       ASMJIT_ASSERT(offset + virtualSize <= codeSize);
105       memset(rw + offset + bufferSize, 0, virtualSize - bufferSize);
106     }
107   }
108 
109   if (codeSize < estimatedCodeSize)
110     _allocator.shrink(ro, codeSize);
111 
112   flush(ro, codeSize);
113   *dst = ro;
114 
115   return kErrorOk;
116 }
117 
_release(void * p)118 Error JitRuntime::_release(void* p) noexcept {
119   return _allocator.release(p);
120 }
121 
flush(const void * p,size_t size)122 void JitRuntime::flush(const void* p, size_t size) noexcept {
123   JitRuntime_flushInstructionCache(p, size);
124 }
125 
126 ASMJIT_END_NAMESPACE
127 
128 #endif
129