Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

IndexMaps.java

00001 package edu.ksu.cis.bandera.pdgslicer;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Bandera, a Java(TM) analysis and transformation toolkit           *
00005  * Copyright (C) 1998, 1999   Hongjun Zheng (zheng@cis.ksu.edu)      *
00006  * All rights reserved.                                              *
00007  *                                                                   *
00008  * This work was done as a project in the SAnToS Laboratory,         *
00009  * Department of Computing and Information Sciences, Kansas State    *
00010  * University, USA (http://www.cis.ksu.edu/santos).                  *
00011  * It is understood that any modification not identified as such is  *
00012  * not covered by the preceding statement.                           *
00013  *                                                                   *
00014  * This work is free software; you can redistribute it and/or        *
00015  * modify it under the terms of the GNU Library General Public       *
00016  * License as published by the Free Software Foundation; either      *
00017  * version 2 of the License, or (at your option) any later version.  *
00018  *                                                                   *
00019  * This work is distributed in the hope that it will be useful,      *
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00022  * Library General Public License for more details.                  *
00023  *                                                                   *
00024  * You should have received a copy of the GNU Library General Public *
00025  * License along with this toolkit; if not, write to the             *
00026  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00027  * Boston, MA  02111-1307, USA.                                      *
00028  *                                                                   *
00029  * Java is a trademark of Sun Microsystems, Inc.                     *
00030  *                                                                   *
00031  * To submit a bug report, send a comment, or get the latest news on *
00032  * this project and other SAnToS projects, please visit the web-site *
00033  *                http://www.cis.ksu.edu/santos                      *
00034  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00035 
00036 import ca.mcgill.sable.util.*;
00037 import ca.mcgill.sable.soot.*;
00038 import ca.mcgill.sable.soot.jimple.*;
00039 import edu.ksu.cis.bandera.pdgslicer.exceptions.*;
00040 import edu.ksu.cis.bandera.annotation.*;
00041 import java.util.BitSet;
00042 import java.util.Vector;
00043 import java.util.Enumeration;
00044 
00045 /**
00046 * This class is for collecting all necessary information for one method.
00047 */
00048 public class IndexMaps {
00049     /** a map from {@link Value Value} to {@link BitSet BitSet}
00050     * representing all assignments for one local.
00051     */
00052     private Map locAssIndex;
00053     private JimpleBody jimpleBody;
00054     private StmtGraph stmtGraph;
00055     private StmtList stmtList;
00056     /**
00057     * StmtList before slicing, since slicing will change the contents of stmtList.
00058     */
00059     private StmtList originalStmtList;
00060     /**
00061     * an array of all locals assigned value by parameters identity statements.
00062     * <br> The index of the array is the index of parameters.
00063     * <br> For example,
00064     * <br> <code> m:=@para0; </code>
00065     * <br> <code> n:=@para1; </code>
00066     * <br> will make <code>paraLocalSet = {m,n}</code>.
00067     */
00068     private Local paraLocalSet[]; //local (Local) set
00069     /** an array of parameter identity statements.
00070     * <br> The index of the array is the index of parameters.
00071     * <br> For example,
00072     * <br> <code> m:=@para0; </code>
00073     * <br> <code> n:=@para1; </code>
00074     * <br> will make <code>paraIdentityStmt = {m:=@para0,n:=@para1}</code>.
00075     */
00076     private Stmt paraIdentityStmt[];
00077     /**
00078     * local variable for <b>this</b> reference.
00079     * <br> For example,
00080     * <br> <code> JJJCTEMP$0:=@this; </code>
00081     * <br> will make <code>thisRefLocal</code> be <code>JJJCTEMP$0</code>.
00082     */
00083     private Local thisRefLocal = null;
00084     /**
00085     * statement index of this reference statement.
00086     */
00087     private Integer thisRefStmtIndex;
00088     private Stmt thisRefStmt;
00089         /**
00090     * a map from {@link CallSite CallSite} to {@link SootMethod SootMethod}
00091     * where SootMethod is called in the CallSite.
00092     */
00093     private Map callSiteMap;
00094     private Fields MOD = new Fields();
00095     private Fields REF = new Fields();
00096     /**
00097     * a list of {@link SpecialInvokeStmt SpecialInvokeStmt}.
00098     */
00099     private List specialInvokeList = new ArrayList();
00100     /**
00101     * a map from {@link Stmt Stmt} to {@link BitSet BitSet}
00102     * representing a set of (control flow transfer) statements from which
00103     * they can <code>goto</code> the key statement of the map.
00104     */
00105     private Map jumpTargetMap = new HashMap();
00106     protected final static int ENTRY = -1;
00107     protected final static int SPECIALEXIT = -2;
00108     protected final static Integer specialExitNode = new Integer(SPECIALEXIT);
00109     public ca.mcgill.sable.soot.SootMethod sootMethod;
00110     protected final static java.lang.Integer EntryNode = new Integer(ENTRY);
00111     private Set returnAnnotations = new ArraySet();
00112 /**
00113 * Analyse one method:
00114 * <br> {@link #buildJumpTargetMap() buildJumpTargetMap()};
00115 * <br> {@link #buildLocalAssIndexMap() buildLocalAssIndexMap()};
00116 * <br> {@link #collectFieldReferences() collectFieldReferences()};
00117 * <br> {@link #collectSpecialInvokes() collectSpecialInvokes()};
00118 * <br> {@link #buildCallSiteMap() buildCallSiteMap()}.
00119 */
00120 public IndexMaps(SootMethod sm) {
00121     sootMethod = sm;
00122     jimpleBody = (JimpleBody) sootMethod.getBody(Jimple.v());
00123     stmtList = jimpleBody.getStmtList();
00124     originalStmtList = new StmtList(jimpleBody);
00125     originalStmtList.addAll(stmtList);
00126     stmtGraph = new CompleteStmtGraph(stmtList);
00127     buildJumpTargetMap();
00128     buildLocalAssIndexMap();
00129     collectFieldReferences();
00130 
00131     //previous four procedure can be combined into one
00132 
00133     //at this moment, we only collect the virtualinvoke call site,
00134     //special invoke callsite and
00135     //not  static invoke callsite
00136     collectSpecialInvokes();
00137     buildCallSiteMap();
00138     //collectSpecialInvokes();
00139     collectReturnAnnotations();
00140 }
00141 /**
00142  * Insert the method's description here.
00143  * Creation date: (00-11-14 14:54:19)
00144  * @return boolean
00145  * @param ann edu.ksu.cis.bandera.annotation.Annotation
00146  */
00147 private boolean annotationContainsReturn(Annotation ann) {
00148     Stmt[] statements = ann.getStatements();
00149     for (int i = 0; i < statements.length; i++) {
00150         if ((statements[i] instanceof ReturnStmt) || (statements[i] instanceof ReturnVoidStmt))
00151             return true;
00152     }
00153     return false;
00154 }
00155 /**
00156    * Build call site map into {@link #callSiteMap callSiteMap}.
00157    */
00158 private void buildCallSiteMap() {
00159     callSiteMap = new HashMap();
00160     InvokeExpr invokeExpr = null;
00161     for (Iterator stmtIt = stmtList.iterator(); stmtIt.hasNext();) {
00162         Stmt stmt = (Stmt) stmtIt.next();
00163         if (SlicingMethod.isBanderaInvoke(stmt))
00164             continue;
00165         if ((stmt instanceof InvokeStmt))
00166             invokeExpr = (InvokeExpr) ((InvokeStmt) stmt).getInvokeExpr();
00167         else
00168 
00169             
00170             //suppose there is only one invokeExpr in one Stmt
00171             invokeExpr = getInvokeExprFrom(stmt);
00172         if (invokeExpr != null) {
00173             SootMethod calledMethod;
00174             if (invokeExpr instanceof InterfaceInvokeExpr)
00175                 calledMethod = getImplementedMd(invokeExpr);
00176             else
00177                 calledMethod = invokeExpr.getMethod();
00178             if (calledMethod == null)
00179                 continue;
00180             int modifier = calledMethod.getModifiers();
00181             if (Modifier.isAbstract(modifier)) {
00182                 calledMethod = getImplementedMd(calledMethod);
00183             }
00184             if (calledMethod == null)
00185                 continue;
00186             String calledMethodSignature = calledMethod.getSignature();
00187             if (InfoAnalysis.nativeMdSig.contains(calledMethod))
00188                 continue;
00189             if (calledMethodSignature.startsWith("java.lang.Thread.start()"))
00190                 calledMethod = getInvokeMethodForStart(invokeExpr, stmt);
00191             else
00192                 if (calledMethodSignature.startsWith("java.") || calledMethodSignature.startsWith("javax."))
00193                     continue;
00194             if (calledMethod == null)
00195                 continue;
00196             CallSite callSite = new CallSite();
00197             callSite.invokeExpr = invokeExpr;
00198             callSite.callerSootMethod = jimpleBody.getMethod();
00199             callSite.callStmt = stmt;
00200             callSiteMap.put(callSite, calledMethod);
00201         }
00202     }
00203 }
00204   /** 
00205    * Build a map from jump target to jump sources into {@link #jumpTargetMap jumpTargetMap}.
00206    */
00207 private void buildJumpTargetMap() {
00208     for (Iterator stmtIt = stmtList.iterator(); stmtIt.hasNext();) {
00209         Stmt stmt = (Stmt) stmtIt.next();
00210         if (stmt instanceof GotoStmt) {
00211             Stmt gotoTarget = (Stmt) ((GotoStmt) stmt).getTarget();
00212             putTargetIntoMap(gotoTarget, stmt);
00213         } else
00214             if (stmt instanceof IfStmt) {
00215                 Stmt ifTarget = ((IfStmt) stmt).getTarget();
00216                 putTargetIntoMap(ifTarget, stmt);
00217             }
00218     }
00219 }
00220   /**
00221    * Build local assignments map into {@link #locAssIndex locAssIndex};
00222    * <br> Fill the array {@link #paraLocalSet paraLocalSet};
00223    * <br> Fill the array {@link #paraIdentityStmt paraIdentityStmt}.
00224    */
00225 private void buildLocalAssIndexMap() {
00226     int paraCount = sootMethod.getParameterCount();
00227     paraLocalSet = new Local[paraCount];
00228     paraIdentityStmt = new Stmt[paraCount];
00229     locAssIndex = new HashMap();
00230     for (Iterator stmtIt = stmtList.iterator(); stmtIt.hasNext();) {
00231         Stmt stmt = (Stmt) stmtIt.next();
00232         List defBoxes = stmt.getDefBoxes();
00233         for (Iterator boxIt = defBoxes.iterator(); boxIt.hasNext();) {
00234             Value defValue = ((ValueBox) boxIt.next()).getValue();
00235             BitSet defSet = new BitSet(stmtList.size());
00236             defSet.set(stmtList.indexOf(stmt));
00237             if (locAssIndex.containsKey(defValue))
00238                 defSet.or((BitSet) locAssIndex.get(defValue));
00239             locAssIndex.put(defValue, defSet);
00240         }
00241         if (stmt instanceof IdentityStmt) {
00242             IdentityStmt defStmt = (IdentityStmt) stmt;
00243             Value rightOp = defStmt.getRightOp();
00244             if (rightOp instanceof ParameterRef) {
00245                 Value left = defStmt.getLeftOp();
00246                 ParameterRef pr = (ParameterRef) rightOp;
00247                 if (left instanceof Local) {
00248                     paraLocalSet[pr.getIndex()] = (Local) left;
00249                     paraIdentityStmt[pr.getIndex()] = stmt;
00250                 } else
00251                     throw new BaseValueNonLocalException("parameter ref should be a local variable in method: IndexMaps.buildLocalAssIndexMap()");
00252             } else
00253                 if (rightOp instanceof ThisRef) {
00254                     Value left = defStmt.getLeftOp();
00255                     if (left instanceof Local) {
00256                         thisRefLocal = (Local) left;
00257                         thisRefStmtIndex = new Integer(stmtList.indexOf(stmt));
00258                         thisRefStmt = defStmt;
00259                     } else
00260                         throw new BaseValueNonLocalException("this ref should be a local variable in method: IndexMaps.buildLocalAssIndexMap()");
00261                 }
00262         }
00263     }
00264 }
00265 //add assignment due to call using call site map
00266 //in MethodCallAnalysis class : assignmentByMdCall()
00267 /**
00268    * Get MOD/REF information on field references for one method.
00269    */
00270 private void collectFieldReferences() {
00271     Set modStaticFields = new ArraySet();
00272     Set modInstanceFields = new ArraySet();
00273     Set modParaFields = new ArraySet();
00274     Set modOtherInsFds = new ArraySet();
00275     Set refStaticFields = new ArraySet();
00276     Set refInstanceFields = new ArraySet();
00277     Set refParaFields = new ArraySet();
00278     Set refOtherInsFds = new ArraySet();
00279     for (Iterator stmtIt = stmtList.iterator(); stmtIt.hasNext();) {
00280         Stmt originalStmt = (Stmt) stmtIt.next();
00281         Stmt newStmt = originalStmt;
00282         List useBoxes = originalStmt.getUseBoxes();
00283         List defBoxes = originalStmt.getDefBoxes();
00284         Set instanceFdsNotInCurrentClass = new ArraySet();
00285         Set staticFields = new ArraySet();
00286         Set instanceFields = new ArraySet();
00287         Set paraFields = new ArraySet();
00288         for (Iterator varBoxIt = useBoxes.iterator(); varBoxIt.hasNext();) {
00289             Value v = ((ValueBox) varBoxIt.next()).getValue();
00290             /*
00291             if (v instanceof ArrayRef) {
00292                 Value basev = ((ArrayRef) v).getBase();
00293                 StmtCls stmtCls = new StmtCls();
00294                 v = LockAnalysis.getValueOfLocal(basev, originalStmt, stmtCls, stmtGraph);
00295                 newStmt = stmtCls.stmt;
00296             }
00297             */
00298             if (v instanceof StaticFieldRef)
00299                 staticFields.add((StaticFieldRef) v);
00300             else
00301                 if (v instanceof InstanceFieldRef) {
00302                     //It's not so simple as just to add this instance field 
00303                     //into the set. We have to determine that
00304                     //if this InstancFieldRef is the field of this class
00305                     InstanceFieldRef insFieldRef = ((InstanceFieldRef) v);
00306                     if (Fields.isThisRef(sootMethod, insFieldRef.getBase(), thisRefStmt))
00307                         instanceFields.add(insFieldRef);
00308 
00309                     //otherwise, to see 
00310                     //if this InstanceFieldRef is the parameter local
00311                     else
00312                         if (isParaField(insFieldRef, newStmt))
00313                             paraFields.add(insFieldRef);
00314                         else
00315                             instanceFdsNotInCurrentClass.add(insFieldRef);
00316                 }
00317         }
00318         if (staticFields.size() != 0) {
00319             DataBox newdbx = new DataBox(originalStmt, staticFields);
00320             refStaticFields.add(newdbx);
00321         }
00322         if (instanceFields.size() != 0) {
00323             DataBox newdbx = new DataBox(originalStmt, instanceFields);
00324             refInstanceFields.add(newdbx);
00325         }
00326         if (paraFields.size() != 0) {
00327             DataBox newdbx = new DataBox(originalStmt, paraFields);
00328             refParaFields.add(newdbx);
00329         }
00330         if (!instanceFdsNotInCurrentClass.isEmpty()) {
00331             DataBox newdbx = new DataBox(originalStmt, instanceFdsNotInCurrentClass);
00332             refOtherInsFds.add(newdbx);
00333         }
00334         staticFields = new ArraySet();
00335         instanceFields = new ArraySet();
00336         paraFields = new ArraySet();
00337         instanceFdsNotInCurrentClass = new ArraySet();
00338         newStmt = originalStmt;
00339         for (Iterator varBoxIt = defBoxes.iterator(); varBoxIt.hasNext();) {
00340             Value v = ((ValueBox) varBoxIt.next()).getValue();
00341             /*
00342             if (v instanceof ArrayRef) {
00343                 Value basev = ((ArrayRef) v).getBase();
00344                 StmtCls stmtCls = new StmtCls();
00345                 v = LockAnalysis.getValueOfLocal(basev, originalStmt, stmtCls, stmtGraph);
00346                 newStmt = stmtCls.stmt;
00347             }
00348             */
00349             if (v instanceof StaticFieldRef)
00350                 staticFields.add((StaticFieldRef) v);
00351             else
00352                 if (v instanceof InstanceFieldRef) {
00353                     InstanceFieldRef insFieldRef = ((InstanceFieldRef) v);
00354                     if (Fields.isThisRef(sootMethod, insFieldRef.getBase(), thisRefStmt))
00355                         instanceFields.add(insFieldRef);
00356                     else
00357                         if (isParaField(insFieldRef, newStmt))
00358                             paraFields.add(insFieldRef);
00359                         else
00360                             instanceFdsNotInCurrentClass.add(insFieldRef);
00361                 }
00362         }
00363         if (staticFields.size() != 0) {
00364             DataBox newdbx = new DataBox(originalStmt, staticFields);
00365             modStaticFields.add(newdbx);
00366         }
00367         if (instanceFields.size() != 0) {
00368             DataBox newdbx = new DataBox(originalStmt, instanceFields);
00369             modInstanceFields.add(newdbx);
00370         }
00371         if (paraFields.size() != 0) {
00372             DataBox newdbx = new DataBox(originalStmt, paraFields);
00373             modParaFields.add(newdbx);
00374         }
00375         if (!instanceFdsNotInCurrentClass.isEmpty()) {
00376             DataBox newdbx = new DataBox(originalStmt, instanceFdsNotInCurrentClass);
00377             modOtherInsFds.add(newdbx);
00378         }
00379     }
00380     MOD.staticFields = modStaticFields;
00381     MOD.instanceFields = modInstanceFields;
00382     MOD.paraFields = modParaFields;
00383     MOD.otherInsFds = modOtherInsFds;
00384     REF.staticFields = refStaticFields;
00385     REF.instanceFields = refInstanceFields;
00386     REF.paraFields = refParaFields;
00387     REF.otherInsFds = refOtherInsFds;
00388 }
00389 /**
00390  * Insert the method's description here.
00391  * Creation date: (00-11-14 12:55:28)
00392  */
00393 private void collectReturnAnnotations() {
00394     SootClass sc= sootMethod.getDeclaringClass();
00395     /*
00396     if (sc.getName().equals("RWPrinter") && sootMethod.getName().equals("read_")){
00397         System.out.println("printer.read");
00398     }
00399     */
00400     Annotation annForSm = Slicer.annManagerForSlicer.getAnnotation(sootMethod.getDeclaringClass(), sootMethod);
00401     Vector currentCFANNs = annForSm.getAllAnnotations(true);
00402     for (Enumeration e = currentCFANNs.elements(); e.hasMoreElements();) {
00403         Annotation cfann = (Annotation) e.nextElement();
00404         if (annotationContainsReturn(cfann))
00405             returnAnnotations.add(cfann);
00406     }
00407 }
00408 /**
00409    * Collect all special invoke statement/expression into {@link #specialInvokeList specialInvokeList}.
00410    */
00411 private void collectSpecialInvokes() {
00412     for (Iterator stmtIt = stmtList.iterator(); stmtIt.hasNext();) {
00413         InvokeExpr invokeExpr = null;
00414         Stmt stmt = (Stmt) stmtIt.next();
00415         if (stmt instanceof InvokeStmt) {
00416             Value invokeValue = ((InvokeStmt) stmt).getInvokeExpr();
00417             invokeExpr = (InvokeExpr) invokeValue;
00418         }
00419         //specialInvokes will only be in the invoke statement, as far as we know,
00420         //specialInovkes will not be any expression in an assignment.
00421         /*else
00422         if (stmt instanceof AssignStmt) {
00423         Value rightOp = ((AssignStmt) stmt).getRightOp();
00424         if (rightOp instanceof InvokeExpr)
00425         invokeExpr = (InvokeExpr) rightOp;
00426         }
00427         */
00428         if (invokeExpr != null)
00429             if (invokeExpr instanceof SpecialInvokeExpr)
00430                 specialInvokeList.add(stmt);
00431     }
00432 }
00433   /**
00434    * Get all exit nodes including <code>throw</code> statements 
00435    * in the control flow graph of the method.
00436    */
00437 public BitSet exitNodes() {
00438     BitSet exitNodeSet = new BitSet(stmtList.size());
00439     List tails = stmtGraph.getTails();
00440     for (Iterator tailIt = tails.iterator(); tailIt.hasNext();) {
00441         Stmt tail = (Stmt) tailIt.next();
00442         exitNodeSet.set(stmtList.indexOf(tail));
00443     }
00444 
00445     //element of tails are those successor is 0
00446     //add return stmt to exitNode, whose successor is not 0
00447     //this is caused from nextnextstmtAddress, 
00448     //the successor of these returns must be an exception catch
00449 
00450     //and some throw statements are also have non 0 successors because
00451     //of the catch "caught"
00452 
00453     for (Iterator stmtIt = stmtList.iterator(); stmtIt.hasNext();) {
00454         Stmt retStmt = (Stmt) stmtIt.next();
00455         if ((retStmt instanceof ReturnStmt) || (retStmt instanceof ReturnVoidStmt) || (retStmt instanceof ThrowStmt)) {
00456             List succs = stmtGraph.getSuccsOf(retStmt);
00457             if (succs.size() != 0)
00458                 
00459                 //maybe should limit to succ.size() == 1, and the succ
00460                 //is an exeception handler
00461                 exitNodeSet.set(stmtList.indexOf(retStmt));
00462         }
00463     }
00464     return exitNodeSet;
00465 }
00466   /**
00467    * Exclude all <code>throw</code> statements in the exit nodes set.
00468    * <p>
00469    * @param exitNodeSet a set of all exit nodes.
00470    * @return a set of exit nodes without <code>throw</code>s.
00471    */
00472 public BitSet exitNodesWithoutThrow(BitSet exitNodeSet) {
00473 
00474     BitSet nodeSet = (BitSet) exitNodeSet.clone();
00475     for (int i = 0; i < exitNodeSet.size(); i++) {
00476         if (! exitNodeSet.get(i))
00477             continue;
00478         Stmt exitStmt = (Stmt) stmtList.get(i);
00479         if (exitStmt instanceof ThrowStmt)
00480             nodeSet.clear(i);
00481     }
00482     return nodeSet;
00483 }
00484   /**
00485    * Get call site map.
00486    * <p>
00487    * @return {@link #callSiteMap callSiteMap}.
00488    */
00489   public Map getCallSiteMap()
00490     {
00491       return callSiteMap;
00492     }
00493   /**
00494    * Get all assignments to a variable.
00495    * <p>
00496    * @param basev query variable.
00497    * @return a set of assignments defining values to <code>basev</code>.
00498    */
00499 private BitSet getDefSetFrom(Value basev)
00500     {
00501       String baseStr = basev.toString();
00502       for (Iterator keyIt = locAssIndex.keySet().iterator(); keyIt.hasNext();)
00503     {
00504       Value keyValue = (Value) keyIt.next();
00505       if (keyValue.toString().equals(baseStr)) return ((BitSet) locAssIndex.get(keyValue));
00506     }
00507       return null;
00508     }
00509 /**
00510  * Get the method that a invoke expression invokes: especially useful
00511  * for methods rewrited in <code>subclass</code> or declared in an 
00512  * <code>interface</code>.
00513  * <p>
00514  * @return the method invoked
00515  * @param invokeExp invoke expression
00516  */
00517 private SootMethod getImplementedMd(InvokeExpr invokeExp) {
00518     SootMethod sm = invokeExp.getMethod();
00519     SootClass interfaceClass = sm.getDeclaringClass();
00520     Set implementingClassSet = (Set) Slicer.interfaceImplementedByMap.get(interfaceClass);
00521     if (implementingClassSet == null || implementingClassSet.isEmpty())
00522         return null;
00523     SootClass implementingClass = getImplementingClassByBOFA(implementingClassSet);
00524     SootMethod impMd = implementingClass.getMethod(sm.getName(), sm.getParameterTypes());
00525     return impMd;
00526 }
00527 /**
00528  * Get the method that implements a given abstract method.
00529  * <p>
00530  * @return the implementing method.
00531  * @param abstractMd abstract method.
00532  */
00533 private SootMethod getImplementedMd(SootMethod abstractMd) {
00534     SootClass interfaceClass = abstractMd.getDeclaringClass();
00535     Set implementingClassSet = (Set) Slicer.interfaceImplementedByMap.get(interfaceClass);
00536     if (implementingClassSet == null || implementingClassSet.isEmpty())
00537         return null;
00538     SootClass implementingClass = getImplementingClassByBOFA(implementingClassSet);
00539     SootMethod impMd = implementingClass.getMethod(abstractMd.getName(), abstractMd.getParameterTypes());
00540     return impMd;
00541 }
00542 /**
00543  * A temporary interface with BOFA.
00544  * <p>
00545  * @return one class that implements the interface at current point.
00546  * @param impClasses a set of classes that implements the same one interface.
00547  */
00548 private SootClass getImplementingClassByBOFA(Set impClasses) {
00549     SootClass returnClass = null;
00550     for (Iterator impIt = impClasses.iterator(); impIt.hasNext();) {
00551         returnClass = (SootClass) impIt.next();
00552         break;
00553     }
00554     return returnClass;
00555 }
00556 /**
00557  * From all used value in one statement, extract one invoke expression, if any.
00558  * <br>Suppose there is at most one invoke expression in one statement.
00559  *<p>
00560  * @return an invoke expression in the statement.
00561  * @param stmt query statement.
00562  */
00563 private InvokeExpr getInvokeExprFrom(Stmt stmt) {
00564     //suppose there is only one invokeExpr in one Stmt
00565     InvokeExpr invokeExpr = null;
00566     for (Iterator useBoxIt = stmt.getUseBoxes().iterator(); useBoxIt.hasNext();) {
00567         Value useValue = ((ValueBox) useBoxIt.next()).getValue();
00568         if (useValue instanceof InvokeExpr)
00569             return ((InvokeExpr) useValue);
00570     }
00571     return invokeExpr;
00572 }
00573 /**
00574    * Get invoke method for <code>start</code>.
00575    * <br>For example, <code>a.start();</code> is actually calling 
00576    * <code>run</code> method in the class of <code>a</code> --- <b>A</b>, 
00577    * where <b>A</b> is subclass of <code>java.lang.Thread</code> or 
00578    * an implementation of <code>java.lang.Runnable</code>.
00579    * <br> Special attention is going to the case such that
00580    * <br> <code> Thread T1; </code>
00581    * <br> <code> T1 = new Thread(new CThread(...), ...); </code>
00582    * <br> <code> ... ... </code>
00583    * <br> <code> T1.start(); </code>
00584    * <br> In this case, <code>T1's</code> is <code>java.lang.Thread</code>. 
00585    * But in <code>T1.start()</code>, we should determine that <code>T1's</code>
00586    * should be <code>CThread</code> which should be a subclass of 
00587    * <code>java.lang.Thread</code>, 
00588    * although <code>T1</code> is declared as type of <code>Thread</code>.
00589    * <br> The method {@link #lookupSootClassByThread(NonStaticInvokeExpr, Stmt) 
00590    * lookupSootClassByThread()} 
00591    * is looking for type of <code>T1</code> in this case.
00592    * <p>
00593    * @param invokeExpr invoke expression calling <code>start</code>.
00594    * @param invokeStmt invoke statement which involves <code>invokeExpr</code>.
00595    * @return corresponding <code>run</code> method in an appropriate class. 
00596    * Null is returned if there is no such method is found.
00597    * @throws SlicerException if the type of base value for an invoke expression is 
00598    * not a reference type.
00599    */
00600 private SootMethod getInvokeMethodForStart(InvokeExpr invokeExpr, Stmt invokeStmt) {
00601     SootMethod returnMd = null;
00602     List paraList = new ArrayList();
00603     if (invokeExpr instanceof StaticInvokeExpr)
00604         throw new SlicerException("the invokeExpr of start should be nonStaticInvokeExpr");
00605     NonStaticInvokeExpr startInvoke = (NonStaticInvokeExpr) invokeExpr;
00606     Type baseType = startInvoke.getBase().getType();
00607     //System.out.println("baseType: " + baseType);
00608     if (baseType instanceof RefType) {
00609         if (baseType.toString().equals("java.lang.Thread")) {
00610             // System.out.println("get sootClass by others");
00611             SootClass sootClass = lookupSootClassByThread(startInvoke, invokeStmt);
00612             while (returnMd == null) {
00613                 if (sootClass != null) {
00614                     try {
00615                         returnMd = sootClass.getMethod("run", paraList);
00616                     } catch (ca.mcgill.sable.soot.NoSuchMethodException nsme) {
00617                         sootClass = sootClass.getSuperClass();
00618                     }
00619                 } else
00620                     return returnMd;
00621             }
00622             //else 
00623             //throw new SlicerException("can not find the target runnable class by the invoke expr: " + invokeExpr + " in sootMethod: " + sootMethod);
00624         } else {
00625             SootClass sootClass = lookupSootClassByName(((RefType) baseType).className);
00626             while (returnMd == null) {
00627                 if (sootClass != null) {
00628                     try {
00629                         returnMd = sootClass.getMethod("run", paraList);
00630                     } catch (ca.mcgill.sable.soot.NoSuchMethodException nsme) {
00631                         sootClass = sootClass.getSuperClass();
00632                     }
00633                 } else
00634                     return returnMd;
00635             }
00636         }
00637     } else
00638         throw new SlicerException("the base type of invokeExpr should be RefType");
00639     return returnMd;
00640 }
00641   /**
00642    * Get jump target map.
00643    * <p>
00644    * @return {@link #jumpTargetMap jumpTargetMap}.
00645    */
00646   public Map getJumpTargetMap()
00647     {
00648       return jumpTargetMap;
00649     }
00650   /** 
00651    * Get MOD information of this method.
00652    * <p>
00653    * @return {@link #MOD MOD}.
00654    */
00655   Fields getMOD()
00656     {
00657       return MOD;
00658     }
00659 /**
00660  * Get original statement list before slicing.
00661  * <p>
00662  * @return {@link #originalStmtList originalStmtList}.
00663  */
00664 StmtList getOriginalStmtList() {
00665     return originalStmtList;
00666 }
00667   /**
00668    * Get the array of parameter identity statements.
00669    * <p>
00670    * @return {@link #paraIdentityStmt paraIdentityStmt}.
00671    */
00672   Stmt [] getParaIdentityStmts()
00673     {
00674       return paraIdentityStmt;
00675     }
00676   /**
00677    * Get the set of parameter locals.
00678    * <p>
00679    * @return {@link #paraLocalSet paraLocalSet}.
00680    */
00681   Local[] getParaLocalSet()
00682     {
00683       return paraLocalSet;
00684     }
00685   /**
00686    * Get REF information of the method.
00687    * <p>
00688    * @return {@link #REF REF}.
00689    */
00690   Fields getREF()
00691     {
00692       return REF;
00693     }
00694 /**
00695  * Insert the method's description here.
00696  * Creation date: (00-11-14 13:06:01)
00697  * @return ca.mcgill.sable.util.Set
00698  */
00699 Set getReturnAnnotations() {
00700     return returnAnnotations;
00701 }
00702   /**
00703    * Get special invoke statement such that of with the same given base value
00704    * and invoke the mehtod <code>java.lang.Thread.init</code>, i.e.,
00705    * the special invoke statement such that 
00706    * <br> <code>specialinvoke base.[java.lang.Thread.init():void]();</code>
00707    * <p>
00708    * @return a special invoke statement. Null is returned if there is no such statement.
00709    */
00710 private InvokeStmt getSpecialInvokeFor(Value base) {
00711     for (Iterator specIt = specialInvokeList.iterator(); specIt.hasNext();) {
00712         InvokeStmt specInvoke = (InvokeStmt) specIt.next();
00713         SpecialInvokeExpr specExpr = (SpecialInvokeExpr) specInvoke.getInvokeExpr();
00714         if (base == specExpr.getBase()) {
00715             String signature = specExpr.getMethod().getSignature();
00716             if (signature.startsWith("java.lang.Thread.<init>"))
00717                 return ((InvokeStmt) (specInvoke));
00718         }
00719     }
00720     return null;
00721 }
00722  /**
00723    * Get special invoke statement for a <code>start</code> invoke in the case such that
00724    * <br> <code> Thread T1; </code>
00725    * <br> <code> T1 = new Thread(new CThread(...), ...); </code>
00726    * <br> <code> ... ... </code>
00727    * <br> <code> T1.start(); </code>
00728    * <br> This method is to get invoke statement for <code>T1</code>, which is 
00729    * <code> T1 = new Thread(new CThread(...), ...); </code>.
00730    * <br> The idea is:
00731    * <br> (1) Get all definitions of <code>T1</code> before the given invoke statement.
00732    * <br> (2) From those definitons of <code>T1</code>, extract one special invoke statement
00733    * which satisfies the constrains given by <code>base</code> and <code>invokeStmt</code>.
00734    * <p>
00735    * @param base the base value of the <code>invokeStmt</code>, e.g., <code>T1</code>.
00736    * @param invokeStmt invoke statement for <code>start()</code>, e.g., 
00737    * <code>T1.start();</code>.
00738    * @return a special invoke statement that assigns value to <code>base</code>, e.g.,
00739    *  <code> T1 = new Thread(new CThread(...), ...); </code>. 
00740    */
00741 private InvokeStmt getSpecialInvokeForThread(Value base, Stmt invokeStmt) {
00742     boolean found = false;
00743     List baseList = new ArrayList();
00744     baseList.add(base);
00745     Set visitedBase = new ArraySet();
00746     InvokeStmt specInvoke = null;
00747     while (!found) {
00748         if (baseList.isEmpty())
00749             found = true;
00750         else {
00751             Value baseV = (Value) baseList.remove(0);
00752             specInvoke = getSpecialInvokeFor(baseV);
00753             if (specInvoke != null)
00754                 found = true;
00755             else {
00756                 visitedBase.add(baseV);
00757                 BitSet defSet = null;
00758                 if (baseV instanceof Local)
00759                     defSet = (BitSet) locAssIndex.get(baseV);
00760                 else
00761                     defSet = getDefSetFrom(baseV);
00762         if (defSet == null)
00763             continue;
00764         Set defStmtSet = SetUtil.bitSetToStmtSet(defSet, stmtList);
00765         for (Iterator defIt = defStmtSet.iterator(); defIt.hasNext();) {
00766             Stmt defStmt = (Stmt) defIt.next();
00767             List reachableStmts = SlicingMethod.reachableStmtFrom(defStmt, stmtGraph);
00768             if (!reachableStmts.contains(invokeStmt))
00769                 continue;
00770             if (!(defStmt instanceof AssignStmt))
00771                 continue;
00772             AssignStmt assDefStmt = (AssignStmt) defStmt;
00773             Value rightOp = assDefStmt.getRightOp();
00774             if (visitedBase.contains(rightOp))
00775                 continue;
00776             if (baseList.contains(rightOp))
00777                 continue;
00778             baseList.add(rightOp);
00779         }
00780     }
00781 }
00782 }
00783 return specInvoke;
00784 }
00785   //callsite map is the map from callsite{className, methodName, callStmt}
00786   //to called method{className, methodName}, in one work it's the map from
00787   //InterClassStmt to InterClassStmt
00788   /**
00789    * Get special invoke statement list.
00790    * <p>
00791    * @return {@link #specialInvokeList specialInvokeList}.
00792    */
00793   List getSpecialInvokeList()
00794     {
00795       return specialInvokeList;
00796     }
00797   /**
00798    * Get statement graph provided by Jimple.
00799    * <p>
00800    * @return {@link #stmtGraph stmtGraph}
00801    */
00802   public StmtGraph getStmtGraph()
00803     {
00804       return stmtGraph;
00805     }
00806 /**
00807  * Get statement list.
00808  * <p>
00809  * @return {@link #stmtList stmtList}.
00810  */
00811 StmtList getStmtList() {
00812     return stmtList;
00813 }
00814   /**
00815    * Get this reference local.
00816    * <p>
00817    * @return {@link #thisRefLocal thisRefLocal}.
00818    */
00819   Local getThisRefLocal()
00820     {
00821       return thisRefLocal;
00822     }
00823 /**
00824    * Get the index of this reference statement.
00825    * <p>
00826    * @return {@link #thisRefStmtIndex thisRefStmtIndex}
00827    */
00828 Stmt getThisRefStmt() {
00829     return thisRefStmt;
00830 }
00831   /**
00832    * Get the index of this reference statement.
00833    * <p>
00834    * @return {@link #thisRefStmtIndex thisRefStmtIndex}
00835    */
00836 Integer getThisRefStmtIndex() {
00837     return thisRefStmtIndex;
00838 }
00839   /**
00840    * Get all statements exception those for exception handling.
00841    * <br> Since we are not dealing with anything about exception handling, 
00842    * in some cases, we need to exclude those statements in exception handling
00843    * block.
00844    * <p>
00845    * @return a set of statement without those of exception handling.
00846    */
00847   BitSet indexSetWithoutExceptionHandling()
00848     {
00849       LinkedList workList = new LinkedList();
00850       BitSet indexSet = new BitSet(stmtList.size());
00851 
00852       workList.addFirst(new Integer(0));
00853 
00854       while (workList.size() != 0)
00855     {
00856       int nodeIndex = ((Integer) workList.removeFirst()).intValue();
00857       indexSet.set(nodeIndex);
00858       Stmt nodeStmt = (Stmt) stmtList.get(nodeIndex);
00859       List nodeStmtSuccs = stmtGraph.getSuccsOf(nodeStmt);
00860       List newSuccs = removeExceptionCaught(nodeStmtSuccs);
00861       for (Iterator succIt = newSuccs.iterator();succIt.hasNext();)
00862         {
00863           Stmt succStmt = (Stmt) succIt.next();
00864           int succIndex = stmtList.indexOf(succStmt);
00865           if (workList.contains(new Integer(succIndex)) || indexSet.get(succIndex))
00866         {
00867         }
00868           else workList.addLast(new Integer(succIndex));
00869         }
00870     }
00871       return indexSet;
00872     }
00873   /** 
00874    * See if an instance field reference is based on parameter. 
00875    * This method will call the other overloaded method
00876    * {@link #isParaField(Local,Stmt) isParaField()}.
00877    * <br>For example, 
00878    * <br><code> void md(A paraA, ...){</code>
00879    * <br><code> ....;</code>
00880    * <br><code> x = paraA.fd+1;</code>
00881    * <br><code> ...;</code>
00882    * <br><code>paraA.fd</code> is a parameter field since the base value
00883    * <code>paraA</code> is from parameter.
00884    * <p>
00885    * @param fieldRef query instance field reference.
00886    * @param stmt statement that use the reference.
00887    * @return <code>true</code> if <code>fieldRef</code> is parameter field; 
00888    * <code>false</code> otherwise.
00889    * @throws BaseValueNonLocalException if the base value is not local variable.
00890    */ 
00891 boolean isParaField(InstanceFieldRef fieldRef, Stmt stmt) {
00892     //SootMethod sootMethod = jimpleBody.getMethod();
00893     Value base = fieldRef.getBase();
00894     Local baseLocal = null;
00895     if (base instanceof Local) {
00896         baseLocal = (Local) base;
00897     } else
00898         throw new BaseValueNonLocalException("the base of field reference should be local in the method isParaField() in IndexMaps.java");
00899     return isParaField(baseLocal, stmt);
00900 }
00901 //using paraLocalSet to see if the type of para local is an class
00902 //to see if the baseName is a local copy of those para locals
00903 
00904 boolean isParaField(Local baseLocal, Stmt stmt) {
00905     Set paraLocalObjects = new ArraySet();
00906     for (int i = 0; i < paraLocalSet.length; i++) {
00907         Local paraLocal = paraLocalSet[i];
00908         Type paraType = paraLocal.getType();
00909         if (paraType instanceof BaseType)
00910             if (paraType instanceof RefType)
00911                 paraLocalObjects.add(paraLocal);
00912     }
00913     SimpleLocalCopies simpleLocalCopies = new SimpleLocalCopies((CompleteStmtGraph) stmtGraph);
00914     for (Iterator j = paraLocalObjects.iterator(); j.hasNext();) {
00915         Local paraObj = (Local) j.next();
00916         if (simpleLocalCopies.isLocalCopyOfBefore(baseLocal, paraObj, stmt)) {
00917             return true;
00918         } else
00919             if (baseLocal.equals(paraObj))
00920                 return true;
00921     }
00922     return false;
00923 }
00924   /**
00925    * Get the map from local to assignments.
00926    * <p>
00927    * @return {@link #locAssIndex locAssIndex}.
00928    */
00929   public Map localAssMap()
00930     {
00931       return locAssIndex;
00932     }
00933   /**
00934    * Look up sootclass by a given class name through 
00935    * {@link Slicer#relevanClassArray Slicer.relevantClassArray}.
00936    * <p>
00937    * @param className query class name.
00938    * @return a sootclass with the name <code>className</code>.
00939    * @throws SlicerException if can not find the sootclass with name 
00940    * <code>className</code>.
00941    */
00942 public static SootClass lookupSootClassByName(String className) {
00943     SootClass classArray[] = Slicer.relevantClassArray;
00944     for (int i = 0; i < classArray.length; i++)
00945         if (classArray[i].getName().equals(className))
00946             return classArray[i];
00947     return null;
00948     //throw new SlicerException("can not find the SootClass in relevant sootClass array by the class name: " + className);
00949 }
00950   /**
00951    * Get the type of a thread for the case such that
00952    * <br> <code> Thread T1; </code>
00953    * <br> <code> T1 = new Thread(new CThread(...), ...); </code>
00954    * <br> <code> ... ... </code>
00955    * <br> <code> T1.start(); </code>
00956    * <br> In this case, <code>T1's</code> is <code>java.lang.Thread</code>. 
00957    * But in <code>T1.start()</code>, we should determine that <code>T1's</code>
00958    * should be <code>CThread</code> which should be a subclass of 
00959    * <code>java.lang.Thread</code>,
00960    * although <code>T1</code> is declared as type of <code>Thread</code>.
00961    * <br> The basic idea of this method is
00962    * <br> (1) Get special invoke statement such that 
00963    * <code> T1 = new Thread(new CThread(...), ...); </code> from <code>T1</code>
00964    * by {@link #getSpecialInvokeForThread(Value,Stmt) getSpecialInvokeForThread()}.
00965    * <br> (2) Analyse the arguments of the special invoke statement to recognize one
00966    * argument of it whose type is a reference type (e.g., CThread) and a subclass of 
00967    * <code>java.lang.Thread</code> or an implementing class of 
00968    * <code>java.lang.Runnable</code>.
00969    * <p>
00970    * @param startInvoke the invoke expression which inovkes <code>start()</code>,
00971    * e.g., <code>T1.start()</code>.
00972    * @param invokeStmt the invoke statement which invokes <code>start()</code>,
00973    * e.g., <code>T1.start()</code>.
00974    * @return a soot class which is the thread type of <code>T1</code>, e.g., 
00975    * <code>CThread</code>. Null is returned is there is no such soot class can be found.
00976    * @throws SlicerExeption if can not find the soot class by allocator.
00977    */
00978 private SootClass lookupSootClassByThread(NonStaticInvokeExpr startInvoke, Stmt invokeStmt) {
00979     Value base = startInvoke.getBase();
00980     //The type of base is java.lang.Thread
00981     InvokeStmt sInvokeStmt = getSpecialInvokeForThread(base, invokeStmt);
00982     if (sInvokeStmt == null)
00983         return null;
00984     SpecialInvokeExpr sInvoke = (SpecialInvokeExpr) sInvokeStmt.getInvokeExpr();
00985 
00986     //definitely cheating !!!!!!!!!
00987     //return lookupSootClassByName("MessageThread");
00988 
00989     //analyse the arguments to figure out which argument is implementing Runnable interface
00990     for (int i = 0; i < sInvoke.getArgCount(); i++) {
00991         Value arg = sInvoke.getArg(i);
00992         Type argType = arg.getType();
00993         if (argType instanceof RefType) {
00994             if (argType.toString().equals("java.lang.Runnable")) {
00995                 //look for allocator of the arg --- BOFA
00996                 SimpleLocalDefs simpleLocalDefs = new SimpleLocalDefs((CompleteStmtGraph) stmtGraph);
00997                 Local argLocal = (Local) arg;
00998                 List defList = simpleLocalDefs.getDefsOfAt(argLocal, sInvokeStmt);
00999                 for (Iterator defIt = defList.iterator(); defIt.hasNext();) {
01000                     DefinitionStmt oneDef = (DefinitionStmt) defIt.next();
01001                     Value rightOp = oneDef.getRightOp();
01002                     if (!(rightOp instanceof NewExpr))
01003                         continue;
01004                     NewExpr newExpr = (NewExpr) rightOp;
01005                     Type opType = newExpr.getType();
01006                     SootClass sootClass = lookupSootClassByName(opType.toString());
01007                     if (sootClass != null) {
01008                         if (sootClass.implementsInterface("java.lang.Runnable"))
01009                             return sootClass;
01010                         else
01011                             if (sootClass.getSuperClass().getName().equals("java.lang.Thread"))
01012                                 return sootClass;
01013                     }
01014                 }
01015                 throw new SlicerException("can not find the SootClass by allocator");
01016             } else {
01017                 SootClass sootClass = lookupSootClassByName(((RefType) argType).className);
01018                 if (sootClass != null) {
01019                     if (sootClass.implementsInterface("java.lang.Runnable"))
01020                         return sootClass;
01021                     else
01022                         if (sootClass.getSuperClass().getName().equals("java.lang.Thread"))
01023                             return sootClass;
01024                 }
01025             }
01026         }
01027     }
01028     return null;
01029 }
01030   /**
01031    * Put given jump target and source into the jump target map 
01032    * {@link #jumpTargetMap jumpTargetMap}.
01033    * <p>
01034    * @param target jump target statement.
01035    * @param source jump source statement.
01036    */
01037 private void putTargetIntoMap(Stmt target, Stmt source) {
01038     BitSet sourceSet;
01039     if (jumpTargetMap.containsKey(target))
01040         sourceSet = (BitSet) jumpTargetMap.get(target);
01041     else
01042         sourceSet = new BitSet(stmtList.size());
01043     sourceSet.set(stmtList.indexOf(source));
01044     jumpTargetMap.put(target, sourceSet);
01045 }
01046   /**
01047    * Remove exception caught statement from a list of statement.
01048    * <p>
01049    * @param actualSuccs a list of {@link Stmt Stmt}.
01050    * @return a list of {@link Stmt Stmt} without any statement 
01051    * for exception handling.
01052    */
01053   private List removeExceptionCaught(List actualSuccs)
01054     {
01055       List newSuccs = new ArrayList();
01056       Iterator asuccsIt = actualSuccs.iterator();
01057       while (asuccsIt.hasNext())
01058     {
01059       Stmt succStmt = (Stmt) asuccsIt.next();
01060       if (!jimpleBody.getTraps().contains(succStmt))
01061         newSuccs.add(succStmt);
01062     }
01063 
01064       return newSuccs;
01065     }
01066 }

Generated at Thu Feb 7 06:46:39 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001