Top

miasm2.arch.aarch64.sem module

from miasm2.expression.expression import ExprId, ExprInt, ExprLoc, ExprMem, \
    ExprSlice, ExprCond, ExprCompose, ExprOp, ExprAff
from miasm2.ir.ir import IntermediateRepresentation, IRBlock, AssignBlock
from miasm2.arch.aarch64.arch import mn_aarch64, conds_expr, replace_regs
from miasm2.arch.aarch64.regs import *
from miasm2.core.sembuilder import SemBuilder
from miasm2.jitter.csts import EXCEPT_DIV_BY_ZERO, EXCEPT_INT_XX


# CPSR: N Z C V


def update_flag_zf(a):
    return [ExprAff(zf, ExprOp("FLAG_EQ", a))]


def update_flag_zf_eq(a, b):
    return [ExprAff(zf, ExprOp("FLAG_EQ_CMP", a, b))]


def update_flag_nf(arg):
    return [
        ExprAff(
            nf,
            ExprOp("FLAG_SIGN_SUB", arg, ExprInt(0, arg.size))
        )
    ]


def update_flag_zn(a):
    e = []
    e += update_flag_zf(a)
    e += update_flag_nf(a)
    return e


def check_ops_msb(a, b, c):
    if not a or not b or not c or a != b or a != c:
        raise ValueError('bad ops size %s %s %s' % (a, b, c))


def update_flag_add_cf(op1, op2):
    "Compute cf in @op1 + @op2"
    return [ExprAff(cf, ExprOp("FLAG_ADD_CF", op1, op2))]


def update_flag_add_of(op1, op2):
    "Compute of in @op1 + @op2"
    return [ExprAff(of, ExprOp("FLAG_ADD_OF", op1, op2))]


def update_flag_sub_cf(op1, op2):
    "Compote CF in @op1 - @op2"
    return [ExprAff(cf, ExprOp("FLAG_SUB_CF", op1, op2) ^ ExprInt(1, 1))]


def update_flag_sub_of(op1, op2):
    "Compote OF in @op1 - @op2"
    return [ExprAff(of, ExprOp("FLAG_SUB_OF", op1, op2))]


def update_flag_arith_add_co(arg1, arg2):
    e = []
    e += update_flag_add_cf(arg1, arg2)
    e += update_flag_add_of(arg1, arg2)
    return e


def update_flag_arith_add_zn(arg1, arg2):
    """
    Compute zf and nf flags for (arg1 + arg2)
    """
    e = []
    e += update_flag_zf_eq(arg1, -arg2)
    e += [ExprAff(nf, ExprOp("FLAG_SIGN_SUB", arg1, -arg2))]
    return e


def update_flag_arith_sub_co(arg1, arg2):
    """
    Compute cf and of flags for (arg1 - arg2)
    """
    e = []
    e += update_flag_sub_cf(arg1, arg2)
    e += update_flag_sub_of(arg1, arg2)
    return e


def update_flag_arith_sub_zn(arg1, arg2):
    """
    Compute zf and nf flags for (arg1 - arg2)
    """
    e = []
    e += update_flag_zf_eq(arg1, arg2)
    e += [ExprAff(nf, ExprOp("FLAG_SIGN_SUB", arg1, arg2))]
    return e




def update_flag_zfaddwc_eq(arg1, arg2, arg3):
    return [ExprAff(zf, ExprOp("FLAG_EQ_ADDWC", arg1, arg2, arg3))]

def update_flag_zfsubwc_eq(arg1, arg2, arg3):
    return [ExprAff(zf, ExprOp("FLAG_EQ_SUBWC", arg1, arg2, arg3))]


def update_flag_arith_addwc_zn(arg1, arg2, arg3):
    """
    Compute znp flags for (arg1 + arg2 + cf)
    """
    e = []
    e += update_flag_zfaddwc_eq(arg1, arg2, arg3)
    e += [ExprAff(nf, ExprOp("FLAG_SIGN_ADDWC", arg1, arg2, arg3))]
    return e


def update_flag_arith_subwc_zn(arg1, arg2, arg3):
    """
    Compute znp flags for (arg1 - (arg2 + cf))
    """
    e = []
    e += update_flag_zfsubwc_eq(arg1, arg2, arg3)
    e += [ExprAff(nf, ExprOp("FLAG_SIGN_SUBWC", arg1, arg2, arg3))]
    return e


def update_flag_addwc_cf(op1, op2, op3):
    "Compute cf in @res = @op1 + @op2 + @op3"
    return [ExprAff(cf, ExprOp("FLAG_ADDWC_CF", op1, op2, op3))]


def update_flag_addwc_of(op1, op2, op3):
    "Compute of in @res = @op1 + @op2 + @op3"
    return [ExprAff(of, ExprOp("FLAG_ADDWC_OF", op1, op2, op3))]


def update_flag_arith_addwc_co(arg1, arg2, arg3):
    e = []
    e += update_flag_addwc_cf(arg1, arg2, arg3)
    e += update_flag_addwc_of(arg1, arg2, arg3)
    return e



def update_flag_subwc_cf(op1, op2, op3):
    "Compute cf in @res = @op1 + @op2 + @op3"
    return [ExprAff(cf, ExprOp("FLAG_SUBWC_CF", op1, op2, op3) ^ ExprInt(1, 1))]


def update_flag_subwc_of(op1, op2, op3):
    "Compute of in @res = @op1 + @op2 + @op3"
    return [ExprAff(of, ExprOp("FLAG_SUBWC_OF", op1, op2, op3))]


def update_flag_arith_subwc_co(arg1, arg2, arg3):
    e = []
    e += update_flag_subwc_cf(arg1, arg2, arg3)
    e += update_flag_subwc_of(arg1, arg2, arg3)
    return e


cond2expr = {'EQ': ExprOp("CC_EQ", zf),
             'NE': ExprOp("CC_NE", zf),
             'CS': ExprOp("CC_U>=", cf ^ ExprInt(1, 1)), # inv cf
             'CC': ExprOp("CC_U<", cf ^ ExprInt(1, 1)), # inv cf
             'MI': ExprOp("CC_NEG", nf),
             'PL': ExprOp("CC_POS", nf),
             'VS': ExprOp("CC_sOVR", of),
             'VC': ExprOp("CC_sNOOVR", of),
             'HI': ExprOp("CC_U>", cf ^ ExprInt(1, 1), zf), # inv cf
             'LS': ExprOp("CC_U<=", cf ^ ExprInt(1, 1), zf), # inv cf
             'GE': ExprOp("CC_S>=", nf, of),
             'LT': ExprOp("CC_S<", nf, of),
             'GT': ExprOp("CC_S>", nf, of, zf),
             'LE': ExprOp("CC_S<=", nf, of, zf),
             'AL': ExprInt(1, 1),
             'NV': ExprInt(0, 1)
             }


def extend_arg(dst, arg):
    if not isinstance(arg, ExprOp):
        return arg

    op, (reg, shift) = arg.op, arg.args
    if op == "SXTB":
        base = reg[:8].signExtend(dst.size)
        op = "<<"
    elif op == "SXTH":
        base = reg[:16].signExtend(dst.size)
        op = "<<"
    elif op == 'SXTW':
        base = reg[:32].signExtend(dst.size)
        op = "<<"
    elif op == "SXTX":
        base = reg.signExtend(dst.size)
        op = "<<"

    elif op == "UXTB":
        base = reg[:8].zeroExtend(dst.size)
        op = "<<"
    elif op == "UXTH":
        base = reg[:16].zeroExtend(dst.size)
        op = "<<"
    elif op == 'UXTW':
        base = reg[:32].zeroExtend(dst.size)
        op = "<<"
    elif op == "UXTX":
        base = reg.zeroExtend(dst.size)
        op = "<<"

    elif op in ['<<', '>>', '<<a', 'a>>', '<<<', '>>>']:
        base = reg.zeroExtend(dst.size)
    else:
        raise NotImplementedError('Unknown shifter operator')

    out = ExprOp(op, base, (shift.zeroExtend(dst.size)
                            & ExprInt(dst.size - 1, dst.size)))
    return out


# SemBuilder context
ctx = {"PC": PC,
       "LR": LR,
       "nf": nf,
       "zf": zf,
       "cf": cf,
       "of": of,
       "cond2expr": cond2expr,
       "extend_arg": extend_arg,
       "ExprId":ExprId,
       "exception_flags": exception_flags,
       "interrupt_num": interrupt_num,
       "EXCEPT_DIV_BY_ZERO": EXCEPT_DIV_BY_ZERO,
       "EXCEPT_INT_XX": EXCEPT_INT_XX,
       }

sbuild = SemBuilder(ctx)


# instruction definition ##############

@sbuild.parse
def add(arg1, arg2, arg3):
    arg1 = arg2 + extend_arg(arg2, arg3)


@sbuild.parse
def sub(arg1, arg2, arg3):
    arg1 = arg2 - extend_arg(arg2, arg3)


@sbuild.parse
def neg(arg1, arg2):
    arg1 = - arg2


@sbuild.parse
def and_l(arg1, arg2, arg3):
    arg1 = arg2 & extend_arg(arg2, arg3)


@sbuild.parse
def eor(arg1, arg2, arg3):
    arg1 = arg2 ^ extend_arg(arg2, arg3)


@sbuild.parse
def eon(arg1, arg2, arg3):
    arg1 = arg2 ^ (~extend_arg(arg2, arg3))


@sbuild.parse
def orr(arg1, arg2, arg3):
    arg1 = arg2 | extend_arg(arg2, arg3)


@sbuild.parse
def orn(arg1, arg2, arg3):
    arg1 = arg2 | (~extend_arg(arg2, arg3))


@sbuild.parse
def bic(arg1, arg2, arg3):
    arg1 = arg2 & (~extend_arg(arg2, arg3))


def bics(ir, instr, arg1, arg2, arg3):
    e = []
    tmp1, tmp2 = arg2, (~extend_arg(arg2, arg3))

    e += [ExprAff(zf, ExprOp('FLAG_EQ_AND', tmp1, tmp2))]
    e += update_flag_nf(res)

    e.append(ExprAff(arg1, res))

    e += null_flag_co()
    return e, []


@sbuild.parse
def mvn(arg1, arg2):
    arg1 = (~extend_arg(arg1, arg2))


def adds(ir, instr, arg1, arg2, arg3):
    e = []
    arg3 = extend_arg(arg2, arg3)
    res = arg2 + arg3

    e += update_flag_arith_add_zn(arg2, arg3)
    e += update_flag_arith_add_co(arg2, arg3)

    e.append(ExprAff(arg1, res))

    return e, []


def subs(ir, instr, arg1, arg2, arg3):
    e = []
    arg3 = extend_arg(arg2, arg3)
    res = arg2 - arg3


    e += update_flag_arith_sub_zn(arg2, arg3)
    e += update_flag_arith_sub_co(arg2, arg3)

    e.append(ExprAff(arg1, res))
    return e, []


