use of soot.toolkits.graph.BriefUnitGraph in project soot by Sable.
the class TryCatchCombiner method internalTransform.
protected void internalTransform(Body b, String phaseName, Map<String, String> options) {
int weight = soot.jbco.Main.getWeight(phaseName, b.getMethod().getSignature());
if (weight == 0)
return;
int trapCount = 0;
PatchingChain<Unit> units = b.getUnits();
ArrayList<Unit> headList = new ArrayList<Unit>();
ArrayList<Trap> trapList = new ArrayList<Trap>();
Iterator<Trap> traps = b.getTraps().iterator();
// build list of heads and corresponding traps
while (traps.hasNext()) {
Trap t = traps.next();
totalcount++;
// skip runtime exceptions
if (!isRewritable(t))
continue;
headList.add(t.getBeginUnit());
trapList.add(t);
trapCount++;
}
if (trapCount == 0)
return;
// check if any traps have same head, if so insert dumby NOP to disambiguate
for (int i = 0; i < headList.size(); i++) {
for (int j = 0; j < headList.size(); j++) {
if (i == j)
continue;
if (headList.get(i) == headList.get(j)) {
Trap t = trapList.get(i);
Unit nop = Baf.v().newNopInst();
units.insertBeforeNoRedirect(nop, headList.get(i));
headList.set(i, nop);
t.setBeginUnit(nop);
}
}
}
Unit first = null;
Iterator<Unit> uit = units.iterator();
while (uit.hasNext()) {
Unit unit = (Unit) uit.next();
if (!(unit instanceof IdentityInst))
break;
first = unit;
}
if (first == null) {
first = Baf.v().newNopInst();
units.insertBefore(first, units.getFirst());
} else {
first = (Unit) units.getSuccOf(first);
}
Collection<Local> locs = b.getLocals();
Map<Unit, Stack<Type>> stackHeightsBefore = null;
Map<Local, Local> bafToJLocals = soot.jbco.Main.methods2Baf2JLocals.get(b.getMethod());
int varCount = trapCount + 1;
traps = b.getTraps().snapshotIterator();
while (traps.hasNext()) {
Trap t = traps.next();
Unit begUnit = t.getBeginUnit();
if (!isRewritable(t) || Rand.getInt(10) > weight)
continue;
stackHeightsBefore = StackTypeHeightCalculator.calculateStackHeights(b, bafToJLocals);
boolean badType = false;
@SuppressWarnings("unchecked") Stack<Type> s = (Stack<Type>) stackHeightsBefore.get(begUnit).clone();
if (s.size() > 0) {
for (int i = 0; i < s.size(); i++) {
if (s.pop() instanceof StmtAddressType) {
badType = true;
break;
}
}
}
if (badType)
continue;
// local to hold control flow flag (0=try, 1=catch)
Local controlLocal = Baf.v().newLocal("controlLocal_tccomb" + trapCount, IntType.v());
locs.add(controlLocal);
// initialize local to 0=try
Unit pushZero = Baf.v().newPushInst(IntConstant.v(0));
Unit storZero = Baf.v().newStoreInst(IntType.v(), controlLocal);
// this is necessary even though it seems like it shouldn't be
units.insertBeforeNoRedirect((Unit) pushZero.clone(), first);
units.insertBeforeNoRedirect((Unit) storZero.clone(), first);
BriefUnitGraph graph = new BriefUnitGraph(b);
List<Unit> l = graph.getPredsOf(begUnit);
// add initializer seq for try - sets local to zero and loads null exc
units.add(pushZero);
units.add(storZero);
Stack<Local> varsToLoad = new Stack<Local>();
s = stackHeightsBefore.get(begUnit);
if (s.size() > 0) {
for (int i = 0; i < s.size(); i++) {
Type type = s.pop();
Local varLocal = Baf.v().newLocal("varLocal_tccomb" + varCount++, type);
locs.add(varLocal);
varsToLoad.push(varLocal);
units.add(Baf.v().newStoreInst(type, varLocal));
units.insertBeforeNoRedirect(FixUndefinedLocals.getPushInitializer(varLocal, type), first);
units.insertBeforeNoRedirect(Baf.v().newStoreInst(type, varLocal), first);
}
}
units.add(Baf.v().newPushInst(NullConstant.v()));
units.add(Baf.v().newGotoInst(begUnit));
// for each pred of the beginUnit of the try, we must insert goto initializer
for (int i = 0; i < l.size(); i++) {
Unit pred = l.get(i);
if (isIf(pred)) {
TargetArgInst ifPred = ((TargetArgInst) pred);
if (ifPred.getTarget() == begUnit) {
ifPred.setTarget(pushZero);
}
Unit succ = units.getSuccOf(ifPred);
if (succ == begUnit) {
units.insertAfter(Baf.v().newGotoInst(pushZero), ifPred);
}
} else if (pred instanceof GotoInst && ((GotoInst) pred).getTarget() == begUnit) {
((GotoInst) pred).setTarget(pushZero);
} else {
units.insertAfter(Baf.v().newGotoInst(pushZero), pred);
}
}
Unit handlerUnit = t.getHandlerUnit();
Unit newBeginUnit = Baf.v().newLoadInst(IntType.v(), controlLocal);
units.insertBefore(newBeginUnit, begUnit);
units.insertBefore(Baf.v().newIfNeInst(handlerUnit), begUnit);
units.insertBefore(Baf.v().newPopInst(RefType.v()), begUnit);
while (varsToLoad.size() > 0) {
Local varLocal = (Local) varsToLoad.pop();
units.insertBefore(Baf.v().newLoadInst(varLocal.getType(), varLocal), begUnit);
}
try {
SootField[] f = FieldRenamer.getRandomOpaques();
if (f[0] != null && f[1] != null) {
loadBooleanValue(units, f[0], begUnit);
loadBooleanValue(units, f[1], begUnit);
units.insertBeforeNoRedirect(Baf.v().newIfCmpEqInst(BooleanType.v(), begUnit), begUnit);
}
} catch (NullPointerException npe) {
}
// randomize the increment - sometimes store one, sometimes just set to 1
if (Rand.getInt() % 2 == 0) {
units.insertBeforeNoRedirect(Baf.v().newPushInst(IntConstant.v(Rand.getInt(3) + 1)), begUnit);
units.insertBeforeNoRedirect(Baf.v().newStoreInst(IntType.v(), controlLocal), begUnit);
} else {
units.insertBeforeNoRedirect(Baf.v().newIncInst(controlLocal, IntConstant.v(Rand.getInt(3) + 1)), begUnit);
}
trapCount--;
t.setBeginUnit(newBeginUnit);
t.setHandlerUnit(newBeginUnit);
changedcount++;
if (debug)
StackTypeHeightCalculator.printStack(units, StackTypeHeightCalculator.calculateStackHeights(b), false);
}
}
Aggregations