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

125 statements  

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

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

2from .tls import TLSArchInfo 

3from .archerror import ArchError 

4 

5try: 

6 import capstone as _capstone 

7except ImportError: 

8 _capstone = None 

9 

10try: 

11 import keystone as _keystone 

12except ImportError: 

13 _keystone = None 

14 

15try: 

16 import unicorn as _unicorn 

17except ImportError: 

18 _unicorn = None 

19 

20try: 

21 import pyvex as _pyvex 

22except ImportError: 

23 _pyvex = None 

24 

25 

26_NATIVE_FUNCTION_PROLOGS = [ 

27 rb"\x55\x48\x89\xe5", # push rbp; mov rbp, rsp 

28 rb"\x48[\x83,\x81]\xec[\x00-\xff]", # sub rsp, xxx 

29] 

30# every function prolog can potentially be prefixed with endbr64 

31_endbr64 = b"\xf3\x0f\x1e\xfa" 

32_prefixed = [(_endbr64 + prolog) for prolog in _NATIVE_FUNCTION_PROLOGS] 

33_FUNCTION_PROLOGS = _prefixed + _NATIVE_FUNCTION_PROLOGS 

34 

35 

36class ArchAMD64(Arch): 

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

38 if endness != Endness.LE: 

39 raise ArchError("Arch AMD64 must be little endian") 

40 super().__init__(endness) 

41 self.argument_register_positions = ( 

42 { 

43 self.registers["rdi"][0]: 0, 

44 self.registers["rsi"][0]: 1, 

45 self.registers["rdx"][0]: 2, 

46 self.registers["rcx"][0]: 3, # Used for user calls 

47 self.registers["r10"][0]: 3, # Used for Linux kernel calls 

48 self.registers["r8"][0]: 4, 

49 self.registers["r9"][0]: 5, 

50 # fp registers 

51 self.registers["xmm0"][0]: 0, 

52 self.registers["xmm1"][0]: 1, 

53 self.registers["xmm2"][0]: 2, 

54 self.registers["xmm3"][0]: 3, 

55 self.registers["xmm4"][0]: 4, 

56 self.registers["xmm5"][0]: 5, 

57 self.registers["xmm6"][0]: 6, 

58 self.registers["xmm7"][0]: 7, 

59 } 

60 if _pyvex is not None 

61 else None 

62 ) 

63 

64 # Register blacklist 

65 reg_blacklist = ("fs", "gs") 

66 if self.reg_blacklist is not None and self.reg_blacklist_offsets is not None: 

67 for register in self.register_list: 

68 if register.name in reg_blacklist: 

69 self.reg_blacklist.append(register.name) 

70 self.reg_blacklist_offsets.append(register.vex_offset) 

71 

72 if _unicorn and _pyvex: 

73 # CPU flag registers 

74 uc_flags_reg = _unicorn.x86_const.UC_X86_REG_EFLAGS 

75 cpu_flag_registers = {"d": 1 << 10, "ac": 1 << 18, "id": 1 << 21} 

76 for reg, reg_bitmask in cpu_flag_registers.items(): 

77 reg_offset = self.get_register_offset(reg) 

78 self.cpu_flag_register_offsets_and_bitmasks_map[reg_offset] = (uc_flags_reg, reg_bitmask) 

79 

80 mxcsr_registers = {"sseround": 1 << 14 | 1 << 13} 

81 uc_mxcsr_reg = _unicorn.x86_const.UC_X86_REG_MXCSR 

82 for reg, reg_bitmask in mxcsr_registers.items(): 

83 reg_offset = self.get_register_offset(reg) 

84 self.cpu_flag_register_offsets_and_bitmasks_map[reg_offset] = (uc_mxcsr_reg, reg_bitmask) 

85 

86 @property 

87 def capstone_x86_syntax(self): 

88 """ 

89 The current syntax Capstone uses for x64. It can be 'intel' or 'at&t' 

90 """ 

91 return self._cs_x86_syntax 

92 

93 @capstone_x86_syntax.setter 

94 def capstone_x86_syntax(self, new_syntax): 

95 if new_syntax not in ("intel", "at&t"): 

96 raise ArchError('Unsupported Capstone x86 syntax. It must be either "intel" or "at&t".') 

97 

98 if new_syntax != self._cs_x86_syntax: 

99 self._cs = None 

100 self._cs_x86_syntax = new_syntax 

101 

102 def _configure_capstone(self): 

103 if self._cs_x86_syntax == "at&t": 

