-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathxform_inst.py
113 lines (90 loc) · 3.37 KB
/
xform_inst.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# ScratchABlock - Program analysis and decompilation framework
#
# Copyright (c) 2015-2018 Paul Sokolovsky
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Transformation passes on instructions"""
from xform_expr import *
import arch
def normalize_cond(inst):
"Normalize conditions so constants are on the right side."
if inst.op == "if":
inst.args[0].normalize()
def booleanize_cond(inst):
"Make conditions be of bool type (have bool operation)."
if inst.op == "if":
cond = inst.args[0]
if not cond.is_relation():
e = cond.expr
if is_expr(e) and e.op == "!":
new = EXPR("==", e.args[0], VALUE(0, 0))
else:
new = EXPR("!=", e, VALUE(0, 0))
cond.expr = new
def sub_const_to_add(inst):
"Replace subtractions of constant with adds."
inst.dest = expr_xform(inst.dest, expr_sub_const_to_add)
for i, a in enumerate(inst.args):
inst.args[i] = expr_xform(a, expr_sub_const_to_add)
def simplify_inst(inst):
if not (inst.dest and inst.op == "="):
return
assert len(inst.args) == 1
inst.args[0] = simplify_expr(inst.args[0])
def struct_access_inst(inst):
if not (inst.dest and inst.op == "="):
return
assert len(inst.args) == 1
inst.args[0] = struct_access_expr(inst.args[0])
def rewrite_complex_dest(inst):
"Rewrite casts and bitfield() on the left hand side of assignment."
dest = inst.dest
if not (inst.dest and inst.op == "="):
return
if not is_expr(inst.dest):
return
if dest.op == "CAST":
lsb = 0
size = dest.args[0].bitsize()
elif dest.op == "SFUNC" and dest.args[0].name == "bitfield":
assert is_value(dest.args[2]) and is_value(dest.args[3])
lsb = dest.args[2].val
size = dest.args[3].val
else:
assert 0
inst.dest = dest.args[1]
if lsb == 0 and size == arch.BITNESS:
return
all_ones = (1 << arch.BITNESS) - 1
mask = (1 << size) - 1
mask <<= lsb
if lsb == 0:
new_rhs = EXPR("&", inst.args[0], VALUE(mask))
else:
new_rhs = EXPR("&",
EXPR("<<", inst.args[0], VALUE(lsb, 10)),
VALUE(mask))
inst.args[0] = EXPR("|",
EXPR("&", inst.dest, VALUE(all_ones ^ mask)),
new_rhs)
def rewrite_stack_vars(inst, rewrite_to=CVAR):
"Rewrite memory references relative to sp0 to local variables."
def mem2loc(m):
if is_mem(m) and is_expr(m.expr) and set(m.expr.regs()) == {REG("sp_0")}:
name = "loc" + str(m.expr.args[1].val).replace("-", "_") + "_" + str(m.type)
return rewrite_to(name)
if inst.dest:
inst.dest = expr_xform(inst.dest, mem2loc)
for arg_no, arg in enumerate(inst.args):
inst.args[arg_no] = expr_xform(arg, mem2loc)