Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/archinfo/arch_arm.py: 74%

151 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-25 06:15 +0000

1import logging 

2 

3from .arch import Arch, register_arch, Endness, Register 

4from .tls import TLSArchInfo 

5 

6log = logging.getLogger("archinfo.arch_arm") 

7 

8try: 

9 import capstone as _capstone 

10except ImportError: 

11 _capstone = None 

12 

13try: 

14 import keystone as _keystone 

15except ImportError: 

16 _keystone = None 

17 

18try: 

19 import unicorn as _unicorn 

20except ImportError: 

21 _unicorn = None 

22 

23 

24# TODO: determine proper base register (if it exists) 

25# TODO: handle multiple return registers? 

26# TODO: which endianness should be default? 

27 

28 

29def is_arm_arch(a): 

30 return a.name.startswith("ARM") 

31 

32 

33def get_real_address_if_arm(arch, addr): 

34 """ 

35 Obtain the real address of an instruction. ARM architectures are supported. 

36 

37 :param archinfo.Arch arch: The Arch object. 

38 :param int addr: The instruction address. 

39 :return: The real address of an instruction. 

40 :rtype: int 

41 """ 

42 

43 return ((addr >> 1) << 1) if is_arm_arch(arch) else addr 

44 

45 

46class ArchARM(Arch): 

47 """ 

48 ARM architecture specific subclass 

49 """ 

50 

51 def __init__(self, endness=Endness.LE): 

52 instruction_endness = None 

53 if endness == Endness.LE: 

54 instruction_endness = Endness.LE 

55 

56 super().__init__(endness, instruction_endness=instruction_endness) 

57 if endness == Endness.BE: 

58 self.function_prologs = { 

59 # br"\xe9\x2d[\x40-\x7f\xc0-\xff][\x00-\xff]", # stmfd sp!, {xxxxx, lr} 

60 rb"\xe5\x2d\xe0\x04", # push {lr} 

61 rb"\xe1\xa0\xc0\x0c\xe5\x2d\xe0\x04", 

62 } 

63 self.thumb_prologs = { 

64 # push.w {r4, r5, r7, r8, lr} 

65 rb"\xe9\x2d\x41\xb0", 

66 # push.w {r4-r7, r8, lr} | push.w {r4-r9, lr} | push.w {r4-r7, r9, r10, lr} | push.w {r4-r10, lr} | 

67 # push.w {r4-r8, r10, r11, lr} | push.w {r4-r11, lr} 

68 rb"\xe9\x2d[\x41\x43\x46\x47\x4d\x4f]\xf0", 

69 # push.w {r3-r9, lr} | push.w {r3-r7, r9, r10, lr} | push.w {r3-r11, lr} 

70 rb"\xe9\x2d[\x43\x46\x4f]\xf8", 

71 rb"[\xb4\xb5][\x00\x10\x30\x70\xf0]\xb0[\x80-\x8f\xa3\xa8]", 

72 # push {??, ??, ..., ??, lr}; sub sp, sp, #?? 

73 rb"\xb4\x80\xb0[\x80-\xff]", # push {r7}; sub sp, sp, #?? 

74 rb"\xb4[\x00-\xff]\xb5\x00\xb0[\x80-\xff]", # push {r?, r?}; push {lr}; sub sp, sp, #?? 

75 rb"\xb0[\x80-\xff]\x90[\x00-\xff]", # sub sp, sp, #??; str r0, [sp, ?] 

76 # stmt0: push {lr} | push {r3, lr} | push {r4, lr} | push {r4, r5, lr} | push {r3, r4, r5, lr} | 

77 # push {r4, r5, r6, lr} | push {r4, r5, r6, r7, lr} | push {r3, r4, r5, r6, r7, lr} 

78 # stmt1: ldr r4, [pc, #??] 

79 # stmt2: add sp, r4 

80 rb"\xb5[\x00\x08\x10\x30\x38\x70\xf0\xf8]\x4c[\x00-\xff]\x44\xa5", 

81 # stmt0: push {lr} | push {r3, lr} | push {r4, lr} | push {r4, r5, lr} | push {r3, r4, r5, lr} | 

82 # push {r4, r5, r6, lr} | push {r4, r5, r6, r7, lr} | push {r3, r4, r5, r6, r7, lr} 

83 # stmt1: mov r3/r4/r5/r6/r7, r0 | mov r4/r5/r6/r7, r1 | mov r6/r7, r3 

84 rb"\xb5[\x00\x08\x10\x30\x38\x70\xf0\xf8]\x46[\x03-\x07\x0c-\x0f\x1e-\x1f]", 

85 # stmt0: push {r3, lr} 

86 # stmt1: movs r2/r3, #0 

87 rb"\xb5\x08[\x22\x23]\x00", 

88 # ldr r3, [pc, #??]; ldr r2, [pc, #??]; add r3, pc; push {r4,r5,lr} 

89 rb"\x4b[\x00-\xff]\x4a[\x00-\xff]\x44\x7b\xb5\x30", 

90 # push {r3,r4,r5,lr}; mov r3, #0; 

91 rb"\xb5\x38\xf2\x40\x03\x00\xf2\xc0\x03\x00", 

92 } 

