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 import org.apache.log4j.Category; 00041 00042 /* 00043 * MethodVariant.java 00044 * $Id: MethodVariant.java,v 1.1.1.1 2002/01/24 03:42:08 pserver Exp $ 00045 */ 00046 00047 /** 00048 * This class represents a variant of a method. 00049 * 00050 * @author <A HREF="http://www.cis.ksu.edu/~hatcliff">John Hatcliff</A> 00051 * @author 00052 * <a href="http://www.cis.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</a> 00053 * @version $Name: $($Revision: 1.1.1.1 $) 00054 */ 00055 public class MethodVariant 00056 { 00057 /** 00058 * The method represented by this object. 00059 */ 00060 private SootMethod sootMethod; 00061 00062 /** 00063 * The index associated with this object. 00064 */ 00065 private Index methodIndex; 00066 00067 /** 00068 *The flow graph nodes corresponding to the parameters of the method. 00069 */ 00070 private FGNodeParameter[] parameterNodes; 00071 00072 /** 00073 * The flow graph nodes correpsonding to the local variables in the 00074 * method. */ 00075 private Map localNodes; 00076 00077 /** 00078 * The flow graph nodes corresponding to the AST nodes occuring in the 00079 * method. */ 00080 private Map ASTNodes; 00081 00082 /** 00083 * The flow graph node corresponding to the return point of the method. 00084 */ 00085 private FGNodeAST returnNode; 00086 00087 /** 00088 * The flow graph node corresponding to the "this" variable of the method. 00089 */ 00090 private FGNodeThis thisNode; 00091 00092 /** 00093 * FGStmt object used to extend the flow graph for this variant. 00094 */ 00095 private FGStmt fgStmt; 00096 00097 /** 00098 * Provides logging capability through log4j. 00099 * 00100 */ 00101 private static Category cat = 00102 Category.getInstance(MethodVariant.class.getName()); 00103 00104 /** 00105 * Constructor of the class. 00106 * 00107 * @param sootMethod the method represented by this variant. 00108 * @param methodIndex the index associated with this variant. 00109 */ 00110 public MethodVariant(SootMethod sootMethod, Index methodIndex) 00111 { 00112 this.sootMethod = sootMethod; 00113 this.methodIndex = methodIndex; 00114 this.returnNode = new FGNodeAST((Object)null); 00115 this.thisNode = new FGNodeThis(this); 00116 this.ASTNodes = new HashMap(); 00117 Local local; 00118 JimpleBody body; 00119 StmtList stmts; 00120 00121 // Create set variables for each parameter. 00122 // Hold in an array indexed by parameter number 00123 int num_parameters = sootMethod.getParameterCount(); 00124 parameterNodes = new FGNodeParameter[num_parameters]; 00125 00126 for (int j=0;j<num_parameters;j++) { 00127 parameterNodes[j] = new FGNodeParameter(j, this); 00128 } 00129 00130 localNodes = new HashMap(); 00131 /* generates graph for each statement */ 00132 fgStmt = new FGStmt(this, ASTNodes); 00133 try { 00134 body = (JimpleBody) sootMethod.getBody(Jimple.v()); 00135 stmts = body.getStmtList(); 00136 } catch (RuntimeException e) { 00137 cat.info("Exception occurred while processing " + sootMethod + ": " 00138 + e.getMessage()); 00139 /* 00140 * External methods will not have body to be compiled and hence an 00141 * exception will be raised. In such a situation we will insert an 00142 * emptyiness and it will act as a sink for all values flowing in. 00143 * Also, if the return type is not void a value of a particular type 00144 * but unknown expression and statement needs to be plugged in. 00145 */ 00146 if (false) { // !sootMethod.getReturnType().equals(VoidType.v())) { 00147 ValueVariant valueVariant = 00148 ValueVariantManager.select(ClassTokenSimple.unknownClassToken, 00149 this, null, null); 00150 FGNode externalNode = new FGNode(); 00151 FGNode.makeArc(externalNode, returnNode); 00152 FGWork work = new FGWorkSendVals(new FASet(valueVariant), 00153 externalNode); 00154 FA.workList.insert(work); 00155 } // end of if (!sootMethod.getReturnType().equals(VoidType.v())) 00156 return; 00157 } 00158 00159 // Create a set of variables for each local held in a hashMap. 00160 for(Iterator i = body.getLocals().iterator(); i.hasNext();) { 00161 local = (Local) i.next(); 00162 // Assume that we only have non-static locals. Can there be 00163 // static locals in Jimple? 00164 localNodes.put(local, new FGNodeLocal(local)); 00165 } 00166 00167 //Venkatesh's original code 00168 /* 00169 for (int i=0; i<stmts.size(); i++) 00170 fgStmt.build((Stmt) stmts.get(i)); 00171 */ 00172 // robbyjo's patch begin 00173 for (int i=0; i<stmts.size(); i++) 00174 { 00175 // System.out.println("Stmt #"+i+": "+stmts.get(i)); 00176 00177 // If one statement dies, don't let it affect others 00178 // to create ripple effect. 00179 // try { 00180 fgStmt.build((Stmt) stmts.get(i)); 00181 /* } catch (Exception e) 00182 { 00183 System.out.println("WAUUUGGH! I'm dead!"); 00184 System.out.println("The statement #"+i+" was: "+stmts.get(i)); 00185 if (e != null) 00186 { 00187 System.out.println("The exception was: "+e.getMessage()); 00188 System.out.println("The stack trace was:"); 00189 e.printStackTrace(); 00190 } 00191 }*/ 00192 } 00193 // robbyjo's patch end 00194 00195 } 00196 /** 00197 * Provides the flow graph node associated with the AST node. 00198 * 00199 * @param obj the AST node corresponding to which the flow graph node is 00200 * required. 00201 * @return the flow graph node associated with the AST node. 00202 */ 00203 FGNodeAST getASTNode(Object obj) 00204 { 00205 return (FGNodeAST) ASTNodes.get(obj); 00206 } 00207 /** 00208 * Provides a collection of flow graph nodes associated with all AST nodes 00209 * in the method. 00210 * 00211 * @return the collection of flow graph nodes associated with all AST nodes 00212 * in the method. 00213 */ 00214 Collection getASTNodes() 00215 { 00216 return ASTNodes.values(); 00217 } 00218 /** 00219 * Assumptions: obj must be a valid reference to Jimple expression 00220 * within the current method. 00221 */ 00222 00223 /** 00224 * Provide the set of FG nodes associated with the given AST node. 00225 * @param obj the AST node corresonding to which the FG nodes are required. 00226 * @return the set of FG nodes assocaited with the given AST node. 00227 */ 00228 public Set getASTValues(Object obj) 00229 { 00230 if (ASTNodes.containsKey(obj)) { 00231 return getASTNode(obj).getValues(); 00232 } else { 00233 /* 00234 * if Node is not found in the ASTNode table and we assume that obj 00235 * is a valid reference, this means that the expression referenced 00236 * by obj has not been included in the flow graph because it doesn't 00237 * give rise to any objects (e.g., it is an expression of base 00238 * type). Thus, we return an empty set. 00239 */ 00240 return new HashSet(); 00241 } 00242 } 00243 /** 00244 * Provides the flow graph node associated with the local variable. 00245 * 00246 * @param local the local variable corresponding to which the flow graph 00247 * node is required. 00248 * @return the flow graph node associated with the local variable. 00249 */ 00250 FGNodeLocal getLocalNode(Local local) 00251 { 00252 return (FGNodeLocal) localNodes.get(local); 00253 } 00254 /** 00255 * Provide a collection of flow graph nodes associated with all local 00256 * variables. 00257 * 00258 * @return the collection of flow graph nodes associated with all local 00259 * variables. 00260 */ 00261 Map getLocalNodes() 00262 { 00263 return localNodes; 00264 } 00265 /** 00266 * Provides the set of values flowing into the provided local variable. 00267 * @param local a <code>Local</code> value 00268 * @return set of values flowing into the given local variable. 00269 */ 00270 public Set getLocalValues(Local local) 00271 { 00272 return getLocalNode(local).getValues(); 00273 } 00274 /* The following methods have public access. They form the interface for 00275 * clients outside of the FA package. These clients should never need to 00276 * know the structure of the flow graph nor the representation for 00277 * flowgraph nodes. Typically, the clients should only be looking up the 00278 * results of the flow analysis, i.e., that should only be fetching the set 00279 * of value variants for a particular construct. 00280 00281 * The methods for an interface for callers within the FA package follows 00282 * the public interface. */ 00283 00284 /** 00285 * Provides the method being represented. 00286 * 00287 * @return the represented method. 00288 */ 00289 public SootMethod getMethod() 00290 { 00291 return sootMethod; 00292 } 00293 /** 00294 * Provides the associated index. 00295 * 00296 * @return the associated index. 00297 */ 00298 public Index getMethodIndex() 00299 { 00300 return methodIndex; 00301 } 00302 /** 00303 * Returns the FGNode for the n'th paramter (0-based indexing) 00304 * 00305 * @param n the parameter number. 00306 * @return the flow graph node describing the nth parameter. 00307 */ 00308 FGNodeParameter getParameterNode(int n) 00309 { 00310 if (n < sootMethod.getParameterCount()) { 00311 return parameterNodes[n]; 00312 } else { 00313 throw new RuntimeException("Parameter count exceeded: " + 00314 sootMethod.getName() + " Param#: " + n); 00315 } 00316 } 00317 /** 00318 * Provide a collection of flow graph nodes associated with all the 00319 * parameters. 00320 * 00321 * @return the array of flow graph nodes associated with all the 00322 * parameters. 00323 */ 00324 FGNodeParameter[] getParameterNodes() 00325 { 00326 return parameterNodes; 00327 } 00328 /** 00329 * Provides the set of values flowing into the nth parameter of the method. 00330 * @param n an <code>int</code> value 00331 * @return set of values flowing into the given parameter. 00332 */ 00333 public Set getParameterValues(int n) 00334 { 00335 return getParameterNode(n).getValues(); 00336 } 00337 /** 00338 * Provides the flow graph node associated with the return value of the 00339 * method. 00340 * 00341 * @return the flow graph node associated with the return value of the 00342 * method. 00343 */ 00344 FGNode getReturnNode() 00345 { 00346 return returnNode; 00347 } 00348 /** 00349 * Provides the set of values flowing returned by the method. 00350 * @return set of values flowing returned by the method. 00351 */ 00352 public Set getReturnValues() 00353 { 00354 return getReturnNode().getValues(); 00355 } 00356 /** 00357 * Provides the flow graph node associated with "this" variable. 00358 * 00359 * @return the flow graph node associated with "this" variable. 00360 */ 00361 FGNodeThis getThisNode() 00362 { 00363 return thisNode; 00364 } 00365 /** 00366 * Provides the set of values flowing into "this" variable. 00367 * @return set of values flowing into "this" variable. 00368 */ 00369 public Set getThisValues() 00370 { 00371 return getThisNode().getValues(); 00372 } 00373 }