Skip to content

Commit e28b2c0

Browse files
committed
IR tweaks
1 parent 8af3747 commit e28b2c0

File tree

1 file changed

+89
-10
lines changed

1 file changed

+89
-10
lines changed

util/patch/dis.py

Lines changed: 89 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from capstone.x86_const import *
2+
import re as _re
23

4+
# TODO: this is all x86_specific :(
35
JMPS = [
46
X86_INS_JA,
57
X86_INS_JAE,
@@ -32,13 +34,17 @@ class Base(object):
3234
def __repr__(self):
3335
return '<%s %s>' % (self.__class__.__name__, repr(str(self)))
3436

37+
def re_match(maybe_re, s):
38+
pass
39+
3540
class Op(Base):
3641
ins = None
3742
op = None
3843

3944
@classmethod
4045
def fromop(cls, ins, op):
4146
i = cls()
47+
i.any = False
4248
i.ins = ins
4349
i.op = op
4450
i.parse()
@@ -49,17 +55,24 @@ def __ne__(self, other):
4955

5056
class LabelOp(Op):
5157
def __init__(self, name=None, any=False):
58+
if name is None:
59+
any = True
5260
self.name = name
5361
self.any = any
5462

5563
def __eq__(self, other):
64+
if other == LabelOp:
65+
return True
5666
return isinstance(other, LabelOp) and (other.name == self.name or self.any or other.any)
5767

5868
def __str__(self):
5969
return self.name
6070

6171
class Imm(Op):
62-
def __init__(self, val=0, any=False):
72+
def __init__(self, val=None, any=False):
73+
if val is None:
74+
val = 0
75+
any = True
6376
self.val = val
6477
self.any = any
6578

@@ -69,6 +82,8 @@ def parse(self):
6982
def __eq__(self, other):
7083
if isinstance(other, (int, long)) and (self.val == other):
7184
return True
85+
if other == Imm:
86+
return True
7287
return isinstance(other, Imm) and (other.val == self.val or self.any or other.any)
7388

7489
def __cmp__(self, other):
@@ -77,25 +92,40 @@ def __cmp__(self, other):
7792
return cmp(self.val, other.val)
7893

7994
def __str__(self):
95+
if self.any:
96+
return '<imm>'
8097
if self.val >= 0:
8198
return '0x%x' % self.val
8299
else:
83100
return '-0x%x' % abs(self.val)
84101

85102
class Reg(Op):
86-
def __init__(self, reg='', any=False):
87-
self.reg = reg
103+
def __init__(self, reg=None, any=False, re=None):
104+
self.re = None
105+
self.reg = reg or ''
88106
self.any = any
107+
if re is not None:
108+
self.re = _re.compile(re)
109+
elif reg is None:
110+
self.any = True
89111

90112
def parse(self):
91113
self.reg = self.ins.reg_name(self.op.reg)
92114

93115
def __eq__(self, other):
94-
if isinstance(other, basestring) and self.reg == other:
116+
if isinstance(other, basestring) and (self.reg == other or self.re and self.re.match(other)):
95117
return True
96-
return isinstance(other, Reg) and (other.reg == self.reg or self.any or other.any)
118+
return isinstance(other, Reg) and (
119+
other.reg == self.reg or
120+
self.any or other.any or
121+
bool(self.re and self.re.match(other.reg)) or
122+
bool(other.re and other.re.match(self.reg)))
97123

98124
def __str__(self):
125+
if self.any:
126+
return '<reg>'
127+
if self.re and not self.reg:
128+
return '/%s/' % self.re.pattern
99129
return self.reg
100130

101131
class Mem(Op):
@@ -133,11 +163,15 @@ def parse(self):
133163
self.off = op.disp
134164

135165
def __eq__(self, other):
166+
if other == Mem:
167+
return True
136168
return isinstance(other, Mem) and ((
137169
self.size, self.base, self.index, self.segment, self.scale, self.off,
138170
) == (other.size, other.base, other.index, other.segment, other.scale, other.off) or self.any or other.any)
139171

140172
def __str__(self):
173+
if self.any:
174+
return '<mem>'
141175
tmp = []
142176
if self.base:
143177
tmp.append(self.base)
@@ -187,29 +221,57 @@ def fromins(cls, ins):
187221
return c
188222

189223
@property
190-
def dst(self):
191-
return self.ops[0]
224+
def dst(self): return self.ops[0]
225+
226+
@property
227+
def src(self): return self.ops[1]
228+
229+
@property
230+
def a(self): return self.ops[0]
231+
232+
@property
233+
def b(self): return self.ops[1]
192234

193235
@property
194-
def src(self):
195-
return self.ops[1]
236+
def c(self): return self.ops[2]
237+
238+
@property
239+
def d(self): return self.ops[3]
240+
241+
@property
242+
def e(self): return self.ops[4]
243+
244+
@property
245+
def f(self): return self.ops[5]
196246

197247
def __init__(self, mne, *ops, **kwargs):
198248
self.mne = mne
199249
self.ops = ops
200250
self.label = None
201251
self.any = kwargs.get('any', False)
252+
re = kwargs.pop('re', None)
253+
self.re = re
254+
if re is not None:
255+
self.re = re.compile(re)
202256

203257
def op_str(self):
204258
return ', '.join(map(str, self.ops))
205259

206260
def __eq__(self, other):
207261
if isinstance(other, basestring) and other == self.mne:
208262
return True
209-
return isinstance(other, Ins) and self.mne == other.mne and (tuple(other.ops) == tuple(self.ops) or self.any or other.any)
263+
elif isinstance(other, Ins):
264+
return isinstance(other, Ins) and (
265+
self.any or other.any or
266+
(self.mne == other.mne or
267+
bool(self.re and self.re.match(other.mne)) or
268+
bool(other.re and other.re.match(self.mne))) and
269+
len(other.ops) == len(self.ops) and all(other.ops[i] == op for i, op in enumerate(self.ops)))
210270

211271
def __str__(self):
212272
out = '%s %s' % (self.mne, self.op_str())
273+
if self.re and not self.mne:
274+
out = '/%s/ %s' % (self.re.pattern, self.op_str)
213275
if self.label:
214276
out = '%s: %s' % self.label
215277
return out
@@ -228,6 +290,23 @@ class IR(list):
228290
def asm(self):
229291
return '\n'.join(map(str, self))
230292

293+
def findall(self, query, stop=None):
294+
def fuzzy(a, match):
295+
if isinstance(match, list):
296+
for other in match:
297+
if a == other:
298+
return True
299+
else:
300+
return a == match
301+
302+
out = []
303+
for ins in self:
304+
if fuzzy(ins, query):
305+
out.append(ins)
306+
if stop and fuzzy(ins, stop):
307+
break
308+
return out
309+
231310
def irdis(dis):
232311
if not dis:
233312
return IR([])

0 commit comments

Comments
 (0)