1import logging
2
3from pyvex.lifting.util import GymratLifter, Instruction, JumpKind, Type
4
5log = logging.getLogger(__name__)
6
7# pylint: disable=missing-class-docstring
8
9
10class Instruction_SWAPGS(Instruction):
11 name = "SWAPGS"
12 bin_format = "000011110000000111111000" # 0f 01 f8
13
14 def compute_result(self, *args):
15 pass # TODO check for priv mode
16
17
18class Instruction_SYSRET(Instruction):
19 name = "SYSRET"
20 bin_format = "010010000000111100000111" # 48 04 07
21
22 def compute_result(self, *args):
23 result = self.dirty(Type.int_64, "%sg_dirtyhelper_SYSRET" % self.arch.name.lower(), ())
24 self.jump(None, result, JumpKind.Ret)
25
26
27class Instruction_IRETQ(Instruction):
28 name = "IRETQ"
29 bin_format = "0100100011001111" # 48 cf
30
31 def compute_result(self, *args):
32 result = self.dirty(Type.int_64, "%sg_dirtyhelper_IRETQ" % self.arch.name.lower(), ())
33 self.jump(None, result, JumpKind.Ret)
34
35
36class Instruction_RDMSR(Instruction):
37 name = "RDMSR"
38 bin_format = "0000111100110010" # 0f 32
39
40 def compute_result(self, *args):
41 ecx = self.get("ecx", Type.int_32)
42 result = self.dirty(Type.int_64, "%sg_dirtyhelper_RDMSR" % self.arch.name.lower(), (ecx,))
43 edx = result.narrow_high(Type.int_32)
44 eax = result.narrow_low(Type.int_32)
45 if self.arch.bits == 32:
46 self.put(eax, "eax")
47 self.put(edx, "edx")
48 else:
49 self.put(eax.widen_unsigned(Type.int_64), "rax")
50 self.put(edx.widen_unsigned(Type.int_64), "rdx")
51
52
53class Instruction_XGETBV(Instruction):
54 name = "XGETBV"
55 bin_format = "000011110000000111010000" # 0f 01 d0
56
57 def compute_result(self, *args):
58 ecx = self.get("ecx", Type.int_32)
59 result = self.dirty(Type.int_64, "%sg_dirtyhelper_XGETBV" % self.arch.name.lower(), (ecx,))
60 edx = result.narrow_high(Type.int_32)
61 eax = result.narrow_low(Type.int_32)
62 if self.arch.bits == 32:
63 self.put(eax, "eax")
64 self.put(edx, "edx")
65 else:
66 self.put(eax.widen_unsigned(Type.int_64), "rax")
67 self.put(edx.widen_unsigned(Type.int_64), "rdx")
68
69
70class Instruction_AAM(Instruction):
71 name = "AAM"
72 bin_format = "11010100iiiiiiii"
73
74 # From https://www.felixcloutier.com/x86/aam
75 def compute_result(self): # pylint: disable=arguments-differ
76 base = self.constant(int(self.data["i"], 2), Type.int_8)
77 temp_al = self.get("al", Type.int_8)
78 temp_ah = temp_al // base
79 temp_al = temp_al % base
80 self.put(temp_ah, "ah")
81 self.put(temp_al, "al")
82 log.debug(
83 "The generalized AAM instruction is not supported by VEX, and is handled specially by pyvex."
84 " It has no flag handling at present. See pyvex/lifting/gym/x86_spotter.py for details"
85 )
86
87 # TODO: Flags
88
89
90class Instruction_AAD(Instruction):
91 name = "AAD"
92 bin_format = "11010101iiiiiiii"
93
94 # From https://www.felixcloutier.com/x86/aad
95 def compute_result(self): # pylint: disable=arguments-differ
96 base = self.constant(int(self.data["i"], 2), Type.int_8)
97 temp_al = self.get("al", Type.int_8)
98 temp_ah = self.get("ah", Type.int_8)
99 temp_al = (temp_al + (temp_ah * base)) & 0xFF
100 temp_ah = self.constant(0, Type.int_8)
101 self.put(temp_ah, "ah")
102 self.put(temp_al, "al")
103 log.debug(
104 "The generalized AAD instruction is not supported by VEX, and is handled specially by pyvex."
105 " It has no flag handling at present. See pyvex/lifting/gym/x86_spotter.py for details"
106 )
107
108 # TODO: Flags
109
110
111class AMD64Spotter(GymratLifter):
112 instrs = [
113 Instruction_RDMSR,
114 Instruction_XGETBV,
115 Instruction_AAD,
116 Instruction_AAM,
117 Instruction_SWAPGS,
118 Instruction_IRETQ,
119 Instruction_SYSRET,
120 ]
121
122
123class X86Spotter(GymratLifter):
124 instrs = [
125 Instruction_RDMSR,
126 Instruction_XGETBV,
127 Instruction_AAD,
128 Instruction_AAM,
129 ]