forked from soot-oss/soot
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathTrapMinimizer.java
More file actions
165 lines (150 loc) · 5.72 KB
/
TrapMinimizer.java
File metadata and controls
165 lines (150 loc) · 5.72 KB
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package soot.dexpler;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 1997 - 2018 Raja Vallée-Rai and others
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-2.1.html>.
* #L%
*/
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import soot.Body;
import soot.Singletons;
import soot.Trap;
import soot.Unit;
import soot.jimple.Jimple;
import soot.options.Options;
import soot.toolkits.exceptions.TrapTransformer;
import soot.toolkits.graph.ExceptionalGraph.ExceptionDest;
import soot.toolkits.graph.ExceptionalUnitGraph;
import soot.toolkits.graph.ExceptionalUnitGraphFactory;
/**
* Transformer that splits traps for Dalvik whenever a statements within the trap cannot reach the trap's handler.
*
* Before: trap from label1 to label2 with handler
*
* label1: stmt1 ----> handler stmt2 stmt3 ----> handler label2:
*
* After: trap from label1 to label2 with handler trap from label3 to label4 with handler
*
* label1: stmt1 ----> handler label2: stmt2 label3: stmt3 ----> handler label4:
*
* @author Alexandre Bartel
*/
public class TrapMinimizer extends TrapTransformer {
public TrapMinimizer(Singletons.Global g) {
}
public static TrapMinimizer v() {
return soot.G.v().soot_dexpler_TrapMinimizer();
}
@Override
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
// If we have less then two traps, there's nothing to do here
if (b.getTraps().size() == 0) {
return;
}
ExceptionalUnitGraph eug = ExceptionalUnitGraphFactory.createExceptionalUnitGraph(b, DalvikThrowAnalysis.v(),
Options.v().omit_excepting_unit_edges());
Set<Unit> unitsWithMonitor = getUnitsWithMonitor(eug);
Map<Trap, List<Trap>> replaceTrapBy = new HashMap<Trap, List<Trap>>(b.getTraps().size());
boolean updateTrap = false;
for (Trap tr : b.getTraps()) {
List<Trap> newTraps = new ArrayList<Trap>(); // will contain the new
// traps
Unit firstTrapStmt = tr.getBeginUnit(); // points to the first unit
// in the trap
boolean goesToHandler = false; // true if there is an edge from the
// unit to the handler of the
// current trap
updateTrap = false;
for (Unit u = tr.getBeginUnit(); u != tr.getEndUnit(); u = b.getUnits().getSuccOf(u)) {
if (goesToHandler) {
goesToHandler = false;
} else {
// if the previous unit has no exceptional edge to the
// handler,
// update firstTrapStmt to point to the current unit
firstTrapStmt = u;
}
// If this is the catch-all block and the current unit has an,
// active monitor, we need to keep the block
if (tr.getException().getName().equals("java.lang.Throwable") && unitsWithMonitor.contains(u)) {
goesToHandler = true;
}
// check if the current unit has an edge to the current trap's
// handler
if (!goesToHandler) {
if (DalvikThrowAnalysis.v().mightThrow(u).catchableAs(tr.getException().getType())) {
// We need to be careful here. The ExceptionalUnitGraph
// will
// always give us an edge from the predecessor of the
// excepting
// unit to the handler. This predecessor, however, does
// not need
// to be inside the new minimized catch block.
for (ExceptionDest<Unit> ed : eug.getExceptionDests(u)) {
if (ed.getTrap() == tr) {
goesToHandler = true;
break;
}
}
}
}
if (!goesToHandler) {
// if the current unit does not have an edge to the current
// trap's handler,
// add a new trap starting at firstTrapStmt ending at the
// unit before the
// current unit 'u'.
updateTrap = true;
if (firstTrapStmt == u) {
// updateTrap to true
continue;
}
Trap t = Jimple.v().newTrap(tr.getException(), firstTrapStmt, u, tr.getHandlerUnit());
newTraps.add(t);
} else {
// if the current unit has an edge to the current trap's
// handler,
// add a trap if the current trap has been updated before
// and if the
// next unit is outside the current trap.
if (b.getUnits().getSuccOf(u) == tr.getEndUnit() && updateTrap) {
Trap t = Jimple.v().newTrap(tr.getException(), firstTrapStmt, tr.getEndUnit(), tr.getHandlerUnit());
newTraps.add(t);
}
}
}
// if updateTrap is true, the current trap has to be replaced by the
// set of newly created traps
// (this set can be empty if the trap covers only instructions that
// cannot throw any exceptions)
if (updateTrap) {
replaceTrapBy.put(tr, newTraps);
}
}
// replace traps where necessary
for (Trap k : replaceTrapBy.keySet()) {
b.getTraps().insertAfter(replaceTrapBy.get(k), k); // we must keep
// the order
b.getTraps().remove(k);
}
}
}