Miasm2
 All Classes Namespaces Files Functions Variables Typedefs Properties Macros
simplifications_cond.py
Go to the documentation of this file.
1 ################################################################################
2 #
3 # By choice, Miasm2 does not handle comparaison as a single operation, but with
4 # operations corresponding to comparaison computation.
5 # One may want to detect those comparaison; this library is designed to add them
6 # in Miasm2 engine thanks to :
7 # - Conditions computation in ExprOp
8 # - Simplifications to catch known condition forms
9 #
10 # Conditions currently supported :
11 # <u, <s, ==
12 #
13 # Authors : Fabrice DESCLAUX (CEA/DAM), Camille MOUGEY (CEA/DAM)
14 #
15 ################################################################################
16 
17 import miasm2.expression.expression as m2_expr
18 
19 
20 # Jokers for expression matching
21 
22 jok1 = m2_expr.ExprId("jok1")
23 jok2 = m2_expr.ExprId("jok2")
24 jok3 = m2_expr.ExprId("jok3")
25 jok_small = m2_expr.ExprId("jok_small", 1)
26 
27 
28 # Constructors
29 
30 def __ExprOp_cond(op, arg1, arg2):
31  "Return an ExprOp standing for arg1 op arg2 with size to 1"
32  ec = m2_expr.ExprOp(op, arg1, arg2)
33  return ec
34 
35 
36 def ExprOp_inf_signed(arg1, arg2):
37  "Return an ExprOp standing for arg1 <s arg2"
38  return __ExprOp_cond(m2_expr.TOK_INF_SIGNED, arg1, arg2)
39 
40 
41 def ExprOp_inf_unsigned(arg1, arg2):
42  "Return an ExprOp standing for arg1 <s arg2"
43  return __ExprOp_cond(m2_expr.TOK_INF_UNSIGNED, arg1, arg2)
44 
45 def ExprOp_equal(arg1, arg2):
46  "Return an ExprOp standing for arg1 == arg2"
47  return __ExprOp_cond(m2_expr.TOK_EQUAL, arg1, arg2)
48 
49 
50 # Catching conditions forms
51 
52 def __check_msb(e):
53  """If @e stand for the most significant bit of its arg, return the arg;
54  False otherwise"""
55 
56  if not isinstance(e, m2_expr.ExprSlice):
57  return False
58 
59  arg = e.arg
60  if e.start != (arg.size - 1) or e.stop != arg.size:
61  return False
62 
63  return arg
64 
65 def __MatchExprWrap(e, to_match, jok_list):
66  "Wrapper around MatchExpr to canonize pattern"
67 
68  to_match = to_match.canonize()
69 
70  r = m2_expr.MatchExpr(e, to_match, jok_list)
71  if r is False:
72  return False
73 
74  if r == {}:
75  return False
76 
77  return r
78 
79 def expr_simp_inf_signed(expr_simp, e):
80  "((x - y) ^ ((x ^ y) & ((x - y) ^ x))) [31:32] == x <s y"
81 
82  arg = __check_msb(e)
83  if arg is False:
84  return e
85 
86  # We want jok3 = jok1 - jok2
87  to_match = jok3 ^ ((jok1 ^ jok2) & (jok3 ^ jok1))
88  r = __MatchExprWrap(arg,
89  to_match,
90  [jok1, jok2, jok3])
91 
92  if r is False:
93  return e
94 
95  new_j3 = expr_simp(r[jok3])
96  sub = expr_simp(r[jok1] - r[jok2])
97 
98  if new_j3 == sub:
99  return ExprOp_inf_signed(r[jok1], r[jok2])
100  else:
101  return e
102 
104  "((x - y) ^ ((x ^ y) & ((x - y) ^ x))) ^ x ^ y [31:32] == x <u y"
105 
106  arg = __check_msb(e)
107  if arg is False:
108  return e
109 
110  # We want jok3 = jok1 - jok2
111  to_match = jok3 ^ ((jok1 ^ jok2) & (jok3 ^ jok1)) ^ jok1 ^ jok2
112  r = __MatchExprWrap(arg,
113  to_match,
114  [jok1, jok2, jok3])
115 
116  if r is False:
117  return e
118 
119  new_j3 = expr_simp(r[jok3])
120  sub = expr_simp(r[jok1] - r[jok2])
121 
122  if new_j3 == sub:
123  return ExprOp_inf_unsigned(r[jok1], r[jok2])
124  else:
125  return e
126 
127 def expr_simp_inverse(expr_simp, e):
128  """(x <u y) ^ ((x ^ y) [31:32]) == x <s y,
129  (x <s y) ^ ((x ^ y) [31:32]) == x <u y"""
130 
131  to_match = (ExprOp_inf_unsigned(jok1, jok2) ^ jok_small)
132  r = __MatchExprWrap(e,
133  to_match,
134  [jok1, jok2, jok_small])
135 
136  # Check for 2 symetric cases
137  if r is False:
138  to_match = (ExprOp_inf_signed(jok1, jok2) ^ jok_small)
139  r = __MatchExprWrap(e,
140  to_match,
141  [jok1, jok2, jok_small])
142 
143  if r is False:
144  return e
145  cur_sig = m2_expr.TOK_INF_SIGNED
146  else:
147  cur_sig = m2_expr.TOK_INF_UNSIGNED
148 
149 
150  arg = __check_msb(r[jok_small])
151  if arg is False:
152  return e
153 
154  if not isinstance(arg, m2_expr.ExprOp) or arg.op != "^":
155  return e
156 
157  op_args = arg.args
158  if len(op_args) != 2:
159  return e
160 
161  if r[jok1] not in op_args or r[jok2] not in op_args:
162  return e
163 
164  if cur_sig == m2_expr.TOK_INF_UNSIGNED:
165  return ExprOp_inf_signed(r[jok1], r[jok2])
166  else:
167  return ExprOp_inf_unsigned(r[jok1], r[jok2])
168 
169 def expr_simp_equal(expr_simp, e):
170  """(x - y)?(0:1) == (x == y)"""
171 
172  to_match = m2_expr.ExprCond(jok1 + jok2, m2_expr.ExprInt1(0), m2_expr.ExprInt1(1))
173  r = __MatchExprWrap(e,
174  to_match,
175  [jok1, jok2])
176  if r is False:
177  return e
178 
179  return ExprOp_equal(r[jok1], expr_simp(-r[jok2]))
180 
181 # Compute conditions
182 
183 def exec_inf_unsigned(expr_simp, e):
184  "Compute x <u y"
185  if e.op != m2_expr.TOK_INF_UNSIGNED:
186  return e
187 
188  arg1, arg2 = e.args
189 
190  if isinstance(arg1, m2_expr.ExprInt) and isinstance(arg2, m2_expr.ExprInt):
191  return m2_expr.ExprInt1(1) if (arg1.arg < arg2.arg) else m2_expr.ExprInt1(0)
192  else:
193  return e
194 
195 
196 def __comp_signed(arg1, arg2):
197  """Return ExprInt1(1) if arg1 <s arg2 else ExprInt1(0)
198  @arg1, @arg2: ExprInt"""
199 
200  val1 = arg1.arg
201  if val1 >> (arg1.size - 1) == 1:
202  val1 = - (arg1.mask.arg ^ val1 + 1)
203 
204  val2 = arg2.arg
205  if val2 >> (arg2.size - 1) == 1:
206  val2 = - (arg2.mask.arg ^ val2 + 1)
207 
208  return m2_expr.ExprInt1(1) if (val1 < val2) else m2_expr.ExprInt1(0)
209 
210 def exec_inf_signed(expr_simp, e):
211  "Compute x <s y"
212 
213  if e.op != m2_expr.TOK_INF_SIGNED:
214  return e
215 
216  arg1, arg2 = e.args
217 
218  if isinstance(arg1, m2_expr.ExprInt) and isinstance(arg2, m2_expr.ExprInt):
219  return __comp_signed(arg1, arg2)
220  else:
221  return e
222 
223 def exec_equal(expr_simp, e):
224  "Compute x == y"
225 
226  if e.op != m2_expr.TOK_EQUAL:
227  return e
228 
229  arg1, arg2 = e.args
230  if isinstance(arg1, m2_expr.ExprInt) and isinstance(arg2, m2_expr.ExprInt):
231  return m2_expr.ExprInt1(1) if (arg1.arg == arg2.arg) else m2_expr.ExprInt1(0)
232  else:
233  return e