93 self.function_epilogs = { 

94 rb"\xe8\xbd[\x00-\xff]{2}\xe1\x2f\xff\x1e" # pop {xxx}; bx lr 

95 rb"\xe4\x9d\xe0\x04\xe1\x2f\xff\x1e" # pop {xxx}; bx lr 

96 } 

97 

98 def __getstate__(self): 

99 self._cs = None 

100 self._cs_thumb = None 

101 self._ks = None 

102 self._ks_thumb = None 

103 return super().__getstate__() 

104 

105 @property 

106 def capstone_thumb(self): 

107 if _capstone is None: 

108 log.warning("Capstone is not installed!") 

109 return None 

110 if self._cs_thumb is None: 

111 self._cs_thumb = _capstone.Cs(self.cs_arch, self.cs_mode + _capstone.CS_MODE_THUMB) 

112 self._cs_thumb.detail = True 

113 return self._cs_thumb 

114 

115 @property 

116 def keystone_thumb(self): 

117 if _keystone is None: 

118 log.warning("Keystone is not installed!") 

119 return None 

120 if self._ks_thumb is None: 

121 self._ks_thumb = _keystone.Ks(self.ks_arch, _keystone.KS_MODE_THUMB) 

122 return self._ks_thumb 

123 

124 @property 

125 def unicorn_thumb(self): 

126 if _unicorn is None: 

127 log.warning("Unicorn is not installed!") 

128 return None 

129 return _unicorn.Uc(self.uc_arch, self.uc_mode + _unicorn.UC_MODE_THUMB) 

130 

131 def m_addr(self, addr, *args, **kwargs): 

132 """ 

133 Given the address of some code block, convert it to the address where this block 

134 is stored in memory. The memory address can also be referred to as the "real" address. 

135 

136 For ARM-architecture, the "real" address is always even (has its lowest bit clear). 

137 

138 :param addr: The address to convert. 

139 :return: The "real" address in memory. 

140 :rtype: int 

141 """ 

142 return addr & ~1 

143 

144 # pylint: disable=keyword-arg-before-vararg, arguments-differ 

145 def x_addr(self, addr, thumb=None, *args, **kwargs): 

146 """ 

147 Given the address of some code block, convert it to the value that should be assigned 

148 to the instruction pointer register in order to execute the code in that block. 

149 

150 :param addr: The address to convert. 

151 :param thumb: Set this parameter to True if you want to convert the address into the THUMB form. 

152 Set this parameter to False if you want to convert the address into the ARM form. 

153 Set this parameter to None (default) if you want to keep the address as is. 

154 :return: The "execution" address. 

155 :rtype: int 

156 """ 

157 if thumb is None: 

158 return addr 

159 elif not thumb: 

160 return addr & ~1 

161 else: # thumb 

162 return addr | 1 

163 

164 def is_thumb(self, addr): # pylint:disable=unused-argument 

165 """ 

166 Return True, if the address is the THUMB address. False otherwise. 

167 

168 :param addr: The address to check. 

169 :return: Whether the given address is the THUMB address. 

170 """ 

171 return bool(addr & 1) 

172 

173 bits = 32 

174 vex_arch = "VexArchARM" 

175 name = "ARMEL" 

176 qemu_name = "arm" 

177 ida_processor = "armb" 

178 linux_name = "arm" 

179 triplet = "arm-linux-gnueabihf" 

180 max_inst_bytes = 4 

181 ret_offset = 8 

182 fp_ret_offset = 8 

183 vex_conditional_helpers = True 

184 syscall_num_offset = 36 

185 call_pushes_ret = False 

186 stack_change = -4 

