diff options
Diffstat (limited to 'miasm2/arch/mips32')
| -rw-r--r-- | miasm2/arch/mips32/arch.py | 91 | ||||
| -rw-r--r-- | miasm2/arch/mips32/jit.py | 38 | ||||
| -rw-r--r-- | miasm2/arch/mips32/regs.py | 13 | ||||
| -rw-r--r-- | miasm2/arch/mips32/sem.py | 42 |
4 files changed, 133 insertions, 51 deletions
diff --git a/miasm2/arch/mips32/arch.py b/miasm2/arch/mips32/arch.py index 3abdc053..15c59cf0 100644 --- a/miasm2/arch/mips32/arch.py +++ b/miasm2/arch/mips32/arch.py @@ -5,11 +5,13 @@ from collections import defaultdict from pyparsing import Literal, Group, Optional -from miasm2.expression.expression import ExprMem, ExprInt, ExprId +from miasm2.expression.expression import ExprMem, ExprInt, ExprId, ExprOp from miasm2.core.bin_stream import bin_stream import miasm2.arch.mips32.regs as regs import miasm2.core.cpu as cpu +from miasm2.core.asm_ast import AstInt, AstId, AstMem, AstOp + log = logging.getLogger("mips32dis") console_handler = logging.StreamHandler() console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) @@ -20,48 +22,26 @@ log.setLevel(logging.DEBUG) gpregs = cpu.reg_info(regs.regs32_str, regs.regs32_expr) - LPARENTHESIS = Literal("(") RPARENTHESIS = Literal(")") -def deref2expr(s, l, t): - t = t[0] - if len(t) != 4: +def cb_deref(tokens): + if len(tokens) != 4: raise NotImplementedError("TODO") + return AstMem(tokens[2] + tokens[0], 32) - return ExprMem(t[2] + t[0], 32) - -def deref2expr_nooff(s, l, t): - t = t[0] - if len(t) != 3: +def cb_deref_nooff(tokens): + if len(tokens) != 3: raise NotImplementedError("TODO") - return ExprMem(t[1], 32) + return AstMem(tokens[1], 32) base_expr = cpu.base_expr -deref_off = Group(Optional(cpu.base_expr) + LPARENTHESIS + gpregs.parser + \ - RPARENTHESIS).setParseAction(deref2expr) -deref_nooff = Group(LPARENTHESIS + gpregs.parser + \ - RPARENTHESIS).setParseAction(deref2expr_nooff) +deref_off = (Optional(base_expr) + LPARENTHESIS + gpregs.parser + RPARENTHESIS).setParseAction(cb_deref) +deref_nooff = (LPARENTHESIS + gpregs.parser + RPARENTHESIS).setParseAction(cb_deref_nooff) deref = deref_off | deref_nooff -variable, operand, base_expr = cpu.gen_base_expr() - -int_or_expr = base_expr - - -def ast_id2expr(t): - return mn_mips32.regs.all_regs_ids_byname.get(t, t) - - -def ast_int2expr(a): - return ExprInt(a, 32) - - -my_var_parser = cpu.ParseAst(ast_id2expr, ast_int2expr) -base_expr.setParseAction(my_var_parser) - class additional_info: def __init__(self): self.except_on_instr = False @@ -274,8 +254,31 @@ def mips32op(name, fields, args=None, alias=False): type(name, (mn_mips32,), dct) #type(name, (mn_mips32b,), dct) - -class mips32_reg(cpu.reg_noarg, cpu.m_arg): +class mips32_arg(cpu.m_arg): + def asm_ast_to_expr(self, arg, symbol_pool): + if isinstance(arg, AstId): + if isinstance(arg.name, ExprId): + return arg.name + if arg.name in gpregs.str: + return None + label = symbol_pool.getby_name_create(arg.name) + return ExprId(label, 32) + if isinstance(arg, AstOp): + args = [self.asm_ast_to_expr(tmp, symbol_pool) for tmp in arg.args] + if None in args: + return None + return ExprOp(arg.op, *args) + if isinstance(arg, AstInt): + return ExprInt(arg.value, 32) + if isinstance(arg, AstMem): + ptr = self.asm_ast_to_expr(arg.ptr, symbol_pool) + if ptr is None: + return None + return ExprMem(ptr, arg.size) + return None + + +class mips32_reg(cpu.reg_noarg, mips32_arg): pass class mips32_gpreg(mips32_reg): @@ -335,14 +338,14 @@ class mips32_soff_noarg(mips32_imm): return True -class mips32_s16imm(mips32_s16imm_noarg, cpu.m_arg): +class mips32_s16imm(mips32_s16imm_noarg, mips32_arg): pass -class mips32_soff(mips32_soff_noarg, cpu.m_arg): +class mips32_soff(mips32_soff_noarg, mips32_arg): pass -class mips32_instr_index(mips32_imm, cpu.m_arg): +class mips32_instr_index(mips32_imm, mips32_arg): def decode(self, v): v = v & self.lmask self.expr = ExprInt(v<<2, 32) @@ -361,7 +364,7 @@ class mips32_instr_index(mips32_imm, cpu.m_arg): return True -class mips32_u16imm(mips32_imm, cpu.m_arg): +class mips32_u16imm(mips32_imm, mips32_arg): def decode(self, v): v = v & self.lmask self.expr = ExprInt(v, 32) @@ -375,7 +378,7 @@ class mips32_u16imm(mips32_imm, cpu.m_arg): self.value = v return True -class mips32_dreg_imm(cpu.m_arg): +class mips32_dreg_imm(mips32_arg): parser = deref def decode(self, v): imm = self.parent.imm.expr @@ -408,7 +411,7 @@ class mips32_dreg_imm(cpu.m_arg): assert(len(arg.args) == 2 and arg.op == '+') return "%s(%s)"%(arg.args[1], arg.args[0]) -class mips32_esize(mips32_imm, cpu.m_arg): +class mips32_esize(mips32_imm, mips32_arg): def decode(self, v): v = v & self.lmask self.expr = ExprInt(v+1, 32) @@ -422,7 +425,7 @@ class mips32_esize(mips32_imm, cpu.m_arg): self.value = v return True -class mips32_eposh(mips32_imm, cpu.m_arg): +class mips32_eposh(mips32_imm, mips32_arg): def decode(self, v): self.expr = ExprInt(v-int(self.parent.epos.expr)+1, 32) return True @@ -437,7 +440,7 @@ class mips32_eposh(mips32_imm, cpu.m_arg): -class mips32_cpr(cpu.m_arg): +class mips32_cpr(mips32_arg): parser = regs.regs_cpr0_info.parser def decode(self, v): index = int(self.parent.cpr0.expr) << 3 @@ -605,6 +608,8 @@ bs_bcc = cpu.bs_name(l=5, name = {"BGEZ": 0b00001, }) +bs_code = cpu.bs(l=10) + mips32op("addi", [cpu.bs('001000'), rs, rt, s16imm], [rt, rs, s16imm]) mips32op("addiu", [cpu.bs('001001'), rs, rt, s16imm], [rt, rs, s16imm]) @@ -740,3 +745,7 @@ mips32op("tlbp", [cpu.bs('010000'), cpu.bs('1'), cpu.bs('0'*19), cpu.bs('001000')]) mips32op("tlbwi", [cpu.bs('010000'), cpu.bs('1'), cpu.bs('0'*19), cpu.bs('000010')]) + + +mips32op("teq", [cpu.bs('000000'), rs, rt, bs_code, cpu.bs('110100')], + [rs, rt]) diff --git a/miasm2/arch/mips32/jit.py b/miasm2/arch/mips32/jit.py index 1d2ec483..16d88067 100644 --- a/miasm2/arch/mips32/jit.py +++ b/miasm2/arch/mips32/jit.py @@ -1,6 +1,6 @@ import logging -from miasm2.jitter.jitload import jitter +from miasm2.jitter.jitload import jitter, named_arguments from miasm2.core import asmblock from miasm2.core.utils import pck32, upck32 from miasm2.arch.mips32.sem import ir_mips32l, ir_mips32b @@ -104,6 +104,42 @@ class jitter_mips32l(jitter): jitter.init_run(self, *args, **kwargs) self.cpu.PC = self.pc + # calling conventions + + @named_arguments + def func_args_stdcall(self, n_args): + args = [self.get_arg_n_stdcall(i) for i in xrange(n_args)] + ret_ad = self.cpu.RA + return ret_ad, args + + def func_ret_stdcall(self, ret_addr, ret_value1=None, ret_value2=None): + self.pc = self.cpu.PC = ret_addr + if ret_value1 is not None: + self.cpu.V0 = ret_value1 + if ret_value2 is not None: + self.cpu.V1 = ret_value2 + return True + + def func_prepare_stdcall(self, ret_addr, *args): + for index in xrange(min(len(args), 4)): + setattr(self.cpu, 'A%d' % index, args[index]) + for index in xrange(4, len(args)): + self.vm.set_mem(self.cpu.SP + 4 * (index - 4), pck32(args[index])) + self.cpu.RA = ret_addr + + def get_arg_n_stdcall(self, index): + if index < 4: + arg = getattr(self.cpu, 'A%d' % index) + else: + arg = self.get_stack_arg(index-4) + return arg + + + func_args_systemv = func_args_stdcall + func_ret_systemv = func_ret_stdcall + func_prepare_systemv = func_prepare_stdcall + get_arg_n_systemv = get_arg_n_stdcall + class jitter_mips32b(jitter_mips32l): diff --git a/miasm2/arch/mips32/regs.py b/miasm2/arch/mips32/regs.py index afade869..7ff949f2 100644 --- a/miasm2/arch/mips32/regs.py +++ b/miasm2/arch/mips32/regs.py @@ -4,11 +4,11 @@ from miasm2.expression.expression import ExprId from miasm2.core.cpu import gen_reg, gen_regs -gen_reg('PC', globals()) -gen_reg('PC_FETCH', globals()) +PC, _ = gen_reg('PC') +PC_FETCH, _ = gen_reg('PC_FETCH') -gen_reg('R_LO', globals()) -gen_reg('R_HI', globals()) +R_LO, _ = gen_reg('R_LO') +R_HI, _ = gen_reg('R_HI') exception_flags = ExprId('exception_flags', 32) @@ -55,11 +55,10 @@ regs_flt_expr, regs_flt_init, fltregs = gen_regs(regs_flt_str, globals(), sz=64) regs_fcc_expr, regs_fcc_init, fccregs = gen_regs(regs_fcc_str, globals()) -all_regs_ids = [PC, PC_FETCH, R_LO, R_HI] + gpregs_expr + regs_flt_expr + \ +all_regs_ids = [PC, PC_FETCH, R_LO, R_HI, exception_flags] + gpregs_expr + regs_flt_expr + \ regs_fcc_expr + regs_cpr0_expr all_regs_ids_byname = dict([(x.name, x) for x in all_regs_ids]) -all_regs_ids_init = [PC_init, PC_FETCH_init, R_LO_init, R_HI_init] + \ - gpregs_init + regs_flt_init + regs_fcc_init + regs_cpr0_init +all_regs_ids_init = [ExprId("%s_init" % reg.name, reg.size) for reg in all_regs_ids] all_regs_ids_no_alias = all_regs_ids[:] attrib_to_regs = { diff --git a/miasm2/arch/mips32/sem.py b/miasm2/arch/mips32/sem.py index 789491f6..99c81a33 100644 --- a/miasm2/arch/mips32/sem.py +++ b/miasm2/arch/mips32/sem.py @@ -1,8 +1,9 @@ import miasm2.expression.expression as m2_expr -from miasm2.ir.ir import IntermediateRepresentation, IRBlock +from miasm2.ir.ir import IntermediateRepresentation, IRBlock, AssignBlock from miasm2.arch.mips32.arch import mn_mips32 -from miasm2.arch.mips32.regs import R_LO, R_HI, PC, RA +from miasm2.arch.mips32.regs import R_LO, R_HI, PC, RA, exception_flags from miasm2.core.sembuilder import SemBuilder +from miasm2.jitter.csts import EXCEPT_DIV_BY_ZERO # SemBuilder context @@ -377,6 +378,18 @@ def multu(arg1, arg2): R_HI = result[32:] @sbuild.parse +def div(arg1, arg2): + """Divide (signed) @arg1 by @arg2 and stores the remaining/result in $R_HI/$R_LO""" + R_LO = ExprOp('idiv' ,arg1, arg2) + R_HI = ExprOp('imod', arg1, arg2) + +@sbuild.parse +def divu(arg1, arg2): + """Divide (unsigned) @arg1 by @arg2 and stores the remaining/result in $R_HI/$R_LO""" + R_LO = ExprOp('udiv', arg1, arg2) + R_HI = ExprOp('umod', arg1, arg2) + +@sbuild.parse def mfhi(arg1): "The contents of register $R_HI are moved to the specified register @arg1." arg1 = R_HI @@ -398,6 +411,30 @@ def ei(arg1): def ehb(arg1): "NOP" + +def teq(ir, instr, arg1, arg2): + e = [] + + lbl_except, lbl_except_expr = ir.gen_label_and_expr(ir.IRDst.size) + lbl_next = ir.get_next_label(instr) + lbl_next_expr = m2_expr.ExprId(lbl_next, ir.IRDst.size) + + do_except = [] + do_except.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt( + EXCEPT_DIV_BY_ZERO, exception_flags.size))) + do_except.append(m2_expr.ExprAff(ir.IRDst, lbl_next_expr)) + blk_except = IRBlock(lbl_except, [AssignBlock(do_except, instr)]) + + cond = arg1 - arg2 + + + e = [] + e.append(m2_expr.ExprAff(ir.IRDst, + m2_expr.ExprCond(cond, lbl_next_expr, lbl_except_expr))) + + return e, [blk_except] + + mnemo_func = sbuild.functions mnemo_func.update({ 'add.d': add_d, @@ -423,6 +460,7 @@ mnemo_func.update({ 'subu': l_sub, 'xor': l_xor, 'xori': l_xor, + 'teq': teq, }) def get_mnemo_expr(ir, instr, *args): |