00001 package edu.ksu.cis.bandera.bofa; 00002 00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00004 * Bandera, a Java(TM) analysis and transformation toolkit * 00005 * Copyright (C) 1998, 1999 Shawn Laubach (laubach@acm.org) * 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.soot.*; 00037 import ca.mcgill.sable.util.*; 00038 import org.apache.log4j.Category; 00039 00040 /* 00041 * ClassTokenSimple.java 00042 * $Id: ClassTokenSimple.java,v 1.1.1.1 2002/01/24 03:42:07 pserver Exp $ 00043 */ 00044 00045 /** 00046 * This class represents the class token for non array types in the flow 00047 * analysis. These are classes in the system being analysed. 00048 * 00049 * @author <A HREF="http://www.cis.ksu.edu/~hatcliff">John Hatcliff</A> 00050 * @author 00051 * <a href="http://www.cis.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</a> 00052 * @version $Name: $($Revision: 1.1.1.1 $) 00053 */ 00054 public class ClassTokenSimple implements ClassToken 00055 { 00056 /** 00057 * Maps <code>SootClass</code> objects to <code>ClassToken</code> objects. 00058 */ 00059 private static Map allocatedTokens = new HashMap(); 00060 00061 /** 00062 * The <code>ClassToken</code> object representing the type of the unknown 00063 * values. Basically the values which are not created in the code being 00064 * analyzed. These are values like command line arguments in main method. 00065 */ 00066 final public static ClassTokenSimple unknownClassToken = 00067 new ClassTokenSimple(new SootClass("unknownClassToken")); 00068 00069 /** 00070 * The <code>ClassToken</code> corresponding to the null object. It is 00071 * reasonable to use the same Class Token for all null values. 00072 */ 00073 final public static ClassTokenSimple nullClassToken = 00074 new ClassTokenSimple(new SootClass("BOFA_NullValue")); 00075 00076 /** 00077 * The <code>ClassToken</code> corresponding to the int objects. It is 00078 * reasonable to use the same Class Token for all int values. 00079 */ 00080 final public static ClassTokenSimple intClassToken = 00081 new ClassTokenSimple(new SootClass("int")); 00082 00083 /** 00084 * Provides logging capability through log4j. 00085 * 00086 */ 00087 private static Category cat; 00088 00089 /** 00090 * Hook in the mappings between SootClass objects and ClassToken objects for 00091 * unknown values and null values. 00092 */ 00093 static { 00094 allocatedTokens.put(unknownClassToken.getSootClass(), 00095 unknownClassToken); 00096 allocatedTokens.put(nullClassToken.getSootClass(), 00097 nullClassToken); 00098 allocatedTokens.put(intClassToken.getSootClass(), 00099 intClassToken); 00100 cat = Category.getInstance("edu.ksu.cis.bandera.bofa.ClassTokenSimple"); 00101 } 00102 00103 /** 00104 * The class associated with this class token. 00105 */ 00106 protected SootClass sootClass; 00107 00108 00109 /** 00110 * Constructor for the class 00111 * 00112 * @param sootClass is the class represented by this ClassTokenSimple object. 00113 */ 00114 private ClassTokenSimple(SootClass sootClass) 00115 { 00116 this.sootClass = sootClass; 00117 } 00118 /** 00119 * Returns the SootClass associated with this class token. 00120 * 00121 * @return the SootClass 00122 */ 00123 public SootClass getSootClass() 00124 { 00125 return this.sootClass; 00126 } 00127 /** 00128 * Initializes the instance and class level data for the given class. Any 00129 * static initialization block then it is enclosed in <clinit> method(in JVM 00130 * bytecodes). If any such method is defined in the class then that method 00131 * is hooked into the flow graph. 00132 * 00133 * @param sootClass is the class for which the information should be set up 00134 * in BOFA before further processing. 00135 */ 00136 static void initClass(SootClass sootClass) { 00137 /* 00138 * According to the JVM Spec: during class initialization, all the super 00139 * class should be initialized first and only then the current class' 00140 * initialization should occur. 00141 * 00142 * This is done in this try-catch block. Also if the class file for a 00143 * class is not found to get the super class it is caught here. We use 00144 * classes denote even primitive types and hence, such a treatment is 00145 * required. 00146 */ 00147 //original Venkatesh's code 00148 /* 00149 try { 00150 ClassTokenSimple.select(sootClass.getSuperClass()); 00151 } catch (NoSuperClassException e) { 00152 cat.info("No super class for " + sootClass); 00153 } catch (RuntimeException e) { 00154 cat.info("No class found for " + sootClass + "\n" + e.getMessage()); 00155 } 00156 */ 00157 00158 // robbyjo's patch on BOFA begins 00159 // try { 00160 if (sootClass.hasSuperClass()) { 00161 ClassTokenSimple.select(sootClass.getSuperClass()); 00162 } // end of if (sootClass.hasSuperClass()) 00163 // } catch (Exception e) { 00164 // Bugs begone! :-) 00165 // } 00166 // robbyjo's patch ends 00167 for (Iterator i = sootClass.getFields().iterator(); i.hasNext();) { 00168 SootField sootField = (SootField) i.next(); 00169 // Assume that we only have to separate class fields into two 00170 // categories: static and instance. 00171 if (Modifier.isStatic(sootField.getModifiers())) 00172 StaticFieldManager.select(sootField); 00173 else 00174 InstanceVariantManager.select(sootField); 00175 } 00176 // Process the class initializing method. 00177 if (sootClass.declaresMethod("<clinit>")) { 00178 MethodVariantManager.select(sootClass.getMethod("<clinit>")); 00179 } // end of if (sootClass.declaresMethod("<clinit>")) 00180 00181 } 00182 /** 00183 * Retrieves the ClassToken object corresponding to the SootClass. If a 00184 * ClassToken is not associated, a new object is created and associated. 00185 * @param sootClass the soot class for which the class token is requested. 00186 * @return the class token corresponding to the soot class. */ 00187 public static ClassTokenSimple select(SootClass sootClass) 00188 { 00189 if (allocatedTokens.containsKey(sootClass)) { 00190 return (ClassTokenSimple) allocatedTokens.get(sootClass); 00191 } else { 00192 ClassTokenSimple classToken 00193 = new ClassTokenSimple((SootClass) sootClass); 00194 allocatedTokens.put(sootClass, classToken); 00195 initClass(sootClass); 00196 return classToken; 00197 } 00198 } 00199 }