187 memory_endness = Endness.LE 

188 register_endness = Endness.LE 

189 sizeof = {"short": 16, "int": 32, "long": 32, "long long": 64} 

190 if _capstone: 

191 cs_arch = _capstone.CS_ARCH_ARM 

192 cs_mode = _capstone.CS_MODE_LITTLE_ENDIAN 

193 _cs_thumb = None 

194 if _keystone: 

195 ks_arch = _keystone.KS_ARCH_ARM 

196 ks_mode = _keystone.KS_MODE_ARM + _keystone.KS_MODE_LITTLE_ENDIAN 

197 _ks_thumb = None 

198 uc_arch = _unicorn.UC_ARCH_ARM if _unicorn else None 

199 uc_mode = _unicorn.UC_MODE_LITTLE_ENDIAN if _unicorn else None 

200 uc_mode_thumb = _unicorn.UC_MODE_LITTLE_ENDIAN + _unicorn.UC_MODE_THUMB if _unicorn else None 

201 uc_const = _unicorn.arm_const if _unicorn else None 

202 uc_prefix = "UC_ARM_" if _unicorn else None 

203 # self.ret_instruction = b"\x0E\xF0\xA0\xE1" # this is mov pc, lr 

204 ret_instruction = b"\x1E\xFF\x2F\xE1" # this is bx lr 

205 nop_instruction = b"\x00\x00\x00\x00" 

206 function_prologs = { 

207 # br"[\x00-\xff][\x40-\x7f\xc0-\xff]\x2d\xe9", # stmfd sp!, {xxxxx,lr} 

208 rb"\x04\xe0\x2d\xe5", # push {lr} 

209 rb"\r\xc0\xa0\xe1[\x00-\xff][\x40-\x7f\xc0-\xff]\x2d\xe9", # mov r12, sp; stmfd sp!, {xxxxx,lr} 

210 rb"\r\xc0\xa0\xe1\x04\xe0\x2d\xe5", # mov r12, sp; push {lr} 

211 } 

212 thumb_prologs = { 

213 # push.w {r4, r5, r7, r8, lr} 

214 rb"\x2d\xe9\xb0\x41", 

215 # push.w {r4-r7, r8, lr} | push.w {r4-r9, lr} | push.w {r4-r7, r9, r10, lr} | push.w {r4-r10, lr} | 

216 # push.w {r4-r8, r10, r11, lr} | push.w {r4-r11, lr} 

217 rb"\x2d\xe9\xf0[\x41\x43\x46\x47\x4d\x4f]", 

218 # push.w {r3-r9, lr} | push.w {r3-r7, r9, r10, lr} | push.w {r3-r11, lr} 

219 rb"\x2d\xe9\xf8[\x43\x46\x4f]", 

220 rb"[\x00\x10\x30\x70\xf0][\xb4\xb5][\x80-\x8f\xa3\xa8]\xb0", # push {??, ??, ..., ??, lr}; sub sp, sp, #?? 

221 rb"\x80\xb4[\x80-\xff]\xb0", # push {r7}; sub sp, sp, #?? 

222 rb"[\x00-\xff]\xb4\x00\xb5[\x80-\xff]\xb0", # push {r?, r?}; push {lr}; sub sp, sp, #?? 

223 rb"[\x80-\xff]\xb0[\x00-\xff]\x90", # sub sp, sp, #??; str r0, [sp, ?] 

224 # stmt0: push {lr} | push {r3, lr} | push {r4, lr} | push {r4, r5, lr} | push {r3, r4, r5, lr} | 

225 # push {r4, r5, r6, lr} | push {r4, r5, r6, r7, lr} | push {r3, r4, r5, r6, r7, lr} 

226 # stmt1: ldr r4, [pc, #??] 

227 # stmt2: add sp, r4 

228 rb"[\x00\x08\x10\x30\x38\x70\xf0\xf8]\xb5[\x00-\xff]\x4c\xa5\x44", 

229 # stmt0: push {lr} | push {r3, lr} | push {r4, lr} | push {r4, r5, lr} | push {r3, r4, r5, lr} | 

230 # push {r4, r5, r6, lr} | push {r4, r5, r6, r7, lr} | push {r3, r4, r5, r6, r7, lr} 

231 # stmt1: mov r3/r4/r5/r6/r7, r0 | mov r4/r5/r6/r7, r1 | mov r6/r7, r3 

232 rb"[\x00\x08\x10\x30\x38\x70\xf0\xf8]\xb5[\x03-\x07\x0c-\x0f\x1e-\x1f]\x46", 

233 # stmt0: push {r3, lr} 

234 # stmt1: movs r2/r3, #0 

235 rb"\x08\xb5\x00[\x22\x23]", 

236 # ldr r3, [pc, #??]; ldr r2, [pc, #??]; add r3, pc; push {r4,r5,lr} 

237 rb"[\x00-\xff]\x4b[\x00-\xff]\x4a\x7b\x44\x30\xb5", 

238 # push {r3,r4,r5,lr}; mov r3, #0; 

239 rb"\x38\xb5\x40\xf2\x00\x03\xc0\xf2\x00\x03", 

240 } 

