001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 2005 Nomair A. Naeem
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.dava.toolkits.base.renamer;
021:
022: import soot.dava.toolkits.base.AST.analysis.*;
023: import soot.*;
024: import soot.jimple.*;
025: import java.util.*; //import soot.util.*;
026: import soot.dava.*;
027: import soot.grimp.*;
028: import soot.grimp.internal.*;
029: import soot.dava.internal.javaRep.*;
030: import soot.dava.internal.asg.*;
031: import soot.jimple.internal.*;
032: import soot.dava.internal.AST.*;
033:
034: public class infoGatheringAnalysis extends DepthFirstAdapter {
035:
036: public boolean DEBUG = false;
037:
038: public final static int CLASSNAME = 0; //used by renamer
039:
040: public final static int METHODNAME = 1;
041:
042: public final static int GETSET = 2;
043:
044: public final static int IF = 3;
045:
046: public final static int WHILE = 4;
047:
048: public final static int SWITCH = 5;
049:
050: public final static int ARRAYINDEX = 6;
051:
052: public final static int MAINARG = 7; //used by renamer
053:
054: public final static int FIELDASSIGN = 8; //used by renamer
055:
056: public final static int FORLOOPUPDATE = 9; //used by renamer
057:
058: public final static int CAST = 10;
059:
060: public final static int NUMBITS = 11;
061:
062: //dataset to store all information gathered
063: heuristicSet info;
064:
065: //if we are within a subtree rooted at a definitionStmt this boolean is true
066: boolean inDefinitionStmt = false;
067:
068: //whenever there is a definition to a local definedLocal will contain a ref to the local
069: Local definedLocal = null;
070:
071: //if we are within a subtree rooted at a ifNode or IfElseNode this boolean is true
072: boolean inIf = false;
073:
074: //if we are within a subtree rooted at a WhileNode or DoWhileNode this boolean is true
075: boolean inWhile = false;
076:
077: //if we are within a subtree rooted at a ForLoop this boolean is true
078: boolean inFor = false;
079:
080: public infoGatheringAnalysis(DavaBody davaBody) {
081: info = new heuristicSet();
082:
083: List localList = new ArrayList();
084: /*
085: Get locals info out of davaBody
086: Copied with modifications from DavaPrinter method printLocalsInBody
087: */
088: HashSet params = new HashSet();
089: // params.addAll(davaBody.get_ParamMap().values());
090: //params.addAll(davaBody.get_CaughtRefs());
091: HashSet<Object> this Locals = davaBody.get_ThisLocals();
092:
093: //System.out.println("params"+params);
094:
095: Iterator localIt = davaBody.getLocals().iterator();
096:
097: while (localIt.hasNext()) {
098: Local local = (Local) localIt.next();
099:
100: if (params.contains(local) || this Locals.contains(local))
101: continue;
102: localList.add(local);
103: }
104:
105: //localList is a list with all locals
106: //initialize the info Set with empty info for each local
107: Iterator it = localList.iterator();
108: while (it.hasNext()) {
109: Local local = (Local) it.next();
110: info.add(local, NUMBITS);
111: debug("infoGatheringAnalysis", "added " + local.getName()
112: + " to the heuristicset");
113: }
114:
115: /*
116: Check if we are dealing with a main method
117: In which case set the MAINARG heuristic of the param
118: */
119: //System.out.println("METHOD:"+davaBody.getMethod());
120: SootMethod method = davaBody.getMethod();
121: //System.out.println(method.getSubSignature());
122: if (method.getSubSignature().compareTo(
123: "void main(java.lang.String[])") == 0) {
124: //means we are currently working on the main method
125: it = davaBody.get_ParamMap().values().iterator();
126: int num = 0;
127: Local param = null;
128: while (it.hasNext()) {
129: num++;
130: param = (Local) it.next();
131: }
132: if (num > 1) {
133: throw new DecompilationException(
134: "main method has greater than 1 args!!");
135: } else {
136: info.setHeuristic(param, infoGatheringAnalysis.MAINARG);
137: }
138: }
139: }
140:
141: /*
142: This can be either an assignment or an identity statement.
143: We are however only concerned with stmts which assign values to locals
144:
145: The method sets the inDefinitionStmt flag to true and if this is a local assignment
146: The ref to the local is stored in definedLocal
147: */
148: public void inDefinitionStmt(DefinitionStmt s) {
149: inDefinitionStmt = true;
150: //System.out.println(s);
151: Value v = s.getLeftOp();
152: if (v instanceof Local) {
153: //System.out.println("This is a local:"+v);
154: /*
155: * We want definedLocal to be set only if we are interested in naming it
156: * Variables that are created by Dava itself e.g. handler (refer to SuperFirstStmtHandler)
157: * Need not be renamed. So we check whether definedLocal is present in the info set
158: * if it is we set this other wise we dont
159: */
160: if (info.contains((Local) v))
161: definedLocal = (Local) v;
162: else
163: definedLocal = null;
164:
165: } else {
166: //System.out.println("Not a local"+v);
167: }
168: }
169:
170: public void outDefinitionStmt(DefinitionStmt s) {
171: //checking casting here because we want to see if the expr
172: //on the right of def stmt is a cast expr not whether it contains a cast expr
173: if (definedLocal != null && s.getRightOp() instanceof CastExpr) {
174: Type castType = ((CastExpr) s.getRightOp()).getCastType();
175: info.addCastString(definedLocal, castType.toString());
176: }
177: inDefinitionStmt = false;
178: definedLocal = null;
179: }
180:
181: /*
182: Deals with cases in which a local is assigned a value from a static field
183: int local = field
184: int local = class.field
185: */
186: public void inStaticFieldRef(StaticFieldRef sfr) {
187: if (inDefinitionStmt && (definedLocal != null)) {
188: SootField field = sfr.getField();
189: info.setFieldName(definedLocal, field.getName());
190: }
191: }
192:
193: /*
194: Deals with cases in which a local is assigned a value from a field
195: int local = field
196: or int local = obj.field
197: */
198:
199: public void inInstanceFieldRef(InstanceFieldRef ifr) {
200: if (ifr instanceof AbstractInstanceFieldRef) {
201: if (inDefinitionStmt && (definedLocal != null)) {
202: SootField field = ((AbstractInstanceFieldRef) ifr)
203: .getField();
204: //System.out.println(definedLocal+" is being assigned field:"+field.getName());
205: info.setFieldName(definedLocal, field.getName());
206: }
207: }
208: }
209:
210: /*
211: * (non-Javadoc)
212: * @see soot.dava.toolkits.base.AST.analysis.DepthFirstAdapter#outInvokeExpr(soot.jimple.InvokeExpr)
213: * If it is a newInvoke expr we know that the name of the class can come in handy
214: * while renaming because this could be a subtype
215: */
216: public void outInvokeExpr(InvokeExpr ie) {
217: //If this is within a definitionStmt of a local
218: if (inDefinitionStmt && (definedLocal != null)) {
219: //if its a new object being created
220: if (ie instanceof NewInvokeExpr) {
221: //System.out.println("new object being created retrieve the name");
222: RefType ref = ((NewInvokeExpr) ie).getBaseType();
223: String className = ref.getClassName();
224: debug("outInvokeExpr", "defined local is"
225: + definedLocal);
226: info.setObjectClassName(definedLocal, className);
227:
228: } else {
229: SootMethodRef methodRef = ie.getMethodRef();
230: String name = methodRef.name();
231: //System.out.println(name);
232: info.setMethodName(definedLocal, name);
233: }
234: }
235: }
236:
237: /*
238: This is the object for a flag use in a conditional
239: If the value is a local set the appropriate heuristic
240: */
241: public void inASTUnaryCondition(ASTUnaryCondition uc) {
242: Value val = uc.getValue();
243: if (val instanceof Local) {
244: if (inIf)
245: info
246: .setHeuristic((Local) val,
247: infoGatheringAnalysis.IF);
248: if (inWhile)
249: info.setHeuristic((Local) val,
250: infoGatheringAnalysis.WHILE);
251: }
252: }
253:
254: public void inASTBinaryCondition(ASTBinaryCondition bc) {
255: ConditionExpr condition = bc.getConditionExpr();
256:
257: Local local = checkBooleanUse(condition);
258: if (local != null) {
259: if (inIf)
260: info.setHeuristic(local, infoGatheringAnalysis.IF);
261: if (inWhile)
262: info.setHeuristic(local, infoGatheringAnalysis.WHILE);
263: }
264: }
265:
266: /*
267: Setting if to true in inASTIfNode so that later we know whether this is a flag use in an if
268: */
269: public void inASTIfNode(ASTIfNode node) {
270: inIf = true;
271: }
272:
273: /*
274: Going out of if set flag to false
275: */
276: public void outASTIfNode(ASTIfNode node) {
277: inIf = false;
278: }
279:
280: /*
281: Setting if to true in inASTIfElseNode so that later we know whether this is a flag use in an ifElse
282: */
283: public void inASTIfElseNode(ASTIfElseNode node) {
284: inIf = true;
285: }
286:
287: /*
288: Going out of ifElse set flag to false
289: */
290: public void outASTIfElseNode(ASTIfElseNode node) {
291: inIf = false;
292: }
293:
294: /*
295: Setting if to true in inASTWhileNode so that later we know whether this is a flag use in a WhileNode
296: */
297: public void inASTWhileNode(ASTWhileNode node) {
298: inWhile = true;
299: }
300:
301: /*
302: setting flag to false
303: */
304: public void outASTWhileNode(ASTWhileNode node) {
305: inWhile = false;
306: }
307:
308: /*
309: Setting if to true in inASTDoWhileNode so that later we know whether this is a flag use in a WhileNode
310: */
311: public void inASTDoWhileNode(ASTDoWhileNode node) {
312: inWhile = true;
313: }
314:
315: /*
316: setting flag to false
317: */
318: public void outASTDoWhileNode(ASTDoWhileNode node) {
319: inWhile = false;
320: }
321:
322: /*
323: Check the key of the switch statement to see if its a local
324: */
325: public void inASTSwitchNode(ASTSwitchNode node) {
326: Value key = node.get_Key();
327: if (key instanceof Local)
328: info
329: .setHeuristic((Local) key,
330: infoGatheringAnalysis.SWITCH);
331: }
332:
333: public void inArrayRef(ArrayRef ar) {
334: Value index = ar.getIndex();
335: if (index instanceof Local)
336: info.setHeuristic((Local) index,
337: infoGatheringAnalysis.ARRAYINDEX);
338: }
339:
340: public void inASTTryNode(ASTTryNode node) {
341:
342: }
343:
344: /*
345: setting flag to true
346: */
347: public void inASTForLoopNode(ASTForLoopNode node) {
348: inFor = true;
349:
350: Iterator<Object> updateIt = node.getUpdate().iterator();
351: while (updateIt.hasNext()) {
352: AugmentedStmt as = (AugmentedStmt) updateIt.next();
353: Stmt s = as.get_Stmt();
354: if (s instanceof GAssignStmt) {
355: Value leftOp = ((GAssignStmt) s).getLeftOp();
356: if (leftOp instanceof Local) {
357: info.setHeuristic((Local) leftOp,
358: infoGatheringAnalysis.FORLOOPUPDATE);
359: }
360: }
361: }
362: }
363:
364: /*
365: setting flag to false
366: */
367: public void outASTForLoopNode(ASTForLoopNode node) {
368: inFor = false;
369: }
370:
371: /*
372: If there are any locals at this point who do not have any className set
373: it might be a good idea to store that information
374: */
375: public void outASTMethodNode(ASTMethodNode node) {
376: if (DEBUG) {
377: System.out.println("SET START");
378: info.print();
379: System.out.println("SET END");
380: }
381: }
382:
383: /*
384: The method checks whether a particular ConditionExpr
385: is a comparison of a local with a boolean
386: If so the local is returned
387: */
388: private Local checkBooleanUse(ConditionExpr condition) {
389: boolean booleanUse = false;
390:
391: //check whether the condition qualifies as a boolean use
392: if (condition instanceof NeExpr || condition instanceof EqExpr) {
393: Value op1 = condition.getOp1();
394: Value op2 = condition.getOp2();
395: if (op1 instanceof DIntConstant) {
396: Type op1Type = ((DIntConstant) op1).type;
397: if (op1Type instanceof BooleanType)
398: booleanUse = true;
399: } else if (op2 instanceof DIntConstant) {
400: Type op2Type = ((DIntConstant) op2).type;
401: if (op2Type instanceof BooleanType)
402: booleanUse = true;
403: }
404: if (booleanUse) {
405: //at this point we know that one of the values op1 or op2 was a boolean
406: //check whether the other is a local
407: if (op1 instanceof Local)
408: return (Local) op1;
409: else if (op2 instanceof Local)
410: return (Local) op2;
411: } else
412: return null;//meaning no local used as boolean found
413: }
414: return null; //meaning no local used as boolean found
415: }
416:
417: public heuristicSet getHeuristicSet() {
418: return info;
419: }
420:
421: public void debug(String methodName, String debug) {
422:
423: if (DEBUG)
424: System.out.println(methodName + " DEBUG: " + debug);
425: }
426:
427: }
|