001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 1997-1999 Raja Vallee-Rai
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the
016: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017: * Boston, MA 02111-1307, USA.
018: */
019:
020: package soot.jbco.jimpleTransformations;
021:
022: import soot.*;
023: import soot.util.*;
024: import soot.jbco.IJbcoTransform;
025: import soot.jbco.util.Rand;
026: import soot.jimple.*;
027: import java.util.*;
028:
029: /**
030: * @author Michael Batchelder
031: *
032: * Created on 15-Feb-2006
033: */
034: public class GotoInstrumenter extends BodyTransformer implements
035: IJbcoTransform {
036:
037: private int trapsAdded = 0;
038: private int gotosInstrumented = 0;
039:
040: public static String dependancies[] = new String[] { "jtp.jbco_gia" };
041:
042: public String[] getDependancies() {
043: return dependancies;
044: }
045:
046: public static String name = "jtp.jbco_gia";
047:
048: public String getName() {
049: return name;
050: }
051:
052: public void outputSummary() {
053: out.println("Gotos Instrumented " + gotosInstrumented);
054: out.println("Traps Added " + trapsAdded);
055: }
056:
057: static boolean verbose = G.v().soot_options_Options().verbose();
058:
059: protected void internalTransform(Body b, String phaseName,
060: Map options) {
061: if (b.getMethod().getName().indexOf("<init>") >= 0)
062: return;
063:
064: int weight = soot.jbco.Main.getWeight(phaseName, b.getMethod()
065: .getSignature());
066: if (weight == 0)
067: return;
068:
069: PatchingChain units = b.getUnits();
070: int size = units.size();
071: Unit first = null;
072: Iterator uit = units.iterator();
073: while (uit.hasNext()) {
074: Object o = uit.next();
075: if (o instanceof IdentityStmt) {
076: first = (Unit) o;
077: size--;
078: } else
079: break;
080: }
081:
082: if (size < 8)
083: return;
084:
085: if (first == null)
086: first = (Unit) units.getFirst();
087:
088: Chain traps = b.getTraps();
089: int i = 0, rand = 0;
090: while (i++ < 10) {
091: rand = Rand.getInt(size);
092: if (rand < 1)
093: rand = 1;
094: else if (rand == size - 1)
095: rand = size - 2;
096:
097: if (isExceptionCaughtAt(units,
098: rand + (units.size() - size), traps.iterator()))
099: continue;
100: break;
101: }
102:
103: // if 10 tries, we give up
104: if (i >= 10)
105: return;
106:
107: i = 0;
108:
109: if (output) {
110: out.println("Applying Gotos to " + b.getMethod().getName());
111: }
112:
113: /*Iterator it = units.iterator();
114: while(it.hasNext()) {
115: Unit x = (Unit)it.next();
116: System.out.println(i+++": "+x.toString() + " : "+isExceptionCaughtAt(units, x,traps.iterator()));
117: }*/
118:
119: // move random-size chunk at beginning to end
120: first = (Unit) units.getSuccOf(first);
121: Unit u = first;
122: do {
123: Object toU[] = u.getBoxesPointingToThis().toArray();
124: for (Object element : toU)
125: u.removeBoxPointingToThis((UnitBox) element);
126:
127: // unit box targets stay with a unit even if the unit is removed.
128: Unit u2 = (Unit) units.getSuccOf(u);
129: units.remove(u);
130: units.add(u);
131:
132: for (Object element : toU)
133: u.addBoxPointingToThis((UnitBox) element);
134:
135: u = u2;
136: } while (++i < rand);
137:
138: Unit oldFirst = first;
139: // add goto as FIRST unit to point to new chunk location
140: if (first instanceof GotoStmt) {
141: oldFirst = ((GotoStmt) first).getTargetBox().getUnit();
142: first = Jimple.v().newGotoStmt(
143: ((GotoStmt) first).getTargetBox().getUnit());
144: } else
145: first = Jimple.v().newGotoStmt(first);
146: units.insertBeforeNoRedirect(first, u);
147:
148: // add goto as LAST unit to point to new position of second chunk
149: if (((Unit) units.getLast()).fallsThrough()) {
150: Stmt gtS = null;
151: if (u instanceof GotoStmt)
152: gtS = Jimple.v().newGotoStmt(
153: ((GotoStmt) u).getTargetBox().getUnit());
154: else
155: gtS = Jimple.v().newGotoStmt(u);
156:
157: units.add(gtS);
158: }
159:
160: RefType throwable = G.v().soot_Scene().getRefType(
161: "java.lang.Throwable");
162: CaughtExceptionRef cexc = Jimple.v().newCaughtExceptionRef();
163: Local excLocal = Jimple.v().newLocal(
164: "jbco_gi_caughtExceptionLocal", throwable);
165: b.getLocals().add(excLocal);
166:
167: Unit handler = Jimple.v().newIdentityStmt(excLocal, cexc);
168: units.add(handler);
169: units.add(Jimple.v().newThrowStmt(excLocal));
170:
171: Unit trapEnd = (Unit) units.getSuccOf(oldFirst);
172: try {
173: while (trapEnd instanceof IdentityStmt)
174: trapEnd = (Unit) units.getSuccOf(trapEnd);
175: trapEnd = (Unit) units.getSuccOf(trapEnd);
176: b.getTraps().add(
177: Jimple.v().newTrap(throwable.getSootClass(),
178: (Unit) units.getPredOf(oldFirst), trapEnd,
179: handler));
180: trapsAdded++;
181: } catch (Exception exc) {
182: }
183: gotosInstrumented++;
184: }
185:
186: private boolean isExceptionCaughtAt(Chain units, int idx,
187: Iterator trapsIt) {
188: Object u = null;
189: Iterator it = units.iterator();
190: while (it.hasNext()) {
191: if (idx-- == 0) {
192: u = it.next();
193: break;
194: }
195: it.next();
196: }
197:
198: //System.out.println("\r\tselected unit is "+u);
199: while (trapsIt.hasNext()) {
200: Trap t = (Trap) trapsIt.next();
201: it = units.iterator(t.getBeginUnit(), units.getPredOf(t
202: .getEndUnit()));
203: while (it.hasNext())
204: if (u.equals(it.next()))
205: return true;
206: if (t.getEndUnit().equals(u))
207: return true;
208: }
209:
210: return false;
211: }
212: }
|