def cmp(ir, instr, arg1, arg2):
    e = []
    arg2 = extend_arg(arg1, arg2)

    e += update_flag_arith_sub_zn(arg1, arg2)
    e += update_flag_arith_sub_co(arg1, arg2)

    return e, []


def cmn(ir, instr, arg1, arg2):
    e = []
    arg2 = extend_arg(arg1, arg2)
    res = arg1 + arg2


    e += update_flag_arith_add_zn(arg1, arg2)
    e += update_flag_arith_add_co(arg1, arg2)

    return e, []


def ands(ir, instr, arg1, arg2, arg3):
    e = []
    arg3 = extend_arg(arg2, arg3)
    res = arg2 & arg3

    e += [ExprAff(zf, ExprOp('FLAG_EQ_AND', arg2, arg3))]
    e += update_flag_nf(res)

    e.append(ExprAff(arg1, res))
    return e, []

def tst(ir, instr, arg1, arg2):
    e = []
    arg2 = extend_arg(arg1, arg2)
    res = arg1 & arg2

    e += [ExprAff(zf, ExprOp('FLAG_EQ_AND', arg1, arg2))]
    e += update_flag_nf(res)

    return e, []


@sbuild.parse
def lsl(arg1, arg2, arg3):
    arg1 = arg2 << (arg3 & ExprInt(arg3.size - 1, arg3.size))


@sbuild.parse
def lsr(arg1, arg2, arg3):
    arg1 = arg2 >> (arg3 & ExprInt(arg3.size - 1, arg3.size))


@sbuild.parse
def asr(arg1, arg2, arg3):
    arg1 = ExprOp(
        'a>>', arg2, (arg3 & ExprInt(arg3.size - 1, arg3.size)))


@sbuild.parse
def mov(arg1, arg2):
    arg1 = arg2


def movk(ir, instr, arg1, arg2):
    e = []
    if isinstance(arg2, ExprOp):
        assert(arg2.op == 'slice_at' and
               isinstance(arg2.args[0], ExprInt) and
               isinstance(arg2.args[1], ExprInt))
        value, shift = int(arg2.args[0].arg), int(arg2.args[1])
        e.append(
            ExprAff(arg1[shift:shift + 16], ExprInt(value, 16)))
    else:
        e.append(ExprAff(arg1[:16], ExprInt(int(arg2), 16)))

    return e, []


@sbuild.parse
def movz(arg1, arg2):
    arg1 = arg2


@sbuild.parse
def movn(arg1, arg2):
    arg1 = ~arg2


@sbuild.parse
def bl(arg1):
    PC = arg1
    ir.IRDst = arg1
    LR = ExprInt(instr.offset + instr.l, 64)

@sbuild.parse
def csel(arg1, arg2, arg3, arg4):
    cond_expr = cond2expr[arg4.name]
    arg1 = arg2 if cond_expr else arg3

