00001 package edu.ksu.cis.bandera.specification.predicate;
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 ca.mcgill.sable.soot.*;
00036 import edu.ksu.cis.bandera.jjjc.*;
00037 import edu.ksu.cis.bandera.annotation.*;
00038 import java.util.*;
00039 import ca.mcgill.sable.soot.grimp.*;
00040 import ca.mcgill.sable.soot.jimple.*;
00041 import edu.ksu.cis.bandera.jext.*;
00042 public class PredicateUpdate extends AbstractBanderaValueSwitch {
00043 private static PredicateUpdate pu = new PredicateUpdate();
00044 private static Grimp grimp = Grimp.v();
00045 private static Jimple jimple = Jimple.v();
00046 private static Stmt currentStmt;
00047 private Value currentValue;
00048
00049
00050
00051 public void caseAddExpr(AddExpr v) {
00052 v.getOp1().apply(this);
00053 Value v1 = currentValue;
00054 v.getOp2().apply(this);
00055 Value v2 = currentValue;
00056 currentValue = grimp.newAddExpr(v1, v2);
00057 }
00058
00059
00060
00061 public void caseAndExpr(AndExpr v) {
00062 v.getOp1().apply(this);
00063 Value v1 = currentValue;
00064 v.getOp2().apply(this);
00065 Value v2 = currentValue;
00066 currentValue = grimp.newAndExpr(v1, v2);
00067 }
00068
00069
00070
00071 public void caseArrayRef(ArrayRef v) {
00072 v.getBase().apply(this);
00073 Value base = currentValue;
00074 v.getIndex().apply(this);
00075 Value index = currentValue;
00076 currentValue = grimp.newArrayRef(base, index);
00077 }
00078
00079
00080
00081 public void caseCastExpr(CastExpr v) {
00082 v.getOp().apply(this);
00083 currentValue = grimp.newCastExpr(currentValue, v.getType());
00084 }
00085
00086
00087
00088 public void caseCaughtExceptionRef(CaughtExceptionRef v) {
00089 defaultCase(v);
00090 }
00091
00092
00093
00094 public void caseChooseExpr(ChooseExpr v) {
00095 Vector values = new Vector();
00096 for (ca.mcgill.sable.util.Iterator i = v.getChoices().iterator(); i.hasNext();) {
00097 ((Value) i.next()).apply(this);
00098 values.add(currentValue);
00099 }
00100 currentValue = new ChooseExpr(values);
00101 }
00102
00103
00104
00105 public void caseCmpExpr(CmpExpr v) {
00106 v.getOp1().apply(this);
00107 Value v1 = currentValue;
00108 v.getOp2().apply(this);
00109 Value v2 = currentValue;
00110 currentValue = grimp.newCmpExpr(v1, v2);
00111 }
00112
00113
00114
00115 public void caseCmpgExpr(CmpgExpr v) {
00116 v.getOp1().apply(this);
00117 Value v1 = currentValue;
00118 v.getOp2().apply(this);
00119 Value v2 = currentValue;
00120 currentValue = grimp.newCmpgExpr(v1, v2);
00121 }
00122
00123
00124
00125 public void caseCmplExpr(CmplExpr v) {
00126 v.getOp1().apply(this);
00127 Value v1 = currentValue;
00128 v.getOp2().apply(this);
00129 Value v2 = currentValue;
00130 currentValue = grimp.newCmplExpr(v1, v2);
00131 }
00132
00133
00134
00135 public void caseComplementExpr(ComplementExpr expr) {
00136 expr.getOp().apply(this);
00137 currentValue = new ComplementExpr(currentValue);
00138 }
00139
00140
00141
00142 public void caseDivExpr(DivExpr v) {
00143 v.getOp1().apply(this);
00144 Value v1 = currentValue;
00145 v.getOp2().apply(this);
00146 Value v2 = currentValue;
00147 currentValue = grimp.newDivExpr(v1, v2);
00148 }
00149
00150
00151
00152 public void caseDoubleConstant(DoubleConstant v) {
00153 currentValue = DoubleConstant.v(v.value);
00154 }
00155
00156
00157
00158 public void caseEqExpr(EqExpr v) {
00159 v.getOp1().apply(this);
00160 Value v1 = currentValue;
00161 v.getOp2().apply(this);
00162 Value v2 = currentValue;
00163 currentValue = grimp.newEqExpr(v1, v2);
00164 }
00165
00166
00167
00168 public void caseFloatConstant(FloatConstant v) {
00169 currentValue = FloatConstant.v(v.value);
00170 }
00171
00172
00173
00174 public void caseGeExpr(GeExpr v) {
00175 v.getOp1().apply(this);
00176 Value v1 = currentValue;
00177 v.getOp2().apply(this);
00178 Value v2 = currentValue;
00179 currentValue = grimp.newGeExpr(v1, v2);
00180 }
00181
00182
00183
00184 public void caseGtExpr(GtExpr v) {
00185 v.getOp1().apply(this);
00186 Value v1 = currentValue;
00187 v.getOp2().apply(this);
00188 Value v2 = currentValue;
00189 currentValue = grimp.newGtExpr(v1, v2);
00190 }
00191
00192
00193
00194 public void caseInExpr(InExpr v) {
00195 v.getOp1().apply(this);
00196 Value v1 = currentValue;
00197
00198 Vector values = new Vector();
00199 for (ca.mcgill.sable.util.Iterator i = v.getSet().iterator(); i.hasNext();) {
00200 ((Value) i.next()).apply(this);
00201 values.add(currentValue);
00202 }
00203 currentValue = new InExpr(v1, values);
00204 }
00205
00206
00207
00208 public void caseInstanceFieldRef(InstanceFieldRef v) {
00209 v.getBase().apply(this);
00210 currentValue = grimp.newInstanceFieldRef(currentValue, v.getField());
00211 }
00212
00213
00214
00215 public void caseInstanceOfExpr(InstanceOfExpr v) {
00216 v.getOp().apply(this);
00217 currentValue = grimp.newInstanceOfExpr(currentValue, v.getType());
00218 }
00219
00220
00221
00222 public void caseIntConstant(IntConstant v) {
00223 currentValue = IntConstant.v(v.value);
00224 }
00225
00226
00227
00228 public void caseInterfaceInvokeExpr(InterfaceInvokeExpr v) {
00229 defaultCase(v);
00230 }
00231
00232
00233
00234 public void caseLeExpr(LeExpr v) {
00235 v.getOp1().apply(this);
00236 Value v1 = currentValue;
00237 v.getOp2().apply(this);
00238 Value v2 = currentValue;
00239 currentValue = grimp.newLeExpr(v1, v2);
00240 }
00241
00242
00243
00244 public void caseLengthExpr(LengthExpr v) {
00245 v.getOp().apply(this);
00246 currentValue = grimp.newLengthExpr(currentValue);
00247 }
00248
00249
00250
00251 public void caseLocal(Local l) {
00252 defaultCase(l);
00253 }
00254
00255
00256
00257 public void caseLocalExpr(LocalExpr v) {
00258 AnnotationManager am = CompilationManager.getAnnotationManager();
00259 HashSet locals = am.getInlinedLocal(v);
00260 Hashtable stmtLocalTable = am.getStmtLocalTable();
00261 HashSet stmtLocals = (HashSet) stmtLocalTable.get(currentStmt);
00262
00263 for (Iterator i = locals.iterator(); i.hasNext();) {
00264 LocalExpr newV = (LocalExpr) i.next();
00265 if (stmtLocals.contains(newV)) {
00266 Hashtable localPackTable = am.getLocalPackingTable();
00267 if (localPackTable.get(newV) != null) {
00268 currentValue = (Value) localPackTable.get(newV);
00269 } else {
00270 currentValue = newV;
00271 }
00272 return;
00273 }
00274 }
00275
00276 System.out.println("*** WARNING: Can't find mapping to " + v + " ***");
00277 }
00278
00279
00280
00281 public void caseLocationTestExpr(LocationTestExpr e) {
00282 defaultCase(e);
00283
00284 }
00285
00286
00287
00288 public void caseLogicalAndExpr(LogicalAndExpr expr) {
00289 expr.getOp1().apply(this);
00290 Value v1 = currentValue;
00291 expr.getOp2().apply(this);
00292 Value v2 = currentValue;
00293 currentValue = new LogicalAndExpr(v1, v2);
00294 }
00295
00296
00297
00298 public void caseLogicalOrExpr(LogicalOrExpr expr) {
00299 expr.getOp1().apply(this);
00300 Value v1 = currentValue;
00301 expr.getOp2().apply(this);
00302 Value v2 = currentValue;
00303 currentValue = new LogicalOrExpr(v1, v2);
00304 }
00305
00306
00307
00308 public void caseLongConstant(LongConstant v) {
00309 currentValue = LongConstant.v(v.value);
00310 }
00311
00312
00313
00314 public void caseLtExpr(LtExpr v) {
00315 v.getOp1().apply(this);
00316 Value v1 = currentValue;
00317 v.getOp2().apply(this);
00318 Value v2 = currentValue;
00319 currentValue = grimp.newLtExpr(v1, v2);
00320 }
00321
00322
00323
00324 public void caseMulExpr(MulExpr v) {
00325 v.getOp1().apply(this);
00326 Value v1 = currentValue;
00327 v.getOp2().apply(this);
00328 Value v2 = currentValue;
00329 currentValue = grimp.newMulExpr(v1, v2);
00330 }
00331
00332
00333
00334 public void caseNeExpr(NeExpr v) {
00335 v.getOp1().apply(this);
00336 Value v1 = currentValue;
00337 v.getOp2().apply(this);
00338 Value v2 = currentValue;
00339 currentValue = grimp.newNeExpr(v1, v2);
00340 }
00341
00342
00343
00344 public void caseNegExpr(NegExpr v) {
00345 v.getOp().apply(this);
00346 currentValue = grimp.newNegExpr(currentValue);
00347 }
00348
00349
00350
00351 public void caseNewArrayExpr(NewArrayExpr v) {
00352 defaultCase(v);
00353 }
00354
00355
00356
00357 public void caseNewExpr(NewExpr v) {
00358 defaultCase(v);
00359 }
00360
00361
00362
00363 public void caseNewInvokeExpr(NewInvokeExpr v) {
00364 defaultCase(v);
00365 }
00366
00367
00368
00369 public void caseNewMultiArrayExpr(NewMultiArrayExpr v) {
00370 defaultCase(v);
00371 }
00372
00373
00374
00375 public void caseNullConstant(NullConstant v) {
00376 currentValue = NullConstant.v();
00377 }
00378
00379
00380
00381 public void caseOrExpr(OrExpr v) {
00382 v.getOp1().apply(this);
00383 Value v1 = currentValue;
00384 v.getOp2().apply(this);
00385 Value v2 = currentValue;
00386 currentValue = grimp.newOrExpr(v1, v2);
00387 }
00388
00389
00390
00391 public void caseParameterRef(ParameterRef v) {
00392 defaultCase(v);
00393 }
00394
00395
00396
00397 public void caseRemExpr(RemExpr v) {
00398 v.getOp1().apply(this);
00399 Value v1 = currentValue;
00400 v.getOp2().apply(this);
00401 Value v2 = currentValue;
00402 currentValue = grimp.newRemExpr(v1, v2);
00403 }
00404
00405
00406
00407 public void caseShlExpr(ShlExpr v) {
00408 v.getOp1().apply(this);
00409 Value v1 = currentValue;
00410 v.getOp2().apply(this);
00411 Value v2 = currentValue;
00412 currentValue = grimp.newShlExpr(v1, v2);
00413 }
00414
00415
00416
00417 public void caseShrExpr(ShrExpr v) {
00418 v.getOp1().apply(this);
00419 Value v1 = currentValue;
00420 v.getOp2().apply(this);
00421 Value v2 = currentValue;
00422 currentValue = grimp.newShrExpr(v1, v2);
00423 }
00424
00425
00426
00427 public void caseSpecialInvokeExpr(SpecialInvokeExpr v) {
00428 defaultCase(v);
00429 }
00430
00431
00432
00433 public void caseStaticFieldRef(StaticFieldRef v) {
00434 currentValue = grimp.newStaticFieldRef(v.getField());
00435 }
00436
00437
00438
00439 public void caseStaticInvokeExpr(StaticInvokeExpr v) {
00440 defaultCase(v);
00441 }
00442
00443
00444
00445 public void caseStringConstant(StringConstant v) {
00446 currentValue = StringConstant.v(v.value);
00447 }
00448
00449
00450
00451 public void caseSubExpr(SubExpr v) {
00452 v.getOp1().apply(this);
00453 Value v1 = currentValue;
00454 v.getOp2().apply(this);
00455 Value v2 = currentValue;
00456 currentValue = grimp.newSubExpr(v1, v2);
00457 }
00458
00459
00460
00461 public void caseThisRef(ThisRef v) {
00462 defaultCase(v);
00463 }
00464
00465
00466
00467 public void caseUshrExpr(UshrExpr v) {
00468 v.getOp1().apply(this);
00469 Value v1 = currentValue;
00470 v.getOp2().apply(this);
00471 Value v2 = currentValue;
00472 currentValue = grimp.newUshrExpr(v1, v2);
00473 }
00474
00475
00476
00477 public void caseVirtualInvokeExpr(VirtualInvokeExpr v) {
00478 defaultCase(v);
00479 }
00480
00481
00482
00483 public void caseXorExpr(XorExpr v) {
00484 v.getOp1().apply(this);
00485 Value v1 = currentValue;
00486 v.getOp2().apply(this);
00487 Value v2 = currentValue;
00488 currentValue = grimp.newXorExpr(v1, v2);
00489 }
00490
00491
00492
00493
00494 private static HashSet getThreadMethods() {
00495 HashSet result = new HashSet();
00496
00497 for (Enumeration e = CompilationManager.getCompiledClasses().elements(); e.hasMoreElements();) {
00498 SootClass sc = (SootClass) e.nextElement();
00499 if (sc.declaresMethod("main")) {
00500 result.add(sc.getMethod("main"));
00501 } else if (sc.declaresMethod("run")) {
00502 result.add(sc.getMethod("run"));
00503 }
00504 }
00505
00506 return result;
00507 }
00508
00509
00510
00511
00512
00513 private static boolean isInThreadBody(Stmt stmt) {
00514 Jimple jimple = Jimple.v();
00515 AnnotationManager am = CompilationManager.getAnnotationManager();
00516
00517 HashSet stmtListSet = new HashSet();
00518 for (Iterator i = getThreadMethods().iterator(); i.hasNext();) {
00519 SootMethod sm = (SootMethod) i.next();
00520 stmtListSet.add(((JimpleBody) sm.getBody(jimple)).getStmtList());
00521 }
00522
00523 for (Iterator j = stmtListSet.iterator(); j.hasNext();) {
00524 StmtList sl = (StmtList) j.next();
00525 if (sl.indexOf(stmt) >= 0) {
00526 return true;
00527 }
00528 }
00529
00530 return false;
00531 }
00532
00533
00534
00535
00536
00537 public static Value update(Value value) {
00538 if (value instanceof LogicalAndExpr) {
00539 if (((LogicalAndExpr) value).getOp1() instanceof LocationTestExpr) {
00540 AnnotationManager am = CompilationManager.getAnnotationManager();
00541 LocationTestExpr lte = (LocationTestExpr) ((LogicalAndExpr) value).getOp1();
00542 Value constraint = (Value) ((LogicalAndExpr) value).getOp2();
00543 Vector newStmts = new Vector();
00544 for (Iterator i = lte.getStmts().iterator(); i.hasNext();) {
00545 Stmt stmt = (Stmt) i.next();
00546 if (am.getReplacedStmt(stmt) != null)
00547 stmt = am.getReplacedStmt(stmt);
00548 if (am.getInlinedStmt(stmt) != null)
00549 newStmts.addAll(am.getInlinedStmt(stmt));
00550 else {
00551
00552 throw new RuntimeException();
00553 }
00554 }
00555 Vector result = new Vector();
00556 for (Iterator i = newStmts.iterator(); i.hasNext();) {
00557 currentStmt = (Stmt) i.next();
00558 if (isInThreadBody(currentStmt)) {
00559 Vector v = new Vector();
00560 v.add(currentStmt);
00561 LocationTestExpr newLte = new LocationTestExpr(v);
00562 pu.currentValue = null;
00563 constraint.apply(pu);
00564 result.add(new LogicalAndExpr(newLte, pu.currentValue));
00565 }
00566 }
00567 Iterator i = result.iterator();
00568 value = (Value) i.next();
00569 while (i.hasNext()) {
00570 value = new LogicalOrExpr(value, (Value) i.next());
00571 }
00572 }
00573 } else
00574 if (value instanceof LocationTestExpr) {
00575 AnnotationManager am = CompilationManager.getAnnotationManager();
00576 LocationTestExpr lte = (LocationTestExpr) value;
00577 Vector newStmts = new Vector();
00578 for (Iterator i = lte.getStmts().iterator(); i.hasNext();) {
00579 Stmt stmt = (Stmt) i.next();
00580 if (am.getReplacedStmt(stmt) != null)
00581 stmt = am.getReplacedStmt(stmt);
00582 if (am.getInlinedStmt(stmt) != null)
00583 newStmts.addAll(am.getInlinedStmt(stmt));
00584 else {
00585
00586 throw new RuntimeException();
00587 }
00588 }
00589 Vector result = new Vector();
00590 for (Iterator i = newStmts.iterator(); i.hasNext();) {
00591 currentStmt = (Stmt) i.next();
00592 if (isInThreadBody(currentStmt)) {
00593 result.add(currentStmt);
00594 }
00595 }
00596 value = new LocationTestExpr(result);
00597 }
00598 return value;
00599 }
00600 }