104 self._cs.syntax = _capstone.CS_OPT_SYNTAX_ATT 

105 else: 

106 self._cs.syntax = _capstone.CS_OPT_SYNTAX_INTEL 

107 

108 @property 

109 def keystone_x86_syntax(self): 

110 """ 

111 The current syntax Keystone uses for x86. It can be 'intel', 

112 'at&t', 'nasm', 'masm', 'gas' or 'radix16' 

113 """ 

114 return self._ks_x86_syntax 

115 

116 @keystone_x86_syntax.setter 

117 def keystone_x86_syntax(self, new_syntax): 

118 if new_syntax not in ("intel", "at&t", "nasm", "masm", "gas", "radix16"): 

119 raise ArchError( 

120 "Unsupported Keystone x86 syntax. It must be one of the following: " 

121 '"intel", "at&t", "nasm", "masm", "gas" or "radix16".' 

122 ) 

123 

124 if new_syntax != self._ks_x86_syntax: 

125 self._ks = None 

126 self._ks_x86_syntax = new_syntax 

127 

128 def _configure_keystone(self): 

129 if self._ks_x86_syntax == "at&t": 

130 self._ks.syntax = _keystone.KS_OPT_SYNTAX_ATT 

131 elif self._ks_x86_syntax == "nasm": 

132 self._ks.syntax = _keystone.KS_OPT_SYNTAX_NASM 

133 elif self._ks_x86_syntax == "masm": 

134 self._ks.syntax = _keystone.KS_OPT_SYNTAX_MASM 

135 elif self._ks_x86_syntax == "gas": 

136 self._ks.syntax = _keystone.KS_OPT_SYNTAX_GAS 

137 elif self._ks_x86_syntax == "radix16": 

138 self._ks.syntax = _keystone.KS_OPT_SYNTAX_RADIX16 

139 else: 

140 self._ks.syntax = _keystone.KS_OPT_SYNTAX_INTEL 

141 

142 bits = 64 

143 vex_arch = "VexArchAMD64" 

144 vex_endness = "VexEndnessLE" 

145 name = "AMD64" 

146 qemu_name = "x86_64" 

147 ida_processor = "metapc" 

148 linux_name = "x86_64" 

149 triplet = "x86_64-linux-gnu" 

150 max_inst_bytes = 15 

151 ret_offset = 16 

152 vex_conditional_helpers = True 

153 syscall_num_offset = 16 

154 call_pushes_ret = True 

155 stack_change = -8 

156 initial_sp = 0x7FFFFFFFFFF0000 

157 call_sp_fix = -8 

158 memory_endness = Endness.LE 

159 register_endness = Endness.LE 

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

161 if _capstone: 

162 cs_arch = _capstone.CS_ARCH_X86 

163 cs_mode = _capstone.CS_MODE_64 + _capstone.CS_MODE_LITTLE_ENDIAN 

164 _cs_x86_syntax = None # Set it to 'att' in order to use AT&T syntax for x86 

165 if _keystone: 

166 ks_arch = _keystone.KS_ARCH_X86 

167 ks_mode = _keystone.KS_MODE_64 + _keystone.KS_MODE_LITTLE_ENDIAN 

168 _ks_x86_syntax = None 

169 uc_arch = _unicorn.UC_ARCH_X86 if _unicorn else None 

170 uc_mode = (_unicorn.UC_MODE_64 + _unicorn.UC_MODE_LITTLE_ENDIAN) if _unicorn else None 

171 uc_const = _unicorn.x86_const if _unicorn else None 

172 uc_prefix = "UC_X86_" if _unicorn else None 

173 function_prologs = _FUNCTION_PROLOGS 

174 function_epilogs = { 

175 rb"\xc9\xc3", # leaveq; retq 

176 rb"([^\x41][\x50-\x5f]{1}|\x41[\x50-\x5f])\xc3", # pop <reg>; retq 

177 rb"\x48[\x83,\x81]\xc4([\x00-\xff]{1}|[\x00-\xff]{4})\xc3", # add rsp, <siz>; retq 

178 } 

179 ret_instruction = b"\xc3" 

180 nop_instruction = b"\x90" 

181 instruction_alignment = 1 