241 function_epilogs = { 

242 rb"[\x00-\xff]{2}\xbd\xe8\x1e\xff\x2f\xe1" # pop {xxx}; bx lr 

243 rb"\x04\xe0\x9d\xe4\x1e\xff\x2f\xe1" # pop {xxx}; bx lr 

244 } 

245 instruction_alignment = 2 # cuz there is also thumb mode 

246 register_list = [ 

247 Register( 

248 name="r0", 

249 size=4, 

250 alias_names=("a1",), 

251 general_purpose=True, 

252 argument=True, 

253 linux_entry_value="ld_destructor", 

254 ), 

255 Register(name="r1", size=4, alias_names=("a2",), general_purpose=True, argument=True), 

256 Register(name="r2", size=4, alias_names=("a3",), general_purpose=True, argument=True), 

257 Register(name="r3", size=4, alias_names=("a4",), general_purpose=True, argument=True), 

258 Register(name="r4", size=4, alias_names=("v1",), general_purpose=True), 

259 Register(name="r5", size=4, alias_names=("v2",), general_purpose=True), 

260 Register(name="r6", size=4, alias_names=("v3",), general_purpose=True), 

261 Register(name="r7", size=4, alias_names=("v4",), general_purpose=True), 

262 Register(name="r8", size=4, alias_names=("v5",), general_purpose=True), 

263 Register(name="r9", size=4, alias_names=("v6", "sb"), general_purpose=True), 

264 Register(name="r10", size=4, alias_names=("v7", "sl"), general_purpose=True), 

265 Register(name="r11", size=4, alias_names=("v8", "fp", "bp"), general_purpose=True), 

266 Register(name="r12", size=4, general_purpose=True), 

267 # r12 is sometimes known as "ip" (intraprocedural call scratch) but we can't have that... 

268 Register( 

269 name="sp", 

270 size=4, 

271 alias_names=("r13",), 

272 general_purpose=True, 

273 default_value=(Arch.initial_sp, True, "global"), 

274 ), 

275 Register(name="lr", size=4, alias_names=("r14",), general_purpose=True, concretize_unique=True), 

276 Register(name="pc", size=4, vex_name="r15t", alias_names=("r15", "ip")), 

277 Register(name="cc_op", size=4, default_value=(0, False, None), artificial=True, concrete=False), 

278 Register(name="cc_dep1", size=4, default_value=(0, False, None), artificial=True, concrete=False), 

279 Register(name="cc_dep2", size=4, default_value=(0, False, None), artificial=True, concrete=False), 

280 Register(name="cc_ndep", size=4, default_value=(0, False, None), artificial=True, concrete=False), 

281 Register(name="qflag32", size=4, default_value=(0, False, None), artificial=True, concrete=False), 

282 Register(name="geflag0", size=4, vector=True, default_value=(0, False, None), artificial=True, concrete=False), 

283 Register(name="geflag1", size=4, vector=True, default_value=(0, False, None), artificial=True, concrete=False), 

284 Register(name="geflag2", size=4, vector=True, default_value=(0, False, None), artificial=True, concrete=False), 

285 Register(name="geflag3", size=4, vector=True, default_value=(0, False, None), artificial=True, concrete=False), 

286 Register(name="emnote", size=4, vector=True, default_value=(0, False, None), artificial=True, concrete=False), 

287 Register(name="cmstart", size=4, artificial=True, vector=True, default_value=(0, False, None), concrete=False), 

288 Register(name="cmlen", size=4, artificial=True, default_value=(0, False, None), concrete=False), 

289 Register(name="nraddr", size=4, artificial=True, default_value=(0, False, None), concrete=False), 

290 Register(name="ip_at_syscall", size=4, artificial=True, concrete=False), 

291 Register(name="d0", size=8, floating_point=True, vector=True, subregisters=[("s0", 0, 4), ("s1", 4, 4)]), 

292 Register(name="d1", size=8, floating_point=True, vector=True, subregisters=[("s2", 0, 4), ("s3", 4, 4)]), 

293 Register(name="d2", size=8, floating_point=True, vector=True, subregisters=[("s4", 0, 4), ("s5", 4, 4)]), 

294 Register(name="d3", size=8, floating_point=True, vector=True, subregisters=[("s6", 0, 4), ("s7", 4, 4)]), 

295 Register(name="d4", size=8, floating_point=True, vector=True, subregisters=[("s8", 0, 4), ("s9", 4, 4)]), 

296 Register(name="d5", size=8, floating_point=True, vector=True, subregisters=[("s10", 0, 4), ("s11", 4, 4)]), 

297 Register(name="d6", size=8, floating_point=True, vector=True, subregisters=[("s12", 0, 4), ("s13", 4, 4)]), 

298 Register(name="d7", size=8, floating_point=True, vector=True, subregisters=[("s14", 0, 4), ("s15", 4, 4)]), 

299 Register(name="d8", size=8, floating_point=True, vector=True, subregisters=[("s16", 0, 4), ("s17", 4, 4)]), 

300 Register(name="d9", size=8, floating_point=True, vector=True, subregisters=[("s18", 0, 4), ("s19", 4, 4)]), 

301 Register(name="d10", size=8, floating_point=True, vector=True, subregisters=[("s20", 0, 4), ("s21", 4, 4)]), 

302 Register(name="d11", size=8, floating_point=True, vector=True, subregisters=[("s22", 0, 4), ("s23", 4, 4)]), 

303 Register(name="d12", size=8, floating_point=True, vector=True, subregisters=[("s24", 0, 4), ("s25", 4, 4)]), 

304 Register(name="d13", size=8, floating_point=True, vector=True, subregisters=[("s26", 0, 4), ("s27", 4, 4)]), 

305 Register(name="d14", size=8, floating_point=True, vector=True, subregisters=[("s28", 0, 4), ("s29", 4, 4)]), 

306 Register(name="d15", size=8, floating_point=True, vector=True, subregisters=[("s30", 0, 4), ("s31", 4, 4)]), 

307 Register(name="d16", size=8, floating_point=True, vector=True), 

308 Register(name="d17", size=8, floating_point=True, vector=True), 

309 Register(name="d18", size=8, floating_point=True, vector=True), 

310 Register(name="d19", size=8, floating_point=True, vector=True), 

311 Register(name="d20", size=8, floating_point=True, vector=True), 

312 Register(name="d21", size=8, floating_point=True, vector=True), 

313 Register(name="d22", size=8, floating_point=True, vector=True), 

314 Register(name="d23", size=8, floating_point=True, vector=True), 

315 Register(name="d24", size=8, floating_point=True, vector=True), 

316 Register(name="d25", size=8, floating_point=True, vector=True), 

317 Register(name="d26", size=8, floating_point=True, vector=True), 

318 Register(name="d27", size=8, floating_point=True, vector=True), 

319 Register(name="d28", size=8, floating_point=True, vector=True), 

320 Register(name="d29", size=8, floating_point=True, vector=True), 

321 Register(name="d30", size=8, floating_point=True, vector=True), 

322 Register(name="d31", size=8, floating_point=True, vector=True), 

323 Register(name="fpscr", size=4, floating_point=True, artificial=True, concrete=False), 

324 Register(name="tpidruro", size=4, artificial=True, concrete=False), 

325 Register(name="itstate", size=4, artificial=True, default_value=(0, False, None), concrete=False), 

326 ] 

