miasm2.arch.ppc.sem module
import miasm2.expression.expression as expr from miasm2.ir.ir import AssignBlock, IntermediateRepresentation, IRBlock from miasm2.arch.ppc.arch import mn_ppc from miasm2.arch.ppc.regs import * from miasm2.core.sembuilder import SemBuilder from miasm2.jitter.csts import * spr_dict = { 8: LR, 9: CTR, 18: DSISR, 19: DAR, 22: DEC, 26: SRR0, 27: SRR1, 272: SPRG0, 273: SPRG0, 274: SPRG1, 275: SPRG2, 276: SPRG3, 284: TBL, 285: TBU, 287: PVR, 1023: PIR } crf_dict = dict((ExprId("CR%d" % i, 4), dict( (bit, ExprId("CR%d_%s" % (i, bit), 1)) for bit in ['LT', 'GT', 'EQ', 'SO' ] )) for i in xrange(8) ) ctx = { 'crf_dict': crf_dict, 'spr_dict': spr_dict } ctx.update(all_regs_ids_byname) sbuild = SemBuilder(ctx) def mn_compute_flags(rvalue, overflow_expr=None): ret = [] ret.append(ExprAff(CR0_LT, rvalue.msb())) ret.append(ExprAff(CR0_GT, (ExprCond(rvalue, ExprInt(1, 1), ExprInt(0, 1)) & ~rvalue.msb()))) ret.append(ExprAff(CR0_EQ, ExprCond(rvalue, ExprInt(0, 1), ExprInt(1, 1)))) if overflow_expr != None: ret.append(ExprAff(CR0_SO, XER_SO | overflow_expr)) else: ret.append(ExprAff(CR0_SO, XER_SO)) return ret def mn_do_add(ir, instr, arg1, arg2, arg3): assert instr.name[0:3] == 'ADD' flags_update = [] has_dot = False has_c = False has_e = False has_o = False for l in instr.name[3:]: if l == '.': has_dot = True elif l == 'C': has_c = True elif l == 'E': has_e = True elif l == 'O': has_o = True elif l == 'I' or l == 'M' or l == 'S' or l == 'Z': pass # Taken care of earlier else: assert False rvalue = arg2 + arg3 if has_e: rvalue = rvalue + XER_CA.zeroExtend(32) over_expr = None if has_o: msb1 = arg2.msb() msb2 = arg3.msb() msba = rvalue.msb() over_expr = ~(msb1 ^ msb2) & (msb1 ^ msba) flags_update.append(ExprAff(XER_OV, over_expr)) flags_update.append(ExprAff(XER_SO, XER_SO | over_expr)) if has_dot: flags_update += mn_compute_flags(rvalue, over_expr) if has_c or has_e: carry_expr = (((arg2 ^ arg3) ^ rvalue) ^ ((arg2 ^ rvalue) & (~(arg2 ^ arg3)))).msb() flags_update.append(ExprAff(XER_CA, carry_expr)) return ([ ExprAff(arg1, rvalue) ] + flags_update), [] def mn_do_and(ir, instr, ra, rs, arg2): if len(instr.name) > 3 and instr.name[3] == 'C': oarg = ~arg2 else: oarg = arg2 rvalue = rs & oarg ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, [] def mn_do_cntlzw(ir, instr, ra, rs): ret = [ ExprAff(ra, ExprOp('cntleadzeros', rs)) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, [] def crbit_to_reg(bit): bit = bit.arg.arg crid = bit / 4 bitname = [ 'LT', 'GT', 'EQ', 'SO' ][bit % 4] return all_regs_ids_byname["CR%d_%s" % (crid, bitname)] def mn_do_cr(ir, instr, crd, cra, crb): a = crbit_to_reg(cra) b = crbit_to_reg(crb) d = crbit_to_reg(crd) op = instr.name[2:] if op == 'AND': r = a & b elif op == 'ANDC': r = a & ~b elif op == 'EQV': r = ~(a ^ b) elif op == 'NAND': r = ~(a & b) elif op == 'NOR': r = ~(a | b) elif op == 'OR': r = a | b elif op == 'ORC': r = a | ~b elif op == 'XOR': r = a ^ b else: raise "Unknown operation on CR" return [ ExprAff(d, r) ], [] def mn_do_div(ir, instr, rd, ra, rb): assert instr.name[0:4] == 'DIVW' flags_update = [] has_dot = False has_c = False has_o = False has_u = False for l in instr.name[3:]: if l == '.': has_dot = True elif l == 'C': has_c = True elif l == 'O': has_o = True elif l == 'U': has_u = True elif l == 'W': pass else: assert False if has_u: op = 'udiv' else: op = 'idiv' rvalue = ExprOp(op, ra, rb) over_expr = None if has_o: over_expr = ExprCond(rb, ExprInt(0, 1), ExprInt(1, 1)) if not has_u: over_expr = over_expr | (ExprCond(ra ^ 0x80000000, ExprInt(0, 1), ExprInt(1, 1)) & ExprCond(rb ^ 0xFFFFFFFF, ExprInt(0, 1), ExprInt(1, 1))) flags_update.append(ExprAff(XER_OV, over_expr)) flags_update.append(ExprAff(XER_SO, XER_SO | over_expr)) if has_dot: flags_update += mn_compute_flags(rvalue, over_expr) return ([ ExprAff(rd, rvalue) ] + flags_update), [] def mn_do_eqv(ir, instr, ra, rs, rb): rvalue = ~(rs ^ rb) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, [] def mn_do_exts(ir, instr, ra, rs): if instr.name[4] == 'B': size = 8 elif instr.name[4] == 'H': size = 16 else: assert False rvalue = rs[0:size].signExtend(32) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, [] def byte_swap(expr): nbytes = expr.size / 8 bytes = [ expr[i*8:i*8+8] for i in xrange(nbytes - 1, -1, -1) ] return ExprCompose(bytes) def mn_do_load(ir, instr, arg1, arg2, arg3=None): assert instr.name[0] == 'L' ret = [] if instr.name[1] == 'M': return mn_do_lmw(ir, instr, arg1, arg2) elif instr.name[1] == 'S': raise RuntimeError("LSWI, and LSWX need implementing") pass # XXX size = {'B': 8, 'H': 16, 'W': 32}[instr.name[1]] has_a = False has_b = False has_u = False is_lwarx = False for l in instr.name[2:]: if l == 'A': has_a = True elif l == 'B': has_b = True elif l == 'U': has_u = True elif l == 'X' or l == 'Z': pass # Taken care of earlier elif l == 'R' and not has_b: is_lwarx = True else: assert False if arg3 is None: assert isinstance(arg2, ExprMem) address = arg2.arg else: address = arg2 + arg3 src = ExprMem(address, size) if has_b: src = byte_swap(src) if has_a: src = src.signExtend(32) else: src = src.zeroExtend(32) ret.append(ExprAff(arg1, src)) if has_u: if arg3 is None: ret.append(ExprAff(arg2.arg.args[0], address)) else: ret.append(ExprAff(arg2, address)) if is_lwarx: ret.append(ExprAff(reserve, ExprInt(1, 1))) ret.append(ExprAff(reserve_address, address)) # XXX should be the PA return ret, [] def mn_do_lmw(ir, instr, rd, src): ret = [] address = src.arg ri = int(rd.name[1:],10) i = 0 while ri <= 31: ret.append(ExprAff(all_regs_ids_byname["R%d" % ri], ExprMem(address + ExprInt(i, 32), 32))) ri += 1 i += 4 return ret, [] def mn_do_lswi(ir, instr, rd, ra, nb): if nb == 0: nb = 32 i = 32 raise "%r not implemented" % instr def mn_do_lswx(ir, instr, rd, ra, nb): raise "%r not implemented" % instr def mn_do_mcrf(ir, instr, crfd, crfs): ret = [] for bit in [ 'LT', 'GT', 'EQ', 'SO' ]: d = all_regs_ids_byname["%s_%s" % (crfd, bit)] s = all_regs_ids_byname["%s_%s" % (crfs, bit)] ret.append(ExprAff(d, s)) return ret, [] def mn_do_mcrxr(ir, instr, crfd): ret = [] for (bit, val) in [ ('LT', XER_SO), ('GT', XER_OV), ('EQ', XER_CA), ('SO', ExprInt(0, 1)) ]: ret.append(ExprAff(all_regs_ids_byname["%s_%s" % (crfd, bit)], val)) return ret, [] def mn_do_mfcr(ir, instr, rd): return ([ ExprAff(rd, ExprCompose(*[ all_regs_ids_byname["CR%d_%s" % (i, b)] for i in xrange(7, -1, -1) for b in ['SO', 'EQ', 'GT', 'LT']]))], []) @sbuild.parse def mn_mfmsr(rd): rd = MSR def mn_mfspr(ir, instr, arg1, arg2): sprid = arg2.arg.arg gprid = int(arg1.name[1:]) if sprid in spr_dict: return [ ExprAff(arg1, spr_dict[sprid]) ], [] elif sprid == 1: # XER return [ ExprAff(arg1, ExprCompose(XER_BC, ExprInt(0, 22), XER_CA, XER_OV, XER_SO)) ], [] else: return [ ExprAff(spr_access, ExprInt(((sprid << SPR_ACCESS_SPR_OFF) | (gprid << SPR_ACCESS_GPR_OFF)), 32)), ExprAff(exception_flags, ExprInt(EXCEPT_SPR_ACCESS, 32)) ], [] def mn_mtcrf(ir, instr, crm, rs): ret = [] for i in xrange(8): if crm.arg.arg & (1 << (7 - i)): j = (28 - 4 * i) + 3 for b in ['LT', 'GT', 'EQ', 'SO']: ret.append(ExprAff(all_regs_ids_byname["CR%d_%s" % (i, b)], rs[j:j+1])) j -= 1 return ret, [] def mn_mtmsr(ir, instr, rs): print "%08x: MSR assigned" % instr.offset return [ ExprAff(MSR, rs) ], [] def mn_mtspr(ir, instr, arg1, arg2): sprid = arg1.arg.arg gprid = int(arg2.name[1:]) if sprid in spr_dict: return [ ExprAff(spr_dict[sprid], arg2) ], [] elif sprid == 1: # XER return [ ExprAff(XER_SO, arg2[31:32]), ExprAff(XER_OV, arg2[30:31]), ExprAff(XER_CA, arg2[29:30]), ExprAff(XER_BC, arg2[0:7]) ], [] else: return [ ExprAff(spr_access, ExprInt(((sprid << SPR_ACCESS_SPR_OFF) | (gprid << SPR_ACCESS_GPR_OFF) | SPR_ACCESS_IS_WRITE), 32)), ExprAff(exception_flags, ExprInt(EXCEPT_SPR_ACCESS, 32)) ], [] def mn_do_mul(ir, instr, rd, ra, arg2): variant = instr.name[3:] if variant[-1] == '.': variant = variant[:-2] if variant == 'HW': v1 = ra.signExtend(64) v2 = arg2.signExtend(64) shift = 32 elif variant == 'HWU': v1 = ra.zeroExtend(64) v2 = arg2.zeroExtend(64) shift = 32 else: v1 = ra v2 = arg2 shift = 0 rvalue = ExprOp('*', v1, v2) if shift != 0: rvalue = rvalue[shift : shift + 32] ret = [ ExprAff(rd, rvalue) ] over_expr = None if variant[-1] == 'O': over_expr = ExprCond((rvalue.signExtend(64) ^ ExprOp('*', v1.signExtend(64), v2.signExtend(64))), ExprInt(1, 1), ExprInt(0, 1)) ret.append(ExprAff(XER_OV, over_expr)) ret.append(ExprAff(XER_SO, XER_SO | over_expr)) if instr.name[-1] == '.': ret += mn_compute_flags(rvalue, over_expr) return ret, [] def mn_do_nand(ir, instr, ra, rs, rb): rvalue = ~(rs & rb) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, [] def mn_do_neg(ir, instr, rd, ra): rvalue = -ra ret = [ ExprAff(rd, rvalue) ] has_o = False over_expr = None if instr.name[-1] == 'O' or instr.name[-2] == 'O': has_o = True over_expr = ExprCond(ra ^ ExprInt(0x80000000, 32), ExprInt(0, 1), ExprInt(1, 1)) ret.append(ExprAff(XER_OV, over_expr)) ret.append(ExprAff(XER_SO, XER_SO | over_expr)) if instr.name[-1] == '.': ret += mn_compute_flags(rvalue, over_expr) return ret, [] def mn_do_nor(ir, instr, ra, rs, rb): rvalue = ~(rs | rb) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, [] def mn_do_or(ir, instr, ra, rs, arg2): if len(instr.name) > 2 and instr.name[2] == 'C': oarg = ~arg2 else: oarg = arg2 rvalue = rs | oarg ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, [] def mn_do_rfi(ir, instr): dest = ExprCompose(ExprInt(0, 2), SRR0[2:32]) ret = [ ExprAff(MSR, (MSR & ~ExprInt(0b1111111101110011, 32) | ExprCompose(SRR1[0:2], ExprInt(0, 2), SRR1[4:7], ExprInt(0, 1), SRR1[8:16], ExprInt(0, 16)))), ExprAff(PC, dest), ExprAff(ir.IRDst, dest) ] return ret, [] def mn_do_rotate(ir, instr, ra, rs, shift, mb, me): r = ExprOp('<<<', rs, shift) if mb <= me: m = ExprInt(((1 << (32 - mb)) - 1) & ~((1 << (32 - me - 1)) - 1), 32) else: m = ExprInt(((1 << (32 - mb)) - 1) | ~((1 << (32 - me - 1)) - 1), 32) rvalue = r & m if instr.name[0:6] == 'RLWIMI': rvalue = rvalue | (ra & ~m) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, [] def mn_do_slw(ir, instr, ra, rs, rb): rvalue = ExprCond(rb[5:6], ExprInt(0, 32), ExprOp('<<', rs, rb & ExprInt(0b11111, 32))) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, [] def mn_do_sraw(ir, instr, ra, rs, rb): rvalue = ExprCond(rb[5:6], ExprInt(0xFFFFFFFF, 32), ExprOp('a>>', rs, rb & ExprInt(0b11111, 32))) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) mask = ExprCond(rb[5:6], ExprInt(0xFFFFFFFF, 32), (ExprInt(0xFFFFFFFF, 32) >> (ExprInt(32, 32) - (rb & ExprInt(0b11111, 32))))) ret.append(ExprAff(XER_CA, rs.msb() & ExprCond(rs & mask, ExprInt(1, 1), ExprInt(0, 1)))) return ret, [] def mn_do_srawi(ir, instr, ra, rs, imm): rvalue = ExprOp('a>>', rs, imm) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) mask = ExprInt(0xFFFFFFFF >> (32 - imm.arg.arg), 32) ret.append(ExprAff(XER_CA, rs.msb() & ExprCond(rs & mask, ExprInt(1, 1), ExprInt(0, 1)))) return ret, [] def mn_do_srw(ir, instr, ra, rs, rb): rvalue = rs >> (rb & ExprInt(0b11111, 32)) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, [] def mn_do_stmw(ir, instr, rs, dest): ret = [] address = dest.arg ri = int(rs.name[1:],10) i = 0 while ri <= 31: ret.append(ExprAff(ExprMem(address + ExprInt(i,32), 32), all_regs_ids_byname["R%d" % ri])) ri += 1 i += 4 return ret, [] def mn_do_store(ir, instr, arg1, arg2, arg3=None): assert instr.name[0:2] == 'ST' ret = [] additional_ir = [] if instr.name[2] == 'S': raise RuntimeError("STSWI, and STSWX need implementing") pass # XXX size = {'B': 8, 'H': 16, 'W': 32}[instr.name[2]] has_b = False has_u = False is_stwcx = False for l in instr.name[3:]: if l == 'B' or l == 'R': has_b = True elif l == 'U': has_u = True elif l == 'X' or l == 'Z': pass # Taken care of earlier elif l == 'C' or l == '.': is_stwcx = True else: assert False if arg3 is None: assert isinstance(arg2, ExprMem) address = arg2.arg else: address = arg2 + arg3 dest = ExprMem(address, size) src = arg1[0:size] if has_b: src = byte_swap(src) ret.append(ExprAff(dest, src)) if has_u: if arg3 is None: ret.append(ExprAff(arg2.arg.args[0], address)) else: ret.append(ExprAff(arg2, address)) if is_stwcx: loc_do = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) loc_dont = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) loc_next = ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) flags = [ ExprAff(CR0_LT, ExprInt(0,1)), ExprAff(CR0_GT, ExprInt(0,1)), ExprAff(CR0_SO, XER_SO)] ret += flags ret.append(ExprAff(CR0_EQ, ExprInt(1,1))) ret.append(ExprAff(ir.IRDst, loc_next)) dont = flags + [ ExprAff(CR0_EQ, ExprInt(0,1)), ExprAff(ir.IRDst, loc_next) ] additional_ir = [ IRBlock(loc_do, [ AssignBlock(ret) ]), IRBlock(loc_dont, [ AssignBlock(dont) ]) ] ret = [ ExprAff(reserve, ExprInt(0, 1)), ExprAff(ir.IRDst, ExprCond(reserve, loc_do, loc_dont)) ] return ret, additional_ir def mn_do_sub(ir, instr, arg1, arg2, arg3): assert instr.name[0:4] == 'SUBF' flags_update = [] has_dot = False has_c = False has_e = False has_o = False for l in instr.name[4:]: if l == '.': has_dot = True elif l == 'C': has_c = True elif l == 'E': has_e = True elif l == 'O': has_o = True elif l == 'I' or l == 'M' or l == 'S' or l == 'Z': pass # Taken care of earlier else: assert False if has_e: arg3 = arg3 + XER_CA.zeroExtend(32) arg2 = arg2 + ExprInt(1, 32) rvalue = arg3 - arg2 over_expr = None if has_o: msb1 = arg2.msb() msb2 = arg3.msb() msba = rvalue.msb() over_expr = (msb1 ^ msb2) & (msb1 ^ msba) flags_update.append(ExprAff(XER_OV, over_expr)) flags_update.append(ExprAff(XER_SO, XER_SO | over_expr)) if has_dot: flags_update += mn_compute_flags(rvalue, over_expr) if has_c or has_e: carry_expr = ((((arg3 ^ arg2) ^ rvalue) ^ ((arg3 ^ rvalue) & (arg3 ^ arg2))).msb()) flags_update.append(ExprAff(XER_CA, ~carry_expr)) return ([ ExprAff(arg1, rvalue) ] + flags_update), [] def mn_do_xor(ir, instr, ra, rs, rb): rvalue = rs ^ rb ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, [] def mn_b(ir, instr, arg1, arg2 = None): if arg2 is not None: arg1 = arg2 return [ ExprAff(PC, arg1), ExprAff(ir.IRDst, arg1) ], [] def mn_bl(ir, instr, arg1, arg2 = None): if arg2 is not None: arg1 = arg2 dst = ir.get_next_instr(instr) return [ ExprAff(LR, ExprLoc(dst, 32)), ExprAff(PC, arg1), ExprAff(ir.IRDst, arg1) ], [] def mn_get_condition(instr): bit = instr.additional_info.bi & 0b11 cr = instr.args[0].name return all_regs_ids_byname[cr + '_' + ['LT', 'GT', 'EQ', 'SO'][bit]] def mn_do_cond_branch(ir, instr, dest): bo = instr.additional_info.bo bi = instr.additional_info.bi ret = [] if bo & 0b00100: ctr_cond = True else: ret.append(ExprAff(CTR, CTR - ExprInt(1, 32))) ctr_cond = ExprCond(CTR ^ ExprInt(1, 32), ExprInt(1, 1), ExprInt(0, 1)) if bo & 0b00010: ctr_cond = ~ctr_cond if (bo & 0b10000): cond_cond = True else: cond_cond = mn_get_condition(instr) if not (bo & 0b01000): cond_cond = ~cond_cond if ctr_cond != True or cond_cond != True: if ctr_cond != True: condition = ctr_cond if cond_cond != True: condition = condition & cond_cond else: condition = cond_cond dst = ir.get_next_instr(instr) dest_expr = ExprCond(condition, dest, ExprLoc(dst, 32)) else: dest_expr = dest if instr.name[-1] == 'L' or instr.name[-2:-1] == 'LA': dst = ir.get_next_instr(instr) ret.append(ExprAff(LR, ExprLoc(dst, 32))) ret.append(ExprAff(PC, dest_expr)) ret.append(ExprAff(ir.IRDst, dest_expr)) return ret, [] def mn_do_nop_warn(ir, instr, *args): print "Warning, instruction %s implemented as NOP" % instr return [], [] @sbuild.parse def mn_cmp_signed(arg1, arg2, arg3): crf_dict[arg1]['LT'] = ((arg2 - arg3) ^ ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))).msb() crf_dict[arg1]['GT'] = ((arg3 - arg2) ^ ((arg3 ^ arg2) & ((arg3 - arg2) ^ arg3))).msb() crf_dict[arg1]['EQ'] = i1(0) if arg2 - arg3 else i1(1) crf_dict[arg1]['SO'] = XER_SO @sbuild.parse def mn_cmp_unsigned(arg1, arg2, arg3): crf_dict[arg1]['LT'] = (((arg2 - arg3) ^ ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))) ^ arg2 ^ arg3).msb() crf_dict[arg1]['GT'] = (((arg3 - arg2) ^ ((arg3 ^ arg2) & ((arg3 - arg2) ^ arg3))) ^ arg2 ^ arg3).msb() crf_dict[arg1]['EQ'] = i1(0) if arg2 - arg3 else i1(1) crf_dict[arg1]['SO'] = XER_SO def mn_nop(ir, instr, *args): return [], [] @sbuild.parse def mn_or(arg1, arg2, arg3): arg1 = arg2 | arg3 @sbuild.parse def mn_assign(arg1, arg2): arg2 = arg1 def mn_stb(ir, instr, arg1, arg2): dest = ExprMem(arg2.arg, 8) return [ExprAff(dest, ExprSlice(arg1, 0, 8))], [] @sbuild.parse def mn_stwu(arg1, arg2): arg2 = arg1 arg1 = arg2.arg sem_dir = { 'B': mn_b, 'BA': mn_b, 'BL': mn_bl, 'BLA': mn_bl, 'CMPLW': mn_cmp_unsigned, 'CMPLWI': mn_cmp_unsigned, 'CMPW': mn_cmp_signed, 'CMPWI': mn_cmp_signed, 'CNTLZW': mn_do_cntlzw, 'CNTLZW.': mn_do_cntlzw, 'ECIWX': mn_do_nop_warn, 'ECOWX': mn_do_nop_warn, 'EIEIO': mn_do_nop_warn, 'EQV': mn_do_eqv, 'EQV.': mn_do_eqv, 'ICBI': mn_do_nop_warn, 'ISYNC': mn_do_nop_warn, 'MCRF': mn_do_mcrf, 'MCRXR': mn_do_mcrxr, 'MFCR': mn_do_mfcr, 'MFMSR': mn_mfmsr, 'MFSPR': mn_mfspr, 'MFSR': mn_do_nop_warn, 'MFSRIN': mn_do_nop_warn, 'MFTB': mn_mfmsr, 'MTCRF': mn_mtcrf, 'MTMSR': mn_mtmsr, 'MTSPR': mn_mtspr, 'MTSR': mn_do_nop_warn, 'MTSRIN': mn_do_nop_warn, 'NAND': mn_do_nand, 'NAND.': mn_do_nand, 'NOR': mn_do_nor, 'NOR.': mn_do_nor, 'RFI': mn_do_rfi, 'SC': mn_do_nop_warn, 'SLW': mn_do_slw, 'SLW.': mn_do_slw, 'SRAW': mn_do_sraw, 'SRAW.': mn_do_sraw, 'SRAWI': mn_do_srawi, 'SRAWI.': mn_do_srawi, 'SRW': mn_do_srw, 'SRW.': mn_do_srw, 'SYNC': mn_do_nop_warn, 'TLBIA': mn_do_nop_warn, 'TLBIE': mn_do_nop_warn, 'TLBSYNC': mn_do_nop_warn, 'TW': mn_do_nop_warn, 'TWI': mn_do_nop_warn, } class ir_ppc32b(IntermediateRepresentation): def __init__(self, loc_db=None): super(ir_ppc32b, self).__init__(mn_ppc, 'b', loc_db) self.pc = mn_ppc.getpc() self.sp = mn_ppc.getsp() self.IRDst = expr.ExprId('IRDst', 32) self.addrsize = 32 def get_ir(self, instr): args = instr.args[:] if instr.name[0:5] in [ 'ADDIS', 'ORIS', 'XORIS', 'ANDIS' ]: args[2] = ExprInt(args[2].arg << 16, 32) if instr.name[0:3] == 'ADD': if instr.name[0:4] == 'ADDZ': last_arg = ExprInt(0, 32) elif instr.name[0:4] == 'ADDM': last_arg = ExprInt(0xFFFFFFFF, 32) else: last_arg = args[2] instr_ir, extra_ir = mn_do_add(self, instr, args[0], args[1], last_arg) elif instr.name[0:3] == 'AND': instr_ir, extra_ir = mn_do_and(self, instr, *args) elif instr.additional_info.bo_bi_are_defined: name = instr.name if name[-1] == '+' or name[-1] == '-': name = name[0:-1] if name[-3:] == 'CTR' or name[-4:] == 'CTRL': arg1 = ExprCompose(ExprInt(0, 2), CTR[2:32]) elif name[-2:] == 'LR' or name[-3:] == 'LRL': arg1 = ExprCompose(ExprInt(0, 2), LR[2:32]) else: arg1 = args[1] instr_ir, extra_ir = mn_do_cond_branch(self, instr, arg1) elif instr.name[0:2] == 'CR': instr_ir, extra_ir = mn_do_cr(self, instr, *args) elif instr.name[0:3] == 'DCB': instr_ir, extra_ir = mn_do_nop_warn(self, instr, *args) elif instr.name[0:3] == 'DIV': instr_ir, extra_ir = mn_do_div(self, instr, *args) elif instr.name[0:4] == 'EXTS': instr_ir, extra_ir = mn_do_exts(self, instr, *args) elif instr.name[0] == 'L': instr_ir, extra_ir = mn_do_load(self, instr, *args) elif instr.name[0:3] == 'MUL': instr_ir, extra_ir = mn_do_mul(self, instr, *args) elif instr.name[0:3] == 'NEG': instr_ir, extra_ir = mn_do_neg(self, instr, *args) elif instr.name[0:2] == 'OR': instr_ir, extra_ir = mn_do_or(self, instr, *args) elif instr.name[0:2] == 'RL': instr_ir, extra_ir = mn_do_rotate(self, instr, args[0], args[1], args[2], args[3].arg.arg, args[4].arg.arg) elif instr.name == 'STMW': instr_ir, extra_ir = mn_do_stmw(self, instr, *args) elif instr.name[0:2] == 'ST': instr_ir, extra_ir = mn_do_store(self, instr, *args) elif instr.name[0:4] == 'SUBF': if instr.name[0:5] == 'SUBFZ': last_arg = ExprInt(0) elif instr.name[0:5] == 'SUBFM': last_arg = ExprInt(0xFFFFFFFF) else: last_arg = args[2] instr_ir, extra_ir = mn_do_sub(self, instr, args[0], args[1], last_arg) elif instr.name[0:3] == 'XOR': instr_ir, extra_ir = mn_do_xor(self, instr, *args) else: instr_ir, extra_ir = sem_dir[instr.name](self, instr, *args) return instr_ir, extra_ir def get_next_instr(self, instr): l = self.loc_db.get_or_create_offset_location(instr.offset + 4) return l def get_next_break_loc_key(self, instr): l = self.loc_db.get_or_create_offset_location(instr.offset + 4) return l
Module variables
var BREAKPOINT_READ
var BREAKPOINT_WRITE
var EXCEPT_ACCESS_VIOL
var EXCEPT_BREAKPOINT_INTERN
var EXCEPT_BREAKPOINT_MEMORY
var EXCEPT_CODE_AUTOMOD
var EXCEPT_DIV_BY_ZERO
var EXCEPT_DO_NOT_UPDATE_PC
var EXCEPT_ILLEGAL_INSN
var EXCEPT_INT_XX
var EXCEPT_NUM_UPDT_EIP
var EXCEPT_PRIV_INSN
var EXCEPT_SOFT_BP
var EXCEPT_SPR_ACCESS
var EXCEPT_UNK_MNEMO
var EXPRAFF
var EXPRCOMPOSE
var EXPRCOND
var EXPRID
var EXPRINT
var EXPRLOC
var EXPRMEM
var EXPROP
var EXPRSLICE
var EXPR_ORDER_DICT
var PAGE_EXEC
var PAGE_READ
var PAGE_WRITE
var PRIORITY_MAX
var SPR_ACCESS_GPR_MASK
var SPR_ACCESS_GPR_OFF
var SPR_ACCESS_IS_WRITE
var SPR_ACCESS_SPR_MASK
var SPR_ACCESS_SPR_OFF
var TOK_EQUAL
var TOK_INF
var TOK_INF_EQUAL
var TOK_INF_EQUAL_SIGNED
var TOK_INF_EQUAL_UNSIGNED
var TOK_INF_SIGNED
var TOK_INF_UNSIGNED
var TOK_POS
var TOK_POS_STRICT
var all_regs_ids
var all_regs_ids_byname
var all_regs_ids_init
var all_regs_ids_no_alias
var crf_dict
var crfbitregs_expr
var crfbitregs_init
var crfbitregs_str
var crfregs_expr
var crfregs_init
var crfregs_str
var ctx
var field
var flag
var gpregs_expr
var gpregs_init
var gpregs_str
var i
var mod_size2uint
var otherregs_expr
var otherregs_init
var otherregs_str
var priorities
var priorities_list
var regs_flt_expr
var regs_init
var sbuild
var sem_dir
var size_to_IEEE754_info
var spr_dict
var superregs_expr
var superregs_init
var superregs_str
var xerbcreg_expr
var xerbcreg_init
var xerbcreg_str
var xerbitregs_expr
var xerbitregs_init
var xerbitregs_str
Functions
def byte_swap(
expr)
def byte_swap(expr): nbytes = expr.size / 8 bytes = [ expr[i*8:i*8+8] for i in xrange(nbytes - 1, -1, -1) ] return ExprCompose(bytes)
def crbit_to_reg(
bit)
def crbit_to_reg(bit): bit = bit.arg.arg crid = bit / 4 bitname = [ 'LT', 'GT', 'EQ', 'SO' ][bit % 4] return all_regs_ids_byname["CR%d_%s" % (crid, bitname)]
def mn_b(
ir, instr, arg1, arg2=None)
def mn_b(ir, instr, arg1, arg2 = None): if arg2 is not None: arg1 = arg2 return [ ExprAff(PC, arg1), ExprAff(ir.IRDst, arg1) ], []
def mn_bl(
ir, instr, arg1, arg2=None)
def mn_bl(ir, instr, arg1, arg2 = None): if arg2 is not None: arg1 = arg2 dst = ir.get_next_instr(instr) return [ ExprAff(LR, ExprLoc(dst, 32)), ExprAff(PC, arg1), ExprAff(ir.IRDst, arg1) ], []
def mn_compute_flags(
rvalue, overflow_expr=None)
def mn_compute_flags(rvalue, overflow_expr=None): ret = [] ret.append(ExprAff(CR0_LT, rvalue.msb())) ret.append(ExprAff(CR0_GT, (ExprCond(rvalue, ExprInt(1, 1), ExprInt(0, 1)) & ~rvalue.msb()))) ret.append(ExprAff(CR0_EQ, ExprCond(rvalue, ExprInt(0, 1), ExprInt(1, 1)))) if overflow_expr != None: ret.append(ExprAff(CR0_SO, XER_SO | overflow_expr)) else: ret.append(ExprAff(CR0_SO, XER_SO)) return ret
def mn_do_add(
ir, instr, arg1, arg2, arg3)
def mn_do_add(ir, instr, arg1, arg2, arg3): assert instr.name[0:3] == 'ADD' flags_update = [] has_dot = False has_c = False has_e = False has_o = False for l in instr.name[3:]: if l == '.': has_dot = True elif l == 'C': has_c = True elif l == 'E': has_e = True elif l == 'O': has_o = True elif l == 'I' or l == 'M' or l == 'S' or l == 'Z': pass # Taken care of earlier else: assert False rvalue = arg2 + arg3 if has_e: rvalue = rvalue + XER_CA.zeroExtend(32) over_expr = None if has_o: msb1 = arg2.msb() msb2 = arg3.msb() msba = rvalue.msb() over_expr = ~(msb1 ^ msb2) & (msb1 ^ msba) flags_update.append(ExprAff(XER_OV, over_expr)) flags_update.append(ExprAff(XER_SO, XER_SO | over_expr)) if has_dot: flags_update += mn_compute_flags(rvalue, over_expr) if has_c or has_e: carry_expr = (((arg2 ^ arg3) ^ rvalue) ^ ((arg2 ^ rvalue) & (~(arg2 ^ arg3)))).msb() flags_update.append(ExprAff(XER_CA, carry_expr)) return ([ ExprAff(arg1, rvalue) ] + flags_update), []
def mn_do_and(
ir, instr, ra, rs, arg2)
def mn_do_and(ir, instr, ra, rs, arg2): if len(instr.name) > 3 and instr.name[3] == 'C': oarg = ~arg2 else: oarg = arg2 rvalue = rs & oarg ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, []
def mn_do_cntlzw(
ir, instr, ra, rs)
def mn_do_cntlzw(ir, instr, ra, rs): ret = [ ExprAff(ra, ExprOp('cntleadzeros', rs)) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, []
def mn_do_cond_branch(
ir, instr, dest)
def mn_do_cond_branch(ir, instr, dest): bo = instr.additional_info.bo bi = instr.additional_info.bi ret = [] if bo & 0b00100: ctr_cond = True else: ret.append(ExprAff(CTR, CTR - ExprInt(1, 32))) ctr_cond = ExprCond(CTR ^ ExprInt(1, 32), ExprInt(1, 1), ExprInt(0, 1)) if bo & 0b00010: ctr_cond = ~ctr_cond if (bo & 0b10000): cond_cond = True else: cond_cond = mn_get_condition(instr) if not (bo & 0b01000): cond_cond = ~cond_cond if ctr_cond != True or cond_cond != True: if ctr_cond != True: condition = ctr_cond if cond_cond != True: condition = condition & cond_cond else: condition = cond_cond dst = ir.get_next_instr(instr) dest_expr = ExprCond(condition, dest, ExprLoc(dst, 32)) else: dest_expr = dest if instr.name[-1] == 'L' or instr.name[-2:-1] == 'LA': dst = ir.get_next_instr(instr) ret.append(ExprAff(LR, ExprLoc(dst, 32))) ret.append(ExprAff(PC, dest_expr)) ret.append(ExprAff(ir.IRDst, dest_expr)) return ret, []
def mn_do_cr(
ir, instr, crd, cra, crb)
def mn_do_cr(ir, instr, crd, cra, crb): a = crbit_to_reg(cra) b = crbit_to_reg(crb) d = crbit_to_reg(crd) op = instr.name[2:] if op == 'AND': r = a & b elif op == 'ANDC': r = a & ~b elif op == 'EQV': r = ~(a ^ b) elif op == 'NAND': r = ~(a & b) elif op == 'NOR': r = ~(a | b) elif op == 'OR': r = a | b elif op == 'ORC': r = a | ~b elif op == 'XOR': r = a ^ b else: raise "Unknown operation on CR" return [ ExprAff(d, r) ], []
def mn_do_div(
ir, instr, rd, ra, rb)
def mn_do_div(ir, instr, rd, ra, rb): assert instr.name[0:4] == 'DIVW' flags_update = [] has_dot = False has_c = False has_o = False has_u = False for l in instr.name[3:]: if l == '.': has_dot = True elif l == 'C': has_c = True elif l == 'O': has_o = True elif l == 'U': has_u = True elif l == 'W': pass else: assert False if has_u: op = 'udiv' else: op = 'idiv' rvalue = ExprOp(op, ra, rb) over_expr = None if has_o: over_expr = ExprCond(rb, ExprInt(0, 1), ExprInt(1, 1)) if not has_u: over_expr = over_expr | (ExprCond(ra ^ 0x80000000, ExprInt(0, 1), ExprInt(1, 1)) & ExprCond(rb ^ 0xFFFFFFFF, ExprInt(0, 1), ExprInt(1, 1))) flags_update.append(ExprAff(XER_OV, over_expr)) flags_update.append(ExprAff(XER_SO, XER_SO | over_expr)) if has_dot: flags_update += mn_compute_flags(rvalue, over_expr) return ([ ExprAff(rd, rvalue) ] + flags_update), []
def mn_do_eqv(
ir, instr, ra, rs, rb)
def mn_do_eqv(ir, instr, ra, rs, rb): rvalue = ~(rs ^ rb) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, []
def mn_do_exts(
ir, instr, ra, rs)
def mn_do_exts(ir, instr, ra, rs): if instr.name[4] == 'B': size = 8 elif instr.name[4] == 'H': size = 16 else: assert False rvalue = rs[0:size].signExtend(32) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, []
def mn_do_lmw(
ir, instr, rd, src)
def mn_do_lmw(ir, instr, rd, src): ret = [] address = src.arg ri = int(rd.name[1:],10) i = 0 while ri <= 31: ret.append(ExprAff(all_regs_ids_byname["R%d" % ri], ExprMem(address + ExprInt(i, 32), 32))) ri += 1 i += 4 return ret, []
def mn_do_load(
ir, instr, arg1, arg2, arg3=None)
def mn_do_load(ir, instr, arg1, arg2, arg3=None): assert instr.name[0] == 'L' ret = [] if instr.name[1] == 'M': return mn_do_lmw(ir, instr, arg1, arg2) elif instr.name[1] == 'S': raise RuntimeError("LSWI, and LSWX need implementing") pass # XXX size = {'B': 8, 'H': 16, 'W': 32}[instr.name[1]] has_a = False has_b = False has_u = False is_lwarx = False for l in instr.name[2:]: if l == 'A': has_a = True elif l == 'B': has_b = True elif l == 'U': has_u = True elif l == 'X' or l == 'Z': pass # Taken care of earlier elif l == 'R' and not has_b: is_lwarx = True else: assert False if arg3 is None: assert isinstance(arg2, ExprMem) address = arg2.arg else: address = arg2 + arg3 src = ExprMem(address, size) if has_b: src = byte_swap(src) if has_a: src = src.signExtend(32) else: src = src.zeroExtend(32) ret.append(ExprAff(arg1, src)) if has_u: if arg3 is None: ret.append(ExprAff(arg2.arg.args[0], address)) else: ret.append(ExprAff(arg2, address)) if is_lwarx: ret.append(ExprAff(reserve, ExprInt(1, 1))) ret.append(ExprAff(reserve_address, address)) # XXX should be the PA return ret, []
def mn_do_lswi(
ir, instr, rd, ra, nb)
def mn_do_lswi(ir, instr, rd, ra, nb): if nb == 0: nb = 32 i = 32 raise "%r not implemented" % instr
def mn_do_lswx(
ir, instr, rd, ra, nb)
def mn_do_lswx(ir, instr, rd, ra, nb): raise "%r not implemented" % instr
def mn_do_mcrf(
ir, instr, crfd, crfs)
def mn_do_mcrf(ir, instr, crfd, crfs): ret = [] for bit in [ 'LT', 'GT', 'EQ', 'SO' ]: d = all_regs_ids_byname["%s_%s" % (crfd, bit)] s = all_regs_ids_byname["%s_%s" % (crfs, bit)] ret.append(ExprAff(d, s)) return ret, []
def mn_do_mcrxr(
ir, instr, crfd)
def mn_do_mcrxr(ir, instr, crfd): ret = [] for (bit, val) in [ ('LT', XER_SO), ('GT', XER_OV), ('EQ', XER_CA), ('SO', ExprInt(0, 1)) ]: ret.append(ExprAff(all_regs_ids_byname["%s_%s" % (crfd, bit)], val)) return ret, []
def mn_do_mfcr(
ir, instr, rd)
def mn_do_mfcr(ir, instr, rd): return ([ ExprAff(rd, ExprCompose(*[ all_regs_ids_byname["CR%d_%s" % (i, b)] for i in xrange(7, -1, -1) for b in ['SO', 'EQ', 'GT', 'LT']]))], [])
def mn_do_mul(
ir, instr, rd, ra, arg2)
def mn_do_mul(ir, instr, rd, ra, arg2): variant = instr.name[3:] if variant[-1] == '.': variant = variant[:-2] if variant == 'HW': v1 = ra.signExtend(64) v2 = arg2.signExtend(64) shift = 32 elif variant == 'HWU': v1 = ra.zeroExtend(64) v2 = arg2.zeroExtend(64) shift = 32 else: v1 = ra v2 = arg2 shift = 0 rvalue = ExprOp('*', v1, v2) if shift != 0: rvalue = rvalue[shift : shift + 32] ret = [ ExprAff(rd, rvalue) ] over_expr = None if variant[-1] == 'O': over_expr = ExprCond((rvalue.signExtend(64) ^ ExprOp('*', v1.signExtend(64), v2.signExtend(64))), ExprInt(1, 1), ExprInt(0, 1)) ret.append(ExprAff(XER_OV, over_expr)) ret.append(ExprAff(XER_SO, XER_SO | over_expr)) if instr.name[-1] == '.': ret += mn_compute_flags(rvalue, over_expr) return ret, []
def mn_do_nand(
ir, instr, ra, rs, rb)
def mn_do_nand(ir, instr, ra, rs, rb): rvalue = ~(rs & rb) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, []
def mn_do_neg(
ir, instr, rd, ra)
def mn_do_neg(ir, instr, rd, ra): rvalue = -ra ret = [ ExprAff(rd, rvalue) ] has_o = False over_expr = None if instr.name[-1] == 'O' or instr.name[-2] == 'O': has_o = True over_expr = ExprCond(ra ^ ExprInt(0x80000000, 32), ExprInt(0, 1), ExprInt(1, 1)) ret.append(ExprAff(XER_OV, over_expr)) ret.append(ExprAff(XER_SO, XER_SO | over_expr)) if instr.name[-1] == '.': ret += mn_compute_flags(rvalue, over_expr) return ret, []
def mn_do_nop_warn(
ir, instr, *args)
def mn_do_nop_warn(ir, instr, *args): print "Warning, instruction %s implemented as NOP" % instr return [], []
def mn_do_nor(
ir, instr, ra, rs, rb)
def mn_do_nor(ir, instr, ra, rs, rb): rvalue = ~(rs | rb) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, []
def mn_do_or(
ir, instr, ra, rs, arg2)
def mn_do_or(ir, instr, ra, rs, arg2): if len(instr.name) > 2 and instr.name[2] == 'C': oarg = ~arg2 else: oarg = arg2 rvalue = rs | oarg ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, []
def mn_do_rfi(
ir, instr)
def mn_do_rfi(ir, instr): dest = ExprCompose(ExprInt(0, 2), SRR0[2:32]) ret = [ ExprAff(MSR, (MSR & ~ExprInt(0b1111111101110011, 32) | ExprCompose(SRR1[0:2], ExprInt(0, 2), SRR1[4:7], ExprInt(0, 1), SRR1[8:16], ExprInt(0, 16)))), ExprAff(PC, dest), ExprAff(ir.IRDst, dest) ] return ret, []
def mn_do_rotate(
ir, instr, ra, rs, shift, mb, me)
def mn_do_rotate(ir, instr, ra, rs, shift, mb, me): r = ExprOp('<<<', rs, shift) if mb <= me: m = ExprInt(((1 << (32 - mb)) - 1) & ~((1 << (32 - me - 1)) - 1), 32) else: m = ExprInt(((1 << (32 - mb)) - 1) | ~((1 << (32 - me - 1)) - 1), 32) rvalue = r & m if instr.name[0:6] == 'RLWIMI': rvalue = rvalue | (ra & ~m) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, []
def mn_do_slw(
ir, instr, ra, rs, rb)
def mn_do_slw(ir, instr, ra, rs, rb): rvalue = ExprCond(rb[5:6], ExprInt(0, 32), ExprOp('<<', rs, rb & ExprInt(0b11111, 32))) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, []
def mn_do_sraw(
ir, instr, ra, rs, rb)
def mn_do_sraw(ir, instr, ra, rs, rb): rvalue = ExprCond(rb[5:6], ExprInt(0xFFFFFFFF, 32), ExprOp('a>>', rs, rb & ExprInt(0b11111, 32))) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) mask = ExprCond(rb[5:6], ExprInt(0xFFFFFFFF, 32), (ExprInt(0xFFFFFFFF, 32) >> (ExprInt(32, 32) - (rb & ExprInt(0b11111, 32))))) ret.append(ExprAff(XER_CA, rs.msb() & ExprCond(rs & mask, ExprInt(1, 1), ExprInt(0, 1)))) return ret, []
def mn_do_srawi(
ir, instr, ra, rs, imm)
def mn_do_srawi(ir, instr, ra, rs, imm): rvalue = ExprOp('a>>', rs, imm) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) mask = ExprInt(0xFFFFFFFF >> (32 - imm.arg.arg), 32) ret.append(ExprAff(XER_CA, rs.msb() & ExprCond(rs & mask, ExprInt(1, 1), ExprInt(0, 1)))) return ret, []
def mn_do_srw(
ir, instr, ra, rs, rb)
def mn_do_srw(ir, instr, ra, rs, rb): rvalue = rs >> (rb & ExprInt(0b11111, 32)) ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, []
def mn_do_stmw(
ir, instr, rs, dest)
def mn_do_stmw(ir, instr, rs, dest): ret = [] address = dest.arg ri = int(rs.name[1:],10) i = 0 while ri <= 31: ret.append(ExprAff(ExprMem(address + ExprInt(i,32), 32), all_regs_ids_byname["R%d" % ri])) ri += 1 i += 4 return ret, []
def mn_do_store(
ir, instr, arg1, arg2, arg3=None)
def mn_do_store(ir, instr, arg1, arg2, arg3=None): assert instr.name[0:2] == 'ST' ret = [] additional_ir = [] if instr.name[2] == 'S': raise RuntimeError("STSWI, and STSWX need implementing") pass # XXX size = {'B': 8, 'H': 16, 'W': 32}[instr.name[2]] has_b = False has_u = False is_stwcx = False for l in instr.name[3:]: if l == 'B' or l == 'R': has_b = True elif l == 'U': has_u = True elif l == 'X' or l == 'Z': pass # Taken care of earlier elif l == 'C' or l == '.': is_stwcx = True else: assert False if arg3 is None: assert isinstance(arg2, ExprMem) address = arg2.arg else: address = arg2 + arg3 dest = ExprMem(address, size) src = arg1[0:size] if has_b: src = byte_swap(src) ret.append(ExprAff(dest, src)) if has_u: if arg3 is None: ret.append(ExprAff(arg2.arg.args[0], address)) else: ret.append(ExprAff(arg2, address)) if is_stwcx: loc_do = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) loc_dont = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) loc_next = ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) flags = [ ExprAff(CR0_LT, ExprInt(0,1)), ExprAff(CR0_GT, ExprInt(0,1)), ExprAff(CR0_SO, XER_SO)] ret += flags ret.append(ExprAff(CR0_EQ, ExprInt(1,1))) ret.append(ExprAff(ir.IRDst, loc_next)) dont = flags + [ ExprAff(CR0_EQ, ExprInt(0,1)), ExprAff(ir.IRDst, loc_next) ] additional_ir = [ IRBlock(loc_do, [ AssignBlock(ret) ]), IRBlock(loc_dont, [ AssignBlock(dont) ]) ] ret = [ ExprAff(reserve, ExprInt(0, 1)), ExprAff(ir.IRDst, ExprCond(reserve, loc_do, loc_dont)) ] return ret, additional_ir
def mn_do_sub(
ir, instr, arg1, arg2, arg3)
def mn_do_sub(ir, instr, arg1, arg2, arg3): assert instr.name[0:4] == 'SUBF' flags_update = [] has_dot = False has_c = False has_e = False has_o = False for l in instr.name[4:]: if l == '.': has_dot = True elif l == 'C': has_c = True elif l == 'E': has_e = True elif l == 'O': has_o = True elif l == 'I' or l == 'M' or l == 'S' or l == 'Z': pass # Taken care of earlier else: assert False if has_e: arg3 = arg3 + XER_CA.zeroExtend(32) arg2 = arg2 + ExprInt(1, 32) rvalue = arg3 - arg2 over_expr = None if has_o: msb1 = arg2.msb() msb2 = arg3.msb() msba = rvalue.msb() over_expr = (msb1 ^ msb2) & (msb1 ^ msba) flags_update.append(ExprAff(XER_OV, over_expr)) flags_update.append(ExprAff(XER_SO, XER_SO | over_expr)) if has_dot: flags_update += mn_compute_flags(rvalue, over_expr) if has_c or has_e: carry_expr = ((((arg3 ^ arg2) ^ rvalue) ^ ((arg3 ^ rvalue) & (arg3 ^ arg2))).msb()) flags_update.append(ExprAff(XER_CA, ~carry_expr)) return ([ ExprAff(arg1, rvalue) ] + flags_update), []
def mn_do_xor(
ir, instr, ra, rs, rb)
def mn_do_xor(ir, instr, ra, rs, rb): rvalue = rs ^ rb ret = [ ExprAff(ra, rvalue) ] if instr.name[-1] == '.': ret += mn_compute_flags(rvalue) return ret, []
def mn_get_condition(
instr)
def mn_get_condition(instr): bit = instr.additional_info.bi & 0b11 cr = instr.args[0].name return all_regs_ids_byname[cr + '_' + ['LT', 'GT', 'EQ', 'SO'][bit]]
def mn_mfspr(
ir, instr, arg1, arg2)
def mn_mfspr(ir, instr, arg1, arg2): sprid = arg2.arg.arg gprid = int(arg1.name[1:]) if sprid in spr_dict: return [ ExprAff(arg1, spr_dict[sprid]) ], [] elif sprid == 1: # XER return [ ExprAff(arg1, ExprCompose(XER_BC, ExprInt(0, 22), XER_CA, XER_OV, XER_SO)) ], [] else: return [ ExprAff(spr_access, ExprInt(((sprid << SPR_ACCESS_SPR_OFF) | (gprid << SPR_ACCESS_GPR_OFF)), 32)), ExprAff(exception_flags, ExprInt(EXCEPT_SPR_ACCESS, 32)) ], []
def mn_mtcrf(
ir, instr, crm, rs)
def mn_mtcrf(ir, instr, crm, rs): ret = [] for i in xrange(8): if crm.arg.arg & (1 << (7 - i)): j = (28 - 4 * i) + 3 for b in ['LT', 'GT', 'EQ', 'SO']: ret.append(ExprAff(all_regs_ids_byname["CR%d_%s" % (i, b)], rs[j:j+1])) j -= 1 return ret, []
def mn_mtmsr(
ir, instr, rs)
def mn_mtmsr(ir, instr, rs): print "%08x: MSR assigned" % instr.offset return [ ExprAff(MSR, rs) ], []
def mn_mtspr(
ir, instr, arg1, arg2)
def mn_mtspr(ir, instr, arg1, arg2): sprid = arg1.arg.arg gprid = int(arg2.name[1:]) if sprid in spr_dict: return [ ExprAff(spr_dict[sprid], arg2) ], [] elif sprid == 1: # XER return [ ExprAff(XER_SO, arg2[31:32]), ExprAff(XER_OV, arg2[30:31]), ExprAff(XER_CA, arg2[29:30]), ExprAff(XER_BC, arg2[0:7]) ], [] else: return [ ExprAff(spr_access, ExprInt(((sprid << SPR_ACCESS_SPR_OFF) | (gprid << SPR_ACCESS_GPR_OFF) | SPR_ACCESS_IS_WRITE), 32)), ExprAff(exception_flags, ExprInt(EXCEPT_SPR_ACCESS, 32)) ], []
def mn_nop(
ir, instr, *args)
def mn_nop(ir, instr, *args): return [], []
def mn_stb(
ir, instr, arg1, arg2)
def mn_stb(ir, instr, arg1, arg2): dest = ExprMem(arg2.arg, 8) return [ExprAff(dest, ExprSlice(arg1, 0, 8))], []
Classes
class ir_ppc32b
class ir_ppc32b(IntermediateRepresentation): def __init__(self, loc_db=None): super(ir_ppc32b, self).__init__(mn_ppc, 'b', loc_db) self.pc = mn_ppc.getpc() self.sp = mn_ppc.getsp() self.IRDst = expr.ExprId('IRDst', 32) self.addrsize = 32 def get_ir(self, instr): args = instr.args[:] if instr.name[0:5] in [ 'ADDIS', 'ORIS', 'XORIS', 'ANDIS' ]: args[2] = ExprInt(args[2].arg << 16, 32) if instr.name[0:3] == 'ADD': if instr.name[0:4] == 'ADDZ': last_arg = ExprInt(0, 32) elif instr.name[0:4] == 'ADDM': last_arg = ExprInt(0xFFFFFFFF, 32) else: last_arg = args[2] instr_ir, extra_ir = mn_do_add(self, instr, args[0], args[1], last_arg) elif instr.name[0:3] == 'AND': instr_ir, extra_ir = mn_do_and(self, instr, *args) elif instr.additional_info.bo_bi_are_defined: name = instr.name if name[-1] == '+' or name[-1] == '-': name = name[0:-1] if name[-3:] == 'CTR' or name[-4:] == 'CTRL': arg1 = ExprCompose(ExprInt(0, 2), CTR[2:32]) elif name[-2:] == 'LR' or name[-3:] == 'LRL': arg1 = ExprCompose(ExprInt(0, 2), LR[2:32]) else: arg1 = args[1] instr_ir, extra_ir = mn_do_cond_branch(self, instr, arg1) elif instr.name[0:2] == 'CR': instr_ir, extra_ir = mn_do_cr(self, instr, *args) elif instr.name[0:3] == 'DCB': instr_ir, extra_ir = mn_do_nop_warn(self, instr, *args) elif instr.name[0:3] == 'DIV': instr_ir, extra_ir = mn_do_div(self, instr, *args) elif instr.name[0:4] == 'EXTS': instr_ir, extra_ir = mn_do_exts(self, instr, *args) elif instr.name[0] == 'L': instr_ir, extra_ir = mn_do_load(self, instr, *args) elif instr.name[0:3] == 'MUL': instr_ir, extra_ir = mn_do_mul(self, instr, *args) elif instr.name[0:3] == 'NEG': instr_ir, extra_ir = mn_do_neg(self, instr, *args) elif instr.name[0:2] == 'OR': instr_ir, extra_ir = mn_do_or(self, instr, *args) elif instr.name[0:2] == 'RL': instr_ir, extra_ir = mn_do_rotate(self, instr, args[0], args[1], args[2], args[3].arg.arg, args[4].arg.arg) elif instr.name == 'STMW': instr_ir, extra_ir = mn_do_stmw(self, instr, *args) elif instr.name[0:2] == 'ST': instr_ir, extra_ir = mn_do_store(self, instr, *args) elif instr.name[0:4] == 'SUBF': if instr.name[0:5] == 'SUBFZ': last_arg = ExprInt(0) elif instr.name[0:5] == 'SUBFM': last_arg = ExprInt(0xFFFFFFFF) else: last_arg = args[2] instr_ir, extra_ir = mn_do_sub(self, instr, args[0], args[1], last_arg) elif instr.name[0:3] == 'XOR': instr_ir, extra_ir = mn_do_xor(self, instr, *args) else: instr_ir, extra_ir = sem_dir[instr.name](self, instr, *args) return instr_ir, extra_ir def get_next_instr(self, instr): l = self.loc_db.get_or_create_offset_location(instr.offset + 4) return l def get_next_break_loc_key(self, instr): l = self.loc_db.get_or_create_offset_location(instr.offset + 4) return l
Ancestors (in MRO)
- ir_ppc32b
- 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): super(ir_ppc32b, self).__init__(mn_ppc, 'b', loc_db) self.pc = mn_ppc.getpc() self.sp = mn_ppc.getsp() self.IRDst = expr.ExprId('IRDst', 32) self.addrsize = 32
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 expr_fix_regs_for_mode(
self, expr, *args, **kwargs)
def expr_fix_regs_for_mode(self, expr, *args, **kwargs): return expr
def expraff_fix_regs_for_mode(
self, expr, *args, **kwargs)
def expraff_fix_regs_for_mode(self, expr, *args, **kwargs): return expr
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 instr.name[0:5] in [ 'ADDIS', 'ORIS', 'XORIS', 'ANDIS' ]: args[2] = ExprInt(args[2].arg << 16, 32) if instr.name[0:3] == 'ADD': if instr.name[0:4] == 'ADDZ': last_arg = ExprInt(0, 32) elif instr.name[0:4] == 'ADDM': last_arg = ExprInt(0xFFFFFFFF, 32) else: last_arg = args[2] instr_ir, extra_ir = mn_do_add(self, instr, args[0], args[1], last_arg) elif instr.name[0:3] == 'AND': instr_ir, extra_ir = mn_do_and(self, instr, *args) elif instr.additional_info.bo_bi_are_defined: name = instr.name if name[-1] == '+' or name[-1] == '-': name = name[0:-1] if name[-3:] == 'CTR' or name[-4:] == 'CTRL': arg1 = ExprCompose(ExprInt(0, 2), CTR[2:32]) elif name[-2:] == 'LR' or name[-3:] == 'LRL': arg1 = ExprCompose(ExprInt(0, 2), LR[2:32]) else: arg1 = args[1] instr_ir, extra_ir = mn_do_cond_branch(self, instr, arg1) elif instr.name[0:2] == 'CR': instr_ir, extra_ir = mn_do_cr(self, instr, *args) elif instr.name[0:3] == 'DCB': instr_ir, extra_ir = mn_do_nop_warn(self, instr, *args) elif instr.name[0:3] == 'DIV': instr_ir, extra_ir = mn_do_div(self, instr, *args) elif instr.name[0:4] == 'EXTS': instr_ir, extra_ir = mn_do_exts(self, instr, *args) elif instr.name[0] == 'L': instr_ir, extra_ir = mn_do_load(self, instr, *args) elif instr.name[0:3] == 'MUL': instr_ir, extra_ir = mn_do_mul(self, instr, *args) elif instr.name[0:3] == 'NEG': instr_ir, extra_ir = mn_do_neg(self, instr, *args) elif instr.name[0:2] == 'OR': instr_ir, extra_ir = mn_do_or(self, instr, *args) elif instr.name[0:2] == 'RL': instr_ir, extra_ir = mn_do_rotate(self, instr, args[0], args[1], args[2], args[3].arg.arg, args[4].arg.arg) elif instr.name == 'STMW': instr_ir, extra_ir = mn_do_stmw(self, instr, *args) elif instr.name[0:2] == 'ST': instr_ir, extra_ir = mn_do_store(self, instr, *args) elif instr.name[0:4] == 'SUBF': if instr.name[0:5] == 'SUBFZ': last_arg = ExprInt(0) elif instr.name[0:5] == 'SUBFM': last_arg = ExprInt(0xFFFFFFFF) else: last_arg = args[2] instr_ir, extra_ir = mn_do_sub(self, instr, args[0], args[1], last_arg) elif instr.name[0:3] == 'XOR': instr_ir, extra_ir = mn_do_xor(self, instr, *args) else: instr_ir, extra_ir = sem_dir[instr.name](self, instr, *args) 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_break_loc_key(
self, instr)
def get_next_break_loc_key(self, instr): l = self.loc_db.get_or_create_offset_location(instr.offset + 4) return l
def get_next_instr(
self, instr)
def get_next_instr(self, instr): l = self.loc_db.get_or_create_offset_location(instr.offset + 4) return l
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, *args, **kwargs)
def irbloc_fix_regs_for_mode(self, irblock, *args, **kwargs): return irblock
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 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])