182 register_list = [ 

183 Register( 

184 name="rax", 

185 size=8, 

186 subregisters=[("eax", 0, 4), ("ax", 0, 2), ("al", 0, 1), ("ah", 1, 1)], 

187 general_purpose=True, 

188 linux_entry_value=0x1C, 

189 ), 

190 Register( 

191 name="rcx", 

192 size=8, 

193 subregisters=[("ecx", 0, 4), ("cx", 0, 2), ("cl", 0, 1), ("ch", 1, 1)], 

194 general_purpose=True, 

195 argument=True, 

196 ), 

197 Register( 

198 name="rdx", 

199 size=8, 

200 subregisters=[("edx", 0, 4), ("dx", 0, 2), ("dl", 0, 1), ("dh", 1, 1)], 

201 general_purpose=True, 

202 argument=True, 

203 linux_entry_value="ld_destructor", 

204 ), 

205 Register( 

206 name="rbx", 

207 size=8, 

208 subregisters=[("ebx", 0, 4), ("bx", 0, 2), ("bl", 0, 1), ("bh", 1, 1)], 

209 general_purpose=True, 

210 linux_entry_value=0, 

211 ), 

212 Register( 

213 name="rsp", 

214 size=8, 

215 subregisters=[("esp", 0, 4)], 

216 alias_names=("sp",), 

217 general_purpose=True, 

218 default_value=(initial_sp, True, "global"), 

219 ), 

220 Register( 

221 name="rbp", 

222 size=8, 

223 subregisters=[("ebp", 0, 4), ("_bp", 0, 2), ("bpl", 0, 1), ("bph", 1, 1)], 

224 alias_names=("bp",), 

225 general_purpose=True, 

226 linux_entry_value=0, 

227 ), 

228 Register( 

229 name="rsi", 

230 size=8, 

231 subregisters=[("esi", 0, 4), ("si", 0, 2), ("sil", 0, 1), ("sih", 1, 1)], 

232 general_purpose=True, 

233 argument=True, 

234 linux_entry_value="argv", 

235 ), 

236 Register( 

237 name="rdi", 

238 size=8, 

239 subregisters=[("edi", 0, 4), ("di", 0, 2), ("dil", 0, 1), ("dih", 1, 1)], 

240 general_purpose=True, 

241 argument=True, 

242 linux_entry_value="argc", 

243 ), 

244 Register( 

245 name="r8", 

246 size=8, 

247 subregisters=[("r8d", 0, 4), ("r8w", 0, 2), ("r8b", 0, 1)], 

248 general_purpose=True, 

249 argument=True, 

250 ), 

251 Register( 

252 name="r9", 

253 size=8, 

254 subregisters=[("r9d", 0, 4), ("r9w", 0, 2), ("r9b", 0, 1)], 

255 general_purpose=True, 

256 argument=True, 

257 ), 

258 Register( 

259 name="r10", 

260 size=8, 

261 subregisters=[("r10d", 0, 4), ("r10w", 0, 2), ("r10b", 0, 1)], 

262 general_purpose=True, 

263 argument=True, 

264 ), 

265 Register( 

266 name="r11", size=8, subregisters=[("r11d", 0, 4), ("r11w", 0, 2), ("r11b", 0, 1)], general_purpose=True 

267 ), 

268 Register( 

269 name="r12", 

270 size=8, 

271 subregisters=[("r12d", 0, 4), ("r12w", 0, 2), ("r12b", 0, 1)], 

272 general_purpose=True, 

273 linux_entry_value=0, 

274 ), 

275 Register( 

276 name="r13", 

277 size=8, 

278 subregisters=[("r13d", 0, 4), ("r13w", 0, 2), ("r13b", 0, 1)], 

279 general_purpose=True, 

280 linux_entry_value=0, 

281 ), 

282 Register( 

283 name="r14", 

284 size=8, 

285 subregisters=[("r14d", 0, 4), ("r14w", 0, 2), ("r14b", 0, 1)], 

286 general_purpose=True, 

287 linux_entry_value=0, 

288 ), 

289 Register( 

290 name="r15", 

291 size=8, 

292 subregisters=[("r15d", 0, 4), ("r15w", 0, 2), ("r15b", 0, 1)], 

293 general_purpose=True, 

294 linux_entry_value=0, 

295 ), 

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

297 Register(name="cc_dep1", size=8, concrete=False, artificial=True), 

298 Register(name="cc_dep2", size=8, concrete=False, artificial=True), 

299 Register(name="cc_ndep", size=8, concrete=False, artificial=True, linux_entry_value=0), 

300 Register(name="d", size=8, alias_names=("dflag",), default_value=(1, False, None), concrete=False), 

301 Register(name="rip", size=8, alias_names=("ip", "pc"), general_purpose=True), 

302 Register(name="ac", size=8, alias_names=("acflag",), concrete=False), 

303 Register(name="id", size=8, alias_names=("idflag",)), 

304 Register( 

305 name="fs", 

306 size=8, 

307 vex_name="fs_const", 

308 alias_names=("fs_const",), 

309 default_value=(0x9000000000000000, True, "global"), 

310 concrete=False, 

311 ), 

312 Register(name="sseround", size=8, vector=True, default_value=(0, False, None)), 

313 Register(name="cr0", size=8), 

314 Register(name="cr2", size=8), 

315 Register(name="cr3", size=8), 

316 Register(name="cr4", size=8), 

317 Register(name="cr8", size=8), 

318 Register( 

319 name="ymm0", 

320 size=32, 

321 subregisters=[("xmm0", 0, 16), ("xmm0lq", 0, 8), ("xmm0hq", 8, 8), ("ymm0hx", 16, 16)], 

322 vector=True, 

323 ), 

324 Register( 

325 name="ymm1", 

326 size=32, 

327 subregisters=[("xmm1", 0, 16), ("xmm1lq", 0, 8), ("xmm1hq", 8, 8), ("ymm1hx", 16, 16)], 

328 vector=True, 

329 ), 

330 Register( 

331 name="ymm2", 

332 size=32, 

333 subregisters=[("xmm2", 0, 16), ("xmm2lq", 0, 8), ("xmm2hq", 8, 8), ("ymm2hx", 16, 16)], 

334 vector=True, 

335 ), 

336 Register( 

337 name="ymm3", 

338 size=32, 

339 subregisters=[("xmm3", 0, 16), ("xmm3lq", 0, 8), ("xmm3hq", 8, 8), ("ymm3hx", 16, 16)], 

340 vector=True, 

341 ), 

342 Register( 

343 name="ymm4", 

344 size=32, 

345 subregisters=[("xmm4", 0, 16), ("xmm4lq", 0, 8), ("xmm4hq", 8, 8), ("ymm4hx", 16, 16)], 

346 vector=True, 

347 ), 

348 Register( 

349 name="ymm5", 

350 size=32, 

351 subregisters=[("xmm5", 0, 16), ("xmm5lq", 0, 8), ("xmm5hq", 8, 8), ("ymm5hx", 16, 16)], 

352 vector=True, 

353 ), 

354 Register( 

355 name="ymm6", 

356 size=32, 

357 subregisters=[("xmm6", 0, 16), ("xmm6lq", 0, 8), ("xmm6hq", 8, 8), ("ymm6hx", 16, 16)], 

358 vector=True, 

359 ), 

360 Register( 

361 name="ymm7", 

362 size=32, 

363 subregisters=[("xmm7", 0, 16), ("xmm7lq", 0, 8), ("xmm7hq", 8, 8), ("ymm7hx", 16, 16)], 

364 vector=True, 

365 ), 

366 Register( 

367 name="ymm8", 

368 size=32, 

369 subregisters=[("xmm8", 0, 16), ("xmm8lq", 0, 8), ("xmm8hq", 8, 8), ("ymm8hx", 16, 16)], 

370 vector=True, 

371 ), 

372 Register( 

373 name="ymm9", 

374 size=32, 

375 subregisters=[("xmm9", 0, 16), ("xmm9lq", 0, 8), ("xmm9hq", 8, 8), ("ymm9hx", 16, 16)], 

376 vector=True, 

377 ), 

378 Register( 

379 name="ymm10", 

380 size=32, 

381 subregisters=[("xmm10", 0, 16), ("xmm10lq", 0, 8), ("xmm10hq", 8, 8), ("ymm10hx", 16, 16)], 

382 vector=True, 

383 ), 

384 Register( 

385 name="ymm11", 

386 size=32, 

387 subregisters=[("xmm11", 0, 16), ("xmm11lq", 0, 8), ("xmm11hq", 8, 8), ("ymm11hx", 16, 16)], 

388 vector=True, 

389 ), 

390 Register( 

391 name="ymm12", 

392 size=32, 

393 subregisters=[("xmm12", 0, 16), ("xmm12lq", 0, 8), ("xmm12hq", 8, 8), ("ymm12hx", 16, 16)], 

394 vector=True, 

395 ), 

396 Register( 

397 name="ymm13", 

398 size=32, 

399 subregisters=[("xmm13", 0, 16), ("xmm13lq", 0, 8), ("xmm13hq", 8, 8), ("ymm13hx", 16, 16)], 

400 vector=True, 

401 ), 

402 Register( 

403 name="ymm14", 

404 size=32, 

405 subregisters=[("xmm14", 0, 16), ("xmm14lq", 0, 8), ("xmm14hq", 8, 8), ("ymm14hx", 16, 16)], 

406 vector=True, 

407 ), 

408 Register( 

409 name="ymm15", 

410 size=32, 

411 subregisters=[("xmm15", 0, 16), ("xmm15lq", 0, 8), ("xmm15hq", 8, 8), ("ymm15hx", 16, 16)], 

412 vector=True, 

413 ), 

414 Register(name="ftop", size=4, floating_point=True, default_value=(7, False, None), artificial=True), 

415 Register( 

416 name="fpreg", 

417 size=64, 

418 subregisters=[ 

419 ("mm0", 0, 8), 

420 ("mm1", 8, 8), 

421 ("mm2", 16, 8), 

422 ("mm3", 24, 8), 

423 ("mm4", 32, 8), 

424 ("mm5", 40, 8), 

425 ("mm6", 48, 8), 

426 ("mm7", 56, 8), 

427 ], 

428 alias_names=("fpu_regs",), 

429 floating_point=True, 

430 ), 

431 Register(name="fptag", size=8, alias_names=("fpu_tags",), floating_point=True, default_value=(0, False, None)), 

432 Register(name="fpround", size=8, floating_point=True, default_value=(0, False, None)), 

433 Register(name="fc3210", size=8, floating_point=True), 

434 Register(name="emnote", size=4, artificial=True), 

435 Register(name="cmstart", size=8), 

436 Register(name="cmlen", size=8), 

437 Register(name="nraddr", size=8), 

438 Register(name="gs", size=8, vex_name="gs_const", alias_names=("gs_const",), concrete=False), 

439 Register(name="ip_at_syscall", size=8, concrete=False, artificial=True), 

440 Register(name="cs_seg", size=2, vex_name="cs"), 

441 Register(name="ds_seg", size=2, vex_name="ds"), 

442 Register(name="es_seg", size=2, vex_name="es"), 

443 Register(name="fs_seg", size=2, vex_name="fs"), 

444 Register(name="fs_seg", size=2, vex_name="gs"), 

445 Register(name="ss_seg", size=2, vex_name="ss"), 

446 ] 