327 

328 got_section_name = ".got" 

329 ld_linux_name = "ld-linux.so.3" 

330 elf_tls = TLSArchInfo(1, 8, [], [0], [], 0, 0) 

331 # elf_tls = TLSArchInfo(1, 32, [], [0], [], 0, 0) 

332 # that line was lying in the original CLE code and I have no clue why it's different 

333 

334 

335class ArchARMHF(ArchARM): 

336 """ 

337 This is an architecture description for the ARM hard-float (armhf). 

338 It supports at least an ARM 32-bit processor with ARMv7 architecture, Thumb-2 and VFP3D16. 

339 """ 

340 

341 name = "ARMHF" 

342 triplet = "arm-linux-gnueabihf" 

343 ld_linux_name = "ld-linux-armhf.so.3" 

344 fp_ret_offset = 128 # s0 

345 

346 

347class ArchARMEL(ArchARM): 

348 """ 

349 This is an architecture description for ARM EABI (armel). 

350 It targets a range of older 32-bit ARM devices without hardware FPUs. 

351 """ 

352 

353 name = "ARMEL" 

354 triplet = "arm-linux-gnueabi" 

355 ld_linux_name = "ld-linux.so.3" 

356 elf_tls = TLSArchInfo(1, 8, [], [0], [], 0, 0) 

