diff options
Diffstat (limited to 'miasm2/jitter/llvmconvert.py')
| -rw-r--r-- | miasm2/jitter/llvmconvert.py | 82 |
1 files changed, 80 insertions, 2 deletions
diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py index 08b1986b..4031d8f2 100644 --- a/miasm2/jitter/llvmconvert.py +++ b/miasm2/jitter/llvmconvert.py @@ -11,6 +11,7 @@ # # +import os from llvmlite import binding as llvm from llvmlite import ir as llvm_ir import miasm2.expression.expression as m2_expr @@ -228,6 +229,9 @@ class LLVMContext_JIT(LLVMContext): "args": [p8, itype, itype]}}) + self.add_fc({"cpuid": {"ret": itype, + "args": [itype, + itype]}}) for k in [8, 16]: self.add_fc({"bcdadd_%s" % k: {"ret": LLVMType.IntType(k), @@ -291,6 +295,57 @@ class LLVMContext_JIT(LLVMContext): value]) + @staticmethod + def cache_notify(module, buffer): + """Called when @module has been compiled to @buffer""" + if not hasattr(module, "fname_out"): + return + fname_out = module.fname_out + + if os.access(fname_out, os.R_OK): + # No need to overwrite + return + + open(fname_out, "w").write(buffer) + + @staticmethod + def cache_getbuffer(module): + """Return a compiled buffer for @module if available""" + if not hasattr(module, "fname_out"): + return None + + fname_out = module.fname_out + if os.access(fname_out, os.R_OK): + return open(fname_out).read() + return None + + def enable_cache(self): + "Enable cache of compiled object" + # Load shared libraries + for lib_fname in self.library_filenames: + self.add_shared_library(lib_fname) + + # Activate cache + self.exec_engine.set_object_cache(self.cache_notify, + self.cache_getbuffer) + + def set_cache_filename(self, func, fname_out): + "Set the filename @fname_out to use for cache for @func" + # Use a custom attribute to propagate the cache filename + func.as_llvm_mod().fname_out = fname_out + + def get_ptr_from_cache(self, file_name, func_name): + "Load @file_name and return a pointer on the jitter @func_name" + # We use an empty module to avoid loosing time on function building + empty_module = llvm.parse_assembly("") + empty_module.fname_out = file_name + + engine = self.exec_engine + engine.add_module(empty_module) + engine.finalize_object() + return engine.get_function_address(func_name) + + class LLVMContext_IRCompilation(LLVMContext): """Extend LLVMContext in order to handle memory management and custom @@ -327,6 +382,7 @@ class LLVMFunction(): # Operation translation ## Basics op_translate = {'parity': 'parity', + 'cpuid': 'cpuid', } ## Add the size as first argument op_translate_with_size = {'<<<': 'rot_left', @@ -418,9 +474,13 @@ class LLVMFunction(): ptr = builder.gep(self.local_vars["vmcpu"], [llvm_ir.Constant(LLVMType.IntType(), offset)]) - int_size = LLVMType.IntType(expr.size) + regs = self.llvm_context.ir_arch.arch.regs + if hasattr(regs, "float_list") and expr in regs.float_list: + pointee_type = llvm_ir.DoubleType() + else: + pointee_type = LLVMType.IntType(expr.size) ptr_casted = builder.bitcast(ptr, - llvm_ir.PointerType(int_size)) + llvm_ir.PointerType(pointee_type)) # Store in cache self.local_vars_pointers[name] = ptr_casted @@ -702,6 +762,20 @@ class LLVMFunction(): self.update_cache(expr, ret) return ret + if op in ["int_16_to_double", "int_32_to_double", "int_64_to_double", + "mem_16_to_double", "mem_32_to_double", "mem_64_to_double"]: + arg = self.add_ir(expr.args[0]) + ret = builder.uitofp(arg, llvm_ir.DoubleType()) + self.update_cache(expr, ret) + return ret + + if op in ["double_to_int_16", "double_to_int_32", "double_to_int_64", + "double_to_mem_16", "double_to_mem_32", "double_to_mem_64"]: + arg = self.add_ir(expr.args[0]) + ret = builder.fptoui(arg, llvm_ir.IntType(expr.size)) + self.update_cache(expr, ret) + return ret + if len(expr.args) > 1: if op == "*": @@ -718,6 +792,10 @@ class LLVMFunction(): callback = builder.urem elif op == "/": callback = builder.udiv + elif op == "fadd": + callback = builder.fadd + elif op == "fdiv": + callback = builder.fdiv else: raise NotImplementedError('Unknown op: %s' % op) |