diff options
| author | Theofilos Augoustis <theofilos.augoustis@gmail.com> | 2025-10-14 09:09:29 +0000 |
|---|---|---|
| committer | Theofilos Augoustis <theofilos.augoustis@gmail.com> | 2025-10-14 09:09:29 +0000 |
| commit | 579cf1d03fb932083e6317967d1613d5c2587fb6 (patch) | |
| tree | 629f039935382a2a7391bce9253f6c9968159049 /src/miasm/jitter/jitcore_llvm.py | |
| parent | 51c15d3ea2e16d4fc5f0f01a3b9befc66b1f982e (diff) | |
| download | focaccia-miasm-579cf1d03fb932083e6317967d1613d5c2587fb6.tar.gz focaccia-miasm-579cf1d03fb932083e6317967d1613d5c2587fb6.zip | |
Convert to src-layout ta/nix
Diffstat (limited to 'src/miasm/jitter/jitcore_llvm.py')
| -rw-r--r-- | src/miasm/jitter/jitcore_llvm.py | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/miasm/jitter/jitcore_llvm.py b/src/miasm/jitter/jitcore_llvm.py new file mode 100644 index 00000000..4f1871b2 --- /dev/null +++ b/src/miasm/jitter/jitcore_llvm.py @@ -0,0 +1,144 @@ +from __future__ import print_function +import os +import glob +import importlib +import tempfile +import sysconfig + +from miasm.jitter.llvmconvert import * +import miasm.jitter.jitcore as jitcore +from miasm.jitter import Jitllvm +import platform + +import llvmlite +llvmlite.binding.load_library_permanently(Jitllvm.__file__) + +is_win = platform.system() == "Windows" + +class JitCore_LLVM(jitcore.JitCore): + "JiT management, using LLVM as backend" + + # Architecture dependent libraries + arch_dependent_libs = { + "x86": "JitCore_x86", + "arm": "JitCore_arm", + "msp430": "JitCore_msp430", + "mips32": "JitCore_mips32", + "aarch64": "JitCore_aarch64", + "ppc32": "JitCore_ppc32", + } + + def __init__(self, lifter, bin_stream): + super(JitCore_LLVM, self).__init__(lifter, bin_stream) + + self.options.update( + { + "safe_mode": True, # Verify each function + "optimise": True, # Optimise functions + "log_func": False, # Print LLVM functions + "log_assembly": False, # Print assembly executed + } + ) + + self.exec_wrapper = Jitllvm.llvm_exec_block + self.lifter = lifter + + # Cache temporary dir + self.tempdir = os.path.join(tempfile.gettempdir(), "miasm_cache") + try: + os.mkdir(self.tempdir, 0o755) + except OSError: + pass + if not os.access(self.tempdir, os.R_OK | os.W_OK): + raise RuntimeError( + 'Cannot access cache directory %s ' % self.tempdir) + + def load(self): + + # Library to load within Jit context + libs_to_load = [] + + # Get architecture dependent Jitcore library (if any) + lib_dir = os.path.dirname(os.path.realpath(__file__)) + ext = sysconfig.get_config_var('EXT_SUFFIX') + if ext is None: + ext = ".so" if not is_win else ".pyd" + if is_win: + # sysconfig.get_config_var('EXT_SUFFIX') is .pyd on Windows and need to be forced to .lib + # Additionally windows built libraries may have a name like VmMngr.cp38-win_amd64.lib + ext_files = glob.glob(os.path.join(lib_dir, "VmMngr.*pyd")) + if len(ext_files) == 1: + ext = os.path.basename(ext_files[0]).replace("VmMngr", "") + lib_dir = os.path.join(lib_dir, 'arch') + try: + jit_lib = os.path.join( + lib_dir, self.arch_dependent_libs[self.lifter.arch.name] + ext + ) + libs_to_load.append(jit_lib) + except KeyError: + pass + + # Create a context + self.context = LLVMContext_JIT(libs_to_load, self.lifter) + + # Set the optimisation level + self.context.optimise_level() + + # Save the current architecture parameters + self.arch = self.lifter.arch + + # Get the correspondence between registers and vmcpu struct + mod_name = "miasm.jitter.arch.JitCore_%s" % (self.lifter.arch.name) + mod = importlib.import_module(mod_name) + self.context.set_vmcpu(mod.get_gpreg_offset_all()) + + # Enable caching + self.context.enable_cache() + + def add_block(self, block): + """Add a block to JiT and JiT it. + @block: the block to add + """ + + block_hash = self.hash_block(block) + fname_out = os.path.join(self.tempdir, "%s.bc" % block_hash) + + if not os.access(fname_out, os.R_OK): + # Build a function in the context + func = LLVMFunction(self.context, self.FUNCNAME) + + # Set log level + func.log_regs = self.log_regs + func.log_mn = self.log_mn + + # Import asm block + func.from_asmblock(block) + + # Verify + if self.options["safe_mode"] is True: + func.verify() + + # Optimise + if self.options["optimise"] is True: + func.optimise() + + # Log + if self.options["log_func"] is True: + print(func) + if self.options["log_assembly"] is True: + print(func.get_assembly()) + + # Use propagate the cache filename + self.context.set_cache_filename(func, fname_out) + + # Get a pointer on the function for JiT + ptr = func.get_function_pointer() + + else: + # The cache file exists: function can be loaded from cache + ptr = self.context.get_ptr_from_cache(fname_out, self.FUNCNAME) + + # Store a pointer on the function jitted code + loc_key = block.loc_key + offset = self.lifter.loc_db.get_location_offset(loc_key) + self.offset_to_jitted_func[offset] = ptr |