357 

358 

359class ArchARMCortexM(ArchARMEL): 

360 """ 

361 This is an architecture description for ARM Cortex-M microcontroller-class CPUs. 

362 

363 These CPUs have the following unusual / annoying distinctions from their relatives: 

364 - Explicitly only support the Thumb-2 instruction set. Executing with the T-bit off causes the processor to fault 

365 instantly 

366 - Always little-endian 

367 - Coprocessors? Nope, none of that rubbish 

368 - Well-known standard memory map across all devices 

369 - Rarely use an MPU, even though this does exist on some devices 

370 - A built-in "NVIC" (Nested Vectored Interrupt Controller) as part of the standard. 

371 - Standardized "blob format" including the IVT, with initial SP and entry prepended 

372 - Usually don't run an OS (SimLinux? No thanks) 

373 - As part of the above, handle syscalls (SVC) instructions through an interrupt (now called PendSV) 

374 Uses its own fancy stack layout for this, which (UGH) varies by sub-sub-architecture 

375 - Some fancy instructions normally never seen in other uses of Thumb (CPSID, CPSIE, WFI, MRS.W, MSR.W) 

376 - New registers, namely: 

377 * FAULTMASK 

378 * PRIMASK 

379 * BASEPRI 

380 * CONTROL 

381 * SP, banked as PSP or MSP 

382 * PSR, now just one PSR, with a few meta-registers APSR, IPSR, and EPSR which take a chunk of that each 

383 

384 """ 

385 

386 name = "ARMCortexM" 

387 triplet = "arm-none-eabi" # ARM's own CM compilers use this triplet 

388 

389 # These are the standard THUMB prologs. We leave these off for other ARMs due to their length 

390 # For CM, we assume the FPs are OK, as they are almost guaranteed to appear all over the place 

391 function_prologs = {} 

392 

393 thumb_prologs = {rb"[\x00-\xff]\xb5", rb"\x2d\xe9[\x00-\xff][\x00-\xff]"} # push {xxx,lr} # push.w {xxx, lr} 

394 function_epilogs = { 

395 rb"[\x00-\xff]\xbd" # pop {xxx, pc} 

396 # TODO: POP.W 

397 } 

398 

