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: /*
021: * Modified by the Sable Research Group and others 1997-1999.
022: * See the 'credits' file distributed with Soot for the complete list of
023: * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
024: */
025:
026: /* Added by Feng, to annotate the object references in the bytecode.
027: */
028:
029: package soot.jimple.toolkits.annotation.nullcheck;
030:
031: import soot.options.*;
032:
033: import soot.*;
034: import soot.jimple.*;
035: import soot.util.*;
036: import java.util.*;
037: import soot.tagkit.*;
038: import soot.jimple.toolkits.annotation.tags.*;
039: import soot.toolkits.graph.*;
040: import soot.toolkits.scalar.*;
041:
042: /*
043: ArrayRef
044: GetField
045: PutField
046: InvokeVirtual
047: InvokeSpecial
048: InvokeInterface
049: ArrayLength
050: - AThrow
051: - MonitorEnter
052: - MonitorExit
053: */
054:
055: public class NullPointerChecker extends BodyTransformer {
056: public NullPointerChecker(Singletons.Global g) {
057: }
058:
059: public static NullPointerChecker v() {
060: return G
061: .v()
062: .soot_jimple_toolkits_annotation_nullcheck_NullPointerChecker();
063: }
064:
065: private boolean isProfiling = false;
066:
067: private boolean enableOther = true;
068:
069: protected void internalTransform(Body body, String phaseName,
070: Map options) {
071: isProfiling = PhaseOptions.getBoolean(options, "profiling");
072: enableOther = !PhaseOptions.getBoolean(options, "onlyarrayref");
073:
074: {
075: Date start = new Date();
076:
077: if (Options.v().verbose())
078: G.v().out.println("[npc] Null pointer check for "
079: + body.getMethod().getName() + " started on "
080: + start);
081:
082: BranchedRefVarsAnalysis analysis = new BranchedRefVarsAnalysis(
083: new ExceptionalUnitGraph(body));
084:
085: SootClass counterClass = null;
086: SootMethod increase = null;
087:
088: if (isProfiling) {
089: counterClass = Scene.v().loadClassAndSupport(
090: "MultiCounter");
091: increase = counterClass.getMethod("void increase(int)");
092: }
093:
094: Chain units = body.getUnits();
095:
096: Iterator stmtIt = units.snapshotIterator();
097:
098: while (stmtIt.hasNext()) {
099: Stmt s = (Stmt) stmtIt.next();
100:
101: Value obj = null;
102:
103: if (s.containsArrayRef()) {
104: ArrayRef aref = s.getArrayRef();
105: obj = aref.getBase();
106: } else {
107: if (enableOther) {
108: // Throw
109: if (s instanceof ThrowStmt) {
110: obj = ((ThrowStmt) s).getOp();
111: } else
112: // Monitor enter and exit
113: if (s instanceof MonitorStmt) {
114: obj = ((MonitorStmt) s).getOp();
115: } else {
116: Iterator boxIt;
117: boxIt = s.getDefBoxes().iterator();
118: while (boxIt.hasNext()) {
119: ValueBox vBox = (ValueBox) boxIt.next();
120: Value v = vBox.getValue();
121:
122: // putfield, and getfield
123: if (v instanceof InstanceFieldRef) {
124: obj = ((InstanceFieldRef) v)
125: .getBase();
126: break;
127: } else
128: // invokevirtual, invokespecial, invokeinterface
129: if (v instanceof InstanceInvokeExpr) {
130: obj = ((InstanceInvokeExpr) v)
131: .getBase();
132: break;
133: } else
134: // arraylength
135: if (v instanceof LengthExpr) {
136: obj = ((LengthExpr) v).getOp();
137: break;
138: }
139: }
140: boxIt = s.getUseBoxes().iterator();
141: while (boxIt.hasNext()) {
142: ValueBox vBox = (ValueBox) boxIt.next();
143: Value v = vBox.getValue();
144:
145: // putfield, and getfield
146: if (v instanceof InstanceFieldRef) {
147: obj = ((InstanceFieldRef) v)
148: .getBase();
149: break;
150: } else
151: // invokevirtual, invokespecial, invokeinterface
152: if (v instanceof InstanceInvokeExpr) {
153: obj = ((InstanceInvokeExpr) v)
154: .getBase();
155: break;
156: } else
157: // arraylength
158: if (v instanceof LengthExpr) {
159: obj = ((LengthExpr) v).getOp();
160: break;
161: }
162: }
163: }
164: }
165: }
166:
167: // annotate it or now
168: if (obj != null) {
169: FlowSet beforeSet = (FlowSet) analysis
170: .getFlowBefore(s);
171:
172: int vInfo = analysis.anyRefInfo(obj, beforeSet);
173:
174: boolean needCheck = (vInfo != BranchedRefVarsAnalysis.kNonNull);
175:
176: if (isProfiling) {
177: int whichCounter = 5;
178: if (!needCheck)
179: whichCounter = 6;
180:
181: units.insertBefore(Jimple.v().newInvokeStmt(
182: Jimple.v().newStaticInvokeExpr(
183: increase.makeRef(),
184: IntConstant.v(whichCounter))),
185: s);
186: }
187:
188: {
189: Tag nullTag = new NullCheckTag(needCheck);
190: s.addTag(nullTag);
191: }
192: }
193: }
194:
195: Date finish = new Date();
196: if (Options.v().verbose()) {
197: long runtime = finish.getTime() - start.getTime();
198: long mins = runtime / 60000;
199: long secs = (runtime % 60000) / 1000;
200: G.v().out
201: .println("[npc] Null pointer checker finished. It took "
202: + mins + " mins and " + secs + " secs.");
203: }
204: }
205: }
206: }
|