예제 #1
0
 private void searchRef(StringArrayRef ref, Loop loop) {
   String temp_name = ref.getArrayName();
   Iterator<Unit> iter = loop.getBodyBlocks().get(0).getBody().getUnits().iterator();
   while (iter.hasNext()) {
     Unit curr = iter.next();
     if (defines(curr, temp_name) && curr instanceof AssignStmt) {
       AssignStmt assign = (AssignStmt) curr;
       Value right = assign.getRightOp();
       if (right instanceof FieldRef) {
         FieldRef field_ref = (FieldRef) right;
         ref.setFieldSignature(field_ref.getField().getSignature());
         ref.setField(field_ref.getField().getName());
       }
     }
   }
 }
예제 #2
0
  private static boolean internalAggregate(
      StmtBody body, Map<ValueBox, Zone> boxToZone, boolean onlyStackVars) {
    LocalUses localUses;
    LocalDefs localDefs;
    ExceptionalUnitGraph graph;
    boolean hadAggregation = false;
    Chain<Unit> units = body.getUnits();

    graph = new ExceptionalUnitGraph(body);
    localDefs = new SmartLocalDefs(graph, new SimpleLiveLocals(graph));
    localUses = new SimpleLocalUses(graph, localDefs);

    List<Unit> unitList = new PseudoTopologicalOrderer<Unit>().newList(graph, false);
    for (Unit u : unitList) {
      if (!(u instanceof AssignStmt)) continue;
      AssignStmt s = (AssignStmt) u;

      Value lhs = s.getLeftOp();
      if (!(lhs instanceof Local)) continue;
      Local lhsLocal = (Local) lhs;

      if (onlyStackVars && !lhsLocal.getName().startsWith("$")) continue;

      List<UnitValueBoxPair> lu = localUses.getUsesOf(s);
      if (lu.size() != 1) continue;

      UnitValueBoxPair usepair = lu.get(0);
      Unit use = usepair.unit;
      ValueBox useBox = usepair.valueBox;

      List<Unit> ld = localDefs.getDefsOfAt(lhsLocal, use);
      if (ld.size() != 1) continue;

      // Check to make sure aggregation pair in the same zone
      if (boxToZone.get(s.getRightOpBox()) != boxToZone.get(usepair.valueBox)) {
        continue;
      }

      /* we need to check the path between def and use */
      /* to see if there are any intervening re-defs of RHS */
      /* in fact, we should check that this path is unique. */
      /* if the RHS uses only locals, then we know what
      to do; if RHS has a method invocation f(a, b,
      c) or field access, we must ban field writes, other method
      calls and (as usual) writes to a, b, c. */

      boolean cantAggr = false;
      boolean propagatingInvokeExpr = false;
      boolean propagatingFieldRef = false;
      boolean propagatingArrayRef = false;
      ArrayList<FieldRef> fieldRefList = new ArrayList<FieldRef>();

      LinkedList<Value> localsUsed = new LinkedList<Value>();
      for (ValueBox vb : s.getUseBoxes()) {
        Value v = vb.getValue();
        if (v instanceof Local) localsUsed.add(v);
        else if (v instanceof InvokeExpr) propagatingInvokeExpr = true;
        else if (v instanceof ArrayRef) propagatingArrayRef = true;
        else if (v instanceof FieldRef) {
          propagatingFieldRef = true;
          fieldRefList.add((FieldRef) v);
        }
      }

      // look for a path from s to use in graph.
      // only look in an extended basic block, though.

      List<Unit> path = graph.getExtendedBasicBlockPathBetween(s, use);

      if (path == null) continue;

      Iterator<Unit> pathIt = path.iterator();

      // skip s.
      if (pathIt.hasNext()) pathIt.next();

      while (pathIt.hasNext() && !cantAggr) {
        Stmt between = (Stmt) (pathIt.next());

        if (between != use) {
          // Check for killing definitions

          for (ValueBox vb : between.getDefBoxes()) {
            Value v = vb.getValue();
            if (localsUsed.contains(v)) {
              cantAggr = true;
              break;
            }

            if (propagatingInvokeExpr || propagatingFieldRef || propagatingArrayRef) {
              if (v instanceof FieldRef) {
                if (propagatingInvokeExpr) {
                  cantAggr = true;
                  break;
                } else if (propagatingFieldRef) {
                  // Can't aggregate a field access if passing a definition of a field
                  // with the same name, because they might be aliased
                  for (FieldRef fieldRef : fieldRefList) {
                    if (((FieldRef) v).getField() == fieldRef.getField()) {
                      cantAggr = true;
                      break;
                    }
                  }
                }
              } else if (v instanceof ArrayRef) {
                if (propagatingInvokeExpr) {
                  // Cannot aggregate an invoke expr past an array write
                  cantAggr = true;
                  break;
                } else if (propagatingArrayRef) {
                  // cannot aggregate an array read past a write
                  // this is somewhat conservative
                  // (if types differ they may not be aliased)

                  cantAggr = true;
                  break;
                }
              }
            }
          }

          // Make sure not propagating past a {enter,exit}Monitor
          if (propagatingInvokeExpr && between instanceof MonitorStmt) cantAggr = true;
        }

        // Check for intervening side effects due to method calls
        if (propagatingInvokeExpr || propagatingFieldRef || propagatingArrayRef) {
          for (final ValueBox box : between.getUseBoxes()) {
            if (between == use && box == useBox) {
              // Reached use point, stop looking for
              // side effects
              break;
            }

            Value v = box.getValue();

            if (v instanceof InvokeExpr
                || (propagatingInvokeExpr && (v instanceof FieldRef || v instanceof ArrayRef))) {
              cantAggr = true;
              break;
            }
          }
        }
      }

      // we give up: can't aggregate.
      if (cantAggr) {
        continue;
      }
      /* assuming that the d-u chains are correct, */
      /* we need not check the actual contents of ld */

      Value aggregatee = s.getRightOp();

      if (usepair.valueBox.canContainValue(aggregatee)) {
        boolean wasSimpleCopy = isSimpleCopy(usepair.unit);
        usepair.valueBox.setValue(aggregatee);
        units.remove(s);
        hadAggregation = true;
        // clean up the tags. If s was not a simple copy, the new statement should get
        // the tags of s.
        // OK, this fix was wrong. The condition should not be
        // "If s was not a simple copy", but rather "If usepair.unit
        // was a simple copy". This way, when there's a load of a constant
        // followed by an invoke, the invoke gets the tags.
        if (wasSimpleCopy) {
          // usepair.unit.removeAllTags();
          usepair.unit.addAllTagsOf(s);
        }
      } else {
        /*
        if(Options.v().verbose())
        {
            G.v().out.println("[debug] failed aggregation");
              G.v().out.println("[debug] tried to put "+aggregatee+
                             " into "+usepair.stmt +
                             ": in particular, "+usepair.valueBox);
              G.v().out.println("[debug] aggregatee instanceof Expr: "
                             +(aggregatee instanceof Expr));
        }*/
      }
    }
    return hadAggregation;
  }
  @Override
  public Type appliesInternal(AndroidMethod method) {
    SootMethod sm = getSootMethod(method);

    // We are only interested in getters and setters
    if (!sm.getName().startsWith("get") && !sm.getName().startsWith("set"))
      return Type.NOT_SUPPORTED;
    String baseName = sm.getName().substring(3);
    String getterName = "get" + baseName;
    String setterName = "set" + baseName;

    try {
      // Find the getter and the setter
      SootMethod getter =
          getSootMethod(new AndroidMethod(getterName, "", sm.getDeclaringClass().getName()));
      SootMethod setter =
          getSootMethod(new AndroidMethod(setterName, "", sm.getDeclaringClass().getName()));
      if (getter == null || setter == null) return Type.FALSE;

      if (!setter.isConcrete() || !getter.isConcrete()) return Type.NOT_SUPPORTED;

      Body bodyGetter = null;
      try {
        bodyGetter = getter.retrieveActiveBody();
      } catch (Exception ex) {
        return Type.NOT_SUPPORTED;
      }

      // Find the local that gets returned
      Local returnLocal = null;
      for (Unit u : bodyGetter.getUnits())
        if (u instanceof ReturnStmt) {
          ReturnStmt ret = (ReturnStmt) u;
          if (ret.getOp() instanceof Local) {
            returnLocal = (Local) ret.getOp();
            break;
          }
        }
      if (returnLocal == null) return Type.FALSE;

      // Find where the local is assigned a value in the code
      List<FieldRef> accessPath = new ArrayList<FieldRef>();
      Local returnBase = returnLocal;
      while (returnBase != null)
        for (Unit u : bodyGetter.getUnits()) {
          if (u instanceof AssignStmt) {
            AssignStmt assign = (AssignStmt) u;
            if (assign.getLeftOp().equals(returnBase))
              if (assign.getRightOp() instanceof InstanceFieldRef) {
                InstanceFieldRef ref = (InstanceFieldRef) assign.getRightOp();
                accessPath.add(0, ref);
                returnBase = (Local) ref.getBase();
                break;
              } else returnBase = null;
          } else if (u instanceof IdentityStmt) {
            IdentityStmt id = (IdentityStmt) u;
            if (id.getLeftOp().equals(returnBase)) returnBase = null;
          }
        }
      if (accessPath.isEmpty()) return Type.FALSE;
      /*
      // Find the corresponding access path in the setter
      for (Unit u : bodySetter.getUnits())
      	if (u instanceof AssignStmt) {
      		AssignStmt assign = (AssignStmt) u;
      		if (assign.getLeftOp() instanceof InstanceFieldRef
      				&& assign.getRightOp() instanceof Local) {
      			InstanceFieldRef iref = (InstanceFieldRef) assign.getLeftOp();
      			if (iref.getFieldRef().toString().equals(accessPath.get(accessPath.size() - 1).getFieldRef().toString())) {
      				// This is a starting point
      				boolean pathFound = false;
      				Local startLocal = (Local) iref.getBase();
      				int accessPathPos = accessPath.size() - 2;
      				while (startLocal != null) {
      					for (Unit u2 : bodySetter.getUnits()) {
      						if (u2 instanceof AssignStmt) {
      							AssignStmt assign2 = (AssignStmt) u2;
      							if (assign2.getLeftOp().equals(startLocal))
      								if (assign2.getRightOp() instanceof InstanceFieldRef) {
      									InstanceFieldRef ref = (InstanceFieldRef) assign2.getRightOp();
      									if (accessPath.get(accessPathPos--).getFieldRef().toString().equals(ref.getFieldRef().toString())) {
      										startLocal = (Local) ref.getBase();
      										break;
      									}
      									else
      										startLocal = null;
      								}
      								else
      									startLocal = null;
      						}
      						else if (u2 instanceof IdentityStmt) {
      							IdentityStmt id = (IdentityStmt) u2;
      							if (id.getLeftOp().equals(startLocal)) {
      								startLocal = null;
      								pathFound = true;
      								break;
      							}
      						}
      					}
      				}

      				if (pathFound) {
      					if (assign.getRightOp() instanceof Local) {
      						// Find the parameter being set
      						for (Unit u2 : bodySetter.getUnits())
      							if (u2 instanceof IdentityStmt) {
      								IdentityStmt id = (IdentityStmt) u2;
      								if (id.getLeftOp().equals(assign.getRightOp()))
      									return Type.TRUE;
      							}
      					}
      					break;
      				}
      			}
      		}
      	}
      return Type.FALSE;
      */
      return Type.TRUE;
    } catch (Exception ex) {
      System.err.println("Something went wrong:");
      ex.printStackTrace();
      return Type.NOT_SUPPORTED;
    }
  }