def ccmp(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    if(arg2.is_int):
        arg2=ExprInt(arg2.arg.arg,arg1.size)
    default_nf = arg3[0:1]
    default_zf = arg3[1:2]
    default_cf = arg3[2:3]
    default_of = arg3[3:4]
    cond_expr = cond2expr[arg4.name]
    res = arg1 - arg2
    new_nf = nf
    new_zf = update_flag_zf(res)[0].src
    new_cf = update_flag_sub_cf(arg1, arg2, res).src
    new_of = update_flag_sub_of(arg1, arg2, res).src

    e.append(ExprAff(nf, ExprCond(cond_expr,
                                                    new_nf,
                                                    default_nf)))
    e.append(ExprAff(zf, ExprCond(cond_expr,
                                                    new_zf,
                                                    default_zf)))
    e.append(ExprAff(cf, ExprCond(cond_expr,
                                                    new_cf,
                                                    default_cf)))
    e.append(ExprAff(of, ExprCond(cond_expr,
                                                    new_of,
                                                    default_of)))
    return e, []


def csinc(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    cond_expr = cond2expr[arg4.name]
    e.append(
        ExprAff(
            arg1,
            ExprCond(
                cond_expr,
                arg2,
                arg3 + ExprInt(1, arg3.size)
            )
        )
    )
    return e, []


def csinv(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    cond_expr = cond2expr[arg4.name]
    e.append(
        ExprAff(
            arg1,
            ExprCond(
                cond_expr,
                arg2,
                ~arg3)
        )
    )
    return e, []


def csneg(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    cond_expr = cond2expr[arg4.name]
    e.append(
        ExprAff(
            arg1,
            ExprCond(
                cond_expr,
                arg2,
                -arg3)
        )
    )
    return e, []


def cset(ir, instr, arg1, arg2):
    e = []
    cond_expr = cond2expr[arg2.name]
    e.append(
        ExprAff(
            arg1,
            ExprCond(
                cond_expr,
                ExprInt(1, arg1.size),
                ExprInt(0, arg1.size)
            )
        )
    )
    return e, []


def csetm(ir, instr, arg1, arg2):
    e = []
    cond_expr = cond2expr[arg2.name]
    e.append(
        ExprAff(
            arg1,
            ExprCond(
                cond_expr,
                ExprInt(-1, arg1.size),
                ExprInt(0, arg1.size)
            )
        )
    )
    return e, []


def get_mem_access(mem):
    updt = None
    if isinstance(mem, ExprOp):
        if mem.op == 'preinc':
            addr = mem.args[0] + mem.args[1]
        elif mem.op == 'segm':
            base = mem.args[0]
            op, (reg, shift) = mem.args[1].op, mem.args[1].args
            if op == 'SXTW':
                off = reg.signExtend(base.size) << shift.zeroExtend(base.size)
                addr = base + off
            elif op == 'UXTW':
                off = reg.zeroExtend(base.size) << shift.zeroExtend(base.size)
                addr = base + off
            elif op == 'LSL':
                if isinstance(shift, ExprInt) and int(shift) == 0:
                    addr = base + reg.zeroExtend(base.size)
                else:
                    addr = base + \
                        (reg.zeroExtend(base.size)
                         << shift.zeroExtend(base.size))
            else:
                raise NotImplementedError('bad op')
        elif mem.op == "postinc":
            addr, off = mem.args
            updt = ExprAff(addr, addr + off)
        elif mem.op == "preinc_wb":
            base, off = mem.args
            addr = base + off
            updt = ExprAff(base, base + off)
        else:
            raise NotImplementedError('bad op')
    else:
        raise NotImplementedError('bad op')
    return addr, updt



def ldr(ir, instr, arg1, arg2):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(ExprAff(arg1, ExprMem(addr, arg1.size)))
    if updt:
        e.append(updt)
    return e, []


def ldr_size(ir, instr, arg1, arg2, size):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(
        ExprAff(arg1, ExprMem(addr, size).zeroExtend(arg1.size)))
    if updt:
        e.append(updt)
    return e, []


def ldrb(ir, instr, arg1, arg2):
    return ldr_size(ir, instr, arg1, arg2, 8)


def ldrh(ir, instr, arg1, arg2):
    return ldr_size(ir, instr, arg1, arg2, 16)


def ldrs_size(ir, instr, arg1, arg2, size):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(
        ExprAff(arg1, ExprMem(addr, size).signExtend(arg1.size)))
    if updt:
        e.append(updt)
    return e, []


def ldrsb(ir, instr, arg1, arg2):
    return ldrs_size(ir, instr, arg1, arg2, 8)


def ldrsh(ir, instr, arg1, arg2):
    return ldrs_size(ir, instr, arg1, arg2, 16)


def ldrsw(ir, instr, arg1, arg2):
    return ldrs_size(ir, instr, arg1, arg2, 32)



def l_str(ir, instr, arg1, arg2):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(ExprAff(ExprMem(addr, arg1.size), arg1))
    if updt:
        e.append(updt)
    return e, []


def strb(ir, instr, arg1, arg2):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(ExprAff(ExprMem(addr, 8), arg1[:8]))
    if updt:
        e.append(updt)
    return e, []


def strh(ir, instr, arg1, arg2):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(ExprAff(ExprMem(addr, 16), arg1[:16]))
    if updt:
        e.append(updt)
    return e, []


def stp(ir, instr, arg1, arg2, arg3):
    e = []
    addr, updt = get_mem_access(arg3)
    e.append(ExprAff(ExprMem(addr, arg1.size), arg1))
    e.append(
        ExprAff(ExprMem(addr + ExprInt(arg1.size / 8, addr.size), arg2.size), arg2))
    if updt:
        e.append(updt)
    return e, []


def ldp(ir, instr, arg1, arg2, arg3):
    e = []
    addr, updt = get_mem_access(arg3)
    e.append(ExprAff(arg1, ExprMem(addr, arg1.size)))
    e.append(
        ExprAff(arg2, ExprMem(addr + ExprInt(arg1.size / 8, addr.size), arg2.size)))
    if updt:
        e.append(updt)
    return e, []


def sbfm(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    rim, sim = int(arg3.arg), int(arg4) + 1
    if sim > rim:
        res = arg2[rim:sim].signExtend(arg1.size)
    else:
        shift = ExprInt(arg2.size - rim, arg2.size)
        res = (arg2[:sim].signExtend(arg1.size) << shift)
    e.append(ExprAff(arg1, res))
    return e, []


def ubfm(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    rim, sim = int(arg3.arg), int(arg4) + 1
    if sim > rim:
        res = arg2[rim:sim].zeroExtend(arg1.size)
    else:
        shift = ExprInt(arg2.size - rim, arg2.size)
        res = (arg2[:sim].zeroExtend(arg1.size) << shift)
    e.append(ExprAff(arg1, res))
    return e, []

def bfm(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    rim, sim = int(arg3.arg), int(arg4) + 1
    if sim > rim:
        res = arg2[rim:sim]
        e.append(ExprAff(arg1[:sim-rim], res))
    else:
        shift_i = arg2.size - rim
        shift = ExprInt(shift_i, arg2.size)
        res = arg2[:sim]
        e.append(ExprAff(arg1[shift_i:shift_i+sim], res))
    return e, []



def mrs(ir, insr, arg1, arg2, arg3, arg4, arg5):
    e = []
    if arg2.is_int(3) and arg3.is_id("c4") and arg4.is_id("c2") and arg5.is_int(0):
        out = []
        out.append(ExprInt(0x0, 28))
        out.append(of)
        out.append(cf)
        out.append(zf)
        out.append(nf)
        e.append(ExprAff(arg1, ExprCompose(*out).zeroExtend(arg1.size)))
    else:
        raise NotImplementedError("MSR not implemented")
    return e, []

def msr(ir, instr, arg1, arg2, arg3, arg4, arg5):

    e = []
    if arg1.is_int(3) and arg2.is_id("c4") and arg3.is_id("c2") and arg4.is_int(0):
        e.append(ExprAff(nf, arg5[31:32]))
        e.append(ExprAff(zf, arg5[30:31]))
        e.append(ExprAff(cf, arg5[29:30]))
        e.append(ExprAff(of, arg5[28:29]))
    else:
        raise NotImplementedError("MRS not implemented")
    return e, []



def adc(ir, instr, arg1, arg2, arg3):
    arg3 = extend_arg(arg2, arg3)
    e = []
    r = arg2 + arg3 + cf.zeroExtend(arg3.size)
    e.append(ExprAff(arg1, r))
    return e, []


def adcs(ir, instr, arg1, arg2, arg3):
    arg3 = extend_arg(arg2, arg3)
    e = []
    r = arg2 + arg3 + cf.zeroExtend(arg3.size)
    e.append(ExprAff(arg1, r))
    e += update_flag_arith_addwc_zn(arg2, arg3, cf)
    e += update_flag_arith_addwc_co(arg2, arg3, cf)
    return e, []


def sbc(ir, instr, arg1, arg2, arg3):
    arg3 = extend_arg(arg2, arg3)
    e = []
    r = arg2 - (arg3 + (~cf).zeroExtend(arg3.size))
    e.append(ExprAff(arg1, r))
    return e, []


def sbcs(ir, instr, arg1, arg2, arg3):
    arg3 = extend_arg(arg2, arg3)
    e = []
    r = arg2 - (arg3 + (~cf).zeroExtend(arg3.size))
    e.append(ExprAff(arg1, r))
    e += update_flag_arith_subwc_zn(arg2, arg3, ~cf)
    e += update_flag_arith_subwc_co(arg2, arg3, ~cf)
    return e, []


@sbuild.parse
def madd(arg1, arg2, arg3, arg4):
    arg1 = arg2 * arg3 + arg4


@sbuild.parse
def msub(arg1, arg2, arg3, arg4):
    arg1 = arg4 - (arg2 * arg3)


@sbuild.parse
def udiv(arg1, arg2, arg3):
    if arg3:
        arg1 = ExprOp('udiv', arg2, arg3)
    else:
        exception_flags = ExprInt(EXCEPT_DIV_BY_ZERO,
                                          exception_flags.size)


@sbuild.parse
def cbz(arg1, arg2):
    dst = ExprLoc(ir.get_next_loc_key(instr), 64) if arg1 else arg2
    PC = dst
    ir.IRDst = dst


@sbuild.parse
def cbnz(arg1, arg2):
    dst = arg2 if arg1 else ExprLoc(ir.get_next_loc_key(instr), 64)
    PC = dst
    ir.IRDst = dst


@sbuild.parse
def tbz(arg1, arg2, arg3):
    bitmask = ExprInt(1, arg1.size) << arg2
    dst = ExprLoc(
        ir.get_next_loc_key(instr),
        64
    ) if arg1 & bitmask else arg3
    PC = dst
    ir.IRDst = dst


@sbuild.parse
def tbnz(arg1, arg2, arg3):
    bitmask = ExprInt(1, arg1.size) << arg2
    dst = arg3 if arg1 & bitmask else ExprLoc(
        ir.get_next_loc_key(instr),
        64
    )
    PC = dst
    ir.IRDst = dst


@sbuild.parse
def b_ne(arg1):
    cond = cond2expr['NE']
    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
    PC = dst
    ir.IRDst = dst


@sbuild.parse
def b_eq(arg1):
    cond = cond2expr['EQ']
    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
    PC = dst
    ir.IRDst = dst


@sbuild.parse
def b_ge(arg1):
    cond = cond2expr['GE']
    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
    PC = dst
    ir.IRDst = dst


@sbuild.parse
def b_gt(arg1):
    cond = cond2expr['GT']
    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
    PC = dst
    ir.IRDst = dst


@sbuild.parse
def b_cc(arg1):
    cond = cond2expr['CC']
    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
    PC = dst
    ir.IRDst = dst


@sbuild.parse
def b_cs(arg1):
    cond = cond2expr['CS']
    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
    PC = dst
    ir.IRDst = dst


@sbuild.parse
def b_hi(arg1):
    cond = cond2expr['HI']
    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
    PC = dst
    ir.IRDst = dst


@sbuild.parse
def b_le(arg1):
    cond = cond2expr['LE']
    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
    PC = dst
    ir.IRDst = dst


@sbuild.parse
def b_ls(arg1):
    cond = cond2expr['LS']
    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
    PC = dst
    ir.IRDst = dst


@sbuild.parse
def b_lt(arg1):
    cond = cond2expr['LT']
    dst = arg1 if cond else ExprLoc(ir.get_next_loc_key(instr), 64)
    PC = dst
    ir.IRDst = dst


@sbuild.parse
def ret(arg1):
    PC = arg1
    ir.IRDst = arg1


@sbuild.parse
def adrp(arg1, arg2):
    arg1 = (PC & ExprInt(0xfffffffffffff000, 64)) + arg2


@sbuild.parse
def adr(arg1, arg2):
    arg1 = PC + arg2


@sbuild.parse
def b(arg1):
    PC = arg1
    ir.IRDst = arg1


@sbuild.parse
def br(arg1):
    PC = arg1
    ir.IRDst = arg1

@sbuild.parse
def blr(arg1):
    PC = arg1
    ir.IRDst = arg1
    LR = ExprLoc(ir.get_next_loc_key(instr), 64)

@sbuild.parse
def nop():
    """Do nothing"""


def rev(ir, instr, arg1, arg2):
    out = []
    for i in xrange(0, arg2.size, 8):
        out.append(arg2[i:i+8])
    out.reverse()
    e = []
    result = ExprCompose(*out)
    e.append(ExprAff(arg1, result))
    return e, []


@sbuild.parse
def extr(arg1, arg2, arg3, arg4):
    compose = ExprCompose(arg2, arg3)
    arg1 = compose[int(arg4.arg):int(arg4)+arg1.size]


@sbuild.parse
def svc(arg1):
    exception_flags = ExprInt(EXCEPT_INT_XX, exception_flags.size)
    interrupt_num = ExprInt(int(arg1), interrupt_num.size)

mnemo_func = sbuild.functions
mnemo_func.update({
    'and': and_l,
    'adds': adds,
    'ands': ands,
    'tst': tst,
    'subs': subs,
    'cmp': cmp,
    'cmn': cmn,
    'movk': movk,
    'ccmp': ccmp,
    'csinc': csinc,
    'csinv': csinv,
    'csneg': csneg,
    'cset': cset,
    'csetm': csetm,

    'b.ne': b_ne,
    'b.eq': b_eq,
    'b.ge': b_ge,
    'b.gt': b_gt,
    'b.cc': b_cc,
    'b.cs': b_cs,
    'b.hi': b_hi,
    'b.le': b_le,
    'b.ls': b_ls,
    'b.lt': b_lt,

    'bics': bics,

    'ret': ret,
    'stp': stp,
    'ldp': ldp,

    'ldr': ldr,
    'ldrb': ldrb,
    'ldrh': ldrh,

    'ldur': ldr,
    'ldurb': ldrb,
    'ldursb': ldrsb,
    'ldurh': ldrh,
    'ldursh': ldrsh,
    'ldursw': ldrsw,

    'ldrsb': ldrsb,
    'ldrsh': ldrsh,
    'ldrsw': ldrsw,

    'str': l_str,
    'strb': strb,
    'strh': strh,

    'stur': l_str,
    'sturb': strb,
    'sturh': strh,


    'bfm': bfm,
    'sbfm': sbfm,
    'ubfm': ubfm,

    'extr': extr,
    'rev': rev,

    'msr': msr,
    'mrs': mrs,

    'adc': adc,
    'adcs': adcs,
    'sbc': sbc,
    'sbcs': sbcs,


})


def get_mnemo_expr(ir, instr, *args):
    if not instr.name.lower() in mnemo_func:
        raise NotImplementedError('unknown mnemo %s' % instr)
    instr, extra_ir = mnemo_func[instr.name.lower()](ir, instr, *args)
    return instr, extra_ir


class aarch64info:
    mode = "aarch64"
    # offset


class ir_aarch64l(IntermediateRepresentation):

    def __init__(self, loc_db=None):
        IntermediateRepresentation.__init__(self, mn_aarch64, "l", loc_db)
        self.pc = PC
        self.sp = SP
        self.IRDst = ExprId('IRDst', 64)
        self.addrsize = 64

    def get_ir(self, instr):
        args = instr.args
        if len(args) and isinstance(args[-1], ExprOp):
            if (args[-1].op in ['<<', '>>', '<<a', 'a>>', '<<<', '>>>'] and
               isinstance(args[-1].args[-1], ExprId)):
                args[-1] = ExprOp(args[-1].op,
                                          args[-1].args[0],
                                          args[-1].args[-1][:8].zeroExtend(32))
        instr_ir, extra_ir = get_mnemo_expr(self, instr, *args)
        self.mod_pc(instr, instr_ir, extra_ir)
        instr_ir, extra_ir = self.del_dst_zr(instr, instr_ir, extra_ir)
        return instr_ir, extra_ir

    def expr_fix_regs_for_mode(self, e):
        return e.replace_expr(replace_regs)

    def expraff_fix_regs_for_mode(self, e):
        dst = self.expr_fix_regs_for_mode(e.dst)
        src = self.expr_fix_regs_for_mode(e.src)
        return ExprAff(dst, src)

    def irbloc_fix_regs_for_mode(self, irblock, mode=64):
        irs = []
        for assignblk in irblock:
            new_assignblk = dict(assignblk)
            for dst, src in assignblk.iteritems():
                del(new_assignblk[dst])
                # Special case for 64 bits:
                # If destination is a 32 bit reg, zero extend the 64 bit reg
                if (isinstance(dst, ExprId) and
                    dst.size == 32 and
                    dst in replace_regs):
                    src = src.zeroExtend(64)
                    dst = replace_regs[dst].arg

                dst = self.expr_fix_regs_for_mode(dst)
                src = self.expr_fix_regs_for_mode(src)
                new_assignblk[dst] = src
            irs.append(AssignBlock(new_assignblk, assignblk.instr))
        return IRBlock(irblock.loc_key, irs)

    def mod_pc(self, instr, instr_ir, extra_ir):
        "Replace PC by the instruction's offset"
        cur_offset = ExprInt(instr.offset, 64)
        pc_fixed = {self.pc: cur_offset}
        for i, expr in enumerate(instr_ir):
            dst, src = expr.dst, expr.src
            if dst != self.pc:
                dst = dst.replace_expr(pc_fixed)
            src = src.replace_expr(pc_fixed)
            instr_ir[i] = ExprAff(dst, src)

        for idx, irblock in enumerate(extra_ir):
            extra_ir[idx] = irblock.modify_exprs(lambda expr: expr.replace_expr(pc_fixed) \
                                                 if expr != self.pc else expr,
                                                 lambda expr: expr.replace_expr(pc_fixed))


    def del_dst_zr(self, instr, instr_ir, extra_ir):
        "Writes to zero register are discarded"
        regs_to_fix = [WZR, XZR]
        instr_ir = [expr for expr in instr_ir if expr.dst not in regs_to_fix]

        new_irblocks = []
        for irblock in extra_ir:
            irs = []
            for assignblk in irblock:
                new_dsts = {dst:src for dst, src in assignblk.iteritems()
                                if dst not in regs_to_fix}
                irs.append(AssignBlock(new_dsts, assignblk.instr))
            new_irblocks.append(IRBlock(irblock.loc_key, irs))

        return instr_ir, new_irblocks


class ir_aarch64b(ir_aarch64l):

    def __init__(self, loc_db=None):
        IntermediateRepresentation.__init__(self, mn_aarch64, "b", loc_db)
        self.pc = PC
        self.sp = SP
        self.IRDst = ExprId('IRDst', 64)

Module variables

var EXCEPT_DIV_BY_ZERO

var EXCEPT_INT_XX

var all_regs_ids

var all_regs_ids_byname

var all_regs_ids_init

var all_regs_ids_no_alias

var attrib_to_regs

var cond2expr

var conds_expr

var cr_expr

var cr_init

var cr_str

var ctx

var gpregs32_expr

var gpregs32_init

var gpregs32_str

var gpregs64_expr

var gpregs64_init

var gpregs64_str

var gpregsz32_expr

var gpregsz32_init

var gpregsz32_str

var gpregsz64_expr

var gpregsz64_init

var gpregsz64_str

var i

var mnemo_func

var reg_cf

var reg_nf

var reg_of

var reg_zf

var regs_flt_expr

var regs_init

var replace_regs

var sbuild

var simd08_expr

var simd08_init

var simd08_str

var simd128_expr

var simd128_init

var simd128_str

var simd16_expr

var simd16_init

var simd16_str

var simd32_expr

var simd32_init

var simd32_str

var simd64_expr

var simd64_init

var simd64_str

Functions

def adc(

ir, instr, arg1, arg2, arg3)

def adc(ir, instr, arg1, arg2, arg3):
    arg3 = extend_arg(arg2, arg3)
    e = []
    r = arg2 + arg3 + cf.zeroExtend(arg3.size)
    e.append(ExprAff(arg1, r))
    return e, []

def adcs(

ir, instr, arg1, arg2, arg3)

def adcs(ir, instr, arg1, arg2, arg3):
    arg3 = extend_arg(arg2, arg3)
    e = []
    r = arg2 + arg3 + cf.zeroExtend(arg3.size)
    e.append(ExprAff(arg1, r))
    e += update_flag_arith_addwc_zn(arg2, arg3, cf)
    e += update_flag_arith_addwc_co(arg2, arg3, cf)
    return e, []

def adds(

ir, instr, arg1, arg2, arg3)

def adds(ir, instr, arg1, arg2, arg3):
    e = []
    arg3 = extend_arg(arg2, arg3)
    res = arg2 + arg3

    e += update_flag_arith_add_zn(arg2, arg3)
    e += update_flag_arith_add_co(arg2, arg3)

    e.append(ExprAff(arg1, res))

    return e, []

def ands(

ir, instr, arg1, arg2, arg3)

def ands(ir, instr, arg1, arg2, arg3):
    e = []
    arg3 = extend_arg(arg2, arg3)
    res = arg2 & arg3

    e += [ExprAff(zf, ExprOp('FLAG_EQ_AND', arg2, arg3))]
    e += update_flag_nf(res)

    e.append(ExprAff(arg1, res))
    return e, []

def bfm(

ir, instr, arg1, arg2, arg3, arg4)

def bfm(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    rim, sim = int(arg3.arg), int(arg4) + 1
    if sim > rim:
        res = arg2[rim:sim]
        e.append(ExprAff(arg1[:sim-rim], res))
    else:
        shift_i = arg2.size - rim
        shift = ExprInt(shift_i, arg2.size)
        res = arg2[:sim]
        e.append(ExprAff(arg1[shift_i:shift_i+sim], res))
    return e, []

def bics(

ir, instr, arg1, arg2, arg3)

def bics(ir, instr, arg1, arg2, arg3):
    e = []
    tmp1, tmp2 = arg2, (~extend_arg(arg2, arg3))

    e += [ExprAff(zf, ExprOp('FLAG_EQ_AND', tmp1, tmp2))]
    e += update_flag_nf(res)

    e.append(ExprAff(arg1, res))

    e += null_flag_co()
    return e, []

def ccmp(

ir, instr, arg1, arg2, arg3, arg4)

def ccmp(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    if(arg2.is_int):
        arg2=ExprInt(arg2.arg.arg,arg1.size)
    default_nf = arg3[0:1]
    default_zf = arg3[1:2]
    default_cf = arg3[2:3]
    default_of = arg3[3:4]
    cond_expr = cond2expr[arg4.name]
    res = arg1 - arg2
    new_nf = nf
    new_zf = update_flag_zf(res)[0].src
    new_cf = update_flag_sub_cf(arg1, arg2, res).src
    new_of = update_flag_sub_of(arg1, arg2, res).src

    e.append(ExprAff(nf, ExprCond(cond_expr,
                                                    new_nf,
                                                    default_nf)))
    e.append(ExprAff(zf, ExprCond(cond_expr,
                                                    new_zf,
                                                    default_zf)))
    e.append(ExprAff(cf, ExprCond(cond_expr,
                                                    new_cf,
                                                    default_cf)))
    e.append(ExprAff(of, ExprCond(cond_expr,
                                                    new_of,
                                                    default_of)))
    return e, []

def check_ops_msb(

a, b, c)

def check_ops_msb(a, b, c):
    if not a or not b or not c or a != b or a != c:
        raise ValueError('bad ops size %s %s %s' % (a, b, c))

def cmn(

ir, instr, arg1, arg2)

def cmn(ir, instr, arg1, arg2):
    e = []
    arg2 = extend_arg(arg1, arg2)
    res = arg1 + arg2


    e += update_flag_arith_add_zn(arg1, arg2)
    e += update_flag_arith_add_co(arg1, arg2)

    return e, []

def cmp(

ir, instr, arg1, arg2)

def cmp(ir, instr, arg1, arg2):
    e = []
    arg2 = extend_arg(arg1, arg2)

    e += update_flag_arith_sub_zn(arg1, arg2)
    e += update_flag_arith_sub_co(arg1, arg2)

    return e, []

def cset(

ir, instr, arg1, arg2)

def cset(ir, instr, arg1, arg2):
    e = []
    cond_expr = cond2expr[arg2.name]
    e.append(
        ExprAff(
            arg1,
            ExprCond(
                cond_expr,
                ExprInt(1, arg1.size),
                ExprInt(0, arg1.size)
            )
        )
    )
    return e, []

def csetm(

ir, instr, arg1, arg2)

def csetm(ir, instr, arg1, arg2):
    e = []
    cond_expr = cond2expr[arg2.name]
    e.append(
        ExprAff(
            arg1,
            ExprCond(
                cond_expr,
                ExprInt(-1, arg1.size),
                ExprInt(0, arg1.size)
            )
        )
    )
    return e, []

def csinc(

ir, instr, arg1, arg2, arg3, arg4)

def csinc(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    cond_expr = cond2expr[arg4.name]
    e.append(
        ExprAff(
            arg1,
            ExprCond(
                cond_expr,
                arg2,
                arg3 + ExprInt(1, arg3.size)
            )
        )
    )
    return e, []

def csinv(

ir, instr, arg1, arg2, arg3, arg4)

def csinv(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    cond_expr = cond2expr[arg4.name]
    e.append(
        ExprAff(
            arg1,
            ExprCond(
                cond_expr,
                arg2,
                ~arg3)
        )
    )
    return e, []

def csneg(

ir, instr, arg1, arg2, arg3, arg4)

def csneg(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    cond_expr = cond2expr[arg4.name]
    e.append(
        ExprAff(
            arg1,
            ExprCond(
                cond_expr,
                arg2,
                -arg3)
        )
    )
    return e, []

def extend_arg(

dst, arg)

def extend_arg(dst, arg):
    if not isinstance(arg, ExprOp):
        return arg

    op, (reg, shift) = arg.op, arg.args
    if op == "SXTB":
        base = reg[:8].signExtend(dst.size)
        op = "<<"
    elif op == "SXTH":
        base = reg[:16].signExtend(dst.size)
        op = "<<"
    elif op == 'SXTW':
        base = reg[:32].signExtend(dst.size)
        op = "<<"
    elif op == "SXTX":
        base = reg.signExtend(dst.size)
        op = "<<"

    elif op == "UXTB":
        base = reg[:8].zeroExtend(dst.size)
        op = "<<"
    elif op == "UXTH":
        base = reg[:16].zeroExtend(dst.size)
        op = "<<"
    elif op == 'UXTW':
        base = reg[:32].zeroExtend(dst.size)
        op = "<<"
    elif op == "UXTX":
        base = reg.zeroExtend(dst.size)
        op = "<<"

    elif op in ['<<', '>>', '<<a', 'a>>', '<<<', '>>>']:
        base = reg.zeroExtend(dst.size)
    else:
        raise NotImplementedError('Unknown shifter operator')

    out = ExprOp(op, base, (shift.zeroExtend(dst.size)
                            & ExprInt(dst.size - 1, dst.size)))
    return out

def get_mem_access(

mem)

def get_mem_access(mem):
    updt = None
    if isinstance(mem, ExprOp):
        if mem.op == 'preinc':
            addr = mem.args[0] + mem.args[1]
        elif mem.op == 'segm':
            base = mem.args[0]
            op, (reg, shift) = mem.args[1].op, mem.args[1].args
            if op == 'SXTW':
                off = reg.signExtend(base.size) << shift.zeroExtend(base.size)
                addr = base + off
            elif op == 'UXTW':
                off = reg.zeroExtend(base.size) << shift.zeroExtend(base.size)
                addr = base + off
            elif op == 'LSL':
                if isinstance(shift, ExprInt) and int(shift) == 0:
                    addr = base + reg.zeroExtend(base.size)
                else:
                    addr = base + \
                        (reg.zeroExtend(base.size)
                         << shift.zeroExtend(base.size))
            else:
                raise NotImplementedError('bad op')
        elif mem.op == "postinc":
            addr, off = mem.args
            updt = ExprAff(addr, addr + off)
        elif mem.op == "preinc_wb":
            base, off = mem.args
            addr = base + off
            updt = ExprAff(base, base + off)
        else:
            raise NotImplementedError('bad op')
    else:
        raise NotImplementedError('bad op')
    return addr, updt

def get_mnemo_expr(

ir, instr, *args)

def get_mnemo_expr(ir, instr, *args):
    if not instr.name.lower() in mnemo_func:
        raise NotImplementedError('unknown mnemo %s' % instr)
    instr, extra_ir = mnemo_func[instr.name.lower()](ir, instr, *args)
    return instr, extra_ir

def l_str(

ir, instr, arg1, arg2)

def l_str(ir, instr, arg1, arg2):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(ExprAff(ExprMem(addr, arg1.size), arg1))
    if updt:
        e.append(updt)
    return e, []

def ldp(

ir, instr, arg1, arg2, arg3)

def ldp(ir, instr, arg1, arg2, arg3):
    e = []
    addr, updt = get_mem_access(arg3)
    e.append(ExprAff(arg1, ExprMem(addr, arg1.size)))
    e.append(
        ExprAff(arg2, ExprMem(addr + ExprInt(arg1.size / 8, addr.size), arg2.size)))
    if updt:
        e.append(updt)
    return e, []

def ldr(

ir, instr, arg1, arg2)

def ldr(ir, instr, arg1, arg2):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(ExprAff(arg1, ExprMem(addr, arg1.size)))
    if updt:
        e.append(updt)
    return e, []

def ldr_size(

ir, instr, arg1, arg2, size)

def ldr_size(ir, instr, arg1, arg2, size):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(
        ExprAff(arg1, ExprMem(addr, size).zeroExtend(arg1.size)))
    if updt:
        e.append(updt)
    return e, []

def ldrb(

ir, instr, arg1, arg2)

def ldrb(ir, instr, arg1, arg2):
    return ldr_size(ir, instr, arg1, arg2, 8)

def ldrh(

ir, instr, arg1, arg2)

def ldrh(ir, instr, arg1, arg2):
    return ldr_size(ir, instr, arg1, arg2, 16)

def ldrs_size(

ir, instr, arg1, arg2, size)

def ldrs_size(ir, instr, arg1, arg2, size):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(
        ExprAff(arg1, ExprMem(addr, size).signExtend(arg1.size)))
    if updt:
        e.append(updt)
    return e, []

def ldrsb(

ir, instr, arg1, arg2)

def ldrsb(ir, instr, arg1, arg2):
    return ldrs_size(ir, instr, arg1, arg2, 8)

def ldrsh(

ir, instr, arg1, arg2)

def ldrsh(ir, instr, arg1, arg2):
    return ldrs_size(ir, instr, arg1, arg2, 16)

def ldrsw(

ir, instr, arg1, arg2)

def ldrsw(ir, instr, arg1, arg2):
    return ldrs_size(ir, instr, arg1, arg2, 32)

def movk(

ir, instr, arg1, arg2)

def movk(ir, instr, arg1, arg2):
    e = []
    if isinstance(arg2, ExprOp):
        assert(arg2.op == 'slice_at' and
               isinstance(arg2.args[0], ExprInt) and
               isinstance(arg2.args[1], ExprInt))
        value, shift = int(arg2.args[0].arg), int(arg2.args[1])
        e.append(
            ExprAff(arg1[shift:shift + 16], ExprInt(value, 16)))
    else:
        e.append(ExprAff(arg1[:16], ExprInt(int(arg2), 16)))

    return e, []

def mrs(

ir, insr, arg1, arg2, arg3, arg4, arg5)

def mrs(ir, insr, arg1, arg2, arg3, arg4, arg5):
    e = []
    if arg2.is_int(3) and arg3.is_id("c4") and arg4.is_id("c2") and arg5.is_int(0):
        out = []
        out.append(ExprInt(0x0, 28))
        out.append(of)
        out.append(cf)
        out.append(zf)
        out.append(nf)
        e.append(ExprAff(arg1, ExprCompose(*out).zeroExtend(arg1.size)))
    else:
        raise NotImplementedError("MSR not implemented")
    return e, []

def msr(

ir, instr, arg1, arg2, arg3, arg4, arg5)

def msr(ir, instr, arg1, arg2, arg3, arg4, arg5):

    e = []
    if arg1.is_int(3) and arg2.is_id("c4") and arg3.is_id("c2") and arg4.is_int(0):
        e.append(ExprAff(nf, arg5[31:32]))
        e.append(ExprAff(zf, arg5[30:31]))
        e.append(ExprAff(cf, arg5[29:30]))
        e.append(ExprAff(of, arg5[28:29]))
    else:
        raise NotImplementedError("MRS not implemented")
    return e, []

def rev(

ir, instr, arg1, arg2)

def rev(ir, instr, arg1, arg2):
    out = []
    for i in xrange(0, arg2.size, 8):
        out.append(arg2[i:i+8])
    out.reverse()
    e = []
    result = ExprCompose(*out)
    e.append(ExprAff(arg1, result))
    return e, []

def sbc(

ir, instr, arg1, arg2, arg3)

def sbc(ir, instr, arg1, arg2, arg3):
    arg3 = extend_arg(arg2, arg3)
    e = []
    r = arg2 - (arg3 + (~cf).zeroExtend(arg3.size))
    e.append(ExprAff(arg1, r))
    return e, []

def sbcs(

ir, instr, arg1, arg2, arg3)

def sbcs(ir, instr, arg1, arg2, arg3):
    arg3 = extend_arg(arg2, arg3)
    e = []
    r = arg2 - (arg3 + (~cf).zeroExtend(arg3.size))
    e.append(ExprAff(arg1, r))
    e += update_flag_arith_subwc_zn(arg2, arg3, ~cf)
    e += update_flag_arith_subwc_co(arg2, arg3, ~cf)
    return e, []

def sbfm(

ir, instr, arg1, arg2, arg3, arg4)

def sbfm(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    rim, sim = int(arg3.arg), int(arg4) + 1
    if sim > rim:
        res = arg2[rim:sim].signExtend(arg1.size)
    else:
        shift = ExprInt(arg2.size - rim, arg2.size)
        res = (arg2[:sim].signExtend(arg1.size) << shift)
    e.append(ExprAff(arg1, res))
    return e, []

def stp(

ir, instr, arg1, arg2, arg3)

def stp(ir, instr, arg1, arg2, arg3):
    e = []
    addr, updt = get_mem_access(arg3)
    e.append(ExprAff(ExprMem(addr, arg1.size), arg1))
    e.append(
        ExprAff(ExprMem(addr + ExprInt(arg1.size / 8, addr.size), arg2.size), arg2))
    if updt:
        e.append(updt)
    return e, []

def strb(

ir, instr, arg1, arg2)

def strb(ir, instr, arg1, arg2):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(ExprAff(ExprMem(addr, 8), arg1[:8]))
    if updt:
        e.append(updt)
    return e, []

def strh(

ir, instr, arg1, arg2)

def strh(ir, instr, arg1, arg2):
    e = []
    addr, updt = get_mem_access(arg2)
    e.append(ExprAff(ExprMem(addr, 16), arg1[:16]))
    if updt:
        e.append(updt)
    return e, []

def subs(

ir, instr, arg1, arg2, arg3)

def subs(ir, instr, arg1, arg2, arg3):
    e = []
    arg3 = extend_arg(arg2, arg3)
    res = arg2 - arg3


    e += update_flag_arith_sub_zn(arg2, arg3)
    e += update_flag_arith_sub_co(arg2, arg3)

    e.append(ExprAff(arg1, res))
    return e, []

def tst(

ir, instr, arg1, arg2)

def tst(ir, instr, arg1, arg2):
    e = []
    arg2 = extend_arg(arg1, arg2)
    res = arg1 & arg2

    e += [ExprAff(zf, ExprOp('FLAG_EQ_AND', arg1, arg2))]
    e += update_flag_nf(res)

    return e, []

def ubfm(

ir, instr, arg1, arg2, arg3, arg4)

def ubfm(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    rim, sim = int(arg3.arg), int(arg4) + 1
    if sim > rim:
        res = arg2[rim:sim].zeroExtend(arg1.size)
    else:
        shift = ExprInt(arg2.size - rim, arg2.size)
        res = (arg2[:sim].zeroExtend(arg1.size) << shift)
    e.append(ExprAff(arg1, res))
    return e, []

def update_flag_add_cf(

op1, op2)

Compute cf in @op1 + @op2

def update_flag_add_cf(op1, op2):
    "Compute cf in @op1 + @op2"
    return [ExprAff(cf, ExprOp("FLAG_ADD_CF", op1, op2))]

def update_flag_add_of(

op1, op2)

Compute of in @op1 + @op2

def update_flag_add_of(op1, op2):
    "Compute of in @op1 + @op2"
    return [ExprAff(of, ExprOp("FLAG_ADD_OF", op1, op2))]

def update_flag_addwc_cf(

op1, op2, op3)

Compute cf in @res = @op1 + @op2 + @op3

def update_flag_addwc_cf(op1, op2, op3):
    "Compute cf in @res = @op1 + @op2 + @op3"
    return [ExprAff(cf, ExprOp("FLAG_ADDWC_CF", op1, op2, op3))]

def update_flag_addwc_of(

op1, op2, op3)

Compute of in @res = @op1 + @op2 + @op3

def update_flag_addwc_of(op1, op2, op3):
    "Compute of in @res = @op1 + @op2 + @op3"
    return [ExprAff(of, ExprOp("FLAG_ADDWC_OF", op1, op2, op3))]

def update_flag_arith_add_co(

arg1, arg2)

def update_flag_arith_add_co(arg1, arg2):
    e = []
    e += update_flag_add_cf(arg1, arg2)
    e += update_flag_add_of(arg1, arg2)
    return e

def update_flag_arith_add_zn(

arg1, arg2)

Compute zf and nf flags for (arg1 + arg2)

def update_flag_arith_add_zn(arg1, arg2):
    """
    Compute zf and nf flags for (arg1 + arg2)
    """
    e = []
    e += update_flag_zf_eq(arg1, -arg2)
    e += [ExprAff(nf, ExprOp("FLAG_SIGN_SUB", arg1, -arg2))]
    return e

def update_flag_arith_addwc_co(

arg1, arg2, arg3)

def update_flag_arith_addwc_co(arg1, arg2, arg3):
    e = []
    e += update_flag_addwc_cf(arg1, arg2, arg3)
    e += update_flag_addwc_of(arg1, arg2, arg3)
    return e

def update_flag_arith_addwc_zn(

arg1, arg2, arg3)

Compute znp flags for (arg1 + arg2 + cf)

def update_flag_arith_addwc_zn(arg1, arg2, arg3):
    """
    Compute znp flags for (arg1 + arg2 + cf)
    """
    e = []
    e += update_flag_zfaddwc_eq(arg1, arg2, arg3)
    e += [ExprAff(nf, ExprOp("FLAG_SIGN_ADDWC", arg1, arg2, arg3))]
    return e

def update_flag_arith_sub_co(

arg1, arg2)

Compute cf and of flags for (arg1 - arg2)

def update_flag_arith_sub_co(arg1, arg2):
    """
    Compute cf and of flags for (arg1 - arg2)
    """
    e = []
    e += update_flag_sub_cf(arg1, arg2)
    e += update_flag_sub_of(arg1, arg2)
    return e

def update_flag_arith_sub_zn(

arg1, arg2)

Compute zf and nf flags for (arg1 - arg2)

def update_flag_arith_sub_zn(arg1, arg2):
    """
    Compute zf and nf flags for (arg1 - arg2)
    """
    e = []
    e += update_flag_zf_eq(arg1, arg2)
    e += [ExprAff(nf, ExprOp("FLAG_SIGN_SUB", arg1, arg2))]
    return e

def update_flag_arith_subwc_co(

arg1, arg2, arg3)

def update_flag_arith_subwc_co(arg1, arg2, arg3):
    e = []
    e += update_flag_subwc_cf(arg1, arg2, arg3)
    e += update_flag_subwc_of(arg1, arg2, arg3)
    return e

def update_flag_arith_subwc_zn(

arg1, arg2, arg3)

Compute znp flags for (arg1 - (arg2 + cf))

def update_flag_arith_subwc_zn(arg1, arg2, arg3):
    """
    Compute znp flags for (arg1 - (arg2 + cf))
    """
    e = []
    e += update_flag_zfsubwc_eq(arg1, arg2, arg3)
    e += [ExprAff(nf, ExprOp("FLAG_SIGN_SUBWC", arg1, arg2, arg3))]
    return e

def update_flag_nf(

arg)

def update_flag_nf(arg):
    return [
        ExprAff(
            nf,
            ExprOp("FLAG_SIGN_SUB", arg, ExprInt(0, arg.size))
        )
    ]

def update_flag_sub_cf(

op1, op2)

Compote CF in @op1 - @op2

def update_flag_sub_cf(op1, op2):
    "Compote CF in @op1 - @op2"
    return [ExprAff(cf, ExprOp("FLAG_SUB_CF", op1, op2) ^ ExprInt(1, 1))]

def update_flag_sub_of(

op1, op2)

Compote OF in @op1 - @op2

def update_flag_sub_of(op1, op2):
    "Compote OF in @op1 - @op2"
    return [ExprAff(of, ExprOp("FLAG_SUB_OF", op1, op2))]

def update_flag_subwc_cf(

op1, op2, op3)

Compute cf in @res = @op1 + @op2 + @op3

def update_flag_subwc_cf(op1, op2, op3):
    "Compute cf in @res = @op1 + @op2 + @op3"
    return [ExprAff(cf, ExprOp("FLAG_SUBWC_CF", op1, op2, op3) ^ ExprInt(1, 1))]

def update_flag_subwc_of(

op1, op2, op3)

Compute of in @res = @op1 + @op2 + @op3

def update_flag_subwc_of(op1, op2, op3):
    "Compute of in @res = @op1 + @op2 + @op3"
    return [ExprAff(of, ExprOp("FLAG_SUBWC_OF", op1, op2, op3))]

def update_flag_zf(

a)

def update_flag_zf(a):
    return [ExprAff(zf, ExprOp("FLAG_EQ", a))]

def update_flag_zf_eq(

a, b)

def update_flag_zf_eq(a, b):
    return [ExprAff(zf, ExprOp("FLAG_EQ_CMP", a, b))]

def update_flag_zfaddwc_eq(

arg1, arg2, arg3)

def update_flag_zfaddwc_eq(arg1, arg2, arg3):
    return [ExprAff(zf, ExprOp("FLAG_EQ_ADDWC", arg1, arg2, arg3))]

def update_flag_zfsubwc_eq(

arg1, arg2, arg3)

def update_flag_zfsubwc_eq(arg1, arg2, arg3):
    return [ExprAff(zf, ExprOp("FLAG_EQ_SUBWC", arg1, arg2, arg3))]

def update_flag_zn(

a)

def update_flag_zn(a):
    e = []
    e += update_flag_zf(a)
    e += update_flag_nf(a)
    return e

Classes

class aarch64info

class aarch64info:
    mode = "aarch64"

Ancestors (in MRO)

Class variables

var mode

class ir_aarch64b

class ir_aarch64b(ir_aarch64l):

    def __init__(self, loc_db=None):
        IntermediateRepresentation.__init__(self, mn_aarch64, "b", loc_db)
        self.pc = PC
        self.sp = SP
        self.IRDst = ExprId('IRDst', 64)

Ancestors (in MRO)

Instance variables

var IRDst

Inheritance: ir_aarch64l.IRDst

var addrsize

Inheritance: ir_aarch64l.addrsize

var pc

Inheritance: ir_aarch64l.pc

var sp

Inheritance: ir_aarch64l.sp

Methods

def __init__(

self, loc_db=None)

Inheritance: ir_aarch64l.__init__

def __init__(self, loc_db=None):
    IntermediateRepresentation.__init__(self, mn_aarch64, "b", loc_db)
    self.pc = PC
    self.sp = SP
    self.IRDst = ExprId('IRDst', 64)

def add_asmblock_to_ircfg(

self, block, ircfg, gen_pc_updt=False)

Inheritance: ir_aarch64l.add_asmblock_to_ircfg

Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions

def add_asmblock_to_ircfg(self, block, ircfg, gen_pc_updt=False):
    """
    Add a native block to the current IR
    @block: native assembly block
    @ircfg: IRCFG instance
    @gen_pc_updt: insert PC update effects between instructions
    """
    loc_key = block.loc_key
    ir_blocks_all = []
    assignments = []
    for instr in block.lines:
        if loc_key is None:
            assignments = []
            loc_key = self.get_loc_key_for_instr(instr)
        split = self.add_instr_to_current_state(
            instr, block, assignments,
            ir_blocks_all, gen_pc_updt
        )
        if split:
            ir_blocks_all.append(IRBlock(loc_key, assignments))
            loc_key = None
            assignments = []
    if loc_key is not None:
        ir_blocks_all.append(IRBlock(loc_key, assignments))
    new_ir_blocks_all = self.post_add_asmblock_to_ircfg(block, ircfg, ir_blocks_all)
    for irblock in new_ir_blocks_all:
        ircfg.add_irblock(irblock)
    return new_ir_blocks_all

def add_bloc(

self, block, gen_pc_updt=False)

Inheritance: ir_aarch64l.add_bloc

DEPRECATED function Use add_block instead of add_block

def add_bloc(self, block, gen_pc_updt=False):
    """
    DEPRECATED function
    Use add_block instead of add_block
    """
    self.add_block(block, gen_pc_updt)

def add_block(

self, block, gen_pc_updt=False)

Inheritance: ir_aarch64l.add_block

DEPRECATED function Use add_block instead of add_block

def add_block(self, block, gen_pc_updt=False):
    """
    DEPRECATED function
    Use add_block instead of add_block
    """
    warnings.warn("""DEPRECATION WARNING
    ircfg is now out of IntermediateRepresentation
    Use:
    ircfg = ir_arch.new_ircfg()
    ir_arch.add_asmblock_to_ircfg(block, ircfg)
    """)
    raise RuntimeError("API Deprecated")

def add_instr_to_current_state(

self, instr, block, assignments, ir_blocks_all, gen_pc_updt)

Inheritance: ir_aarch64l.add_instr_to_current_state

Add the IR effects of an instruction to the current state.

Returns a bool: True if the current assignments list must be split False in other cases.

@instr: native instruction @block: native block source @assignments: list of current AssignBlocks @ir_blocks_all: list of additional effects @gen_pc_updt: insert PC update effects between instructions

def add_instr_to_current_state(self, instr, block, assignments, ir_blocks_all, gen_pc_updt):
    """
    Add the IR effects of an instruction to the current state.
    Returns a bool:
    * True if the current assignments list must be split
    * False in other cases.
    @instr: native instruction
    @block: native block source
    @assignments: list of current AssignBlocks
    @ir_blocks_all: list of additional effects
    @gen_pc_updt: insert PC update effects between instructions
    """
    if gen_pc_updt is not False:
        self.gen_pc_update(assignments, instr)
    assignblk, ir_blocks_extra = self.instr2ir(instr)
    assignments.append(assignblk)
    ir_blocks_all += ir_blocks_extra
    if ir_blocks_extra:
        return True
    return False

def add_instr_to_ircfg(

self, instr, ircfg, loc_key=None, gen_pc_updt=False)

Inheritance: ir_aarch64l.add_instr_to_ircfg

Add the native instruction @instr to the @ircfg @instr: instruction instance @ircfg: IRCFG instance @loc_key: loc_key instance of the instruction destination @gen_pc_updt: insert PC update effects between instructions

def add_instr_to_ircfg(self, instr, ircfg, loc_key=None, gen_pc_updt=False):
    """
    Add the native instruction @instr to the @ircfg
    @instr: instruction instance
    @ircfg: IRCFG instance
    @loc_key: loc_key instance of the instruction destination
    @gen_pc_updt: insert PC update effects between instructions
    """
    if loc_key is None:
        offset = getattr(instr, "offset", None)
        loc_key = self.loc_db.add_location(offset=offset)
    block = AsmBlock(loc_key)
    block.lines = [instr]
    self.add_asmblock_to_ircfg(block, ircfg, gen_pc_updt)
    return loc_key

def del_dst_zr(

self, instr, instr_ir, extra_ir)

Inheritance: ir_aarch64l.del_dst_zr

Writes to zero register are discarded

def del_dst_zr(self, instr, instr_ir, extra_ir):
    "Writes to zero register are discarded"
    regs_to_fix = [WZR, XZR]
    instr_ir = [expr for expr in instr_ir if expr.dst not in regs_to_fix]
    new_irblocks = []
    for irblock in extra_ir:
        irs = []
        for assignblk in irblock:
            new_dsts = {dst:src for dst, src in assignblk.iteritems()
                            if dst not in regs_to_fix}
            irs.append(AssignBlock(new_dsts, assignblk.instr))
        new_irblocks.append(IRBlock(irblock.loc_key, irs))
    return instr_ir, new_irblocks

def expr_fix_regs_for_mode(

self, e)

Inheritance: ir_aarch64l.expr_fix_regs_for_mode

def expr_fix_regs_for_mode(self, e):
    return e.replace_expr(replace_regs)

def expraff_fix_regs_for_mode(

self, e)

Inheritance: ir_aarch64l.expraff_fix_regs_for_mode

def expraff_fix_regs_for_mode(self, e):
    dst = self.expr_fix_regs_for_mode(e.dst)
    src = self.expr_fix_regs_for_mode(e.src)
    return ExprAff(dst, src)

def gen_loc_key_and_expr(

self, size)

Inheritance: ir_aarch64l.gen_loc_key_and_expr

Return a loc_key and it's corresponding ExprLoc @size: size of expression

def gen_loc_key_and_expr(self, size):
    """
    Return a loc_key and it's corresponding ExprLoc
    @size: size of expression
    """
    loc_key = self.loc_db.add_location()
    return loc_key, m2_expr.ExprLoc(loc_key, size)

def gen_pc_update(

self, assignments, instr)

Inheritance: ir_aarch64l.gen_pc_update

def gen_pc_update(self, assignments, instr):
    offset = m2_expr.ExprInt(instr.offset, self.pc.size)
    assignments.append(AssignBlock({self.pc:offset}, instr))

def get_ir(

self, instr)

Inheritance: ir_aarch64l.get_ir

def get_ir(self, instr):
    args = instr.args
    if len(args) and isinstance(args[-1], ExprOp):
        if (args[-1].op in ['<<', '>>', '<<a', 'a>>', '<<<', '>>>'] and
           isinstance(args[-1].args[-1], ExprId)):
            args[-1] = ExprOp(args[-1].op,
                                      args[-1].args[0],
                                      args[-1].args[-1][:8].zeroExtend(32))
    instr_ir, extra_ir = get_mnemo_expr(self, instr, *args)
    self.mod_pc(instr, instr_ir, extra_ir)
    instr_ir, extra_ir = self.del_dst_zr(instr, instr_ir, extra_ir)
    return instr_ir, extra_ir

def get_loc_key_for_instr(

self, instr)

Inheritance: ir_aarch64l.get_loc_key_for_instr

Returns the loc_key associated to an instruction @instr: current instruction

def get_loc_key_for_instr(self, instr):
    """Returns the loc_key associated to an instruction
    @instr: current instruction"""
    return self.loc_db.get_or_create_offset_location(instr.offset)

def get_next_loc_key(

self, instr)

Inheritance: ir_aarch64l.get_next_loc_key

def get_next_loc_key(self, instr):
    loc_key = self.loc_db.get_or_create_offset_location(instr.offset + instr.l)
    return loc_key

def instr2ir(

self, instr)

Inheritance: ir_aarch64l.instr2ir

def instr2ir(self, instr):
    ir_bloc_cur, extra_irblocks = self.get_ir(instr)
    for index, irb in enumerate(extra_irblocks):
        irs = []
        for assignblk in irb:
            irs.append(AssignBlock(assignblk, instr))
        extra_irblocks[index] = IRBlock(irb.loc_key, irs)
    assignblk = AssignBlock(ir_bloc_cur, instr)
    return assignblk, extra_irblocks

def irbloc_fix_regs_for_mode(

self, irblock, mode=64)

Inheritance: ir_aarch64l.irbloc_fix_regs_for_mode

def irbloc_fix_regs_for_mode(self, irblock, mode=64):
    irs = []
    for assignblk in irblock:
        new_assignblk = dict(assignblk)
        for dst, src in assignblk.iteritems():
            del(new_assignblk[dst])
            # Special case for 64 bits:
            # If destination is a 32 bit reg, zero extend the 64 bit reg
            if (isinstance(dst, ExprId) and
                dst.size == 32 and
                dst in replace_regs):
                src = src.zeroExtend(64)
                dst = replace_regs[dst].arg
            dst = self.expr_fix_regs_for_mode(dst)
            src = self.expr_fix_regs_for_mode(src)
            new_assignblk[dst] = src
        irs.append(AssignBlock(new_assignblk, assignblk.instr))
    return IRBlock(irblock.loc_key, irs)

def is_pc_written(

self, block)

Inheritance: ir_aarch64l.is_pc_written

Return the first Assignblk of the @blockin which PC is written @block: IRBlock instance

def is_pc_written(self, block):
    """Return the first Assignblk of the @blockin which PC is written
    @block: IRBlock instance"""
    all_pc = self.arch.pc.values()
    for assignblk in block:
        if assignblk.dst in all_pc:
            return assignblk
    return None

def mod_pc(

self, instr, instr_ir, extra_ir)

Inheritance: ir_aarch64l.mod_pc

Replace PC by the instruction's offset

def mod_pc(self, instr, instr_ir, extra_ir):
    "Replace PC by the instruction's offset"
    cur_offset = ExprInt(instr.offset, 64)
    pc_fixed = {self.pc: cur_offset}
    for i, expr in enumerate(instr_ir):
        dst, src = expr.dst, expr.src
        if dst != self.pc:
            dst = dst.replace_expr(pc_fixed)
        src = src.replace_expr(pc_fixed)
        instr_ir[i] = ExprAff(dst, src)
    for idx, irblock in enumerate(extra_ir):
        extra_ir[idx] = irblock.modify_exprs(lambda expr: expr.replace_expr(pc_fixed) \
                                             if expr != self.pc else expr,
                                             lambda expr: expr.replace_expr(pc_fixed))

def new_ircfg(

self, *args, **kwargs)

Inheritance: ir_aarch64l.new_ircfg

Return a new instance of IRCFG

def new_ircfg(self, *args, **kwargs):
    """
    Return a new instance of IRCFG
    """
    return IRCFG(self.IRDst, self.loc_db, *args, **kwargs)

def new_ircfg_from_asmcfg(

self, asmcfg, *args, **kwargs)

Inheritance: ir_aarch64l.new_ircfg_from_asmcfg

Return a new instance of IRCFG from an @asmcfg @asmcfg: AsmCFG instance

def new_ircfg_from_asmcfg(self, asmcfg, *args, **kwargs):
    """
    Return a new instance of IRCFG from an @asmcfg
    @asmcfg: AsmCFG instance
    """
    ircfg = IRCFG(self.IRDst, self.loc_db, *args, **kwargs)
    for block in asmcfg.blocks:
        self.add_asmblock_to_ircfg(block, ircfg)
    return ircfg

def post_add_asmblock_to_ircfg(

self, block, ircfg, ir_blocks)

Inheritance: ir_aarch64l.post_add_asmblock_to_ircfg

def post_add_asmblock_to_ircfg(self, block, ircfg, ir_blocks):
    self.set_empty_dst_to_next(block, ir_blocks)
    new_irblocks = []
    for irblock in ir_blocks:
        new_irblock = self.irbloc_fix_regs_for_mode(irblock, self.attrib)
        ircfg.add_irblock(new_irblock)
        new_irblocks.append(new_irblock)
    return new_irblocks

def set_empty_dst_to_next(

self, block, ir_blocks)

Inheritance: ir_aarch64l.set_empty_dst_to_next

def set_empty_dst_to_next(self, block, ir_blocks):
    for index, irblock in enumerate(ir_blocks):
        if irblock.dst is not None:
            continue
        next_loc_key = block.get_next()
        if next_loc_key is None:
            loc_key = None
            if block.lines:
                line = block.lines[-1]
                if line.offset is not None:
                    loc_key = self.loc_db.get_or_create_offset_location(line.offset + line.l)
            if loc_key is None:
                loc_key = self.loc_db.add_location()
            block.add_cst(loc_key, AsmConstraint.c_next)
        else:
            loc_key = next_loc_key
        dst = m2_expr.ExprLoc(loc_key, self.pc.size)
        if irblock.assignblks:
            instr = irblock.assignblks[-1].instr
        else:
            instr = None
        assignblk = AssignBlock({self.IRDst: dst}, instr)
        ir_blocks[index] = IRBlock(irblock.loc_key, list(irblock.assignblks) + [assignblk])

class ir_aarch64l

class ir_aarch64l(IntermediateRepresentation):

    def __init__(self, loc_db=None):
        IntermediateRepresentation.__init__(self, mn_aarch64, "l", loc_db)
        self.pc = PC
        self.sp = SP
        self.IRDst = ExprId('IRDst', 64)
        self.addrsize = 64

    def get_ir(self, instr):
        args = instr.args
        if len(args) and isinstance(args[-1], ExprOp):
            if (args[-1].op in ['<<', '>>', '<<a', 'a>>', '<<<', '>>>'] and
               isinstance(args[-1].args[-1], ExprId)):
                args[-1] = ExprOp(args[-1].op,
                                          args[-1].args[0],
                                          args[-1].args[-1][:8].zeroExtend(32))
        instr_ir, extra_ir = get_mnemo_expr(self, instr, *args)
        self.mod_pc(instr, instr_ir, extra_ir)
        instr_ir, extra_ir = self.del_dst_zr(instr, instr_ir, extra_ir)
        return instr_ir, extra_ir

    def expr_fix_regs_for_mode(self, e):
        return e.replace_expr(replace_regs)

    def expraff_fix_regs_for_mode(self, e):
        dst = self.expr_fix_regs_for_mode(e.dst)
        src = self.expr_fix_regs_for_mode(e.src)
        return ExprAff(dst, src)

    def irbloc_fix_regs_for_mode(self, irblock, mode=64):
        irs = []
        for assignblk in irblock:
            new_assignblk = dict(assignblk)
            for dst, src in assignblk.iteritems():
                del(new_assignblk[dst])
                # Special case for 64 bits:
                # If destination is a 32 bit reg, zero extend the 64 bit reg
                if (isinstance(dst, ExprId) and
                    dst.size == 32 and
                    dst in replace_regs):
                    src = src.zeroExtend(64)
                    dst = replace_regs[dst].arg

                dst = self.expr_fix_regs_for_mode(dst)
                src = self.expr_fix_regs_for_mode(src)
                new_assignblk[dst] = src
            irs.append(AssignBlock(new_assignblk, assignblk.instr))
        return IRBlock(irblock.loc_key, irs)

    def mod_pc(self, instr, instr_ir, extra_ir):
        "Replace PC by the instruction's offset"
        cur_offset = ExprInt(instr.offset, 64)
        pc_fixed = {self.pc: cur_offset}
        for i, expr in enumerate(instr_ir):
            dst, src = expr.dst, expr.src
            if dst != self.pc:
                dst = dst.replace_expr(pc_fixed)
            src = src.replace_expr(pc_fixed)
            instr_ir[i] = ExprAff(dst, src)

        for idx, irblock in enumerate(extra_ir):
            extra_ir[idx] = irblock.modify_exprs(lambda expr: expr.replace_expr(pc_fixed) \
                                                 if expr != self.pc else expr,
                                                 lambda expr: expr.replace_expr(pc_fixed))


    def del_dst_zr(self, instr, instr_ir, extra_ir):
        "Writes to zero register are discarded"
        regs_to_fix = [WZR, XZR]
        instr_ir = [expr for expr in instr_ir if expr.dst not in regs_to_fix]

        new_irblocks = []
        for irblock in extra_ir:
            irs = []
            for assignblk in irblock:
                new_dsts = {dst:src for dst, src in assignblk.iteritems()
                                if dst not in regs_to_fix}
                irs.append(AssignBlock(new_dsts, assignblk.instr))
            new_irblocks.append(IRBlock(irblock.loc_key, irs))

        return instr_ir, new_irblocks

Ancestors (in MRO)

  • ir_aarch64l
  • miasm2.ir.ir.IntermediateRepresentation
  • __builtin__.object

Instance variables

var IRDst

var addrsize

var pc

var sp

Methods

def __init__(

self, loc_db=None)

def __init__(self, loc_db=None):
    IntermediateRepresentation.__init__(self, mn_aarch64, "l", loc_db)
    self.pc = PC
    self.sp = SP
    self.IRDst = ExprId('IRDst', 64)
    self.addrsize = 64

def add_asmblock_to_ircfg(

self, block, ircfg, gen_pc_updt=False)

Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions

def add_asmblock_to_ircfg(self, block, ircfg, gen_pc_updt=False):
    """
    Add a native block to the current IR
    @block: native assembly block
    @ircfg: IRCFG instance
    @gen_pc_updt: insert PC update effects between instructions
    """
    loc_key = block.loc_key
    ir_blocks_all = []
    assignments = []
    for instr in block.lines:
        if loc_key is None:
            assignments = []
            loc_key = self.get_loc_key_for_instr(instr)
        split = self.add_instr_to_current_state(
            instr, block, assignments,
            ir_blocks_all, gen_pc_updt
        )
        if split:
            ir_blocks_all.append(IRBlock(loc_key, assignments))
            loc_key = None
            assignments = []
    if loc_key is not None:
        ir_blocks_all.append(IRBlock(loc_key, assignments))
    new_ir_blocks_all = self.post_add_asmblock_to_ircfg(block, ircfg, ir_blocks_all)
    for irblock in new_ir_blocks_all:
        ircfg.add_irblock(irblock)
    return new_ir_blocks_all

def add_bloc(

self, block, gen_pc_updt=False)

DEPRECATED function Use add_block instead of add_block

def add_bloc(self, block, gen_pc_updt=False):
    """
    DEPRECATED function
    Use add_block instead of add_block
    """
    self.add_block(block, gen_pc_updt)

def add_block(

self, block, gen_pc_updt=False)

DEPRECATED function Use add_block instead of add_block

def add_block(self, block, gen_pc_updt=False):
    """
    DEPRECATED function
    Use add_block instead of add_block
    """
    warnings.warn("""DEPRECATION WARNING
    ircfg is now out of IntermediateRepresentation
    Use:
    ircfg = ir_arch.new_ircfg()
    ir_arch.add_asmblock_to_ircfg(block, ircfg)
    """)
    raise RuntimeError("API Deprecated")

def add_instr_to_current_state(

self, instr, block, assignments, ir_blocks_all, gen_pc_updt)

Add the IR effects of an instruction to the current state.

Returns a bool: True if the current assignments list must be split False in other cases.

@instr: native instruction @block: native block source @assignments: list of current AssignBlocks @ir_blocks_all: list of additional effects @gen_pc_updt: insert PC update effects between instructions

def add_instr_to_current_state(self, instr, block, assignments, ir_blocks_all, gen_pc_updt):
    """
    Add the IR effects of an instruction to the current state.
    Returns a bool:
    * True if the current assignments list must be split
    * False in other cases.
    @instr: native instruction
    @block: native block source
    @assignments: list of current AssignBlocks
    @ir_blocks_all: list of additional effects
    @gen_pc_updt: insert PC update effects between instructions
    """
    if gen_pc_updt is not False:
        self.gen_pc_update(assignments, instr)
    assignblk, ir_blocks_extra = self.instr2ir(instr)
    assignments.append(assignblk)
    ir_blocks_all += ir_blocks_extra
    if ir_blocks_extra:
        return True
    return False

def add_instr_to_ircfg(

self, instr, ircfg, loc_key=None, gen_pc_updt=False)

Add the native instruction @instr to the @ircfg @instr: instruction instance @ircfg: IRCFG instance @loc_key: loc_key instance of the instruction destination @gen_pc_updt: insert PC update effects between instructions

def add_instr_to_ircfg(self, instr, ircfg, loc_key=None, gen_pc_updt=False):
    """
    Add the native instruction @instr to the @ircfg
    @instr: instruction instance
    @ircfg: IRCFG instance
    @loc_key: loc_key instance of the instruction destination
    @gen_pc_updt: insert PC update effects between instructions
    """
    if loc_key is None:
        offset = getattr(instr, "offset", None)
        loc_key = self.loc_db.add_location(offset=offset)
    block = AsmBlock(loc_key)
    block.lines = [instr]
    self.add_asmblock_to_ircfg(block, ircfg, gen_pc_updt)
    return loc_key

def del_dst_zr(

self, instr, instr_ir, extra_ir)

Writes to zero register are discarded

def del_dst_zr(self, instr, instr_ir, extra_ir):
    "Writes to zero register are discarded"
    regs_to_fix = [WZR, XZR]
    instr_ir = [expr for expr in instr_ir if expr.dst not in regs_to_fix]
    new_irblocks = []
    for irblock in extra_ir:
        irs = []
        for assignblk in irblock:
            new_dsts = {dst:src for dst, src in assignblk.iteritems()
                            if dst not in regs_to_fix}
            irs.append(AssignBlock(new_dsts, assignblk.instr))
        new_irblocks.append(IRBlock(irblock.loc_key, irs))
    return instr_ir, new_irblocks

def expr_fix_regs_for_mode(

self, e)

def expr_fix_regs_for_mode(self, e):
    return e.replace_expr(replace_regs)

def expraff_fix_regs_for_mode(

self, e)

def expraff_fix_regs_for_mode(self, e):
    dst = self.expr_fix_regs_for_mode(e.dst)
    src = self.expr_fix_regs_for_mode(e.src)
    return ExprAff(dst, src)

def gen_loc_key_and_expr(

self, size)

Return a loc_key and it's corresponding ExprLoc @size: size of expression

def gen_loc_key_and_expr(self, size):
    """
    Return a loc_key and it's corresponding ExprLoc
    @size: size of expression
    """
    loc_key = self.loc_db.add_location()
    return loc_key, m2_expr.ExprLoc(loc_key, size)

def gen_pc_update(

self, assignments, instr)

def gen_pc_update(self, assignments, instr):
    offset = m2_expr.ExprInt(instr.offset, self.pc.size)
    assignments.append(AssignBlock({self.pc:offset}, instr))

def get_ir(

self, instr)

def get_ir(self, instr):
    args = instr.args
    if len(args) and isinstance(args[-1], ExprOp):
        if (args[-1].op in ['<<', '>>', '<<a', 'a>>', '<<<', '>>>'] and
           isinstance(args[-1].args[-1], ExprId)):
            args[-1] = ExprOp(args[-1].op,
                                      args[-1].args[0],
                                      args[-1].args[-1][:8].zeroExtend(32))
    instr_ir, extra_ir = get_mnemo_expr(self, instr, *args)
    self.mod_pc(instr, instr_ir, extra_ir)
    instr_ir, extra_ir = self.del_dst_zr(instr, instr_ir, extra_ir)
    return instr_ir, extra_ir

def get_loc_key_for_instr(

self, instr)

Returns the loc_key associated to an instruction @instr: current instruction

def get_loc_key_for_instr(self, instr):
    """Returns the loc_key associated to an instruction
    @instr: current instruction"""
    return self.loc_db.get_or_create_offset_location(instr.offset)

def get_next_loc_key(

self, instr)

def get_next_loc_key(self, instr):
    loc_key = self.loc_db.get_or_create_offset_location(instr.offset + instr.l)
    return loc_key

def instr2ir(

self, instr)

def instr2ir(self, instr):
    ir_bloc_cur, extra_irblocks = self.get_ir(instr)
    for index, irb in enumerate(extra_irblocks):
        irs = []
        for assignblk in irb:
            irs.append(AssignBlock(assignblk, instr))
        extra_irblocks[index] = IRBlock(irb.loc_key, irs)
    assignblk = AssignBlock(ir_bloc_cur, instr)
    return assignblk, extra_irblocks

def irbloc_fix_regs_for_mode(

self, irblock, mode=64)

def irbloc_fix_regs_for_mode(self, irblock, mode=64):
    irs = []
    for assignblk in irblock:
        new_assignblk = dict(assignblk)
        for dst, src in assignblk.iteritems():
            del(new_assignblk[dst])
            # Special case for 64 bits:
            # If destination is a 32 bit reg, zero extend the 64 bit reg
            if (isinstance(dst, ExprId) and
                dst.size == 32 and
                dst in replace_regs):
                src = src.zeroExtend(64)
                dst = replace_regs[dst].arg
            dst = self.expr_fix_regs_for_mode(dst)
            src = self.expr_fix_regs_for_mode(src)
            new_assignblk[dst] = src
        irs.append(AssignBlock(new_assignblk, assignblk.instr))
    return IRBlock(irblock.loc_key, irs)

def is_pc_written(

self, block)

Return the first Assignblk of the @blockin which PC is written @block: IRBlock instance

def is_pc_written(self, block):
    """Return the first Assignblk of the @blockin which PC is written
    @block: IRBlock instance"""
    all_pc = self.arch.pc.values()
    for assignblk in block:
        if assignblk.dst in all_pc:
            return assignblk
    return None

def mod_pc(

self, instr, instr_ir, extra_ir)

Replace PC by the instruction's offset

def mod_pc(self, instr, instr_ir, extra_ir):
    "Replace PC by the instruction's offset"
    cur_offset = ExprInt(instr.offset, 64)
    pc_fixed = {self.pc: cur_offset}
    for i, expr in enumerate(instr_ir):
        dst, src = expr.dst, expr.src
        if dst != self.pc:
            dst = dst.replace_expr(pc_fixed)
        src = src.replace_expr(pc_fixed)
        instr_ir[i] = ExprAff(dst, src)
    for idx, irblock in enumerate(extra_ir):
        extra_ir[idx] = irblock.modify_exprs(lambda expr: expr.replace_expr(pc_fixed) \
                                             if expr != self.pc else expr,
                                             lambda expr: expr.replace_expr(pc_fixed))

def new_ircfg(

self, *args, **kwargs)

Return a new instance of IRCFG

def new_ircfg(self, *args, **kwargs):
    """
    Return a new instance of IRCFG
    """
    return IRCFG(self.IRDst, self.loc_db, *args, **kwargs)

def new_ircfg_from_asmcfg(

self, asmcfg, *args, **kwargs)

Return a new instance of IRCFG from an @asmcfg @asmcfg: AsmCFG instance

def new_ircfg_from_asmcfg(self, asmcfg, *args, **kwargs):
    """
    Return a new instance of IRCFG from an @asmcfg
    @asmcfg: AsmCFG instance
    """
    ircfg = IRCFG(self.IRDst, self.loc_db, *args, **kwargs)
    for block in asmcfg.blocks:
        self.add_asmblock_to_ircfg(block, ircfg)
    return ircfg

def post_add_asmblock_to_ircfg(

self, block, ircfg, ir_blocks)

def post_add_asmblock_to_ircfg(self, block, ircfg, ir_blocks):
    self.set_empty_dst_to_next(block, ir_blocks)
    new_irblocks = []
    for irblock in ir_blocks:
        new_irblock = self.irbloc_fix_regs_for_mode(irblock, self.attrib)
        ircfg.add_irblock(new_irblock)
        new_irblocks.append(new_irblock)
    return new_irblocks

def set_empty_dst_to_next(

self, block, ir_blocks)

def set_empty_dst_to_next(self, block, ir_blocks):
    for index, irblock in enumerate(ir_blocks):
        if irblock.dst is not None:
            continue
        next_loc_key = block.get_next()
        if next_loc_key is None:
            loc_key = None
            if block.lines:
                line = block.lines[-1]
                if line.offset is not None:
                    loc_key = self.loc_db.get_or_create_offset_location(line.offset + line.l)
            if loc_key is None:
                loc_key = self.loc_db.add_location()
            block.add_cst(loc_key, AsmConstraint.c_next)
        else:
            loc_key = next_loc_key
        dst = m2_expr.ExprLoc(loc_key, self.pc.size)
        if irblock.assignblks:
            instr = irblock.assignblks[-1].instr
        else:
            instr = None
        assignblk = AssignBlock({self.IRDst: dst}, instr)
        ir_blocks[index] = IRBlock(irblock.loc_key, list(irblock.assignblks) + [assignblk])