Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/archinfo/arch_x86.py: 67%
123 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:15 +0000
« 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
5try:
6 import capstone as _capstone
7except ImportError:
8 _capstone = None
10try:
11 import keystone as _keystone
12except ImportError:
13 _keystone = None
15try:
16 import unicorn as _unicorn
17except ImportError:
18 _unicorn = None
20try:
21 import pyvex as _pyvex
22except ImportError:
23 _pyvex = None
26_NATIVE_FUNCTION_PROLOGS = [
27 rb"\x8b\xff\x55\x8b\xec", # mov edi, edi; push ebp; mov ebp, esp
28 rb"\x55\x8b\xec", # push ebp; mov ebp, esp
29 rb"\x55\x89\xe5", # push ebp; mov ebp, esp
30 rb"\x55\x57\x56", # push ebp; push edi; push esi
31 # mov eax, 0x000000??; (push ebp; push eax; push edi; push ebx; push esi; push edx; push ecx) sub esp
32 rb"\xb8[\x00-\xff]\x00\x00\x00[\x50\x51\x52\x53\x55\x56\x57]{0,7}\x8b[\x00-\xff]{2}",
33 # (push ebp; push eax; push edi; push ebx; push esi; push edx; push ecx) sub esp
34 rb"[\x50\x51\x52\x53\x55\x56\x57]{1,7}\x83\xec[\x00-\xff]{2,4}",
35 # (push ebp; push eax; push edi; push ebx; push esi; push edx; push ecx) mov xxx, xxx
36 rb"[\x50\x51\x52\x53\x55\x56\x57]{1,7}\x8b[\x00-\xff]{2}",
37 rb"(\x81|\x83)\xec", # sub xxx %esp
38]
39# every function prolog can potentially be prefixed with endbr32
40_endbr32 = b"\xf3\x0f\x1e\xfb"
41_prefixed = [(_endbr32 + prolog) for prolog in _NATIVE_FUNCTION_PROLOGS]
42_FUNCTION_PROLOGS = _prefixed + _NATIVE_FUNCTION_PROLOGS
45class ArchX86(Arch):
46 def __init__(self, endness=Endness.LE):
47 if endness != Endness.LE:
48 raise ArchError("Arch i386 must be little endian")
49 super().__init__(endness)
50 if self.vex_archinfo:
51 self.vex_archinfo["x86_cr0"] = 0xFFFFFFFF
53 # Register blacklist
54 reg_blacklist = ("cs", "ds", "es", "fs", "gs", "ss", "gdt", "ldt")
55 if self.reg_blacklist is not None and self.reg_blacklist_offsets is not None:
56 for register in self.register_list:
57 if register.name in reg_blacklist:
58 self.reg_blacklist.append(register.name)
59 self.reg_blacklist_offsets.append(register.vex_offset)
61 if _unicorn and _pyvex:
62 # CPU flag registers
63 uc_flags_reg = _unicorn.x86_const.UC_X86_REG_EFLAGS
64 cpu_flag_registers = {"d": 1 << 10, "ac": 1 << 18, "id": 1 << 21}
65 for reg, reg_bitmask in cpu_flag_registers.items():
66 reg_offset = self.get_register_offset(reg)
67 self.cpu_flag_register_offsets_and_bitmasks_map[reg_offset] = (uc_flags_reg, reg_bitmask)
69 mxcsr_registers = {"sseround": 1 << 14 | 1 << 13}
70 uc_mxcsr_reg = _unicorn.x86_const.UC_X86_REG_MXCSR
71 for reg, reg_bitmask in mxcsr_registers.items():
72 reg_offset = self.get_register_offset(reg)
73 self.cpu_flag_register_offsets_and_bitmasks_map[reg_offset] = (uc_mxcsr_reg, reg_bitmask)
75 @property
76 def capstone_x86_syntax(self):
77 """
78 Get the current syntax Capstone uses for x86. It can be 'intel' or 'at&t'
80 :return: Capstone's current x86 syntax
81 :rtype: str
82 """
84 return self._cs_x86_syntax
86 @capstone_x86_syntax.setter
87 def capstone_x86_syntax(self, new_syntax):
88 """
89 Set the syntax that Capstone outputs for x86.
90 """
92 if new_syntax not in ("intel", "at&t"):
93 raise ArchError('Unsupported Capstone x86 syntax. It must be either "intel" or "at&t".')
95 if new_syntax != self._cs_x86_syntax:
96 self._cs = None
97 self._cs_x86_syntax = new_syntax
99 def _configure_capstone(self):
100 self._cs.syntax = (
101 _capstone.CS_OPT_SYNTAX_ATT if self._cs_x86_syntax == "at&t" else _capstone.CS_OPT_SYNTAX_INTEL
102 )
104 @property
105 def keystone_x86_syntax(self):
106 """
107 Get the current syntax Keystone uses for x86. It can be 'intel',
108 'at&t', 'nasm', 'masm', 'gas' or 'radix16'
110 :return: Keystone's current x86 syntax
111 :rtype: str
112 """
114 return self._ks_x86_syntax
116 @keystone_x86_syntax.setter
117 def keystone_x86_syntax(self, new_syntax):
118 """
119 Set the syntax that Keystone uses for x86.
120 """
122 if new_syntax not in ("intel", "at&t", "nasm", "masm", "gas", "radix16"):
123 raise ArchError(
124 "Unsupported Keystone x86 syntax. It must be one of the following: "
125 '"intel", "at&t", "nasm", "masm", "gas" or "radix16".'
126 )
128 if new_syntax != self._ks_x86_syntax:
129 self._ks = None
130 self._ks_x86_syntax = new_syntax
132 def _configure_keystone(self):
133 if self._ks_x86_syntax == "at&t":
134 self._ks.syntax = _keystone.KS_OPT_SYNTAX_ATT
135 elif self._ks_x86_syntax == "nasm":
136 self._ks.syntax = _keystone.KS_OPT_SYNTAX_NASM
137 elif self._ks_x86_syntax == "masm":
138 self._ks.syntax = _keystone.KS_OPT_SYNTAX_MASM
139 elif self._ks_x86_syntax == "gas":
140 self._ks.syntax = _keystone.KS_OPT_SYNTAX_GAS
141 elif self._ks_x86_syntax == "radix16":
142 self._ks.syntax = _keystone.KS_OPT_SYNTAX_RADIX16
143 else:
144 self._ks.syntax = _keystone.KS_OPT_SYNTAX_INTEL
146 bits = 32
147 vex_arch = "VexArchX86"
148 name = "X86"
149 qemu_name = "i386"
150 ida_processor = "metapc"
151 linux_name = "i386"
152 triplet = "i386-linux-gnu"
153 max_inst_bytes = 15
154 call_sp_fix = -4
155 ret_offset = 8
156 vex_conditional_helpers = True
157 syscall_num_offset = 8
158 call_pushes_ret = True
159 stack_change = -4
160 memory_endness = Endness.LE
161 register_endness = Endness.LE
162 sizeof = {"short": 16, "int": 32, "long": 32, "long long": 64}
163 if _capstone:
164 cs_arch = _capstone.CS_ARCH_X86
165 cs_mode = _capstone.CS_MODE_32 + _capstone.CS_MODE_LITTLE_ENDIAN
166 _cs_x86_syntax = None # Set it to 'att' in order to use AT&T syntax for x86
167 if _keystone:
168 ks_arch = _keystone.KS_ARCH_X86
169 ks_mode = _keystone.KS_MODE_32 + _keystone.KS_MODE_LITTLE_ENDIAN
170 _ks_x86_syntax = None
171 uc_arch = _unicorn.UC_ARCH_X86 if _unicorn else None
172 uc_mode = (_unicorn.UC_MODE_32 + _unicorn.UC_MODE_LITTLE_ENDIAN) if _unicorn else None
173 uc_const = _unicorn.x86_const if _unicorn else None
174 uc_prefix = "UC_X86_" if _unicorn else None
175 function_prologs = _FUNCTION_PROLOGS
176 function_epilogs = {
177 rb"\xc9\xc3", # leave; ret
178 rb"([^\x41][\x50-\x5f]{1}|\x41[\x50-\x5f])\xc3", # pop <reg>; ret
179 rb"[^\x48][\x83,\x81]\xc4([\x00-\xff]{1}|[\x00-\xff]{4})\xc3", # add esp, <siz>; retq
180 }
181 ret_instruction = b"\xc3"
182 nop_instruction = b"\x90"
183 instruction_alignment = 1
184 register_list = [
185 Register(
186 name="eax",
187 size=4,
188 subregisters=[("ax", 0, 2), ("al", 0, 1), ("ah", 1, 1)],
189 general_purpose=True,
190 argument=True,
191 linux_entry_value=0x1C,
192 ),
193 Register(
194 name="ecx",
195 size=4,
196 subregisters=[("cx", 0, 2), ("cl", 0, 1), ("ch", 1, 1)],
197 general_purpose=True,
198 argument=True,
199 ),
200 Register(
201 name="edx",
202 size=4,
203 subregisters=[("dx", 0, 2), ("dl", 0, 1), ("dh", 1, 1)],
204 general_purpose=True,
205 argument=True,
206 linux_entry_value="ld_destructor",
207 ),
208 Register(
209 name="ebx",
210 size=4,
211 subregisters=[("bx", 0, 2), ("bl", 0, 1), ("bh", 1, 1)],
212 general_purpose=True,
213 argument=True,
214 ),
215 Register(
216 name="esp",
217 size=4,
218 alias_names=("sp",),
219 general_purpose=True,
220 default_value=(Arch.initial_sp, True, "global"),
221 ),
222 Register(name="ebp", size=4, alias_names=("bp",), general_purpose=True, argument=True, linux_entry_value=0),
223 Register(
224 name="esi",
225 size=4,
226 subregisters=[("si", 0, 2), ("sil", 0, 1), ("sih", 1, 1)],
227 general_purpose=True,
228 argument=True,
229 ),
230 Register(
231 name="edi",
232 size=4,
233 subregisters=[("di", 0, 2), ("dil", 0, 1), ("dih", 1, 1)],
234 general_purpose=True,
235 argument=True,
236 ),
237 Register(name="cc_op", size=4, default_value=(0, False, None), concrete=False, artificial=True),
238 Register(name="cc_dep1", size=4, concrete=False, artificial=True),
239 Register(name="cc_dep2", size=4, concrete=False, artificial=True),
240 Register(name="cc_ndep", size=4, concrete=False, artificial=True),
241 Register(name="d", size=4, alias_names=("dflag",), default_value=(1, False, None), concrete=False),
242 Register(name="id", size=4, alias_names=("idflag",), default_value=(1, False, None), concrete=False),
243 Register(name="ac", size=4, alias_names=("acflag",), default_value=(0, False, None), concrete=False),
244 Register(name="eip", size=4, alias_names=("ip", "pc")),
245 Register(
246 name="fpreg",
247 size=64,
248 subregisters=[
249 ("mm0", 0, 8),
250 ("mm1", 8, 8),
251 ("mm2", 16, 8),
252 ("mm3", 24, 8),
253 ("mm4", 32, 8),
254 ("mm5", 40, 8),
255 ("mm6", 48, 8),
256 ("mm7", 56, 8),
257 ],
258 alias_names=("fpu_regs",),
259 floating_point=True,
260 concrete=False,
261 ),
262 Register(name="fptag", size=8, alias_names=("fpu_tags",), floating_point=True, default_value=(0, False, None)),
263 Register(name="fpround", size=4, floating_point=True, default_value=(0, False, None)),
264 Register(name="fc3210", size=4, floating_point=True),
265 Register(name="ftop", size=4, floating_point=True, default_value=(7, False, None), artificial=True),
266 Register(name="sseround", size=4, vector=True, default_value=(0, False, None)),
267 Register(name="xmm0", size=16, vector=True),
268 Register(name="xmm1", size=16, vector=True),
269 Register(name="xmm2", size=16, vector=True),
270 Register(name="xmm3", size=16, vector=True),
271 Register(name="xmm4", size=16, vector=True),
272 Register(name="xmm5", size=16, vector=True),
273 Register(name="xmm6", size=16, vector=True),
274 Register(name="xmm7", size=16, vector=True),
275 Register(name="cs", size=2),
276 Register(name="ds", size=2),
277 Register(name="es", size=2),
278 Register(name="fs", size=2, default_value=(0, False, None), concrete=False),
279 Register(name="gs", size=2, default_value=(0, False, None), concrete=False),
280 Register(name="ss", size=2),
281 Register(name="ldt", size=8, default_value=(0, False, None), concrete=False),
282 Register(name="gdt", size=8, default_value=(0, False, None), concrete=False),
283 Register(name="emnote", size=4, artificial=True),
284 Register(name="cmstart", size=4),
285 Register(name="cmlen", size=4),
286 Register(name="nraddr", size=4),
287 Register(name="sc_class", size=4),
288 Register(name="ip_at_syscall", size=4, concrete=False, artificial=True),
289 ]
291 symbol_type_translation = {10: "STT_GNU_IFUNC", "STT_LOOS": "STT_GNU_IFUNC"}
292 lib_paths = ["/lib32", "/usr/lib32"]
293 got_section_name = ".got.plt"
294 ld_linux_name = "ld-linux.so.2"
295 elf_tls = TLSArchInfo(2, 56, [8], [4], [0], 0, 0)
296 dwarf_registers = [
297 "eax",
298 "ecx",
299 "edx",
300 "ebx",
301 "esp",
302 "ebp",
303 "esi",
304 "edi",
305 "eip",
306 "eflags",
307 "<none>",
308 "st0",
309 "st1",
310 "st2",
311 "st3",
312 "st4",
313 "st5",
314 "st6",
315 "st7",
316 "<none>",
317 "<none>",
318 "xmm0",
319 "xmm1",
320 "xmm2",
321 "xmm3",
322 "xmm4",
323 "xmm5",
324 "xmm6",
325 "xmm7",
326 "mm0",
327 "mm1",
328 "mm2",
329 "mm3",
330 "mm4",
331 "mm5",
332 "mm6",
333 "mm7",
334 "fcw",
335 "fsw",
336 "mxcsr",
337 "es",
338 "cs",
339 "ss",
340 "ds",
341 "fs",
342 "gs",
343 "<none>",
344 "<none>",
345 "tr",
346 "ldtr",
347 ]
350register_arch([r".*i?\d86|.*x32|.*x86|.*metapc"], 32, Endness.LE, ArchX86)