diff options
| author | Ajax <commial@gmail.com> | 2015-12-23 16:37:16 +0100 |
|---|---|---|
| committer | Ajax <commial@gmail.com> | 2017-01-04 17:14:55 +0100 |
| commit | a993473c6e2b4225c629eeb88eae98f7ee655333 (patch) | |
| tree | b816cfe6c706caffca42b052c9d69a806a9876db | |
| parent | 2b93bc6682f3a08a5eccccefa135535708434f9e (diff) | |
| download | miasm-a993473c6e2b4225c629eeb88eae98f7ee655333.tar.gz miasm-a993473c6e2b4225c629eeb88eae98f7ee655333.zip | |
Ugly modification to have llvm work again
| -rw-r--r-- | miasm2/jitter/Jitllvm.c | 11 | ||||
| -rw-r--r-- | miasm2/jitter/jitcore_llvm.py | 10 | ||||
| -rw-r--r-- | miasm2/jitter/llvmconvert.py | 319 | ||||
| -rw-r--r-- | miasm2/jitter/vm_mngr.c | 5 | ||||
| -rw-r--r-- | miasm2/jitter/vm_mngr.h | 2 | ||||
| -rw-r--r-- | test/test_all.py | 7 |
6 files changed, 200 insertions, 154 deletions
diff --git a/miasm2/jitter/Jitllvm.c b/miasm2/jitter/Jitllvm.c index 6622e615..ff537728 100644 --- a/miasm2/jitter/Jitllvm.c +++ b/miasm2/jitter/Jitllvm.c @@ -3,17 +3,24 @@ #include <inttypes.h> #include <stdint.h> +#include "queue.h" +#include "vm_mngr.h" +#include "vm_mngr_py.h" +#include "JitCore.h" +// Needed to get the JitCpu.cpu offset, arch independent +#include "arch/JitCore_x86.h" PyObject* llvm_exec_bloc(PyObject* self, PyObject* args) { uint64_t func_addr; uint64_t (*func)(void*, void*); uint64_t vm; - uint64_t cpu; uint64_t ret; + JitCpu* jitcpu; - if (!PyArg_ParseTuple(args, "KKK", &func_addr, &cpu, &vm)) + if (!PyArg_ParseTuple(args, "KOK", &func_addr, &jitcpu, &vm)) return NULL; + vm_cpu_t* cpu = jitcpu->cpu; func = (void *) (intptr_t) func_addr; ret = func((void*)(intptr_t) cpu, (void*)(intptr_t) vm); return PyLong_FromUnsignedLongLong(ret); diff --git a/miasm2/jitter/jitcore_llvm.py b/miasm2/jitter/jitcore_llvm.py index acf91d15..4f4a17c7 100644 --- a/miasm2/jitter/jitcore_llvm.py +++ b/miasm2/jitter/jitcore_llvm.py @@ -68,7 +68,7 @@ class JitCore_LLVM(jitcore.JitCore): def add_bloc(self, bloc): # Search in IR cache - if self.options["cache_ir"] is not None: + if False and self.options["cache_ir"] is not None: # /!\ This part is under development # Use it at your own risk @@ -153,3 +153,11 @@ class JitCore_LLVM(jitcore.JitCore): # Store a pointer on the function jitted code self.lbl2jitbloc[label.offset] = func.get_function_pointer() + + def jit_call(self, label, cpu, _vmmngr, breakpoints): + """Call the function label with cpu and vmmngr states + @label: function's label + @cpu: JitCpu instance + @breakpoints: Dict instance of used breakpoints + """ + return self.exec_wrapper(self.lbl2jitbloc[label], cpu, cpu.vmmngr.vmmngr) diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py index 3ac75cd7..0d9ab356 100644 --- a/miasm2/jitter/llvmconvert.py +++ b/miasm2/jitter/llvmconvert.py @@ -11,27 +11,25 @@ # # -import llvm -import llvm.core as llvm_c -import llvm.ee as llvm_e -import llvm.passes as llvm_p +from llvmlite import binding as llvm +from llvmlite import ir as llvm_ir import miasm2.expression.expression as m2_expr import miasm2.jitter.csts as m2_csts import miasm2.core.asmbloc as m2_asmbloc -class LLVMType(llvm_c.Type): +class LLVMType(llvm_ir.Type): "Handle LLVM Type" int_cache = {} @classmethod - def int(cls, size=32): + def IntType(cls, size=32): try: return cls.int_cache[size] except KeyError: - cls.int_cache[size] = llvm_c.Type.int(size) + cls.int_cache[size] = llvm_ir.IntType(size) return cls.int_cache[size] @classmethod @@ -43,7 +41,7 @@ class LLVMType(llvm_c.Type): def generic(cls, e): "Generic value for execution" if isinstance(e, m2_expr.ExprInt): - return llvm_e.GenericValue.int(LLVMType.int(e.size), int(e)) + return llvm_e.GenericValue.int(LLVMType.IntType(e.size), int(e.arg)) elif isinstance(e, llvm_e.GenericValue): return e else: @@ -58,10 +56,7 @@ class LLVMContext(): def __init__(self, name="mod"): "Initialize a context with a module named 'name'" - self.mod = llvm_c.Module.new(name) - self.pass_manager = llvm_p.FunctionPassManager.new(self.mod) - self.exec_engine = llvm_e.ExecutionEngine.new(self.mod) - self.add_fc(self.known_fc) + self.new_module(name) def optimise_level(self, classic_passes=True, dead_passes=True): """Set the optimisation level : @@ -78,7 +73,7 @@ class LLVMContext(): """ # Set up the optimiser pipeline - + """ if classic_passes is True: # self.pass_manager.add(llvm_p.PASS_INSTCOMBINE) self.pass_manager.add(llvm_p.PASS_REASSOCIATE) @@ -91,6 +86,20 @@ class LLVMContext(): self.pass_manager.add(llvm_p.PASS_DIE) self.pass_manager.initialize() + """ + + def new_module(self, name="mod"): + self.mod = llvm_ir.Module(name=name) + # self.pass_manager = llvm.FunctionPassManager(self.mod) + llvm.initialize() + llvm.initialize_native_target() + llvm.initialize_native_asmprinter() + target = llvm.Target.from_default_triple() + target_machine = target.create_target_machine() + backing_mod = llvm.parse_assembly("") + self.exec_engine = llvm.create_mcjit_compiler(backing_mod, + target_machine) + self.add_fc(self.known_fc) def get_execengine(self): "Return the Execution Engine associated with this context" @@ -106,98 +115,103 @@ class LLVMContext(): def add_shared_library(self, filename): "Load the shared library 'filename'" - return llvm_c.load_library_permanently(filename) + return llvm.load_library_permanently(filename) def add_fc(self, fc): "Add function into known_fc" - for name, detail in fc.items(): - self.mod.add_function(LLVMType.function(detail["ret"], - detail["args"]), - name) + for name, detail in fc.iteritems(): + fnty = llvm_ir.FunctionType(detail["ret"], detail["args"]) + llvm_ir.Function(self.mod, fnty, name=name) class LLVMContext_JIT(LLVMContext): - "Extend LLVMContext_JIT in order to handle memory management" + """Extend LLVMContext_JIT in order to handle memory management and custom + operations""" def __init__(self, library_filenames, name="mod"): "Init a LLVMContext object, and load the mem management shared library" + self.library_filenames = library_filenames LLVMContext.__init__(self, name) - for lib_fname in library_filenames: + self.vmcpu = {} + self.engines = [] + + def new_module(self, name="mod"): + LLVMContext.new_module(self, name) + for lib_fname in self.library_filenames: self.add_shared_library(lib_fname) self.add_memlookups() self.add_get_exceptionflag() self.add_op() self.add_log_functions() - self.vmcpu = {} def add_memlookups(self): "Add MEM_LOOKUP functions" fc = {} - p8 = llvm_c.PointerType.pointer(LLVMType.int(8)) + p8 = llvm_ir.PointerType(LLVMType.IntType(8)) for i in [8, 16, 32, 64]: - fc["MEM_LOOKUP_%02d" % i] = {"ret": LLVMType.int(i), + fc["vm_MEM_LOOKUP_%02d" % i] = {"ret": LLVMType.IntType(i), "args": [p8, - LLVMType.int(64)]} + LLVMType.IntType(64)]} - fc["MEM_WRITE_%02d" % i] = {"ret": LLVMType.void(), + fc["vm_MEM_WRITE_%02d" % i] = {"ret": llvm_ir.VoidType(), "args": [p8, - LLVMType.int(64), - LLVMType.int(i)]} + LLVMType.IntType(64), + LLVMType.IntType(i)]} self.add_fc(fc) def add_get_exceptionflag(self): "Add 'get_exception_flag' function" - p8 = llvm_c.PointerType.pointer(LLVMType.int(8)) - self.add_fc({"get_exception_flag": {"ret": LLVMType.int(64), + p8 = llvm_ir.PointerType(LLVMType.IntType(8)) + self.add_fc({"get_exception_flag": {"ret": LLVMType.IntType(64), "args": [p8]}}) def add_op(self): "Add operations functions" - p8 = llvm_c.PointerType.pointer(LLVMType.int(8)) - self.add_fc({"parity": {"ret": LLVMType.int(), - "args": [LLVMType.int()]}}) - self.add_fc({"rot_left": {"ret": LLVMType.int(), - "args": [LLVMType.int(), - LLVMType.int(), - LLVMType.int()]}}) - self.add_fc({"rot_right": {"ret": LLVMType.int(), - "args": [LLVMType.int(), - LLVMType.int(), - LLVMType.int()]}}) - - self.add_fc({"segm2addr": {"ret": LLVMType.int(64), + p8 = llvm_ir.PointerType(LLVMType.IntType(8)) + self.add_fc({"parity": {"ret": LLVMType.IntType(), + "args": [LLVMType.IntType()]}}) + self.add_fc({"rot_left": {"ret": LLVMType.IntType(), + "args": [LLVMType.IntType(), + LLVMType.IntType(), + LLVMType.IntType()]}}) + self.add_fc({"rot_right": {"ret": LLVMType.IntType(), + "args": [LLVMType.IntType(), + LLVMType.IntType(), + LLVMType.IntType()]}}) + + self.add_fc({"segm2addr": {"ret": LLVMType.IntType(64), "args": [p8, - LLVMType.int(64), - LLVMType.int(64)]}}) + LLVMType.IntType(64), + LLVMType.IntType(64)]}}) for k in [8, 16]: - self.add_fc({"bcdadd_%s" % k: {"ret": LLVMType.int(k), - "args": [LLVMType.int(k), - LLVMType.int(k)]}}) - self.add_fc({"bcdadd_cf_%s" % k: {"ret": LLVMType.int(k), - "args": [LLVMType.int(k), - LLVMType.int(k)]}}) + self.add_fc({"bcdadd_%s" % k: {"ret": LLVMType.IntType(k), + "args": [LLVMType.IntType(k), + LLVMType.IntType(k)]}}) + self.add_fc({"bcdadd_cf_%s" % k: {"ret": LLVMType.IntType(k), + "args": [LLVMType.IntType(k), + LLVMType.IntType(k)]}}) for k in [16, 32, 64]: - self.add_fc({"imod%s" % k: {"ret": LLVMType.int(k), + self.add_fc({"imod%s" % k: {"ret": LLVMType.IntType(k), "args": [p8, - LLVMType.int(k), - LLVMType.int(k)]}}) - self.add_fc({"idiv%s" % k: {"ret": LLVMType.int(k), + LLVMType.IntType(k), + LLVMType.IntType(k)]}}) + self.add_fc({"idiv%s" % k: {"ret": LLVMType.IntType(k), "args": [p8, - LLVMType.int(k), - LLVMType.int(k)]}}) + LLVMType.IntType(k), + LLVMType.IntType(k)]}}) def add_log_functions(self): "Add functions for state logging" - p8 = llvm_c.PointerType.pointer(LLVMType.int(8)) - self.add_fc({"dump_gpregs": {"ret": LLVMType.void(), + p8 = llvm_ir.PointerType(LLVMType.IntType(8)) + self.add_fc({"dump_gpregs": {"ret": llvm_ir.VoidType(), "args": [p8]}}) def set_vmcpu(self, lookup_table): @@ -218,11 +232,12 @@ class LLVMFunction(): # Default logging values log_mn = False - log_regs = False + log_regs = True def __init__(self, llvm_context, name="fc"): "Create a new function with name fc" self.llvm_context = llvm_context + self.llvm_context.new_module() self.mod = self.llvm_context.get_module() self.my_args = [] # (Expr, LLVMType, Name) @@ -257,15 +272,14 @@ class LLVMFunction(): "Init the function" # Build type for fc signature - fc_type = LLVMType.function( - self.ret_type, [k[1] for k in self.my_args]) + fc_type = llvm_ir.FunctionType(self.ret_type, [k[1] for k in self.my_args]) # Add fc in module try: - fc = self.mod.add_function(fc_type, self.name) + fc = llvm_ir.Function(self.mod, fc_type, name=self.name) except llvm.LLVMException: # Overwrite the previous function - previous_fc = self.mod.get_function_named(self.name) + previous_fc = self.mod.get_global(self.name) previous_fc.delete() fc = self.mod.add_function(fc_type, self.name) @@ -292,7 +306,7 @@ class LLVMFunction(): self.entry_bbl = self.append_basic_block("entry") # Instruction builder - self.builder = llvm_c.Builder.new(self.entry_bbl) + self.builder = llvm_ir.IRBuilder(self.entry_bbl) def CreateEntryBlockAlloca(self, var_type): "Create an alloca instruction at the beginning of the current fc" @@ -328,11 +342,11 @@ class LLVMFunction(): # Pointer cast ptr = builder.gep(self.local_vars["vmcpu"], - [llvm_c.Constant.int(LLVMType.int(), - offset)]) - int_size = LLVMType.int(expr.size) + [llvm_ir.Constant(LLVMType.IntType(), + offset)]) + int_size = LLVMType.IntType(expr.size) ptr_casted = builder.bitcast(ptr, - llvm_c.PointerType.pointer(int_size)) + llvm_ir.PointerType(int_size)) # Store in cache self.local_vars_pointers[name] = ptr_casted @@ -365,7 +379,7 @@ class LLVMFunction(): builder = self.builder if isinstance(expr, m2_expr.ExprInt): - ret = llvm_c.Constant.int(LLVMType.int(expr.size), int(expr)) + ret = llvm_ir.Constant(LLVMType.IntType(expr.size), int(expr.arg)) self.update_cache(expr, ret) return ret @@ -374,7 +388,7 @@ class LLVMFunction(): if not isinstance(name, str): # Resolve label offset = name.offset - ret = llvm_c.Constant.int(LLVMType.int(expr.size), offset) + ret = llvm_ir.Constant(LLVMType.IntType(expr.size), offset) self.update_cache(expr, ret) return ret @@ -394,35 +408,35 @@ class LLVMFunction(): op = expr.op if op == "parity": - fc_ptr = self.mod.get_function_named("parity") + fc_ptr = self.mod.get_global("parity") arg = builder.zext(self.add_ir(expr.args[0]), - LLVMType.int()) + LLVMType.IntType()) ret = builder.call(fc_ptr, [arg]) - ret = builder.trunc(ret, LLVMType.int(expr.size)) + ret = builder.trunc(ret, LLVMType.IntType(expr.size)) self.update_cache(expr, ret) return ret if op in ["<<<", ">>>"]: fc_name = "rot_left" if op == "<<<" else "rot_right" - fc_ptr = self.mod.get_function_named(fc_name) + fc_ptr = self.mod.get_global(fc_name) args = [self.add_ir(arg) for arg in expr.args] arg_size = expr.args[0].size if arg_size < 32: # Cast args - args = [builder.zext(arg, LLVMType.int(32)) + args = [builder.zext(arg, LLVMType.IntType(32)) for arg in args] - arg_size_cst = llvm_c.Constant.int(LLVMType.int(), + arg_size_cst = llvm_ir.Constant(LLVMType.IntType(), arg_size) ret = builder.call(fc_ptr, [arg_size_cst] + args) if arg_size < 32: # Cast ret - ret = builder.trunc(ret, LLVMType.int(arg_size)) + ret = builder.trunc(ret, LLVMType.IntType(arg_size)) self.update_cache(expr, ret) return ret if op == "bcdadd": size = expr.args[0].size - fc_ptr = self.mod.get_function_named("bcdadd_%s" % size) + fc_ptr = self.mod.get_global("bcdadd_%s" % size) args = [self.add_ir(arg) for arg in expr.args] ret = builder.call(fc_ptr, args) self.update_cache(expr, ret) @@ -430,32 +444,32 @@ class LLVMFunction(): if op == "bcdadd_cf": size = expr.args[0].size - fc_ptr = self.mod.get_function_named("bcdadd_cf_%s" % size) + fc_ptr = self.mod.get_global("bcdadd_cf_%s" % size) args = [self.add_ir(arg) for arg in expr.args] ret = builder.call(fc_ptr, args) - ret = builder.trunc(ret, LLVMType.int(expr.size)) + ret = builder.trunc(ret, LLVMType.IntType(expr.size)) self.update_cache(expr, ret) return ret if op == "-": - zero = llvm_c.Constant.int(LLVMType.int(expr.size), - 0) + zero = llvm_ir.Constant(LLVMType.IntType(expr.size), + 0) ret = builder.sub(zero, self.add_ir(expr.args[0])) self.update_cache(expr, ret) return ret if op == "segm": - fc_ptr = self.mod.get_function_named("segm2addr") - args_casted = [builder.zext(self.add_ir(arg), LLVMType.int(64)) + fc_ptr = self.mod.get_global("segm2addr") + args_casted = [builder.zext(self.add_ir(arg), LLVMType.IntType(64)) for arg in expr.args] args = [self.local_vars["vmcpu"]] + args_casted ret = builder.call(fc_ptr, args) - ret = builder.trunc(ret, LLVMType.int(expr.size)) + ret = builder.trunc(ret, LLVMType.IntType(expr.size)) self.update_cache(expr, ret) return ret if op in ["imod", "idiv"]: - fc_ptr = self.mod.get_function_named( + fc_ptr = self.mod.get_global( "%s%s" % (op, expr.args[0].size)) args_casted = [self.add_ir(arg) for arg in expr.args] args = [self.local_vars["vmcpu"]] + args_casted @@ -502,10 +516,10 @@ class LLVMFunction(): if isinstance(expr, m2_expr.ExprMem): - fc_name = "MEM_LOOKUP_%02d" % expr.size - fc_ptr = self.mod.get_function_named(fc_name) + fc_name = "vm_MEM_LOOKUP_%02d" % expr.size + fc_ptr = self.mod.get_global(fc_name) addr_casted = builder.zext(self.add_ir(expr.arg), - LLVMType.int(64)) + LLVMType.IntType(64)) ret = builder.call(fc_ptr, [self.local_vars["vmmngr"], addr_casted]) @@ -516,13 +530,13 @@ class LLVMFunction(): if isinstance(expr, m2_expr.ExprCond): # Compute cond cond = self.add_ir(expr.cond) - zero_casted = llvm_c.Constant.int(LLVMType.int(expr.cond.size), + zero_casted = llvm_ir.Constant(LLVMType.IntType(expr.cond.size), 0) - condition_bool = builder.icmp(llvm_c.ICMP_NE, cond, - zero_casted) + condition_bool = builder.icmp_unsigned("!=", cond, + zero_casted) # Alloc return var - alloca = self.CreateEntryBlockAlloca(LLVMType.int(expr.size)) + alloca = self.CreateEntryBlockAlloca(LLVMType.IntType(expr.size)) # Create bbls branch_id = self.new_branch_name() @@ -564,22 +578,22 @@ class LLVMFunction(): # Remove trailing bits if expr.start != 0: - to_shr = llvm_c.Constant.int(LLVMType.int(expr.arg.size), - expr.start) + to_shr = llvm_ir.Constant(LLVMType.IntType(expr.arg.size), + expr.start) shred = builder.lshr(src, to_shr) else: shred = src # Remove leading bits - to_and = llvm_c.Constant.int(LLVMType.int(expr.arg.size), - (1 << (expr.stop - expr.start)) - 1) + to_and = llvm_ir.Constant(LLVMType.IntType(expr.arg.size), + (1 << (expr.stop - expr.start)) - 1) anded = builder.and_(shred, to_and) # Cast into e.size ret = builder.trunc(anded, - LLVMType.int(expr.size)) + LLVMType.IntType(expr.size)) self.update_cache(expr, ret) return ret @@ -589,22 +603,20 @@ class LLVMFunction(): args = [] # Build each part - for arg in expr.args: - src, start, stop = arg - - # src & (stop - start) + for start, src in expr.iter_args(): + # src & size src = self.add_ir(src) src_casted = builder.zext(src, - LLVMType.int(expr.size)) - to_and = llvm_c.Constant.int(LLVMType.int(expr.size), - (1 << (stop - start)) - 1) + LLVMType.IntType(expr.size)) + to_and = llvm_ir.Constant(LLVMType.IntType(expr.size), + (1 << src.type.width) - 1) anded = builder.and_(src_casted, to_and) if (start != 0): # result << start - to_shl = llvm_c.Constant.int(LLVMType.int(expr.size), - start) + to_shl = llvm_ir.Constant(LLVMType.IntType(expr.size), + start) shled = builder.shl(anded, to_shl) final = shled else: @@ -626,7 +638,7 @@ class LLVMFunction(): def set_ret(self, var): "Cast @var and return it at the end of current bbl" if var.type.width < 64: - var_casted = self.builder.zext(var, LLVMType.int(64)) + var_casted = self.builder.zext(var, LLVMType.IntType(64)) else: var_casted = var self.builder.ret(var_casted) @@ -638,9 +650,9 @@ class LLVMFunction(): args = expr.get_r(True) for a in args: if not isinstance(a, m2_expr.ExprMem): - self.my_args.append((a, LLVMType.int(a.size), a.name)) + self.my_args.append((a, LLVMType.IntType(a.size), a.name)) - self.ret_type = LLVMType.int(expr.size) + self.ret_type = LLVMType.IntType(expr.size) # Initialise the function self.init_fc() @@ -662,18 +674,21 @@ class LLVMFunction(): if isinstance(dst, m2_expr.ExprId): dst_name = dst.name + "_new" if add_new else dst.name - ptr_casted = self.get_ptr_by_expr( - m2_expr.ExprId(dst_name, dst.size)) - builder.store(src, ptr_casted) + if add_new or dst_name == "IRDst": + self.local_vars[dst_name] = src + else: + ptr_casted = self.get_ptr_by_expr( + m2_expr.ExprId(dst_name, dst.size)) + builder.store(src, ptr_casted) elif isinstance(dst, m2_expr.ExprMem): self.add_ir(dst.arg) # Function call - fc_name = "MEM_WRITE_%02d" % dst.size - fc_ptr = self.mod.get_function_named(fc_name) + fc_name = "vm_MEM_WRITE_%02d" % dst.size + fc_ptr = self.mod.get_global(fc_name) dst = self.add_ir(dst.arg) - dst_casted = builder.zext(dst, LLVMType.int(64)) + dst_casted = builder.zext(dst, LLVMType.IntType(64)) builder.call(fc_ptr, [self.local_vars["vmmngr"], dst_casted, src]) @@ -689,26 +704,26 @@ class LLVMFunction(): # VmMngr "get_exception_flag" return's size size = 64 - t_size = LLVMType.int(size) + t_size = LLVMType.IntType(size) # Current address pc_to_return = line.offset # Get exception flag value builder = self.builder - fc_ptr = self.mod.get_function_named("get_exception_flag") + fc_ptr = self.mod.get_global("get_exception_flag") exceptionflag = builder.call(fc_ptr, [self.local_vars["vmmngr"]]) if except_do_not_update_pc is True: auto_mod_flag = m2_csts.EXCEPT_DO_NOT_UPDATE_PC - m2_flag = llvm_c.Constant.int(t_size, auto_mod_flag) + m2_flag = llvm_ir.Constant(t_size, auto_mod_flag) exceptionflag = builder.and_(exceptionflag, m2_flag) # Compute cond - zero_casted = llvm_c.Constant.int(t_size, 0) - condition_bool = builder.icmp(llvm_c.ICMP_NE, - exceptionflag, - zero_casted) + zero_casted = llvm_ir.Constant(t_size, 0) + condition_bool = builder.icmp_unsigned("!=", + exceptionflag, + zero_casted) # Create bbls branch_id = self.new_branch_name() @@ -723,7 +738,7 @@ class LLVMFunction(): # Then Bloc builder.position_at_end(then_block) - self.set_ret(llvm_c.Constant.int(self.ret_type, pc_to_return)) + self.set_ret(llvm_ir.Constant(self.ret_type, pc_to_return)) builder.position_at_end(merge_block) @@ -741,13 +756,13 @@ class LLVMFunction(): if self.log_regs is True: # Call dump general purpose registers - fc_ptr = self.mod.get_function_named("dump_gpregs") + fc_ptr = self.mod.get_global("dump_gpregs") builder.call(fc_ptr, [self.local_vars["vmcpu"]]) def add_bloc(self, bloc, lines): "Add a bloc of instruction in the current function" - for instruction, line in zip(bloc, lines): + for assignblk, line in zip(bloc, lines): new_reg = set() # Check general errors only at the beggining of instruction @@ -756,23 +771,24 @@ class LLVMFunction(): self.check_error(line) # Log mn and registers if options is set - self.log_instruction(instruction, line) + self.log_instruction(assignblk, line) # Pass on empty instruction - if len(instruction) == 0: + if not assignblk: continue - for expression in instruction: + for dst, src in assignblk.iteritems(): # Apply preinit transformation for func in self.llvm_context.IR_transformation_functions: - expression = func(expression) + dst = func(dst) + src = func(src) # Treat current expression - self.affect(expression.src, expression.dst) + self.affect(src, dst) # Save registers updated - new_reg.update(expression.dst.get_w()) + new_reg.update(dst.get_w()) # Check for errors (without updating PC) self.check_error(line, except_do_not_update_pc=True) @@ -795,12 +811,12 @@ class LLVMFunction(): # Build function signature self.my_args.append((m2_expr.ExprId("vmcpu"), - llvm_c.PointerType.pointer(LLVMType.int(8)), + llvm_ir.PointerType.pointer(LLVMType.IntType(8)), "vmcpu")) self.my_args.append((m2_expr.ExprId("vmmngr"), - llvm_c.PointerType.pointer(LLVMType.int(8)), + llvm_ir.PointerType.pointer(LLVMType.IntType(8)), "vmmngr")) - self.ret_type = LLVMType.int(final_expr.size) + self.ret_type = LLVMType.IntType(final_expr.size) # Initialise the function self.init_fc() @@ -881,10 +897,10 @@ class LLVMFunction(): if isinstance(dest, m2_expr.ExprCond): # Compute cond cond = self.add_ir(dest.cond) - zero_casted = llvm_c.Constant.int(LLVMType.int(dest.cond.size), - 0) - condition_bool = builder.icmp(llvm_c.ICMP_NE, cond, - zero_casted) + zero_casted = llvm_ir.Constant(LLVMType.IntType(dest.cond.size), + 0) + condition_bool = builder.icmp_unsigned("!=", cond, + zero_casted) # Create bbls branch_id = self.new_branch_name() @@ -907,6 +923,9 @@ class LLVMFunction(): elif isinstance(dest, m2_expr.ExprSlice): self.gen_ret_or_branch(dest) + elif isinstance(dest, m2_expr.ExprMem): + self.set_ret(self.add_ir(m2_expr.ExprId("IRDst"))) + else: raise Exception("Bloc dst has to be an ExprId or an ExprCond") @@ -916,14 +935,14 @@ class LLVMFunction(): # Build function signature self.my_args.append((m2_expr.ExprId("vmcpu"), - llvm_c.PointerType.pointer(LLVMType.int(8)), + llvm_ir.PointerType(LLVMType.IntType(8)), "vmcpu")) self.my_args.append((m2_expr.ExprId("vmmngr"), - llvm_c.PointerType.pointer(LLVMType.int(8)), + llvm_ir.PointerType(LLVMType.IntType(8)), "vmmngr")) ret_size = 64 - self.ret_type = LLVMType.int(ret_size) + self.ret_type = LLVMType.IntType(ret_size) # Initialise the function self.init_fc() @@ -978,9 +997,19 @@ class LLVMFunction(): def get_function_pointer(self): "Return a pointer on the Jitted function" - e = self.llvm_context.get_execengine() - - return e.get_pointer_to_function(self.fc) + # Parse our generated module + mod = llvm.parse_assembly( str( self.mod ) ) + mod.verify() + # Now add the module and make sure it is ready for execution + target = llvm.Target.from_default_triple() + target_machine = target.create_target_machine() + engine = llvm.create_mcjit_compiler(mod, + target_machine) + engine.finalize_object() + + # For debug: obj_bin = target_machine.emit_object(mod) + self.llvm_context.engines.append(engine) + return engine.get_function_address(self.fc.name) # TODO: # - Add more expressions diff --git a/miasm2/jitter/vm_mngr.c b/miasm2/jitter/vm_mngr.c index a8cc7639..5dd844c3 100644 --- a/miasm2/jitter/vm_mngr.c +++ b/miasm2/jitter/vm_mngr.c @@ -76,6 +76,11 @@ const uint8_t parity_table[256] = { 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, }; +uint8_t parity(uint64_t a) { + return parity_table[(a) & 0xFF]; +} + + // #define DEBUG_MIASM_AUTOMOD_CODE void memory_access_list_init(struct memory_access_list * access) diff --git a/miasm2/jitter/vm_mngr.h b/miasm2/jitter/vm_mngr.h index d3583b52..88ecf34d 100644 --- a/miasm2/jitter/vm_mngr.h +++ b/miasm2/jitter/vm_mngr.h @@ -194,7 +194,7 @@ int vm_write_mem(vm_mngr_t* vm_mngr, uint64_t addr, char *buffer, uint64_t size) extern const uint8_t parity_table[256]; -#define parity(a) (parity_table[(a) & 0xFF]) +uint8_t parity(uint64_t a); unsigned int my_imul08(unsigned int a, unsigned int b); diff --git a/test/test_all.py b/test/test_all.py index 62f1cd4b..78e97be1 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -55,7 +55,7 @@ class ArchUnitTest(RegressionTest): # script -> blacklisted jitter blacklist = { - "x86/unit/mn_float.py": ["python"], + "x86/unit/mn_float.py": ["python", "llvm"], } for script in ["x86/sem.py", "x86/unit/mn_strings.py", @@ -684,7 +684,7 @@ By default, no tag is omitted." % ", ".join(TAGS.keys()), default="") # Handle llvm modularity llvm = True try: - import llvm + import llvmlite except ImportError: llvm = False @@ -695,9 +695,6 @@ By default, no tag is omitted." % ", ".join(TAGS.keys()), default="") except ImportError: tcc = False - # TODO XXX: fix llvm jitter (deactivated for the moment) - llvm = False - if llvm is False: print "%(red)s[LLVM]%(end)s Python" % cosmetics.colors + \ "'py-llvm 3.2' module is required for llvm tests" |