diff options
| -rw-r--r-- | miasm2/analysis/machine.py | 5 | ||||
| -rw-r--r-- | miasm2/arch/arm/jit.py | 58 | ||||
| -rw-r--r-- | miasm2/arch/arm/sem.py | 113 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_arm.c | 10 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_arm.h | 7 | ||||
| -rw-r--r-- | miasm2/jitter/codegen.py | 2 | ||||
| -rw-r--r-- | miasm2/jitter/jitload.py | 3 | ||||
| -rw-r--r-- | miasm2/jitter/llvmconvert.py | 4 |
8 files changed, 200 insertions, 2 deletions
diff --git a/miasm2/analysis/machine.py b/miasm2/analysis/machine.py index f361b412..73b90aef 100644 --- a/miasm2/analysis/machine.py +++ b/miasm2/analysis/machine.py @@ -79,6 +79,11 @@ class Machine(object): mn = arch.mn_armt from miasm2.arch.arm.ira import ir_a_armtl as ira from miasm2.arch.arm.sem import ir_armtl as ir + try: + from miasm2.arch.arm import jit + jitter = jit.jitter_armtl + except ImportError: + pass elif machine_name == "armtb": from miasm2.arch.arm.disasm import dis_armtb as dis_engine from miasm2.arch.arm import arch diff --git a/miasm2/arch/arm/jit.py b/miasm2/arch/arm/jit.py index b07f2a38..1a37b7f1 100644 --- a/miasm2/arch/arm/jit.py +++ b/miasm2/arch/arm/jit.py @@ -3,7 +3,10 @@ import logging from miasm2.jitter.jitload import jitter, named_arguments from miasm2.core import asmblock from miasm2.core.utils import pck32, upck32 -from miasm2.arch.arm.sem import ir_armb, ir_arml +from miasm2.arch.arm.sem import ir_armb, ir_arml, ir_armtl, ir_armtb, cond_dct_inv, tab_cond +from miasm2.jitter.codegen import CGen +from miasm2.expression.expression import ExprId, ExprAff, ExprCond +from miasm2.ir.ir import IRBlock, AssignBlock log = logging.getLogger('jit_arm') hnd = logging.StreamHandler() @@ -11,7 +14,49 @@ hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s")) log.addHandler(hnd) log.setLevel(logging.CRITICAL) + + +class arm_CGen(CGen): + def __init__(self, ir_arch): + self.ir_arch = ir_arch + self.PC = self.ir_arch.arch.regs.PC + self.init_arch_C() + + + def block2assignblks(self, block): + """ + Return the list of irblocks for a native @block + @block: AsmBlock + """ + irblocks_list = [] + index = -1 + while index + 1 < len(block.lines): + index += 1 + instr = block.lines[index] + + if instr.name.startswith("IT"): + assignments = [] + label = self.ir_arch.get_instr_label(instr) + irblocks = [] + index, irblocks = self.ir_arch.do_it_block(label, index, block, assignments, True) + irblocks_list += irblocks + continue + + + assignblk_head, assignblks_extra = self.ir_arch.instr2ir(instr) + # Keep result in ordered list as first element is the assignblk head + # The remainings order is not really important + irblock_head = self.assignblk_to_irbloc(instr, assignblk_head) + irblocks = [irblock_head] + assignblks_extra + + for irblock in irblocks: + assert irblock.dst is not None + irblocks_list.append(irblocks) + return irblocks_list + + class jitter_arml(jitter): + C_Gen = arm_CGen def __init__(self, *args, **kwargs): sp = asmblock.AsmSymbolPool() @@ -69,9 +114,20 @@ class jitter_arml(jitter): jitter.init_run(self, *args, **kwargs) self.cpu.PC = self.pc + class jitter_armb(jitter_arml): + C_Gen = arm_CGen def __init__(self, *args, **kwargs): sp = asmblock.AsmSymbolPool() jitter.__init__(self, ir_armb(sp), *args, **kwargs) self.vm.set_big_endian() + + +class jitter_armtl(jitter_arml): + C_Gen = arm_CGen + + def __init__(self, *args, **kwargs): + sp = asmblock.AsmSymbolPool() + jitter.__init__(self, ir_armtl(sp), *args, **kwargs) + self.vm.set_little_endian() diff --git a/miasm2/arch/arm/sem.py b/miasm2/arch/arm/sem.py index d4efba84..9e4da3f6 100644 --- a/miasm2/arch/arm/sem.py +++ b/miasm2/arch/arm/sem.py @@ -1222,6 +1222,7 @@ cond_dct = { # COND_NV: "NV", } +cond_dct_inv = dict((name, num) for num, name in cond_dct.iteritems()) tab_cond = {COND_EQ: zf, COND_NE: ExprCond(zf, ExprInt(0, 1), ExprInt(1, 1)), @@ -1512,6 +1513,118 @@ class ir_arml(IntermediateRepresentation): self.mod_pc(instr, instr_ir, extra_ir) return instr_ir, extra_ir + def parse_itt(self, instr): + name = instr.name + assert name.startswith('IT') + name = name[1:] + out = [] + for hint in name: + if hint == 'T': + out.append(0) + elif hint == "E": + out.append(1) + else: + raise ValueError("IT name invalid %s" % instr) + return out, instr.args[0] + + def do_it_block(self, label, index, block, assignments, gen_pc_updt): + instr = block.lines[index] + it_hints, it_cond = self.parse_itt(instr) + cond_num = cond_dct_inv[it_cond.name] + cond_eq = tab_cond[cond_num] + + if not index + len(it_hints) <= len(block.lines): + raise NotImplementedError("Splitted IT block non supported yet") + + ir_blocks_all = [] + + # Gen dummy irblock for IT instr + label_next = self.get_next_label(instr) + dst = ExprAff(self.IRDst, ExprId(label_next, 32)) + dst_blk = AssignBlock([dst], instr) + assignments.append(dst_blk) + irblock = IRBlock(label, assignments) + ir_blocks_all.append([irblock]) + + label = label_next + assignments = [] + for hint in it_hints: + irblocks = [] + index += 1 + instr = block.lines[index] + + # Add conditionnal jump to current irblock + label_do = self.symbol_pool.gen_label() + label_next = self.get_next_label(instr) + + if hint: + local_cond = ~cond_eq + else: + local_cond = cond_eq + dst = ExprAff(self.IRDst, ExprCond(local_cond, ExprId(label_do, 32), ExprId(label_next, 32))) + dst_blk = AssignBlock([dst], instr) + assignments.append(dst_blk) + irblock = IRBlock(label, assignments) + + irblocks.append(irblock) + + assignments = [] + label = label_do + split = self.add_instr_to_irblock(block, instr, assignments, + irblocks, gen_pc_updt) + if split: + raise NotImplementedError("Unsupported instr in IT block (%s)" % instr) + + dst = ExprAff(self.IRDst, ExprId(label_next, 32)) + dst_blk = AssignBlock([dst], instr) + assignments.append(dst_blk) + irblock = IRBlock(label, assignments) + irblocks.append(irblock) + label = label_next + assignments = [] + ir_blocks_all.append(irblocks) + return index, ir_blocks_all + + def add_block(self, block, gen_pc_updt=False): + """ + Add a native block to the current IR + @block: native assembly block + @gen_pc_updt: insert PC update effects between instructions + """ + + it_hints = None + it_cond = None + label = None + ir_blocks_all = [] + index = -1 + while index + 1 < len(block.lines): + index += 1 + instr = block.lines[index] + if label is None: + assignments = [] + label = self.get_instr_label(instr) + if instr.name.startswith("IT"): + index, irblocks_it = self.do_it_block(label, index, block, assignments, gen_pc_updt) + for irblocks in irblocks_it: + ir_blocks_all += irblocks + label = None + continue + + split = self.add_instr_to_irblock(block, instr, assignments, + ir_blocks_all, gen_pc_updt) + if split: + ir_blocks_all.append(IRBlock(label, assignments)) + label = None + assignments = [] + if label is not None: + ir_blocks_all.append(IRBlock(label, assignments)) + + new_ir_blocks_all = self.post_add_block(block, ir_blocks_all) + for irblock in new_ir_blocks_all: + self.blocks[irblock.label] = irblock + return new_ir_blocks_all + + class ir_armb(ir_arml): def __init__(self, symbol_pool=None): diff --git a/miasm2/jitter/arch/JitCore_arm.c b/miasm2/jitter/arch/JitCore_arm.c index 93fab030..cce0997d 100644 --- a/miasm2/jitter/arch/JitCore_arm.c +++ b/miasm2/jitter/arch/JitCore_arm.c @@ -186,6 +186,16 @@ void check_automod(JitCpu* jitcpu, uint64_t addr, uint64_t size) } + +UDIV(32) + +UMOD(32) + +IDIV(32) + +IMOD(32) + + void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) { vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); diff --git a/miasm2/jitter/arch/JitCore_arm.h b/miasm2/jitter/arch/JitCore_arm.h index 3e531fa9..445ac44a 100644 --- a/miasm2/jitter/arch/JitCore_arm.h +++ b/miasm2/jitter/arch/JitCore_arm.h @@ -38,6 +38,13 @@ typedef struct { void dump_gpregs(vm_cpu_t* vmcpu); + +uint32_t udiv32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b); +uint32_t umod32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b); +int32_t idiv32(vm_cpu_t* vmcpu, int32_t a, int32_t b); +int32_t imod32(vm_cpu_t* vmcpu, int32_t a, int32_t b); + + #define RETURN_PC return BlockDst; uint32_t clz(uint32_t arg); diff --git a/miasm2/jitter/codegen.py b/miasm2/jitter/codegen.py index 9ed55f37..2c546be8 100644 --- a/miasm2/jitter/codegen.py +++ b/miasm2/jitter/codegen.py @@ -572,7 +572,7 @@ class CGen(object): irblocks_list = self.block2assignblks(block) out, instr_offsets = self.gen_init(block) - + assert len(block.lines) == len(irblocks_list) for instr, irblocks in zip(block.lines, irblocks_list): instr_attrib, irblocks_attributes = self.get_attributes(instr, irblocks, log_mn, log_regs) diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py index 499d6c47..8eb7659e 100644 --- a/miasm2/jitter/jitload.py +++ b/miasm2/jitter/jitload.py @@ -182,6 +182,9 @@ class jitter(object): from miasm2.jitter.arch import JitCore_x86 as jcore elif arch_name == "arm": from miasm2.jitter.arch import JitCore_arm as jcore + elif arch_name == "armt": + from miasm2.jitter.arch import JitCore_arm as jcore + ir_arch.arch.name = 'arm' elif arch_name == "aarch64": from miasm2.jitter.arch import JitCore_aarch64 as jcore elif arch_name == "msp430": diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py index 0e4368a8..35db1538 100644 --- a/miasm2/jitter/llvmconvert.py +++ b/miasm2/jitter/llvmconvert.py @@ -180,6 +180,10 @@ class LLVMContext_JIT(LLVMContext): from miasm2.arch.mips32.jit import mipsCGen self.cgen_class = mipsCGen self.has_delayslot = True + elif arch.name == "arm": + from miasm2.arch.arm.jit import arm_CGen + self.cgen_class = arm_CGen + self.has_delayslot = False else: self.cgen_class = CGen self.has_delayslot = False |