-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathscript_decompile.py
116 lines (87 loc) · 2.8 KB
/
script_decompile.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
114
115
116
from dom import *
from dataflow import *
from xform import *
from decomp import *
from xform_utils import apply_iterative
def do_propagate(cfg):
analyze_reach_defs(cfg)
make_du_chains(cfg)
# Choose one, expr_propagation is required for true decompilation
#const_propagation(cfg)
#copy_propagation(cfg)
#mem_propagation(cfg)
expr_propagation(cfg)
def dce(cfg):
analyze_live_vars(cfg)
foreach_bblock(cfg, dead_code_elimination)
def structure(cfg):
def _(res):
return 1 if res else 0
cnt = 1
while cnt:
cnt = 0
cnt += _(match_if(cfg))
# Opportunity for applying match_if_else_unjumped arises after
# match_if pass, and we should match all such cases, or they
# will be consumed by match_seq instead.
cnt += apply_iterative(match_if_else_unjumped, (cfg,))
cnt += _(match_ifelse(cfg))
cnt += _(match_if_else_inv_ladder(cfg))
cnt += _(match_if_else_ladder(cfg))
cnt += _(match_while(cfg))
cnt += _(match_dowhile(cfg))
cnt += _(match_if_dowhile(cfg))
cnt += _(match_seq(cfg))
# Apply arch-specific transformations
def arch_specific(cfg):
# Remove Xtensa memw instructions. TODO: should instead be used to
# recover volatile types.
foreach_bblock(cfg, remove_sfunc, name="memw")
def apply(cfg):
#
# Data flow
#
# Various algos below don't work with no explicit entry in CFG
cfg_preheader(cfg)
# Also don't work with >1 entries
remove_unreachable_entries(cfg)
# Various algos below require single-exit CFG
cfg_single_exit(cfg)
foreach_inst(cfg, sub_const_to_add)
foreach_inst(cfg, rewrite_complex_dest)
foreach_inst(cfg, booleanize_cond)
# Initial pass on simplifying expressions
foreach_inst(cfg, simplify_inst)
analyze_live_vars(cfg)
insert_initial_regs(cfg)
do_propagate(cfg)
# Estimate args only at the beginning of processing
analyze_live_vars(cfg)
estimate_params(cfg)
dce(cfg)
# This should be run after propagation, so it caught all cases.
# Run this after DCE to not do useless work ;-).
foreach_inst(cfg, normalize_cond)
#
# Control flow
#
remove_trailing_jumps(cfg)
remove_jump_over_jump(cfg)
arch_specific(cfg)
cfg.number_postorder()
compute_idom(cfg)
structure(cfg)
# match_abnormal_sel() requires updated DFS numbers
cfg.number_postorder()
# We can't know which node to split before we start control flow processing,
# but splitting node changes data flow, so need to recompute it
if match_abnormal_sel(cfg):
do_propagate(cfg)
dce(cfg)
cfg.number_postorder()
compute_idom(cfg)
structure(cfg)
#
# Post-processing
#
foreach_inst(cfg, rewrite_stack_vars)