1
1
from capstone .x86_const import *
2
+ import re as _re
2
3
4
+ # TODO: this is all x86_specific :(
3
5
JMPS = [
4
6
X86_INS_JA ,
5
7
X86_INS_JAE ,
@@ -32,13 +34,17 @@ class Base(object):
32
34
def __repr__ (self ):
33
35
return '<%s %s>' % (self .__class__ .__name__ , repr (str (self )))
34
36
37
+ def re_match (maybe_re , s ):
38
+ pass
39
+
35
40
class Op (Base ):
36
41
ins = None
37
42
op = None
38
43
39
44
@classmethod
40
45
def fromop (cls , ins , op ):
41
46
i = cls ()
47
+ i .any = False
42
48
i .ins = ins
43
49
i .op = op
44
50
i .parse ()
@@ -49,17 +55,24 @@ def __ne__(self, other):
49
55
50
56
class LabelOp (Op ):
51
57
def __init__ (self , name = None , any = False ):
58
+ if name is None :
59
+ any = True
52
60
self .name = name
53
61
self .any = any
54
62
55
63
def __eq__ (self , other ):
64
+ if other == LabelOp :
65
+ return True
56
66
return isinstance (other , LabelOp ) and (other .name == self .name or self .any or other .any )
57
67
58
68
def __str__ (self ):
59
69
return self .name
60
70
61
71
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
63
76
self .val = val
64
77
self .any = any
65
78
@@ -69,6 +82,8 @@ def parse(self):
69
82
def __eq__ (self , other ):
70
83
if isinstance (other , (int , long )) and (self .val == other ):
71
84
return True
85
+ if other == Imm :
86
+ return True
72
87
return isinstance (other , Imm ) and (other .val == self .val or self .any or other .any )
73
88
74
89
def __cmp__ (self , other ):
@@ -77,25 +92,40 @@ def __cmp__(self, other):
77
92
return cmp (self .val , other .val )
78
93
79
94
def __str__ (self ):
95
+ if self .any :
96
+ return '<imm>'
80
97
if self .val >= 0 :
81
98
return '0x%x' % self .val
82
99
else :
83
100
return '-0x%x' % abs (self .val )
84
101
85
102
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 ''
88
106
self .any = any
107
+ if re is not None :
108
+ self .re = _re .compile (re )
109
+ elif reg is None :
110
+ self .any = True
89
111
90
112
def parse (self ):
91
113
self .reg = self .ins .reg_name (self .op .reg )
92
114
93
115
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 )) :
95
117
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 )))
97
123
98
124
def __str__ (self ):
125
+ if self .any :
126
+ return '<reg>'
127
+ if self .re and not self .reg :
128
+ return '/%s/' % self .re .pattern
99
129
return self .reg
100
130
101
131
class Mem (Op ):
@@ -133,11 +163,15 @@ def parse(self):
133
163
self .off = op .disp
134
164
135
165
def __eq__ (self , other ):
166
+ if other == Mem :
167
+ return True
136
168
return isinstance (other , Mem ) and ((
137
169
self .size , self .base , self .index , self .segment , self .scale , self .off ,
138
170
) == (other .size , other .base , other .index , other .segment , other .scale , other .off ) or self .any or other .any )
139
171
140
172
def __str__ (self ):
173
+ if self .any :
174
+ return '<mem>'
141
175
tmp = []
142
176
if self .base :
143
177
tmp .append (self .base )
@@ -187,29 +221,57 @@ def fromins(cls, ins):
187
221
return c
188
222
189
223
@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 ]
192
234
193
235
@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 ]
196
246
197
247
def __init__ (self , mne , * ops , ** kwargs ):
198
248
self .mne = mne
199
249
self .ops = ops
200
250
self .label = None
201
251
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 )
202
256
203
257
def op_str (self ):
204
258
return ', ' .join (map (str , self .ops ))
205
259
206
260
def __eq__ (self , other ):
207
261
if isinstance (other , basestring ) and other == self .mne :
208
262
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 )))
210
270
211
271
def __str__ (self ):
212
272
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 )
213
275
if self .label :
214
276
out = '%s: %s' % self .label
215
277
return out
@@ -228,6 +290,23 @@ class IR(list):
228
290
def asm (self ):
229
291
return '\n ' .join (map (str , self ))
230
292
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
+
231
310
def irdis (dis ):
232
311
if not dis :
233
312
return IR ([])
0 commit comments