00001 package edu.ksu.cis.bandera.bofa; 00002 00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00004 * Bandera, a Java(TM) analysis and transformation toolkit * 00005 * Copyright (C) 1998, 1999 * 00006 * John Hatcliff (hatcliff@cis.ksu.edu) 00007 * All rights reserved. * 00008 * * 00009 * This work was done as a project in the SAnToS Laboratory, * 00010 * Department of Computing and Information Sciences, Kansas State * 00011 * University, USA (http://www.cis.ksu.edu/santos). * 00012 * It is understood that any modification not identified as such is * 00013 * not covered by the preceding statement. * 00014 * * 00015 * This work is free software; you can redistribute it and/or * 00016 * modify it under the terms of the GNU Library General Public * 00017 * License as published by the Free Software Foundation; either * 00018 * version 2 of the License, or (at your option) any later version. * 00019 * * 00020 * This work is distributed in the hope that it will be useful, * 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00023 * Library General Public License for more details. * 00024 * * 00025 * You should have received a copy of the GNU Library General Public * 00026 * License along with this toolkit; if not, write to the * 00027 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * 00028 * Boston, MA 02111-1307, USA. * 00029 * * 00030 * Java is a trademark of Sun Microsystems, Inc. * 00031 * * 00032 * To submit a bug report, send a comment, or get the latest news on * 00033 * this project and other SAnToS projects, please visit the web-site * 00034 * http://www.cis.ksu.edu/santos * 00035 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 00036 00037 import ca.mcgill.sable.soot.*; 00038 import ca.mcgill.sable.soot.jimple.*; 00039 import ca.mcgill.sable.util.*; 00040 00041 import org.apache.log4j.Category; 00042 00043 /* 00044 * FGActionInvoke.java 00045 * 00046 * $Id: FGActionInvoke.java,v 1.1.1.1 2002/01/24 03:42:07 pserver Exp $ 00047 */ 00048 00049 /* 00050 * Open questions: 00051 * - what is the appropriate time place for the flowgraph to be 00052 * generated for the body of the method. Currently in the 00053 * driver and FA classes, it seems like the nodes for the body of a method 00054 * are already created before this action is invoked. 00055 * 00056 * - what happens when we have multiple value variants that map to the 00057 * same method variants (e.g., two different value variants of the 00058 * same class but allocated at different positions)? 00059 * 00060 */ 00061 00062 /** 00063 * This class describes the action to be taken when new values arrive at the 00064 * method position of a method invocation AST node. 00065 * 00066 * @author <A HREF="http://www.cis.ksu.edu/~hatcliff">John Hatcliff</A> 00067 * @author 00068 * <a href="http://www.ci.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</a> 00069 * @version $Revision: 1.1.1.1 $ 00070 */ 00071 public class FGActionInvoke implements FGAction 00072 { 00073 /** 00074 * Number of arguments to the method 00075 */ 00076 private int argCount; 00077 00078 /** 00079 * Array of FGNodes corresponding to the argument ASTs 00080 */ 00081 private FGNode[] argNodes; 00082 00083 /** 00084 * FGNode for the invocation AST 00085 */ 00086 private FGNode invokeNode; 00087 00088 /** 00089 * Name of the method 00090 */ 00091 private String methodName; 00092 00093 /** 00094 * Types of the parameters provided to the method 00095 */ 00096 private List parameterTypes; 00097 00098 /** 00099 * Return type of the method 00100 */ 00101 private Type returnType; 00102 00103 /** 00104 * Set of method variants that have been hooked into the flow graph for this 00105 * node. 00106 */ 00107 private Set installedMethodVariants; 00108 00109 /** 00110 * The class from which the method needs to be hooked into the flow graph. 00111 * This is required for constructor calls. 00112 */ 00113 private SootClass sc; 00114 00115 /** 00116 * Provides logging capabilities through log4j. 00117 * 00118 */ 00119 private static Category cat; 00120 00121 static { 00122 cat = Category.getInstance(FGActionInvoke.class.getName()); 00123 } 00124 00125 /** 00126 * Constructor of the class. 00127 * 00128 * @param argCount number of arguments to the invoked method. 00129 * @param argNodes the nodes corresponding to the arguments. 00130 * @param invokeNode the node corresponding to the invocation AST. This 00131 * will also be the node which provides the return value of the method 00132 * during flow analysis. 00133 * @param methodName the name of the invoked method. 00134 * @param parameterTypes the types of the parameter provided to the method. 00135 * @param returnType the type of the return value. 00136 */ 00137 public FGActionInvoke(int argCount, 00138 FGNode[] argNodes, 00139 FGNode invokeNode, 00140 String methodName, 00141 List parameterTypes, 00142 Type returnType) 00143 { 00144 this.argCount = argCount; 00145 this.argNodes = argNodes; 00146 this.invokeNode = invokeNode; 00147 this.methodName = methodName; 00148 this.parameterTypes = parameterTypes; 00149 this.returnType = returnType; 00150 this.installedMethodVariants = new HashSet(); 00151 } 00152 /** 00153 * Constructor of the class to be used when SpecialInvokeExpr is being 00154 * handled. 00155 * 00156 * @param argCount number of arguments to the invoked method. 00157 * @param argNodes the nodes corresponding to the arguments. 00158 * @param invokeNode the node corresponding to the invocation AST.This 00159 * will also be the node which provides the return value of the method during 00160 * flow analysis. This will not have any use as constructors do not return 00161 * values. 00162 * @param methodName the name of the invoked method. 00163 * @param parameterTypes the types of the parameter provided to the method. 00164 * @param returnType the type of the return value. 00165 * @param sootClass the class to which the method body belongs during 00166 * invocation. 00167 */ 00168 public FGActionInvoke(int argCount, 00169 FGNode[] argNodes, 00170 FGNode invokeNode, 00171 String methodName, 00172 List parameterTypes, 00173 Type returnType, 00174 SootClass sootClass) 00175 { 00176 this.sc = sootClass; 00177 this.argCount = argCount; 00178 this.argNodes = argNodes; 00179 this.invokeNode = invokeNode; 00180 this.methodName = methodName; 00181 this.parameterTypes = parameterTypes; 00182 this.returnType = returnType; 00183 this.installedMethodVariants = new HashSet(); 00184 } 00185 /** 00186 * 00187 * 00188 * @param values the set of new values that arrived at the node to 00189 * to which this action is attached. 00190 */ 00191 public void doAction(FASet values) 00192 { 00193 ClassToken classToken; 00194 SootClass sootClass; // class of a particular value variant 00195 00196 /* the declaring method for a particular value variant */ 00197 SootMethod sootMethod; 00198 00199 /* the selected method variant for the * given base class and method 00200 signature. */ 00201 MethodVariant methodVariant; 00202 00203 /* Iterate through the given set of value variants */ 00204 for(Iterator i = values.iterator(); i.hasNext();) { 00205 ValueVariant valueVariant = (ValueVariant) i.next(); 00206 00207 /* valueVariant is a new variant for this site, so... 00208 Scan class hierarchy (starting from class of value 00209 variant) to find the appropriate declaring class for this 00210 method, and call the Method Variant Manager to select 00211 the appropriate variant. 00212 00213 If the method variant is not already installed here, 00214 - hook the code for the method into the flow graph. This 00215 involves connecting the argument nodes to parameter nodes, 00216 connecting the method outflow node ('last' node) to 00217 the node for the AST of the invoke. 00218 - generate work to move ALL values 00219 at the argument Nodes along to parameter nodes 00220 - push current value variant to 'this' parameter. 00221 If the method is already installed (i.e., already hooked 00222 into the flowgraph), then argument nodes and return 00223 points are already connected. We only ... 00224 - push current value variant to 'this' parameter. 00225 */ 00226 00227 /* Scan class hierarchy and find the soot method that 00228 matches the method signature */ 00229 00230 classToken = valueVariant.getClassToken(); 00231 /* In case there is a null in the values ignore it */ 00232 if (classToken.equals(ClassTokenSimple.unknownClassToken) 00233 || classToken.equals(ClassTokenSimple.nullClassToken)) { 00234 System.out 00235 .println("BOFA: Null may flow into the invocation site."); 00236 continue; 00237 } 00238 00239 if (classToken instanceof ClassTokenSimple) { 00240 if (sc == null) { 00241 sootClass = 00242 ((ClassTokenSimple) classToken).getSootClass(); 00243 } // end of if () 00244 else { 00245 sootClass = sc; 00246 } // end of else 00247 sootMethod = MethodVariantManager.findDeclaringMethod 00248 (sootClass, methodName, parameterTypes, returnType); 00249 } else { 00250 throw new RuntimeException 00251 ("BOFA: array object flowing into invoke site"); 00252 } 00253 00254 /* Select the appropriate method variant */ 00255 methodVariant = MethodVariantManager.select(sootMethod); 00256 00257 if (!installedMethodVariants.contains(methodVariant)) { 00258 /* - hook method variant into the flowgraph 00259 * For each arg... 00260 * - make arcs from arg to corresponding parameter node 00261 * - add work: send values that are currently 00262 * at arg to corresponding method parameter 00263 */ 00264 FGNode paramNode; 00265 for (int j=0; j<argCount; j++) { 00266 paramNode = methodVariant.getParameterNode(j); 00267 FGNode.makeArc(argNodes[j], paramNode); 00268 try { 00269 FA.workList.insert(new FGWorkSendVals 00270 (argNodes[j].getValues(), paramNode)); 00271 } 00272 catch (NullPointerException e) { 00273 cat.error(e.getMessage() + "\n Argument Node: " + 00274 argNodes[j]); 00275 System.out.println(argNodes[j] + 00276 "==============="); 00277 } 00278 } 00279 00280 /* make arc from last node of method to AST node. */ 00281 00282 FGNode lastNode = methodVariant.getReturnNode(); 00283 FGNode.makeArc(lastNode, invokeNode); 00284 /* This below should be optimized? 00285 If value set is currently empty, 00286 no work should be created. 00287 */ 00288 FA.workList.insert(new FGWorkSendVals 00289 (lastNode.getValues(), invokeNode)); 00290 00291 /* The value set for 'this' parameter for the method 00292 should include only the objects that are flowing into 00293 this variant. Therefore, we should not make an arc 00294 from the base node to the 'this' parameter (in 00295 analogy with the conventional parameters above). 00296 Instead, we should send only the current value 00297 variant. In essence, we are picking up information 00298 at a split point --- we know that this variant will 00299 only be called on objects that are represented by the 00300 current value variant. TRY TO EXPLAIN THIS BETTER. */ 00301 00302 FA.workList.insert 00303 (new FGWorkSendVals(new FASet(valueVariant), 00304 methodVariant.getThisNode())); 00305 00306 /* Add the method variant to the list of variants 00307 * installed at this node. */ 00308 00309 installedMethodVariants.add(methodVariant); 00310 } else { 00311 /* Push current value variant to 'this' node */ 00312 00313 FA.workList.insert 00314 (new FGWorkSendVals(new FASet(valueVariant), 00315 methodVariant.getThisNode())); 00316 } /* end: if */ 00317 } /* end: for each valueVariant */ 00318 } 00319 }