399 register_list = [ 

400 Register( 

401 name="r0", 

402 size=4, 

403 alias_names=("a1",), 

404 general_purpose=True, 

405 argument=True, 

406 linux_entry_value="ld_destructor", 

407 ), 

408 Register(name="r1", size=4, alias_names=("a2",), general_purpose=True, argument=True), 

409 Register(name="r2", size=4, alias_names=("a3",), general_purpose=True, argument=True), 

410 Register(name="r3", size=4, alias_names=("a4",), general_purpose=True, argument=True), 

411 Register(name="r4", size=4, alias_names=("v1",), general_purpose=True), 

412 Register(name="r5", size=4, alias_names=("v2",), general_purpose=True), 

413 Register(name="r6", size=4, alias_names=("v3",), general_purpose=True), 

414 Register(name="r7", size=4, alias_names=("v4",), general_purpose=True), 

415 Register(name="r8", size=4, alias_names=("v5",), general_purpose=True), 

416 Register(name="r9", size=4, alias_names=("v6", "sb"), general_purpose=True), 

417 Register(name="r10", size=4, alias_names=("v7", "sl"), general_purpose=True), 

418 Register(name="r11", size=4, alias_names=("v8", "fp", "bp"), general_purpose=True), 

419 # r11 is used as frame pointer 

420 Register(name="r12", size=4, general_purpose=True), 

421 # r12 is sometimes known as "ip" (intraprocedural call scratch) but we can't have that... 

422 Register( 

423 name="sp", 

424 size=4, 

425 alias_names=("r13",), 

426 general_purpose=True, 

427 default_value=(Arch.initial_sp, True, "global"), 

428 ), 

429 Register(name="lr", size=4, alias_names=("r14",), general_purpose=True, concretize_unique=True), 

430 Register(name="pc", size=4, vex_name="r15t", alias_names=("r15", "ip")), 

431 # Control registers for Cortex-M33 with ArmV8 securtiy extension enabled (Trustzone) 

432 Register(name="msp", size=4, general_purpose=True), 

433 Register(name="msp_s", size=4, general_purpose=True), 

434 Register(name="msp_ns", size=4, general_purpose=True), 

435 Register(name="psp", size=4, general_purpose=True), 

436 Register(name="psp_s", size=4, general_purpose=True), 

437 Register(name="psp_ns", size=4, general_purpose=True), 

438 Register(name="msplim", size=4, general_purpose=True), 

439 Register(name="msplim_s", size=4, general_purpose=True), 

440 Register(name="msplim_ns", size=4, general_purpose=True), 

441 Register(name="msplim_ns", size=4, general_purpose=True), 

442 # additional stack pointers for secure/non_secure world 

443 Register(name="sp_process", size=4, general_purpose=True), 

444 Register(name="sp_process_s", size=4, general_purpose=True), 

445 Register(name="sp_process_ns", size=4, general_purpose=True), 

446 Register(name="sp_main", size=4, general_purpose=True), 

447 Register(name="sp_main_s", size=4, general_purpose=True), 

448 Register(name="sp_main_ns", size=4, general_purpose=True), 

449 Register(name="cc_op", size=4, default_value=(0, False, None), artificial=True, concrete=False), 

450 Register(name="cc_dep1", size=4, default_value=(0, False, None), artificial=True, concrete=False), 

451 Register(name="cc_dep2", size=4, default_value=(0, False, None), artificial=True, concrete=False), 

452 Register(name="cc_ndep", size=4, default_value=(0, False, None), artificial=True, concrete=False), 

453 Register(name="qflag32", size=4, default_value=(0, False, None), artificial=True, concrete=False), 

454 Register(name="ip_at_syscall", size=4, artificial=True, concrete=False), 

455 # Cortex-M Has a different FPU from all other ARMs. 

456 Register(name="d0", size=8, subregisters=[("s0", 0, 4), ("s1", 4, 4)], floating_point=True), 

457 Register(name="d1", size=8, subregisters=[("s2", 0, 4), ("s3", 4, 4)], floating_point=True), 

458 Register(name="d2", size=8, subregisters=[("s4", 0, 4), ("s5", 4, 4)], floating_point=True), 

459 Register(name="d3", size=8, subregisters=[("s6", 0, 4), ("s7", 4, 4)], floating_point=True), 

460 Register(name="d4", size=8, subregisters=[("s8", 0, 4), ("s9", 4, 4)], floating_point=True), 

461 Register(name="d5", size=8, subregisters=[("s10", 0, 4), ("s11", 4, 4)], floating_point=True), 

462 Register(name="d6", size=8, subregisters=[("s12", 0, 4), ("s13", 4, 4)], floating_point=True), 

463 Register(name="d7", size=8, subregisters=[("s14", 0, 4), ("s15", 4, 4)], floating_point=True), 

464 Register(name="d8", size=8, subregisters=[("s16", 0, 4), ("s17", 4, 4)], floating_point=True), 

465 Register(name="d9", size=8, subregisters=[("s18", 0, 4), ("s19", 4, 4)], floating_point=True), 

466 Register(name="d10", size=8, subregisters=[("s20", 0, 4), ("s21", 4, 4)], floating_point=True), 

467 Register(name="d11", size=8, subregisters=[("s22", 0, 4), ("s23", 4, 4)], floating_point=True), 

468 Register(name="d12", size=8, subregisters=[("s24", 0, 4), ("s25", 4, 4)], floating_point=True), 

469 Register(name="d13", size=8, subregisters=[("s26", 0, 4), ("s27", 4, 4)], floating_point=True), 

470 Register(name="d14", size=8, subregisters=[("s28", 0, 4), ("s29", 4, 4)], floating_point=True), 

471 Register(name="d15", size=8, subregisters=[("s30", 0, 4), ("s31", 4, 4)], floating_point=True), 

472 # xPSR register. Includes APSR, IPSR and EPSR. 

473 Register(name="cpsr", size=4, default_value=(0, False, None)), 

474 # TODO: NOTE: This is technically part of the EPSR, not its own register 

475 Register(name="fpscr", size=4, floating_point=True), 

476 # TODO: NOTE: This is also part of EPSR 

477 Register(name="itstate", size=4, artificial=True, default_value=(0, False, None), concrete=False), 

478 # Whether exceptions are masked or not. (e.g., everything but NMI) 

479 Register(name="faultmask", size=4, default_value=(0, False, None)), 

480 Register(name="faultmask_s", size=4, default_value=(0, False, None)), 

481 Register(name="faultmask_ns", size=4, default_value=(0, False, None)), 

482 # The one-byte priority, above which interrupts will not be handled if PRIMASK is 1. 

483 # Yes, you can implement an RTOS scheduler in hardware with this and the NVIC, you monster! 

484 Register(name="basepri", size=4, default_value=(0, False, None)), 

485 Register(name="basepri_s", size=4, default_value=(0, False, None)), 

486 Register(name="basepri_ns", size=4, default_value=(0, False, None)), 

487 # Only the bottom bit of PRIMASK is relevant, even though the docs say its 32bit. 

488 # Configures whether interrupt priorities are respected or not. 

489 Register(name="primask", size=4, default_value=(0, False, None)), 

490 Register(name="primask_s", size=4, default_value=(0, False, None)), 

491 Register(name="primask_ns", size=4, default_value=(0, False, None)), 

492 # NOTE: We specifically declare IEPSR here. Not PSR, .... variants.for 

493 # VEX already handles the content of APSR, and half of EPSR (as ITSTATE) above. 

494 # We only keep here the data not computed via CCalls 

495 # The default is to have the T bit on. 

496 Register(name="iepsr", size=4, default_value=(0x01000000, False, None)), 

497 # CONTROL: 

498 # Bit 2: Whether the FPU is active or not 

499 # Bit 1: Whether we use MSP (0) or PSP (1) 

500 # Bit 0: Thread mode privilege level. 0 for privileged, 1 for unprivileged. 

501 Register(name="control", size=4, default_value=(0, False, None)), 

502 ] 

