Package envi :: Package archs :: Package arm :: Module thumbdisasm
[hide private]
[frames] | no frames]

Source Code for Module envi.archs.arm.thumbdisasm

  1  
 
  2  import envi.bits as e_bits 
  3  import envi.bintree as e_btree 
  4  
 
  5  from envi.bits import binary 
  6  
 
  7  from envi.archs.arm.armdisasm import * 
  8  
 
  9  thumb_32 = [
 
 10          binary('11101'),
 
 11          binary('11110'),
 
 12          binary('11111'),
 
 13  ] 
 14  
 
 15  
 
 16  O_REG = 0 
 17  O_IMM = 1 
 18  
 
 19  OperType = (
 
 20      ArmRegOper,
 
 21      ArmImmOper,
 
 22      ) 
23 -def shmaskval(value, shval, mask): #FIXME: unnecessary to make this another fn call. will be called a bajillion times.
24 return (value >> shval) & mask 25
26 -class simpleops:
27 - def __init__(self, *operdef):
28 self.operdef = operdef
29
30 - def __call__(self, va, value):
31 ret = [] 32 for otype, shval, mask in self.operdef: 33 oval = shmaskval(value, shval, mask) 34 oper = OperType[otype]((value >> shval) & mask) 35 ret.append( oper ) 36 return ret
37 38 imm5_rm_rd = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7), (O_IMM, 6, 0x1f)) 39 rm_rn_rd = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7), (O_REG, 6, 0x7)) 40 imm3_rn_rd = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7), (O_IMM, 6, 0x7)) 41 imm8_rd = simpleops((O_REG, 8, 0x7), (O_IMM, 0, 0xff)) 42 rm_rd = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7)) 43 rn_rdm = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7)) 44 rm_rdn = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7)) 45 rm_rd_imm0 = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7), (O_IMM, 0, 0)) 46 rm4_shift3 = simpleops((O_REG, 3, 0xf)) 47 rm_rn_rt = simpleops((O_REG, 0, 0x7), (O_REG, 3, 0x7), (O_REG, 6, 0x7)) 48 imm8 = simpleops((O_IMM, 8, 0xff)) 49 imm11 = simpleops((O_IMM, 11, 0x7ff)) 50 51 sh4_imm1 = simpleops((O_IMM, 3, 0x1)) 52
53 -def d1_rm4_rd3(va, value):
54 # 0 1 0 0 0 1 0 0 DN(1) Rm(4) Rdn(3) 55 rdbit = shmaskval(value, 4, 0x8) 56 rd = shmaskval(value, 0, 0x7) + rdbit 57 rm = shmaskval(value, 3, 0xf) 58 return ArmRegOper(rd),ArmRegOper(rm)
59
60 -def rm_rn_rt(va, value):
61 rt = shmaskval(value, 0, 0x7) # target 62 rn = shmaskval(value, 3, 0x7) # base 63 rm = shmaskval(value, 6, 0x7) # offset 64 oper0 = ArmRegOper(rt) 65 oper1 = ArmRegOffsetOper(rn, rm, va) 66 return oper0,oper1
67
68 -def imm5_rn_rt(va, value):
69 imm = shmaskval(value, 6, 0x1f) 70 rn = shmaskval(value, 3, 0x7) 71 rt = shmaskval(value, 0, 0x7) 72 oper0 = ArmRegOper(rt) 73 oper1 = ArmImmOffsetOper(rn, imm, va) 74 return oper0,oper1
75
76 -def rd_sp_imm8(va, value):
77 rd = shmaskval(value, 8, 0x7) 78 imm = shmaskval(value, 0, 0xff) * 4 79 oper0 = ArmRegOper(rd) 80 # pre-compute PC relative addr 81 oper1 = ArmImmOffsetOper(REG_SP, imm, va) 82 return oper0,oper1
83
84 -def rd_pc_imm8(va, value):
85 rd = shmaskval(value, 8, 0x7) 86 imm = shmaskval(value, 0, 0xff) * 4 87 oper0 = ArmRegOper(rd) 88 # pre-compute PC relative addr 89 oper1 = ArmImmOper(va+imm) 90 return oper0,oper1
91
92 -def rt_pc_imm8(va, value):
93 rt = shmaskval(value, 8, 0x7) 94 imm = shmaskval(value, 0, 0xff) * 4 95 oper0 = ArmRegOper(rt) 96 oper1 = ArmImmOffsetOper(rt, imm, va) # FIXME offset from PC 97 return oper0,oper1
98
99 -def ldmia(va, value):
100 rd = shmaskval(value, 8, 0x7) 101 reg_list = value & 0xff 102 oper0 = ArmRegOper(rd) 103 oper1 = ArmRegListOper(reg_list) 104 flags = 1<<11 # W flag indicating that write back should occur (marked by "!") 105 return oper0,oper1 106
107 -def sp_sp_imm7(va, value):
108 imm = shmaskval(value, 0, 0x7f) 109 o0 = ArmRegOper(REG_SP) 110 o1 = ArmRegOper(REG_SP) 111 o2 = ArmImmOper(imm*4) 112 return o0,o1,o2
113
114 -def rm_reglist(va, value):
115 rm = shmaskval(value, 8, 0x7) 116 reglist = value & 0xff 117 oper0 = ArmRegOper(rm) 118 oper1 = ArmRegListOper(reglist) 119 return oper0,oper1
120 121 122 # opinfo is: 123 # ( <mnem>, <operdef>, <flags> ) 124 # operdef is: 125 # ( (otype, oshift, omask), ...) 126 thumb_table = [ 127 ('00000', ( 0,'lsl', imm5_rm_rd, 0)), # LSL<c> <Rd>,<Rm>,#<imm5> 128 ('00001', ( 1,'lsr', imm5_rm_rd, 0)), # LSR<c> <Rd>,<Rm>,#<imm> 129 ('00010', ( 2,'asr', imm5_rm_rd, 0)), # ASR<c> <Rd>,<Rm>,#<imm> 130 ('0001100', ( 3,'add', rm_rn_rd, 0)), # ADD<c> <Rd>,<Rn>,<Rm> 131 ('0001101', ( 4,'sub', rm_rn_rd, 0)), # SUB<c> <Rd>,<Rn>,<Rm> 132 ('0001110', ( 5,'add', imm3_rn_rd, 0)), # ADD<c> <Rd>,<Rn>,#<imm3> 133 ('0001111', ( 6,'sub', imm3_rn_rd, 0)), # SUB<c> <Rd>,<Rn>,#<imm3> 134 ('00100', ( 7,'mov', imm8_rd, 0)), # MOV<c> <Rd>,#<imm8> 135 ('00101', ( 8,'cmp', imm8_rd, 0)), # CMP<c> <Rn>,#<imm8> 136 ('00110', ( 9,'add', imm8_rd, 0)), # ADD<c> <Rdn>,#<imm8> 137 ('00111', (10,'sub', imm8_rd, 0)), # SUB<c> <Rdn>,#<imm8> 138 # Data processing instructions 139 ('0100000000', (11,'and', rm_rdn, 0)), # AND<c> <Rdn>,<Rm> 140 ('0100000001', (12,'eor', rm_rdn, 0)), # EOR<c> <Rdn>,<Rm> 141 ('0100000010', (13,'lsl', rm_rdn, 0)), # LSL<c> <Rdn>,<Rm> 142 ('0100000011', (14,'lsr', rm_rdn, 0)), # LSR<c> <Rdn>,<Rm> 143 ('0100000100', (15,'asr', rm_rdn, 0)), # ASR<c> <Rdn>,<Rm> 144 ('0100000101', (16,'adc', rm_rdn, 0)), # ADC<c> <Rdn>,<Rm> 145 ('0100000110', (17,'sbc', rm_rdn, 0)), # SBC<c> <Rdn>,<Rm> 146 ('0100000111', (18,'ror', rm_rdn, 0)), # ROR<c> <Rdn>,<Rm> 147 ('0100001000', (19,'tst', rm_rd, 0)), # TST<c> <Rn>,<Rm> 148 ('0100001001', (20,'rsb', rm_rd_imm0, 0)), # RSB<c> <Rd>,<Rn>,#0 149 ('0100001010', (21,'cmp', rm_rd, 0)), # CMP<c> <Rn>,<Rm> 150 ('0100001011', (22,'cmn', rm_rd, 0)), # CMN<c> <Rn>,<Rm> 151 ('0100001100', (23,'orr', rm_rdn, 0)), # ORR<c> <Rdn>,<Rm> 152 ('0100001101', (24,'mul', rn_rdm, 0)), # MUL<c> <Rdm>,<Rn>,<Rdm> 153 ('0100001110', (25,'bic', rm_rdn, 0)), # BIC<c> <Rdn>,<Rm> 154 ('0100001111', (26,'mvn', rm_rd, 0)), # MVN<c> <Rd>,<Rm> 155 # Special data in2tructions and branch and exchange 156 ('0100010000', (27,'add', d1_rm4_rd3, 0)), # ADD<c> <Rdn>,<Rm> 157 ('0100010001', (28,'add', d1_rm4_rd3, 0)), # ADD<c> <Rdn>,<Rm> 158 ('010001001', (29,'add', d1_rm4_rd3, 0)), # ADD<c> <Rdn>,<Rm> 159 ('0100010101', (30,'cmp', d1_rm4_rd3, 0)), # CMP<c> <Rn>,<Rm> 160 ('010001011', (31,'cmp', d1_rm4_rd3, 0)), # CMP<c> <Rn>,<Rm> 161 ('0100011000', (32,'mov', d1_rm4_rd3, 0)), # MOV<c> <Rd>,<Rm> 162 ('0100011001', (33,'mov', d1_rm4_rd3, 0)), # MOV<c> <Rd>,<Rm> 163 ('0100011010', (34,'mov', d1_rm4_rd3, 0)), # MOV<c> <Rd>,<Rm> 164 ('010001110', (35,'bx', rm4_shift3, 0)), # BX<c> <Rm> 165 ('010001111', (36,'blx', rm4_shift3, 0)), # BLX<c> <Rm> 166 # Load from Litera7 Pool 167 ('01001', (37,'ldr', rt_pc_imm8, 0)), # LDR<c> <Rt>,<label> 168 # Load/Stor single data item 169 ('0101000', (38,'str', rm_rn_rt, 0)), # STR<c> <Rt>,[<Rn>,<Rm>] 170 ('0101001', (39,'strh', rm_rn_rt, 0)), # STRH<c> <Rt>,[<Rn>,<Rm>] 171 ('0101010', (40,'strb', rm_rn_rt, 0)), # STRB<c> <Rt>,[<Rn>,<Rm>] 172 ('0101011', (41,'ldrsb', rm_rn_rt, 0)), # LDRSB<c> <Rt>,[<Rn>,<Rm>] 173 ('0101100', (42,'ldr', rm_rn_rt, 0)), # LDR<c> <Rt>,[<Rn>,<Rm>] 174 ('0101101', (43,'ldrh', rm_rn_rt, 0)), # LDRH<c> <Rt>,[<Rn>,<Rm>] 175 ('0101110', (44,'ldrb', rm_rn_rt, 0)), # LDRB<c> <Rt>,[<Rn>,<Rm>] 176 ('0101111', (45,'ldrsh', rm_rn_rt, 0)), # LDRSH<c> <Rt>,[<Rn>,<Rm>] 177 ('01100', (46,'str', imm5_rn_rt, 0)), # STR<c> <Rt>, [<Rn>{,#<imm5>}] 178 ('01101', (47,'ldr', imm5_rn_rt, 0)), # LDR<c> <Rt>, [<Rn>{,#<imm5>}] 179 ('01110', (48,'strb', imm5_rn_rt, 0)), # STRB<c> <Rt>,[<Rn>,#<imm5>] 180 ('01111', (49,'ldrb', imm5_rn_rt, 0)), # LDRB<c> <Rt>,[<Rn>{,#<imm5>}] 181 ('10000', (50,'strh', imm5_rn_rt, 0)), # STRH<c> <Rt>,[<Rn>{,#<imm>}] 182 ('10001', (51,'ldrh', imm5_rn_rt, 0)), # LDRH<c> <Rt>,[<Rn>{,#<imm>}] 183 ('10010', (52,'str', imm5_rn_rt, 0)), # STR<c> <Rt>, [<Rn>{,#<imm>}] 184 ('10011', (53,'ldr', imm5_rn_rt, 0)), # LDR<c> <Rt>, [<Rn>{,#<imm>}] 185 # Generate PC rel54ive address 186 ('10100', (54,'add', rd_pc_imm8, 0)), # ADD<c> <Rd>,<label> 187 # Generate SP rel5tive address 188 ('10101', (55,'add', rd_sp_imm8, 0)), # ADD<c> <Rd>,SP,#<imm> 189 # Miscellaneous in6tructions 190 ('10110110010', (56,'setend', sh4_imm1, 0)), # SETEND <endian_specifier> 191 ('10110110011', (57,'cps', simpleops(),0)), # CPS<effect> <iflags> FIXME 192 ('1011101000', (58,'rev', rn_rdm, 0)), # REV Rd, Rn 193 ('1011101001', (59,'rev16', rn_rdm, 0)), # REV16 Rd, Rn 194 ('1011101011', (60,'revsh', rn_rdm, 0)), # REVSH Rd, Rn 195 ('101100000', (61,'add', sp_sp_imm7, 0)), # ADD<c> SP,SP,#<imm> 196 ('101100001', (62,'sub', sp_sp_imm7, 0)), # SUB<c> SP,SP,#<imm> 197 ('10111110', (63,'bkpt', imm8, 0)), # BKPT <blahblah> 198 # Load / Store Mu64iple 199 ('11000', (64,'stmia', rm_reglist, 0x800)), # LDMIA Rd!, reg_list 200 ('11001', (65,'ldmia', rm_reglist, 0x800)), # STMIA Rd!, reg_list 201 # Conditional Bran6hes 202 ('11010000', (66,'b', imm8, 0)), 203 ('11010001', (67,'bn', imm8, 0)), 204 ('11010010', (68,'bz', imm8, 0)), 205 ('11010011', (69,'bnz', imm8, 0)), 206 ('11010100', (70,'bc', imm8, 0)), 207 ('11010101', (71,'bnc', imm8, 0)), 208 ('11010100', (72,'bzc', imm8, 0)), 209 ('11010111', (73,'bnzc', imm8, 0)), 210 ('11011000', (74,'bv', imm8, 0)), 211 ('11011001', (75,'bnv', imm8, 0)), 212 ('11011010', (76,'bzv', imm8, 0)), 213 ('11011011', (77,'bnzv', imm8, 0)), 214 ('11011100', (78,'bcv', imm8, 0)), 215 ('11011101', (79,'bncv', imm8, 0)), 216 ('11011110', (80,'bzcv', imm8, 0)), 217 ('11011111', (81,'bnzcv', imm8, 0)), 218 # Software Interru2t 219 ('11011111', (82,'swi', imm8, 0)), # SWI <blahblah> 220 ('11100', (83,'b', imm11, 0)), # B <addr11> 221 ('11101', (84,'blx', imm11, 0)), # BLX suffix <addr11> -- SEE p542 of 14218.pdf manual for how this if gonna fuck with emulation. 222 ('11110', (85,'bl', imm11, 0)), # BL/BLX prefix <addr11> -- SEE p542 of 14218.pdf manual for how this if gonna fuck with emulation. 223 ('11111', (86,'blx', imm11, 0)), # BL suffix <addr11> -- SEE p542 of 14218.pdf manual for how this if gonna fuck with emulation. 224 ] 225 226 ttree = e_btree.BinaryTree() 227 for binstr, opinfo in thumb_table: 228 ttree.addBinstr(binstr, opinfo) 229 230 thumb32mask = binary('11111') 231 thumb32min = binary('11100') 232
233 -def is_thumb32(val):
234 ''' 235 Take a 16 bit integer (opcode) value and determine 236 if it is really the first 16 bits of a 32 bit 237 instruction. 238 ''' 239 bval = val >> 11 240 return (bval & thumb32mask) > thumb32min
241 242
243 -class ThumbOpcode(ArmOpcode):
244 pass
245
246 -class ArmThumbDisasm:
247
248 - def disasm(self, bytes, offset, va, trackMode=True):
249 val, = struct.unpack("H", bytes[offset:offset+2]) 250 opcode, mnem, opermkr, flags = ttree.getInt(val, 16) 251 olist = opermkr(va, val) 252 op = ThumbOpcode(va, opcode, mnem, 0xe, 2, olist, flags) 253 return op
254