diff options
| -rw-r--r-- | miasm/arch/arm_arch.py | 373 |
1 files changed, 236 insertions, 137 deletions
diff --git a/miasm/arch/arm_arch.py b/miasm/arch/arm_arch.py index d575d16f..258ad933 100644 --- a/miasm/arch/arm_arch.py +++ b/miasm/arch/arm_arch.py @@ -59,13 +59,13 @@ def str2imm(i): except: return False return a - + def imm2str(i): if type(i) in [int, long]: if i<0: - return "-0x%.x"%-i + return "-0x%x"%-i else: - return "0x%.x"%i + return "0x%x"%i return str(i) def is_imm(i): @@ -73,7 +73,7 @@ def is_imm(i): i = i[0] if type(i) is list: return False - + return type(str2imm(i)) is not bool @@ -93,7 +93,7 @@ def split_args(args): if x != t_v: o.append(x) continue - + if x != t_v: o.append(x) if x in t_enclosed: @@ -104,11 +104,11 @@ def split_args(args): if lvl and lvl != [',']: raise ValueError('unbalanced expr') return o - - + + o = [] t = [x for x in shlex.shlex(args)] - + new_t = [] i = 0 while i < len(t): @@ -127,10 +127,10 @@ def split_args(args): a = get_until_t(t, [',']) o.append(a) return o - - - - + + + + class bm(object): class __metaclass__(type): def __new__(cls, name, bases, odct): @@ -143,11 +143,11 @@ class bm(object): if name.startswith('bm_'): pname = name[3:] dct["p_property"] = [pname]+dct["p_property"] - - + + b = bases[0] - + dct["check"] = b.check_no l = dct["l"] fbits = dct["fbits"] @@ -175,9 +175,9 @@ class bm(object): dct["check"] = b.check_fbits_inv else: dct["check"] = b.check_fbits - + p_property = dct["p_property"] - + for p in p_property: dct["get_"+p] = lambda self, p=p:getattr(self, p) dct["set_"+p] = lambda self, p=p:setattr(self, p) @@ -198,15 +198,15 @@ class bm(object): def get_val(self, v): return (v>>self.off) & ((1<<self.l)-1) def set_val(self, v = None): - + if v == None and len(self.p_property) >= 1: p = self.p_property[0] v = getattr(self, p) - return (v&((1<<self.l)-1))<<self.off + return (v&((1<<self.l)-1))<<self.off def bin(self): return self.set_val() - + def parse(self, v): if len(self.p_property) >= 1: p = self.p_property[0] @@ -248,8 +248,8 @@ class bm_cond(bm): def str2cond(self, cond): if not cond in self.n: raise ValueError('unknown cond') - self.cond = self.n.index(cond) - + self.cond = self.n.index(cond) + class bm_int0(bm): fbits = '0' @@ -410,7 +410,7 @@ class bm_reglist(bm): for r in self.reglist: v|=(1<<r) return self.set_val(v) - + class bm_rn(bm): l = 4 @@ -471,7 +471,7 @@ class bm_op2(bm): self.shift>>=1 self.shiftt = self.shift&0x3 self.shift>>=2 - + if self.sub_shift_type: #sub shift type is reg if self.shift&1: @@ -482,7 +482,7 @@ class bm_op2(bm): else: #sub shift type is imm self.amount = self.shift - + return True def bin(self): @@ -497,7 +497,7 @@ class bm_op2(bm): else: shift|=self.amount<<3 val = (shift<<4) | (self.rm&0xf) - + self.op2 = val return self.set_val() @@ -508,20 +508,20 @@ class bm_opoff(bm): def parse(self, v): val = self.get_val(v) self.opoff = val - + if self.parent.immop: self.shift = val>>4 self.rm = val&0xf if self.shift&1: #no reg shift return False - + self.shift>>=1 self.shiftt = self.shift&0x3 self.amount = self.shift>>2 else: self.imm = val&0xfff - + return True def bin(self): @@ -532,7 +532,7 @@ class bm_opoff(bm): val = (shift<<4) | (self.rm&0xf) else: val = self.imm&0xfff - + self.opoff = val return self.set_val() @@ -563,7 +563,16 @@ class bm_int000100101111111111110001(bm): class bm_int0001001011111111111100(bm): fbits = '0001001011111111111100' - + +class bm_int00010010(bm): + fbits = '00010010' + +class bm_bkptimm1(bm): + l = 12 + +class bm_bkptimm2(bm): + l = 4 + class bmi_int1XXXX1(bm): fbits = '1XXXXXXXXXXXXXXXXXXXX1' checkinv = True @@ -596,10 +605,12 @@ class arm_mnemo_metaclass(type): else: raise ValueError('zarb arg') return i - + def class_from_op(cls, op): #print "dis", hex(op), hex2bin(op) - tab_mn = [arm_data, arm_mul, arm_mull, arm_swp, arm_brxchg, arm_hdtreg, arm_hdtimm, arm_sdt, arm_bdt, arm_br, arm_codt, arm_cort, arm_codo, arm_swi, arm_szext]#, arm_undef] + tab_mn = [arm_data, arm_mul, arm_mull, arm_swp, arm_brreg, arm_hdtreg, + arm_hdtimm, arm_sdt, arm_bdt, arm_brimm, arm_codt, arm_cort, + arm_codo, arm_swi, arm_bkpt, arm_szext]#, arm_undef] ret = filter(lambda x:x.check(op), tab_mn) if len(ret)==1: return ret[0] @@ -615,14 +626,17 @@ class arm_mnemo_metaclass(type): op = bin.readbs(4) op = struct.unpack('<L', op)[0] return cls(op, bin.offset-4) - + def asm_instr(cls, txt): - tab_mn = [arm_data, arm_mul, arm_mull, arm_swp, arm_brxchg, arm_hdtreg, arm_hdtimm, arm_sdt, arm_bdt, arm_br, arm_codt, arm_cort, arm_codo, arm_swi, arm_szext]#, arm_undef] + tab_mn = [arm_data, arm_mul, arm_mull, arm_swp, arm_brreg, arm_hdtreg, + arm_hdtimm, arm_sdt, arm_bdt, arm_brimm, arm_codt, arm_cort, + arm_codo, arm_swi, arm_bkpt, arm_szext]#, arm_undef] t = [x for x in shlex.shlex(txt)] t.reverse() name = t.pop() - ret = filter(lambda x:x.check_mnemo(name), tab_mn) + first_arg = len(t) > 0 and t.pop() + ret = filter(lambda x:x.check_mnemo(name, first_arg), tab_mn) if len(ret)!=1: raise ValueError('parse name err %s'%str(ret)) cls = ret[0] @@ -633,7 +647,7 @@ class arm_mnemo_metaclass(type): def asm(cls, txt, symbol_reloc_off = {}): i = cls.asm_instr(txt) return [struct.pack('<L', i.bin())] - + def __new__(cls, name, bases, dct): ret_c = type.__new__(cls, name, bases, dct) if name is "arm_mn": @@ -644,7 +658,7 @@ class arm_mnemo_metaclass(type): for off in dct['mask']: mc = dct['mask'][off](None, off+1) mask.append(mc) - + mask_orig = [bm_cond]+dct["mask_list"] ret_c.mask_orig = mask_orig off = 32 @@ -659,15 +673,15 @@ class arm_mnemo_metaclass(type): ''' p = property(lambda self, pname=pname:getattr(getattr(self, "bm_"+pname), pname), lambda self, val=None,pname=pname:setattr(getattr(self, "bm_"+pname), pname, val)) - + setattr(ret_c, pname, p) - + if off!=0: raise ValueError('invalid mnemonic %d'%off) ret_c.mask_chk = mask - + return ret_c - + def check(self, op): for m in self.mask_chk: if m.off<20 and m.fbits==None: @@ -681,7 +695,7 @@ class arm_mnemo_metaclass(type): return False return True - def check_mnemo(self, mnemo): + def check_mnemo(self, mnemo, first_arg = None): found = False for n in self.namestr: if mnemo.startswith(n): @@ -689,14 +703,14 @@ class arm_mnemo_metaclass(type): break if not found: return False - + rest = mnemo[len(n):] for c in bm_cond.n: if rest.startswith(c): rest = rest[len(c):] break return self.check_opts(rest) - + def pre_parse_mnemo(self, args): mn = [x for x in shlex.shlex(args)][0] t = split_args(args[args.index(mn)+len(mn):]) @@ -708,7 +722,7 @@ class arm_mnemo_metaclass(type): t = cls.pre_parse_mnemo(args) mn = t.pop() t.reverse() - + return [], mn, t @@ -759,7 +773,7 @@ class arm_mnemo_metaclass(type): if n[k] != 1: return None return k - + regs_str = ['R%d'%r for r in xrange(0x10)] regs_str[13] = 'SP' regs_str[14] = 'LR' @@ -779,14 +793,14 @@ def cop2str(r): return cop_str[r] def str2cop(r): if type(r) is list and len(r) == 1: - r = r[0] + r = r[0] return cop_str.index(r) def copr2str(r): return copr_str[r] def str2copr(r): if type(r) is list and len(r) == 1: - r = r[0] + r = r[0] return copr_str.index(r) def reglist2str(rlist): @@ -828,7 +842,7 @@ def str2reglist(rlist): out.append(r_start) r_start = str2reg(tmp) return out - + def args2reduce(args): out = [] for a in args: @@ -853,13 +867,13 @@ def arglist2str(args): def args2str(args): return arglist2str(args2reduce(args)) - - + + class arm_mn(object): mask_list = [] __metaclass__ = arm_mnemo_metaclass def __init__(self, op, offset = 0, dis = True): - + off=32 mask = [] self.offset = offset @@ -876,7 +890,7 @@ class arm_mn(object): setattr(self, "bm_"+pname, mc) mask.append(mc) self.mask = mask - + if dis: for m in self.mask: ret = m.parse(op) @@ -885,7 +899,7 @@ class arm_mn(object): else: for m in self.mask: ret = m.setprop() - + full_mnemo = arm_mn.pre_parse_mnemo(op) mnemo = full_mnemo.pop() name, cond, rest = self.parse_name_cond(mnemo) @@ -900,13 +914,13 @@ class arm_mn(object): pass def str2name(self, n): pass - + def getname(self): name = self.name2str() cond = self.cond2str() scc = "" - if cond =="AL":cond = "" #XXX smart display - + if cond in ("AL","NV"):cond = "" #XXX smart display + return name+cond+scc def bin(self): @@ -930,7 +944,7 @@ class arm_mn(object): if rest.startswith(c): cond = i break - + if cond == None: cond = COND_AL #default cond is AL else: @@ -969,7 +983,8 @@ class arm_data(arm_mn): mask_list = [bm_int00, bm_immop, bm_opc, bm_scc, bm_rn, bm_rd, bm_op2] mask = {25:bmi_int1XX1, 26:bmi_int11110XX1} - namestr = ['AND', 'EOR', 'SUB', 'RSB', 'ADD', 'ADC', 'SBC', 'RSC', 'TST', 'TEQ', 'CMP', 'CMN', 'ORR', 'MOV', 'BIC', 'MVN'] + namestr = ['AND', 'EOR', 'SUB', 'RSB', 'ADD', 'ADC', 'SBC', 'RSC', + 'TST', 'TEQ', 'CMP', 'CMN', 'ORR', 'MOV', 'BIC', 'MVN'] allshifts = ['LSL', 'LSR', 'ASR', 'ROR'] def name2str(self): @@ -992,7 +1007,7 @@ class arm_data(arm_mn): else: args.append(reg2str(self.rd)) args.append(reg2str(self.rn)) - + if self.immop: #arg is pure imm imm = myror(self.imm, self.rot*2) @@ -1006,7 +1021,7 @@ class arm_data(arm_mn): a = [a, self.allshifts[self.shiftt], imm2str(self.amount)] args.append(a) return args - + def __str__(self): name = self.getname() name+=self.scc2str() @@ -1073,12 +1088,16 @@ class arm_data(arm_mn): self.shiftt = self.allshifts.index(args.pop()) if args: raise ValueError('zarb arg2', args) - - + def is_subcall(self): + return False + + + class arm_mul(arm_mn): - mask_list = [bm_int000000, bm_accum, bm_scc, bm_rd, bm_rn, bm_rs, bm_int1001, bm_rm] + mask_list = [bm_int000000, bm_accum, bm_scc, bm_rd, bm_rn, bm_rs, + bm_int1001, bm_rm] #cannot have pc in reg namestr = ['MUL', 'MLA'] def name2str(self): @@ -1100,7 +1119,7 @@ class arm_mul(arm_mn): if self.accum: args.append(reg2str(self.rn)) return args - + def __str__(self): name = self.getname() name+=self.scc2str() @@ -1123,10 +1142,14 @@ class arm_mul(arm_mn): self.rn = str2reg(args.pop()) else: self.rn = 0 #default reg value - + + def is_subcall(self): + return False + class arm_mull(arm_mn): - mask_list = [bm_int00001, bm_sign, bm_accum, bm_scc, bm_rdh, bm_rdl, bm_rs, bm_int1001, bm_rm] + mask_list = [bm_int00001, bm_sign, bm_accum, bm_scc, bm_rdh, bm_rdl, + bm_rs, bm_int1001, bm_rm] #cannot habe pc as reg namestr = ['UMULL', 'UMLAL', 'SMULL', 'SMLAL'] def name2str(self): @@ -1149,7 +1172,7 @@ class arm_mull(arm_mn): args.append(reg2str(self.rm)) args.append(reg2str(self.rs)) return args - + def __str__(self): name = self.getname() name+= self.scc2str() @@ -1169,16 +1192,20 @@ class arm_mull(arm_mn): self.rdl = str2reg(args.pop()) self.rm = str2reg(args.pop()) self.rs = str2reg(args.pop()) - + + def is_subcall(self): + return False + class arm_swp(arm_mn): - mask_list = [bm_int00010, bm_size, bm_int00, bm_rn, bm_rd, bm_int0000, bm_int1001, bm_rm] + mask_list = [bm_int00010, bm_size, bm_int00, bm_rn, bm_rd, + bm_int0000, bm_int1001, bm_rm] mask = {19:bmi_int1111, 15:bmi_int1111, 3:bmi_int1111} #cannot have PC as reg namestr = ["SWP"] def name2str(self): return self.namestr[0] - + @classmethod def check_opts(cls, rest): if not rest or rest == 'B': @@ -1191,7 +1218,7 @@ class arm_swp(arm_mn): args.append(reg2str(self.rm)) args.append(['[', reg2str(self.rn), ']']) return args - + def __str__(self): name = self.getname() name+=self.size2str() @@ -1216,10 +1243,10 @@ class arm_swp(arm_mn): return raise ValueError('cannot parse %s %s'%(str(p1), str(p2))) -class arm_brxchg(arm_mn): +class arm_brreg(arm_mn): mask_list = [bm_int0001001011111111111100, bm_lnk, bm_int1, bm_rn] - namestr = ["BX", "BXL"] + namestr = ["BX", "BLX"] def name2str(self): return self.namestr[self.lnk] def str2name(self, n): @@ -1227,12 +1254,12 @@ class arm_brxchg(arm_mn): def parse_name_cond(self, mnemo): name, cond = None, None - if not mnemo.startswith('BX'): + if not any(mnemo.startswith(name) for name in self.namestr): raise ValueError('zarb mnemo %s'%str(mnemo)) l = len(mnemo) if l in [2,4]: n = mnemo[:2] - elif l in [3,4]: + elif l in [3,5]: n = mnemo[:3] else: raise ValueError('zarb mnemo %s'%str(mnemo)) @@ -1249,11 +1276,8 @@ class arm_brxchg(arm_mn): return name, cond, rest @classmethod - def check_mnemo(self, mnemo): - if mnemo in self.namestr: - return True - return False - + def check_mnemo(self, mnemo, first_arg): + return any(mnemo.startswith(name) for name in self.namestr) and first_arg in regs_str def args2str(self): args = [] @@ -1265,14 +1289,14 @@ class arm_brxchg(arm_mn): args = self.args2str() args = args2str(args) return name+' '+args - + def parse_args(self, args): self.rn = str2reg(args.pop()) def breakflow(self): return True def splitflow(self): - return self.cond != COND_AL + return self.cond != COND_AL or self.lnk def dstflow(self): return True def getdstflow(self): @@ -1283,10 +1307,11 @@ class arm_brxchg(arm_mn): return self.lnk class arm_hdtreg(arm_mn): - mask_list = [bm_int000, bm_ppndx, bm_updown, bm_int0, bm_wback, bm_ldst, bm_rn, bm_rd, bm_int00001, bm_sh, bm_int1, bm_rm] + mask_list = [bm_int000, bm_ppndx, bm_updown, bm_int0, bm_wback, + bm_ldst, bm_rn, bm_rd, bm_int00001, bm_sh, bm_int1, bm_rm] #and XXX str cant be SB nor SH mask = {24:bmi_intX00X} - + typestr = ["XXX", "H", "SB", "SH"] namestr = ['STR', 'LDR'] def name2str(self): @@ -1319,13 +1344,13 @@ class arm_hdtreg(arm_mn): o.append(reg2str(self.rm)) if self.ppndx: o.append(']') - + args.append(o) return args - + def __str__(self): name = self.getname() - #XXX XXX swp?? + #XXX XXX swp?? name += self.typestr[self.sh] args = self.args2str() args = args2str(args) @@ -1344,10 +1369,13 @@ class arm_hdtreg(arm_mn): return self.cond != COND_AL def dstflow(self): return True - + def is_subcall(self): + return False class arm_hdtimm(arm_mn): - mask_list = [bm_int000, bm_ppndx, bm_updown, bm_int1, bm_wback, bm_ldst, bm_rn, bm_rd, bm_hdoff1, bm_int1, bm_sh, bm_int1, bm_hdoff2] + mask_list = [bm_int000, bm_ppndx, bm_updown, bm_int1, bm_wback, + bm_ldst, bm_rn, bm_rd, bm_hdoff1, bm_int1, bm_sh, + bm_int1, bm_hdoff2] #and XXX str cant be SB nor SH mask = {24:bmi_intX00X} @@ -1360,7 +1388,7 @@ class arm_hdtimm(arm_mn): @classmethod def check_opts(cls, rest): - found = False + found = False for t in cls.typestr: if rest.startswith(t): found = True @@ -1382,14 +1410,14 @@ class arm_hdtimm(arm_mn): o.append(imm2str(imm)) if self.ppndx: o.append(']') - + args.append(o) return args - + def __str__(self): name = self.getname() - #XXX XXX swp?? + #XXX XXX swp?? name += self.typestr[self.sh] args = self.args2str() args = args2str(args) @@ -1410,13 +1438,16 @@ class arm_hdtimm(arm_mn): return self.cond != COND_AL def dstflow(self): return True + def is_subcall(self): + return False class arm_sdt(arm_mn): - mask_list = [bm_int01, bm_immop, bm_ppndx, bm_updown, bm_size, bm_wback, bm_ldst, bm_rn, bm_rd, bm_opoff] + mask_list = [bm_int01, bm_immop, bm_ppndx, bm_updown, bm_size, + bm_wback, bm_ldst, bm_rn, bm_rd, bm_opoff] #cannot shift amount with immop mask = {25:bmi_int1XXXX1} - + namestr = ['STR', 'LDR'] def name2str(self): return self.namestr[self.ldst] @@ -1459,8 +1490,8 @@ class arm_sdt(arm_mn): o.append(']') args.append(o) return args - - + + def __str__(self): name = self.getname() name+=self.size2str() @@ -1559,21 +1590,22 @@ class arm_undef(arm_mn): args.append(imm2str(self.undef1)) args.append(imm2str(self.undef2)) return args - + def __str__(self): name = self.getname() args = self.args2str() args = args2str(args) - + return name+' '+args - + def parse_args(self, args): self.undef1 = str2imm(args.pop()) self.undef2 = str2imm(args.pop()) class arm_bdt(arm_mn): - mask_list = [bm_int100, bm_ppndx, bm_updown, bm_psr, bm_wback, bm_ldst, bm_rn, bm_reglist] - + mask_list = [bm_int100, bm_ppndx, bm_updown, bm_psr, bm_wback, + bm_ldst, bm_rn, bm_reglist] + ad_mode_nostack = ['DA', 'DB', 'IA', 'IB'] ad_mode_stack = ['FA', 'EA', 'FD', 'ED'] @@ -1641,8 +1673,8 @@ class arm_bdt(arm_mn): self.wback = 1 else: raise ValueError('zarb arg 4', (args, a, w)) - - + + self.rn = str2reg(a.pop()) if self.stackattr != (self.rn==13): raise ValueError('unmatch stack/nostack') @@ -1682,25 +1714,29 @@ class arm_bdt(arm_mn): def is_subcall(self): return False -class arm_br(arm_mn): +class arm_brimm(arm_mn): mask_list = [bm_int101, bm_lnk, bm_offs] - namestr = ["B", "BL"] + namestr = ["B", "BL", "BLX"] def name2str(self): - return self.namestr[self.lnk] + return self.cond == COND_NV and 'BLX' or self.namestr[self.lnk] def str2name(self, n): - self.lnk = self.namestr.index(n) + if n == 'BLX': + self.cond = COND_NV + self.lnk = 0 + else: + self.lnk = self.namestr.index(n) @classmethod - def check_mnemo(self, mnemo): - if not mnemo.startswith('B'): + def check_mnemo(self, mnemo, first_arg = None): + if first_arg in regs_str or not mnemo.startswith('B'): return False - l = len(mnemo) + l = len(mnemo) if l==1 and mnemo in ['B']: return True elif l in [2,4] and mnemo.startswith('BL'): return True - elif l == 3 and mnemo[1:] in bm_cond.n: + elif l == 3 and (mnemo == 'BLX' or mnemo[1:] in bm_cond.n): return True return False @@ -1709,7 +1745,9 @@ class arm_br(arm_mn): if not mnemo.startswith('B'): raise ValueError('zarb mnemo %s'%str(mnemo)) l = len(mnemo) - if l in [1,3]: + if mnemo == 'BLX': + return mnemo, COND_NV, "" + elif l in [1,3]: n = mnemo[:1] elif l in [2,4]: n = mnemo[:2] @@ -1729,11 +1767,14 @@ class arm_br(arm_mn): def args2str(self): if type(self.offs) in [int, long]: - args = [imm2str(self.offs)] + offset = self.offs + if self.cond == COND_NV: # BLX + offset |= (self.lnk << 1) + args = [imm2str(offset)] else: args = [self.offs] return args - + def __str__(self): name = self.getname() args = self.args2str() @@ -1744,6 +1785,9 @@ class arm_br(arm_mn): ad = args.pop() if is_imm(ad): self.offs = str2imm(ad) + if self.cond == COND_NV: # BLX + self.lnk = (self.offs & 2) >> 1 + self.offs &= ~2 else: self.offs = {x86_afs.symb:{ad[0]:1}} def breakflow(self): @@ -1756,6 +1800,8 @@ class arm_br(arm_mn): def getdstflow(self): if type(self.offs) in [int, long]: dst = (self.offset+8+self.offs)&0xFFFFFFFF + if self.cond == COND_NV: # BLX + dst |= self.lnk << 1 else: dst = self.arg[0] return [dst] @@ -1769,9 +1815,11 @@ class arm_br(arm_mn): #patch only known symbols if l.offset !=None: self.offs = l + if self.cond == COND_NV: # BLX + self.lnk = (self.offs & 2) >> 1 + self.offs &= ~2 def is_subcall(self): - return self.lnk - + return self.cond == COND_NV or self.lnk # BLX or link def fixdst(self, lbls, my_offset, is_mem): l = self.offs[x86_afs.symb].keys()[0] offset = lbls[l] @@ -1781,9 +1829,13 @@ class arm_br(arm_mn): arg = {x86_afs.imm:offset-(my_offset)} self.arg = [arg] self.offs = lbls[l]-my_offset-4 + if self.cond == COND_NV: # BLX + self.lnk = (self.offs & 2) >> 1 + self.offs &= ~2 class arm_codt(arm_mn): - mask_list = [bm_int110, bm_ppndx, bm_updown, bm_tlen, bm_wback, bm_ldst, bm_rn, bm_crd, bm_cpnum, bm_cooff] + mask_list = [bm_int110, bm_ppndx, bm_updown, bm_tlen, bm_wback, + bm_ldst, bm_rn, bm_crd, bm_cpnum, bm_cooff] namestr = ['STC', 'LDC'] def name2str(self): @@ -1811,7 +1863,7 @@ class arm_codt(arm_mn): o.append(']') args.append(o) return args - + def __str__(self): name = self.getname() if self.tlen: @@ -1859,7 +1911,7 @@ class arm_codt(arm_mn): tmp = param.pop() self.cooff = str2imm(tmp) - + if args: tmp = args.pop() if tmp!= '!': @@ -1867,11 +1919,12 @@ class arm_codt(arm_mn): self.wback = 1 if args: raise ValueError('rest args...'%str(param)) - + class arm_codo(arm_mn): - mask_list = [bm_int1110, bm_cpopc, bm_crn, bm_crd, bm_cpnum, bm_info, bm_int0, bm_crm] + mask_list = [bm_int1110, bm_cpopc, bm_crn, bm_crd, bm_cpnum, + bm_info, bm_int0, bm_crm] namestr = ["CDP"] def name2str(self): @@ -1886,7 +1939,7 @@ class arm_codo(arm_mn): args.append(copr2str(self.crm)) args.append(imm2str(self.info)) return args - + def __str__(self): name = self.getname() args = self.args2str() @@ -1900,12 +1953,13 @@ class arm_codo(arm_mn): self.crn = str2copr(args.pop()) self.crm = str2copr(args.pop()) self.info = str2imm(args.pop()) - - + + class arm_cort(arm_mn): - mask_list = [bm_int1110, bm_opmode, bm_ldst, bm_crn, bm_rd, bm_cpnum, bm_info, bm_int1, bm_crm] + mask_list = [bm_int1110, bm_opmode, bm_ldst, bm_crn, bm_rd, bm_cpnum, + bm_info, bm_int1, bm_crm] namestr = ['MCR', 'MRC'] def name2str(self): @@ -1922,7 +1976,7 @@ class arm_cort(arm_mn): args.append(copr2str(self.crm)) args.append(imm2str(self.info)) return args - + def __str__(self): name = self.getname() args = self.args2str() @@ -1967,9 +2021,54 @@ class arm_swi(arm_mn): def is_subcall(self): return False +class arm_bkpt(arm_mn): + mask_list = [bm_int00010010, bm_bkptimm1, bm_int0111, bm_bkptimm2] + namestr = ['BKPT'] + + def name2str(self): + return self.namestr[0] + + def args2str(self): + args = [imm2str(self.bkptimm1 << 4 + self.bkptimm2)] + return args + + def __str__(self): + name = self.getname() + args = self.args2str() + args = args2str(args) + if args == "0": + return name + else: + return name+' '+args + + def parse_args(self, args): + if len(args) > 0: + imm = str2imm(args.pop()) + else: + imm = 0 + self.bkptimm1 = imm & 0xf + self.bkptimm2 = imm >> 4 + + def parse_name_cond(self, mnemo): + if mnemo != self.namestr[0]: + raise ValueError('zarb mnemo %s'%str(mnemo)) + return mnemo, COND_AL, "" + + def breakflow(self): + return True + + def splitflow(self): + return True + + def dstflow(self): + return False + + def is_subcall(self): + return False class arm_szext(arm_mn): - mask_list = [bm_int01101, bm_opsz, bm_szext, bm_rn, bm_rd, bm_rot, bm_int00, bm_int0111, bm_rm] + mask_list = [bm_int01101, bm_opsz, bm_szext, bm_rn, bm_rd, bm_rot, + bm_int00, bm_int0111, bm_rm] #szext may not be 01 namestr = ['SXT', 'UXT'] szextname = ['B16', None, 'B', 'H'] @@ -1979,7 +2078,7 @@ class arm_szext(arm_mn): self.opsz = self.namestr.index(n) @classmethod - def check_mnemo(self, mnemo): + def check_mnemo(self, mnemo, first_arg = None): if len(mnemo)<3: return False if not mnemo[:3] in self.namestr: @@ -2024,7 +2123,7 @@ class arm_szext(arm_mn): if not szextname: raise ValueError('zarb mnemo2 %s'%str(mnemo)) rest = rest[len(n):] - + for i, c in enumerate(bm_cond.n): if rest.startswith(c): cond = i @@ -2049,7 +2148,7 @@ class arm_szext(arm_mn): args.append(reg2str(self.rn)) args.append(reg2str(self.rm)) return args - + def __str__(self): name = self.getname() args = self.args2str() @@ -2058,16 +2157,16 @@ class arm_szext(arm_mn): def parse_args(self, args): - + self.rd = str2reg(args.pop()) if self.rn!=15: self.rn = str2reg(args.pop()) self.rm = str2reg(args.pop()) self.rot = 0 - - + + if __name__ == "__main__": - + import struct |