503 

504 # Special handling of CM mode in *stone 

505 if _capstone: 

506 cs_arch = _capstone.CS_ARCH_ARM 

507 cs_mode = _capstone.CS_MODE_LITTLE_ENDIAN + _capstone.CS_MODE_THUMB + _capstone.CS_MODE_MCLASS 

508 _cs_thumb = None 

509 if _keystone: 

510 ks_arch = _keystone.KS_ARCH_ARM 

511 ks_mode = _keystone.KS_MODE_THUMB + _keystone.KS_MODE_LITTLE_ENDIAN 

512 _ks_thumb = None 

513 uc_arch = _unicorn.UC_ARCH_ARM if _unicorn else None 

514 uc_mode = _unicorn.UC_MODE_THUMB + _unicorn.UC_MODE_LITTLE_ENDIAN if _unicorn else None 

515 uc_mode_thumb = _unicorn.UC_MODE_THUMB + _unicorn.UC_MODE_LITTLE_ENDIAN if _unicorn else None 

516 

517 dwarf_registers = [ 

518 "r0", 

519 "r1", 

520 "r2", 

521 "r3", 

522 "r4", 

523 "r5", 

524 "r6", 

525 "r7", 

526 "r8", 

527 "r9", 

528 "r10", 

529 "r11", 

530 "r12", 

531 "sp", 

532 "lr", 

533 "pc", 

534 ] 

535 

536 @property 

537 def capstone_thumb(self): 

538 return self.capstone 

539 

540 @property 

541 def keystone_thumb(self): 

542 return self.keystone 

543 

544 def __init__(self, *args, **kwargs): 

545 super().__init__(*args, **kwargs) 

546 

547 # TODO: Make arm_spotter use these 

548 # TODO: Make SimOS use these. 

549 # TODO: Add.... the NVIC? to SimOS 

550 

551 

552register_arch([r".*cortexm|.*cortex\-m.*|.*v7\-m.*"], 32, "any", ArchARMCortexM) 

553register_arch([r".*armhf.*"], 32, "any", ArchARMHF) 

554register_arch([r".*armeb|.*armbe"], 32, Endness.BE, ArchARM) 

555register_arch([r".*armel|arm.*"], 32, Endness.LE, ArchARMEL) 

556register_arch([r".*arm.*|.*thumb.*"], 32, "any", ArchARM)