diff --git a/miasm/arch/arm/arch.py b/miasm/arch/arm/arch.py index 497d6d689..69c673e11 100644 --- a/miasm/arch/arm/arch.py +++ b/miasm/arch/arm/arch.py @@ -1415,6 +1415,7 @@ def encode(self): sbit = bs(l=1, fname="sbit") rn_sp = bs("1101", cls=(arm_reg_wb,), fname='rnsp') +rn_sp_ = bs("1101", cls=(arm_gpreg,), fname='rnsp') rn_wb = bs(l=4, cls=(arm_reg_wb_nosp,), fname='rn') rlist = bs(l=16, cls=(arm_rlist,), fname='rlist') @@ -2350,6 +2351,7 @@ class arm_sp(arm_reg): sppc = bs(l=1, cls=(arm_sppc,)) off12 = bs(l=12, cls=(arm_off,), fname="off", order=-1) +off8_ = bs(l=8, cls=(arm_off,), fname="off", order=-1) rn_deref = bs(l=4, cls=(arm_deref_reg_imm,), fname="rt") @@ -2451,6 +2453,7 @@ class arm_sp(arm_reg): armtop("addsp", [bs('10110000'), bs_addsubsp_name, sp, off7], [sp, off7]) armtop("pushpop", [bs('1011'), bs_pushpop_name, bs('10'), pclr, trlistpclr], [trlistpclr]) armtop("btransfersp", [bs('1100'), bs_tbtransfer_name, rbl_wb, trlist]) +armtop("btransfersp", [bs('1110100010'), wback, bs_tbtransfer_name, rn_wb, pc_in, lr_in, bs('0'), trlist13pclr]) armtop("br", [bs('1101'), bs_br_name, offs8]) armtop("blx", [bs("01000111"), bs('1'), rm, bs('000')]) armtop("svc", [bs('11011111'), imm8]) @@ -3303,6 +3306,7 @@ def check_fbits(self, v): armtop("sub", [bs('11110'), imm12_1, bs('01101'), scc, rn, bs('0'), imm12_3, rd_nopc, imm12_8], [rd_nopc, rn, imm12_8]) armtop("eor", [bs('11110'), imm12_1, bs('00100'), scc, rn, bs('0'), imm12_3, rd_nopc, imm12_8], [rd_nopc, rn, imm12_8]) armtop("add", [bs('11110'), imm12_1, bs('10000'), scc, rn_nosppc, bs('0'), imm12_3, rd, imm12_8_t4], [rd, rn_nosppc, imm12_8_t4]) +armtop("add", [bs('11110'), imm12_1, bs('10000'), bs('0'), rn_sp_, bs('0'), imm12_3, rd, imm12_8], [rd, rn_sp_, imm12_8]) armtop("cmp", [bs('11110'), imm12_1, bs('01101'), bs('1'), rn, bs('0'), imm12_3, bs('1111'), imm12_8] ) armtop("cmp", [bs('11101011101'), bs('1'), rn, bs('0'), imm5_3, bs('1111'), imm5_2, imm_stype, rm_sh], [rn, rm_sh] ) @@ -3342,6 +3346,7 @@ def check_fbits(self, v): armtop("str", [bs('111110000100'), rn_noarg, rt, bs('1'), ppi, updown, wback_no_t, deref_immpuw], [rt, deref_immpuw]) armtop("strb", [bs('111110001000'), rn_deref, rt, off12], [rt, rn_deref]) armtop("strb", [bs('111110000000'), rn_noarg, rt, bs('1'), ppi, updown, wback_no_t, deref_immpuw], [rt, deref_immpuw]) +armtop("strb", [bs('111110000000'), rn_noarg, rt, bs('000000'), imm2_noarg, rm_deref_reg], [rt, rm_deref_reg]) armtop("strh", [bs('111110001010'), rn_deref, rt, off12], [rt, rn_deref]) armtop("strh", [bs('111110000010'), rn_noarg, rt, bs('1'), ppi, updown, wback_no_t, deref_immpuw], [rt, deref_immpuw]) @@ -3359,6 +3364,8 @@ def check_fbits(self, v): armtop("ldrsh",[bs('111110011011'), rn_deref, rt, off12], [rt, rn_deref]) armtop("ldrh", [bs('111110001011'), rn_deref, rt, off12], [rt, rn_deref]) armtop("ldrh", [bs('111110000011'), rn_noarg, rt, bs('1'), ppi, updown, wback_no_t, deref_immpuw], [rt, deref_immpuw]) +armtop("ldrex",[bs('111010000101'), rn_deref, rt, bs('1111'), off8_], [rt, rn_deref]) +armtop("strex", [bs('111010000100'), rn_deref, rt, rd, off8_], [rd, rt, rn_deref]) armtop("pld", [bs('111110001001'), rn_deref, bs('1111'), off12], [rn_deref]) armtop("pldw", [bs('111110001011'), rn_deref, bs('1111'), off12], [rn_deref]) @@ -3367,5 +3374,7 @@ def check_fbits(self, v): armtop("tbb", [bs('111010001101'), rn_noarg, bs('11110000000'), bs('0'), bs_deref_reg_reg], [bs_deref_reg_reg]) armtop("tbh", [bs('111010001101'), rn_noarg, bs('11110000000'), bs('1'), bs_deref_reg_reg_lsl_1], [bs_deref_reg_reg_lsl_1]) armtop("dsb", [bs('111100111011'), bs('1111'), bs('1000'), bs('1111'), bs('0100'), barrier_option]) +armtop("dmb", [bs('111100111011'), bs('1111'), bs('1000'), bs('1111'), bs('0101'), barrier_option]) +armtop("teq", [bs('111010101001'), rn_nosppc, bs('0'), imm5_3, bs('1111'), imm5_2, imm_stype, rm_sh]) armtop("adr", [bs('11110'), imm12_1, bs('100000'), bs('1111'), bs('0'), imm12_3, rd, imm12_8_t4], [rd, imm12_8_t4]) diff --git a/miasm/arch/arm/sem.py b/miasm/arch/arm/sem.py index 981a50605..a4ede41cd 100644 --- a/miasm/arch/arm/sem.py +++ b/miasm/arch/arm/sem.py @@ -827,6 +827,9 @@ def st_ld_r(ir, instr, a, a2, b, store=False, size=32, s_ext=False, z_ext=False) def ldr(ir, instr, a, b): return st_ld_r(ir, instr, a, None, b, store=False) +def ldrex(ir, instr, a, b): + return st_ld_r(ir, instr, a, None, b, store=False) + def ldrd(ir, instr, a, b, c=None): if c is None: @@ -841,6 +844,84 @@ def l_str(ir, instr, a, b): return st_ld_r(ir, instr, a, None, b, store=True) +def strex(ir, instr, a, b, c=None): + if c is None: + a2 = ir.arch.regs.all_regs_ids[ir.arch.regs.all_regs_ids.index(a) + 1] + else: + a2 = b + b = c + + s_ext=False + z_ext=False + size = 64 + store = True + + e = [] + wb = False + b = b.copy() + postinc = False + b = b.ptr + if isinstance(b, ExprOp): + if b.op == "wback": + wb = True + b = b.args[0] + if b.op == "postinc": + postinc = True + if isinstance(b, ExprOp) and b.op in ["postinc", 'preinc']: + # XXX TODO CHECK + base, off = b.args[0], b.args[1] # ExprInt(size/8, 32) + else: + base, off = b, ExprInt(0, 32) + if postinc: + ad = base + else: + ad = base + off + + # PC base lookup uses PC 4 byte alignment + ad = ad.replace_expr({PC: PC & ExprInt(0xFFFFFFFC, 32)}) + + dmem = False + if size in [8, 16]: + if store: + a = a[:size] + m = ExprMem(ad, size=size) + elif s_ext: + m = ExprMem(ad, size=size).signExtend(a.size) + elif z_ext: + m = ExprMem(ad, size=size).zeroExtend(a.size) + else: + raise ValueError('unhandled case') + elif size == 32: + m = ExprMem(ad, size=size) + elif size == 64: + assert a2 is not None + m = ExprMem(ad, size=32) + dmem = True + size = 32 + else: + raise ValueError('the size DOES matter') + dst = None + + if store: + # always 0 + e.append(ExprAssign(a, ExprInt(0, 32))) + if dmem: + e.append(ExprAssign(ExprMem(ad + ExprInt(4, 32), size=size), a2)) + else: + if a == PC: + dst = PC + e.append(ExprAssign(ir.IRDst, m)) + e.append(ExprAssign(a, m)) + if dmem: + e.append(ExprAssign(a2, ExprMem(ad + ExprInt(4, 32), size=size))) + + # XXX TODO check multiple write cause by wb + if wb or postinc: + e.append(ExprAssign(base, base + off)) + + return e, [] + + def l_strd(ir, instr, a, b, c=None): if c is None: a2 = ir.arch.regs.all_regs_ids[ir.arch.regs.all_regs_ids.index(a) + 1] @@ -1314,6 +1395,10 @@ def nop(ir, instr): e = [] return e, [] +def dmb(ir, instr, a): + # XXX TODO + e = [] + return e, [] def dsb(ir, instr, a): # XXX TODO @@ -1526,8 +1611,10 @@ def add_condition_expr(ir, instr, cond, instr_ir, extra_ir): 'ldr': ldr, 'ldrd': ldrd, 'ldrsb': ldrsb, + 'ldrex': ldrex, # XXX TODO: check 'str': l_str, 'strd': l_strd, + 'strex': strex, # XXX TODO: check 'b': b, 'bl': bl, 'svc': svc, @@ -1642,6 +1729,7 @@ def add_condition_expr(ir, instr, cond, instr_ir, extra_ir): 'smlatt': smlatt, 'uadd8': uadd8, 'sel': sel, + 'dmb': dmb, } mn_cond_x = [mnemo_condm0, diff --git a/test/arch/arm/arch.py b/test/arch/arm/arch.py index 5aa619ea4..199004a80 100644 --- a/test/arch/arm/arch.py +++ b/test/arch/arm/arch.py @@ -703,7 +703,32 @@ def u16swap(i): ("xxxxxxxx CMP R5, R0 LSR 0x8", "B5EB102F"), + ("xxxxxxxx LDMIA R0, {R2, R3, R6, R7}", + "90E8CC00"), + ("xxxxxxxx DMB SY", + "BFF35F8F"), + + ("xxxxxxxx STRB R3, [R4, R8]", + "04F80830"), + + ("xxxxxxxx STRB R2, [R3, R9]", + "03F80920"), + + ("xxxxxxxx LDREX R3, [R1]", + "51E8003F"), + + ("xxxxxxxx LDREX R2, [R12]", + "5CE8002F"), + + ("xxxxxxxx STREX LR, R1, [R3]", + "43E8001E"), + + ("xxxxxxxx STREX R0, LR, [R2]", + "42E800E0"), + + ("xxxxxxxx TEQ R0, R1", + "90EA010F"), ] print("#" * 40, 'armthumb', '#' * 40)