447 

448 symbol_type_translation = {10: "STT_GNU_IFUNC", "STT_LOOS": "STT_GNU_IFUNC"} 

449 got_section_name = ".got.plt" 

450 ld_linux_name = "ld-linux-x86-64.so.2" 

451 elf_tls = TLSArchInfo(2, 704, [16], [8], [0], 0, 0) 

452 dwarf_registers = [ 

453 "rax", 

454 "rdx", 

455 "rcx", 

456 "rbx", 

457 "rsi", 

458 "rdi", 

459 "rbp", 

460 "rsp", 

461 "r8", 

462 "r9", 

463 "r10", 

464 "r11", 

465 "r12", 

466 "r13", 

467 "r14", 

468 "r15", 

469 "rip", 

470 "xmm0", 

471 "xmm1", 

472 "xmm2", 

473 "xmm3", 

474 "xmm4", 

475 "xmm5", 

476 "xmm6", 

477 "xmm7", 

478 "xmm8", 

479 "xmm9", 

480 "xmm10", 

481 "xmm11", 

482 "xmm12", 

483 "xmm13", 

484 "xmm14", 

485 "xmm15", 

486 "st0", 

487 "st1", 

488 "st2", 

489 "st3", 

490 "st4", 

491 "st5", 

492 "st6", 

493 "st7", 

494 "mm0", 

495 "mm1", 

496 "mm2", 

497 "mm3", 

498 "mm4", 

499 "mm5", 

500 "mm6", 

501 "mm7", 

502 "rflags", 

503 "es", 

504 "cs", 

505 "ss", 

506 "ds", 

507 "fs", 

508 "gs", 

509 "<none>", 

510 "<none>", 

511 "fs.base", 

512 "gs.base", 

513 "<none>", 

514 "<none>", 

515 "tr", 

516 "ldtr", 

517 "mxcsr", 

518 "fcw", 

519 "fsw", 

520 ] 

521 

522 

523register_arch([r".*amd64|.*x64|.*x86_64|.*metapc"], 64, Endness.LE, ArchAMD64)