00001 package edu.ksu.cis.bandera.bui.counterexample;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import java.lang.reflect.Method;
00036 import javax.swing.*;
00037 import javax.swing.tree.*;
00038 import ca.mcgill.sable.soot.*;
00039 import ca.mcgill.sable.soot.jimple.*;
00040 import edu.ksu.cis.bandera.jjjc.*;
00041 import edu.ksu.cis.bandera.annotation.*;
00042 import edu.ksu.cis.bandera.birc.*;
00043 import edu.ksu.cis.bandera.jext.*;
00044 import java.util.*;
00045 import edu.ksu.cis.bandera.abstraction.*;
00046 import edu.ksu.cis.bandera.abstraction.typeinference.*;
00047 public class BIRCTraceManager implements TraceManager {
00048 private static Jimple jimple = Jimple.v();
00049 private TypeTable typeTable;
00050 private AnnotationManager am = CompilationManager.getAnnotationManager();
00051 private SootClassManager scm = CompilationManager.getSootClassManager();
00052 private Vector threadAnnotations = new Vector();
00053 private Vector threadTreeModels = new Vector();
00054 private Vector annotationTrace = new Vector();
00055 private Vector stmtIndexTrace = new Vector();
00056 private Hashtable valueNodeValueTable;
00057 private JimpleTrace trace;
00058 private int traceLength;
00059 private Stmt[] stmts;
00060 private JimpleStore currentStore;
00061 private Vector threads;
00062 private int currentStep = 0;
00063
00064
00065
00066 public BIRCTraceManager(JimpleTrace trace, TypeTable typeTable) {
00067 this.trace = trace;
00068 this.am = CompilationManager.getAnnotationManager();
00069 this.scm = CompilationManager.getSootClassManager();
00070 this.typeTable = typeTable;
00071 stmts = trace.getStatements();
00072 for (int i = 0; i < stmts.length; i++) {
00073 try {
00074 Annotation a = am.getContainingAnnotation((Stmt) stmts[i]);
00075 if ("edu.ksu.cis.bandera.annotation.SequentialAnnotation".equals(a.getClass().getName())) continue;
00076 if (annotationTrace.size() > 0) {
00077 if (a != annotationTrace.lastElement()) {
00078 stmtIndexTrace.add(new Integer(i));
00079 annotationTrace.add(a);
00080 System.out.println(a.getClass().getName() + ":" + a);
00081 }
00082 } else {
00083 stmtIndexTrace.add(new Integer(i));
00084 annotationTrace.add(a);
00085 System.out.println(a.getClass().getName() + ":" + a);
00086 }
00087 } catch (Exception e) {
00088 System.out.println("Couldn't find annotation for " + stmts[i]);
00089 }
00090 }
00091 traceLength = annotationTrace.size();
00092 currentStore = trace.getStore(0);
00093 threads = currentStore.getThreads();
00094 threadTreeModels.setSize(threads.size());
00095 threadAnnotations.setSize(threads.size());
00096 reset();
00097 }
00098
00099
00100
00101 public void back() {
00102 int index = ((Integer) stmtIndexTrace.elementAt(--currentStep)).intValue();
00103 Annotation a = (Annotation) annotationTrace.elementAt(currentStep);
00104 currentStore = trace.getStore(index);
00105 currentStore.print();
00106 int tid = 0;
00107 for (Iterator i = threads.iterator(); i.hasNext(); tid++) {
00108 SootMethod sm = (SootMethod) i.next();
00109 if (((JimpleBody) sm.getBody(jimple)).getStmtList().indexOf(stmts[index]) >= 0) {
00110 threadAnnotations.setElementAt(a, tid);
00111 break;
00112 }
00113 }
00114 }
00115
00116
00117
00118 public void cleanup() {}
00119
00120
00121
00122 public void forward() {
00123 if (currentStep == traceLength-1) {
00124 currentStore = trace.getLastStore();
00125 currentStore.print();
00126 currentStep++;
00127 return;
00128 }
00129 int index = ((Integer) stmtIndexTrace.elementAt(++currentStep)).intValue();
00130 currentStore = trace.getStore(index);
00131 currentStore.print();
00132 Annotation a = (Annotation) annotationTrace.elementAt(currentStep);
00133 int tid = 0;
00134 for (Iterator i = threads.iterator(); i.hasNext(); tid++) {
00135 SootMethod sm = (SootMethod) i.next();
00136 if (((JimpleBody) sm.getBody(jimple)).getStmtList().indexOf(stmts[index]) >= 0) {
00137 System.out.println("ThID: " + tid + ", annotation: " + a);
00138 threadAnnotations.setElementAt(a, tid);
00139 break;
00140 }
00141 }
00142 }
00143
00144
00145
00146
00147
00148
00149 private String getAbstractToken(Object type, int value) {
00150 String className = type.getClass().getName();
00151 String methodName = "getToken";
00152 try {
00153 Class cls = Class.forName(className);
00154 Method mtd = cls.getMethod(methodName, new Class[] {int.class});
00155 return (String) mtd.invoke(null, new Object[] {new Integer(value)});
00156 } catch (Exception e) {
00157 return "" + value;
00158 }
00159 }
00160
00161
00162
00163 public edu.ksu.cis.bandera.annotation.Annotation getAnnotation() {
00164 if (currentStep == traceLength) return (Annotation) annotationTrace.elementAt(currentStep - 1);
00165 return (Annotation) annotationTrace.elementAt(currentStep);
00166 }
00167
00168
00169
00170 public edu.ksu.cis.bandera.annotation.Annotation getAnnotation(int threadID) {
00171 return (Annotation) threadAnnotations.elementAt(threadID);
00172 }
00173
00174
00175
00176
00177
00178
00179
00180 private JimpleLiteral getLocalValue(SootMethod topMethod, SootMethod realMethod, Local local) {
00181 System.out.println(topMethod + ";" + realMethod + ";" + local);
00182 if (topMethod == realMethod) return currentStore.getLocalValue(topMethod, local);
00183 Vector v = new Vector();
00184 HashSet inlinedLocal = am.getInlinedLocal(new LocalExpr(realMethod, local));
00185 if (inlinedLocal != null) {
00186 for (Iterator i = inlinedLocal.iterator(); i.hasNext();) {
00187 LocalExpr le = (LocalExpr) i.next();
00188 if (le.getMethod() == topMethod) {
00189 v.add(le.getLocal());
00190 }
00191 }
00192 }
00193 if ((v.size() == 0) || (v.size() > 1)) {
00194 System.out.println("Unable to find value for <" + realMethod + ", " + local + ">, default to null");
00195 return null;
00196 } else {
00197 return currentStore.getLocalValue(topMethod, (Local) v.firstElement());
00198 }
00199 }
00200
00201
00202
00203 public int getNumOfSteps() {
00204 return traceLength;
00205 }
00206
00207
00208
00209 public java.util.Vector getThreadTreeModels() {
00210 return threadTreeModels;
00211 }
00212
00213
00214
00215 public String getValueText(javax.swing.tree.DefaultTreeModel model, javax.swing.tree.DefaultMutableTreeNode node) {
00216 if (!(node.getUserObject() instanceof ValueNode))
00217 return "";
00218 ValueNode vn = (ValueNode) node.getUserObject();
00219 Object literal = valueNodeValueTable.get(vn);
00220 if (literal == null)
00221 return "";
00222 if (literal instanceof ReferenceLiteral) {
00223 if (((ReferenceLiteral) literal).value == null)
00224 return "null";
00225 literal = ((ReferenceLiteral) literal).value;
00226 if (literal instanceof ArrayLiteral) {
00227 ArrayLiteral arrayLiteral = (ArrayLiteral) literal;
00228 if (node.getChildCount() == 0) {
00229 int size = arrayLiteral.length;
00230 for (int i = 0; i < size; i++) {
00231 ValueNode vNode = new ValueNode(arrayLiteral, i);
00232 model.insertNodeInto(new DefaultMutableTreeNode(vNode), node, node.getChildCount());
00233 valueNodeValueTable.put(vNode, arrayLiteral.contents[i]);
00234 }
00235 }
00236 return "#" + arrayLiteral.getId();
00237 } else {
00238 ClassLiteral classLiteral = (ClassLiteral) literal;
00239 if (node.getChildCount() == 0) {
00240 SootClass sc = classLiteral.getSource();
00241 for (ca.mcgill.sable.util.Iterator i = sc.getFields().iterator(); i.hasNext();) {
00242 SootField sf = (SootField) i.next();
00243 ValueNode vNode = new ValueNode(sf);
00244 model.insertNodeInto(new DefaultMutableTreeNode(vNode), node, node.getChildCount());
00245 valueNodeValueTable.put(vNode, classLiteral.getFieldValue(sf));
00246 }
00247 }
00248 String result = "#" + classLiteral.getId() + "\nHolding: ";
00249 LockLiteral lockLiteral = classLiteral.getLockValue();
00250 if (threads.indexOf(lockLiteral.getHoldingThread()) != -1)
00251 result += "Thread ID" + threads.indexOf(lockLiteral.getHoldingThread());
00252 result += "\nWaiting: ";
00253 for (int i = 0; i < lockLiteral.getNumWaiting(); i++) {
00254 if (i == (lockLiteral.getNumWaiting() - 1)) {
00255 result += ("ThreadID:" + threads.indexOf(lockLiteral.getWaitingThread(i)));
00256 } else {
00257 result += ("ThreadID:" + threads.indexOf(lockLiteral.getWaitingThread(i)) + ", ");
00258 }
00259 }
00260 return result;
00261 }
00262 } else if (literal instanceof BooleanLiteral) {
00263 return "" + ((BooleanLiteral) literal).value;
00264 } else if (literal instanceof IntegerLiteral) {
00265 return "" + ((IntegerLiteral) literal).value;
00266 } else {
00267 return literal.toString();
00268 }
00269 }
00270
00271
00272
00273 public javax.swing.tree.TreeModel getVariableTreeModel() {
00274 valueNodeValueTable = new Hashtable();
00275
00276 DefaultMutableTreeNode root = new DefaultMutableTreeNode("Store");
00277
00278 Hashtable compiledClasses = CompilationManager.getCompiledClasses();
00279 for (Enumeration e = compiledClasses.elements(); e.hasMoreElements();) {
00280 SootClass sc = (SootClass) e.nextElement();
00281 for (ca.mcgill.sable.util.Iterator i = sc.getFields().iterator(); i.hasNext();) {
00282 SootField sf = (SootField) i.next();
00283 if (Modifier.isStatic(sf.getModifiers())) {
00284 Object o = currentStore.getStaticFieldValue(sf);
00285 if (o != null) {
00286 ValueNode vn = new ValueNode(sf);
00287 Object t = typeTable.get(sf);
00288 if ((t != null) && (t instanceof IntegralAbstraction) && !(t instanceof ConcreteIntegralAbstraction)) {
00289 o = getAbstractToken(typeTable.get(sf), ((IntegerLiteral) o).value);
00290 }
00291 valueNodeValueTable.put(vn, o);
00292 root.add(new DefaultMutableTreeNode(vn));
00293 }
00294 }
00295 }
00296 }
00297
00298 for (int i = 0; i < threadAnnotations.size(); i++) {
00299 threadTreeModels.setElementAt(null, i);
00300 if (!isAlive(i)) continue;
00301 Annotation a = (Annotation) threadAnnotations.elementAt(i);
00302 if (a == null) continue;
00303 Annotation ta = am.getMethodAnnotationContainingAnnotation(a);
00304 if ((a instanceof MethodDeclarationAnnotation)
00305 || (a instanceof ConstructorDeclarationAnnotation)
00306 || (a instanceof FieldDeclarationAnnotation)
00307 || (a instanceof ClassDeclarationAnnotation))
00308 ta = a;
00309 Hashtable locals = a.getDeclaredLocalVariables();
00310 SootMethod sm;
00311 if (ta instanceof MethodDeclarationAnnotation) {
00312 sm = ((MethodDeclarationAnnotation) ta).getSootMethod();
00313 Hashtable parameters = ((MethodDeclarationAnnotation) ta).getParameterLocals();
00314 for (Enumeration e = parameters.keys(); e.hasMoreElements();) {
00315 Object key = e.nextElement();
00316 locals.put(key, parameters.get(key));
00317 }
00318 } else if (ta instanceof ConstructorDeclarationAnnotation) {
00319 sm = ((ConstructorDeclarationAnnotation) ta).getSootMethod();
00320 Hashtable parameters = ((ConstructorDeclarationAnnotation) ta).getParameterLocals();
00321 for (Enumeration e = parameters.keys(); e.hasMoreElements();) {
00322 Object key = e.nextElement();
00323 locals.put(key, parameters.get(key));
00324 }
00325 } else {
00326 DefaultMutableTreeNode node = new DefaultMutableTreeNode("Thread<no information available>, ID " + i);
00327 root.add(node);
00328 threadTreeModels.setElementAt(new DefaultTreeModel(node), i);
00329 continue;
00330 }
00331 DefaultMutableTreeNode mNode = new DefaultMutableTreeNode(new ValueNode(sm, i));
00332 if (!Modifier.isStatic(sm.getModifiers())) {
00333 Local lcl = ((JimpleBody) sm.getBody(jimple)).getLocal("JJJCTEMP$0");
00334 Object o = getLocalValue((SootMethod) threads.elementAt(i), sm, lcl);
00335 if (o != null) {
00336 ValueNode vn = new ValueNode(lcl);
00337 mNode.add(new DefaultMutableTreeNode(vn));
00338 valueNodeValueTable.put(vn, o);
00339 }
00340 }
00341 for (Enumeration e = locals.elements(); e.hasMoreElements();) {
00342 Local lcl = (Local) e.nextElement();
00343 Object o = getLocalValue((SootMethod) threads.elementAt(i), sm, lcl);
00344 if (o != null) {
00345 Object t = typeTable.get(lcl);
00346 if ((t != null) && (t instanceof IntegralAbstraction) && !(t instanceof ConcreteIntegralAbstraction)) {
00347 o = getAbstractToken(typeTable.get(lcl), ((IntegerLiteral) o).value);
00348 }
00349 ValueNode vn = new ValueNode(lcl);
00350 mNode.add(new DefaultMutableTreeNode(vn));
00351 valueNodeValueTable.put(vn, o);
00352 }
00353 }
00354 root.add(mNode);
00355 threadTreeModels.setElementAt(new DefaultTreeModel(mNode), i);
00356 }
00357
00358 return new DefaultTreeModel(root);
00359 }
00360
00361
00362
00363 public boolean isAlive(int threadID) {
00364 return currentStore.isActive((SootMethod) threads.elementAt(threadID));
00365 }
00366
00367
00368
00369 public void reset() {
00370 currentStep = 0;
00371 currentStore = trace.getStore(0);
00372 currentStore.print();
00373 Annotation a = (Annotation) annotationTrace.elementAt(0);
00374 int tid = 0;
00375 for (Iterator i = threads.iterator(); i.hasNext(); tid++) {
00376 SootMethod sm = (SootMethod) i.next();
00377 if (((JimpleBody) sm.getBody(jimple)).getStmtList().indexOf(stmts[0]) >= 0) {
00378 threadAnnotations.setElementAt(a, tid);
00379 break;
00380 }
00381 }
00382 }
00383 }