00001 package edu.ksu.cis.bandera.birc;
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.io.*;
00036 import java.util.Vector;
00037 import java.util.Hashtable;
00038
00039 import edu.ksu.cis.bandera.bir.TransSystem;
00040 import edu.ksu.cis.bandera.bir.BirThread;
00041 import edu.ksu.cis.bandera.bir.BirConstants;
00042 import edu.ksu.cis.bandera.bir.LockAction;
00043 import edu.ksu.cis.bandera.bir.LockTest;
00044 import edu.ksu.cis.bandera.bir.ThreadLocTest;
00045 import edu.ksu.cis.bandera.bir.Location;
00046 import edu.ksu.cis.bandera.bir.LocVector;
00047 import edu.ksu.cis.bandera.bir.StateVar;
00048 import edu.ksu.cis.bandera.bir.Transformation;
00049 import edu.ksu.cis.bandera.bir.ActionVector;
00050 import edu.ksu.cis.bandera.bir.TransVector;
00051 import edu.ksu.cis.bandera.bir.BirTrace;
00052 import edu.ksu.cis.bandera.util.DefaultValues;
00053 import edu.ksu.cis.bandera.prog.HierarchyQuery;
00054
00055 import ca.mcgill.sable.util.*;
00056 import ca.mcgill.sable.soot.*;
00057 import ca.mcgill.sable.soot.jimple.*;
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 public class Builder implements BirConstants {
00086
00087
00088
00089
00090
00091 public static int COLLECTION_SIZE = DefaultValues.birMaxInstances;
00092 public static int MAX_ARRAY_LENGTH = DefaultValues.birMaxArrayLen;
00093
00094 BirThread thread;
00095 StmtGraph stmtGraph;
00096 SootMethod method;
00097 int mark;
00098 Vector reachableStmts;
00099
00100 static TransSystem system;
00101 static TypeExtractor typeExtract;
00102 static DynamicMap dynamicMap;
00103 static HashSet lockedClasses;
00104 static HashSet parentClasses;
00105
00106 private Builder(BirThread thread, StmtGraph stmtGraph, SootMethod method) {
00107 this.thread = thread;
00108 this.stmtGraph = stmtGraph;
00109 this.method = method;
00110 }
00111
00112
00113
00114
00115
00116
00117
00118 static void buildThread(SootClass sClass, boolean mainClass,
00119 PredicateSet predSet) {
00120
00121 String methodName = (mainClass) ? "main" : "run";
00122 SootMethod method = sClass.getMethod(methodName);
00123 BirThread thread = system.threadOfKey(method);
00124
00125
00126 JimpleBody body = (JimpleBody)
00127 new StoredBody(Jimple.v()).resolveFor(method);
00128 StmtList stmtList = body.getStmtList();
00129 if (stmtList.size() == 0)
00130 return;
00131 CompleteStmtGraph cStmtGraph = new CompleteStmtGraph(stmtList);
00132 LocalDefs localDefs = new SimpleLocalDefs(cStmtGraph);
00133 LiveLocals liveLocals = new SparseLiveLocals(cStmtGraph);
00134 BriefStmtGraph stmtGraph = new BriefStmtGraph(stmtList);
00135
00136
00137 Stmt head = (Stmt) stmtList.get(0);
00138 Location startLoc = system.locationOfKey(head, thread);
00139 thread.setStartLoc(startLoc);
00140 thread.setMain(mainClass);
00141
00142
00143 Iterator localIt = body.getLocals().iterator();
00144 while (localIt.hasNext()) {
00145 Local local = (Local) localIt.next();
00146 String key = ExprExtractor.localKey(method, local);
00147 declareVar(key, local.getName(), local.getType(), thread);
00148 }
00149
00150
00151 Builder builder = new Builder(thread, stmtGraph, method);
00152 Vector reachableStmts = builder.reachableFrom(head);
00153
00154
00155 TransExtractor extractor =
00156 new TransExtractor(system, thread, stmtGraph, localDefs,
00157 liveLocals, method, typeExtract, predSet);
00158 for (int i = 0; i < reachableStmts.size(); i++)
00159 ((Stmt)reachableStmts.elementAt(i)).apply(extractor);
00160 }
00161
00162
00163
00164
00165
00166
00167 static void checkForStatics(DefinitionStmt defStmt, Hashtable done) {
00168 if (defStmt.getRightOp() instanceof StaticFieldRef) {
00169 StaticFieldRef fieldRef = (StaticFieldRef)defStmt.getRightOp();
00170 SootClass sClass = fieldRef.getField().getDeclaringClass();
00171 if (done.get(sClass) == null) {
00172 declareClassGlobals(sClass);
00173 done.put(sClass,sClass);
00174 }
00175 }
00176 if (defStmt.getLeftOp() instanceof StaticFieldRef) {
00177 StaticFieldRef fieldRef = (StaticFieldRef)defStmt.getLeftOp();
00178 SootClass sClass = fieldRef.getField().getDeclaringClass();
00179 if (done.get(sClass) == null) {
00180 declareClassGlobals(sClass);
00181 done.put(sClass,sClass);
00182 }
00183 }
00184 }
00185
00186
00187
00188
00189
00190
00191 static void createCollections() {
00192
00193
00194
00195
00196 Vector keys = dynamicMap.getCollections();
00197 for (int i = 0; i < keys.size(); i++) {
00198 String name;
00199 edu.ksu.cis.bandera.bir.Type elementType;
00200 edu.ksu.cis.bandera.bir.Type collectType;
00201
00202
00203 Object key = keys.elementAt(i);
00204 int size = dynamicMap.getCollectionSize(key);
00205 SootClass sootClass = dynamicMap.getCollectionClass(key);
00206 ArrayType arrayType = dynamicMap.getCollectionArray(key);
00207
00208 if (sootClass != null) {
00209 elementType = typeExtract.getRecordType(sootClass);
00210 name = sootClass.getName();
00211 } else {
00212 elementType = typeExtract.getArrayType(arrayType);
00213 name = typeExtract.arrayName(arrayType);
00214 }
00215 collectType = typeExtract.createCollectionType(elementType,size);
00216 StateVar col =
00217 system.declareVar(key,name + "_col",null,collectType,null);
00218
00219
00220 if (sootClass != null) {
00221
00222
00223
00224 typeExtract.getRefType(sootClass).addTarget(col, sootClass, typeExtract);
00225 Vector superClasses = typeExtract.getSuperClasses(sootClass);
00226 for (int j = 0; j < superClasses.size(); j++) {
00227 SootClass supClass = (SootClass) superClasses.elementAt(j);
00228 typeExtract.getRefType(supClass).addTarget(col, sootClass, typeExtract);
00229 }
00230 Vector intClasses = typeExtract.getInterfaceClasses(sootClass);
00231 for (int j = 0; j < intClasses.size(); j++) {
00232 SootClass intClass = (SootClass) intClasses.elementAt(j);
00233 typeExtract.getRefType(intClass).addTarget(col, sootClass, typeExtract);
00234 }
00235 } else
00236
00237
00238 typeExtract.getRefType(arrayType).addTarget(col);
00239 }
00240 }
00241
00242
00243
00244
00245
00246 static void createRecordAndArrayTypes() {
00247
00248
00249 Vector sootClasses = dynamicMap.getClasses();
00250 for (int i = 0; i < sootClasses.size(); i++) {
00251 SootClass sootClass = (SootClass) sootClasses.elementAt(i);
00252 SootClass ancestor = sootClass;
00253 while (ancestor.hasSuperClass()) {
00254 ancestor = ancestor.getSuperClass();
00255 if (lockedClasses.contains(ancestor))
00256 lockedClasses.add(sootClass);
00257 }
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 sootClasses = dynamicMap.getClasses();
00271 for (int i = 0; i < sootClasses.size(); i++) {
00272 SootClass sootClass = (SootClass) sootClasses.elementAt(i);
00273 typeExtract.createRecordType(sootClass,
00274 lockedClasses.contains(sootClass));
00275 }
00276
00277
00278 for (Iterator pIt = parentClasses.iterator(); pIt.hasNext(); ) {
00279 SootClass sootClass = (SootClass) pIt.next();
00280 typeExtract.createRecordType(sootClass,
00281 lockedClasses.contains(sootClass));
00282 }
00283
00284
00285 Vector arrayTypes = dynamicMap.getArrays();
00286 for (int i = 0; i < arrayTypes.size(); i++) {
00287 ArrayType arrayType = (ArrayType) arrayTypes.elementAt(i);
00288 typeExtract.createArrayType(arrayType,MAX_ARRAY_LENGTH);
00289 }
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 static void createRefTypes() {
00301
00302 Vector sootClasses = dynamicMap.getClasses();
00303 for (int i = 0; i < sootClasses.size(); i++) {
00304 SootClass sootClass = (SootClass) sootClasses.elementAt(i);
00305 typeExtract.createRefType(sootClass);
00306 }
00307
00308
00309 for (Iterator pIt = parentClasses.iterator(); pIt.hasNext(); ) {
00310 SootClass sootClass = (SootClass) pIt.next();
00311 typeExtract.createRefType(sootClass);
00312 }
00313
00314
00315 Vector arrayTypes = dynamicMap.getArrays();
00316 for (int i = 0; i < arrayTypes.size(); i++) {
00317 ArrayType arrayType = (ArrayType) arrayTypes.elementAt(i);
00318 typeExtract.createRefType(arrayType);
00319 }
00320
00321 Vector interfaces = dynamicMap.getInterfaces();
00322 for (int i = 0; i < interfaces.size(); i++) {
00323 SootClass sootClass = (SootClass) interfaces.elementAt(i);
00324 typeExtract.createRefType(sootClass);
00325 }
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 public static TransSystem createTransSystem(SootClass [] sootClasses,
00345 String name,
00346 int maxArrayLength,
00347 int maxCollectSize,
00348 int minInt,
00349 int maxInt,
00350 PredicateSet predSet) {
00351 MAX_ARRAY_LENGTH = maxArrayLength;
00352 COLLECTION_SIZE = maxCollectSize;
00353 edu.ksu.cis.bandera.bir.Type.defaultRangeType = new edu.ksu.cis.bandera.bir.Range(minInt, maxInt);
00354 return createTransSystem(sootClasses, name, predSet);
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 public static TransSystem createTransSystem(SootClass [] sootClasses,
00371 String name,
00372 PredicateSet predSet) {
00373 if (predSet == null)
00374 predSet = new PredicateSet();
00375 system = new TransSystem(name);
00376 typeExtract = new TypeExtractor(system, sootClasses[0].getManager());
00377
00378
00379 declareClasses(sootClasses);
00380 for (int i = 0; i < sootClasses.length; i++)
00381 declareThread(sootClasses[i], (i == 0));
00382 declareGlobals(sootClasses);
00383
00384
00385 for (int i = 0; i < sootClasses.length; i++)
00386 buildThread(sootClasses[i], (i == 0), predSet);
00387
00388
00389 (new Reducer(system)).run();
00390 system.numberLocations();
00391
00392
00393 declarePredicates(predSet);
00394 return system;
00395 }
00396 static void declareClasses(SootClass [] sootClasses) {
00397 identifyAllocatorsLocks(sootClasses);
00398 createRefTypes();
00399 createRecordAndArrayTypes();
00400 createCollections();
00401 }
00402
00403
00404
00405
00406
00407
00408
00409 static void declareClassGlobals(SootClass sClass) {
00410
00411 if (sClass.getName().startsWith("java."))
00412 return;
00413
00414
00415 Iterator fieldIt = sClass.getFields().iterator();
00416 while(fieldIt.hasNext()) {
00417 SootField field = (SootField) fieldIt.next();
00418 if (Modifier.isStatic(field.getModifiers()))
00419 declareVar(field, field.getName(), field.getType(), null);
00420 }
00421
00422
00423 if (sClass.declaresMethod("<clinit>")) {
00424 SootMethod method = sClass.getMethod("<clinit>");
00425 JimpleBody body = (JimpleBody)
00426 new StoredBody(Jimple.v()).resolveFor(method);
00427 StmtList stmtList = body.getStmtList();
00428 for (int i = 0; i < stmtList.size(); i++) {
00429 if (stmtList.get(i) instanceof AssignStmt) {
00430 AssignStmt stmt = (AssignStmt) stmtList.get(i);
00431 if (stmt.getLeftOp() instanceof StaticFieldRef) {
00432 StaticFieldRef lhs = (StaticFieldRef)stmt.getLeftOp();
00433 if (lhs.getType() instanceof RefType)
00434 warn("ignoring initialization of " + lhs);
00435 else
00436 initializeGlobal(lhs, stmt.getRightOp());
00437 }
00438 }
00439 }
00440 }
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 static void declareGlobals(SootClass [] sootClasses) {
00452 Hashtable done = new Hashtable();
00453 for (int i = 0; i < sootClasses.length; i++) {
00454 SootClass sClass = sootClasses[i];
00455 List methods = sootClasses[i].getMethods();
00456 Iterator methodIt = methods.iterator();
00457 while (methodIt.hasNext()) {
00458 SootMethod method = (SootMethod) methodIt.next();
00459 JimpleBody body = (JimpleBody)
00460 new StoredBody(Jimple.v()).resolveFor(method);
00461 StmtList stmtList = body.getStmtList();
00462 for (int j = 0; j < stmtList.size(); j++) {
00463 Stmt stmt = (Stmt) stmtList.get(j);
00464 if (stmt instanceof DefinitionStmt)
00465 checkForStatics((DefinitionStmt)stmt,done);
00466 }
00467 }
00468 if (i > 0) {
00469 String name = sClass.getName() + "__this";
00470 Type type = RefType.v(sClass.getName());
00471 StateVar var = declareVar(sClass,name,type,null);
00472 var.setConstant(true);
00473 }
00474 }
00475 }
00476
00477
00478
00479
00480
00481
00482 static void declarePredicates(PredicateSet predSet) {
00483 Vector valPreds = predSet.getValuePredicates();
00484 for (int i = 0; i < valPreds.size(); i++) {
00485 Expr valPred = (Expr) valPreds.elementAt(i);
00486 ExprExtractor extractor =
00487 new ExprExtractor(system,null,null,null,typeExtract,predSet);
00488 valPred.apply(extractor);
00489 edu.ksu.cis.bandera.bir.Expr predExpr =
00490 (edu.ksu.cis.bandera.bir.Expr) extractor.getResult();
00491 system.declarePredicate(predSet.predicateName(valPred),predExpr);
00492 }
00493 }
00494 static void declareThread(SootClass sClass, boolean mainClass) {
00495
00496 String methodName = (mainClass) ? "main" : "run";
00497 SootMethod method = sClass.getMethod(methodName);
00498 system.createThread(sClass.getName(), method);
00499 }
00500
00501
00502
00503
00504
00505
00506
00507
00508 static StateVar declareVar(Object key, String name, Type sootType,
00509 BirThread thread) {
00510 sootType.apply(typeExtract);
00511 edu.ksu.cis.bandera.bir.Type type =
00512 (edu.ksu.cis.bandera.bir.Type) typeExtract.getResult();
00513 if (type == null) {
00514 warn("ignoring object of type " + sootType);
00515 return null;
00516 }
00517
00518 return system.declareVar(key, name, thread, type, null);
00519 }
00520 void findReachableFrom(Stmt stmt) {
00521 Location loc = system.locationOfKey(stmt, thread);
00522 if (loc.getMark() != mark) {
00523 loc.setMark(mark);
00524 Iterator stmtIt = stmtGraph.getSuccsOf(stmt).iterator();
00525
00526 if (stmtIt.hasNext())
00527 reachableStmts.addElement(stmt);
00528 while (stmtIt.hasNext()) {
00529 Stmt nextStmt = (Stmt) stmtIt.next();
00530 findReachableFrom(nextStmt);
00531 }
00532 }
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 static void identifyAllocatorsLocks(SootClass [] sootClasses) {
00553 dynamicMap = new DynamicMap(sootClasses[0].getManager());
00554 lockedClasses = new HashSet();
00555 HashSet dynamicClasses = new HashSet();
00556
00557 for (int i = 0; i < sootClasses.length; i++) {
00558 List methods = sootClasses[i].getMethods();
00559 Iterator methodIt = methods.iterator();
00560 while (methodIt.hasNext()) {
00561 SootMethod method = (SootMethod) methodIt.next();
00562 JimpleBody body = (JimpleBody)
00563 new StoredBody(Jimple.v()).resolveFor(method);
00564 StmtList stmtList = body.getStmtList();
00565 for (int j = 0; j < stmtList.size(); j++) {
00566 Stmt stmt = (Stmt) stmtList.get(j);
00567
00568 if (stmt instanceof DefinitionStmt) {
00569 DefinitionStmt defStmt = (DefinitionStmt)stmt;
00570 if (defStmt.getRightOp() instanceof NewExpr) {
00571 NewExpr newExpr = (NewExpr) defStmt.getRightOp();
00572
00573 SootClass newClass = sootClasses[0].getManager().getClass(newExpr.getBaseType().className);
00574
00575 boolean throwableClass = false;
00576 SootClass ancestor = newClass;
00577 while (ancestor.hasSuperClass()) {
00578 ancestor = ancestor.getSuperClass();
00579 if (ancestor.getName().equals("java.lang.Throwable")) {
00580 throwableClass = true;
00581 }
00582 }
00583 if (!throwableClass) {
00584 dynamicMap.addEntry(newExpr, newExpr,
00585 COLLECTION_SIZE);
00586 dynamicClasses.add(sootClasses[0].getManager().getClass(newExpr.getBaseType().className));
00587 }
00588 }
00589 if (defStmt.getRightOp() instanceof NewArrayExpr) {
00590 NewArrayExpr newExpr =
00591 (NewArrayExpr) defStmt.getRightOp();
00592 dynamicMap.addEntry(newExpr, newExpr,
00593 COLLECTION_SIZE,
00594 MAX_ARRAY_LENGTH);
00595 }
00596 if (defStmt.getRightOp() instanceof NewMultiArrayExpr)
00597 warn("multi-dimensional arrays not supported");
00598 }
00599
00600
00601 if (stmt instanceof EnterMonitorStmt) {
00602 EnterMonitorStmt enterStmt = (EnterMonitorStmt)stmt;
00603 Type type = enterStmt.getOp().getType();
00604 if (type instanceof RefType) {
00605 lockedClasses.add(sootClasses[0].getManager().getClass(((RefType)type).className));
00606 }
00607 }
00608 }
00609 }
00610 }
00611 parentClasses = new HashSet();
00612 for (Iterator dcIt = dynamicClasses.iterator(); dcIt.hasNext(); ) {
00613 SootClass sootClass = (SootClass) dcIt.next();
00614
00615 HierarchyQuery.buildAncestors(sootClass);
00616
00617
00618 SootClass ancestor = sootClass;
00619 while (ancestor.hasSuperClass()) {
00620 ancestor = ancestor.getSuperClass();
00621 if (!dynamicClasses.contains(ancestor)) {
00622 parentClasses.add(ancestor);
00623 HierarchyQuery.buildAncestors(ancestor);
00624 }
00625 }
00626 }
00627 dynamicMap.print();
00628 }
00629
00630
00631
00632
00633
00634
00635
00636 static void initializeGlobal(StaticFieldRef lhs, Value rhs) {
00637 StateVar var = system.getVarOfKey(lhs.getField());
00638 ExprExtractor extractor = new ExprExtractor(system, null, null, null,
00639 typeExtract,
00640 new PredicateSet());
00641 rhs.apply(extractor);
00642 if (extractor.getResult() != null)
00643 var.setInitVal((edu.ksu.cis.bandera.bir.Expr)
00644 extractor.getResult());
00645 }
00646
00647
00648
00649
00650
00651
00652
00653 public static JimpleTrace interpretTrace(BirTrace trace) {
00654 return new JimpleTrace(trace);
00655 }
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667 Vector reachableFrom(Stmt stmt) {
00668 reachableStmts = new Vector();
00669 mark = Location.getNewMark();
00670 findReachableFrom(stmt);
00671 return reachableStmts;
00672 }
00673 static void warn(String s) {
00674 System.out.println("Warning: " + s);
00675 }
00676 }