/**
  * Creates a KILL set for a given Unit and it to the FlowSet dest. In this case, our KILL set are
  * the Assignments made to the same Value that this Unit assigns to.
  *
  * @param src the src
  * @param unit the unit
  * @param dest the dest
  */
 private void kill(FlowSet source, AssignStmt assignment, FlowSet dest) {
   FlowSet kills = new ArraySparseSet();
   for (Object earlierAssignment : source.toList()) {
     if (earlierAssignment instanceof AssignStmt) {
       AssignStmt stmt = (AssignStmt) earlierAssignment;
       if (stmt.getLeftOp().equivTo(assignment.getLeftOp())) {
         kills.add(earlierAssignment);
       }
     }
   }
   source.difference(kills, dest);
 }
 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());
       }
     }
   }
 }
  /*
   * (non-Javadoc)
   *
   * @see soot.toolkits.scalar.FlowAnalysis#flowThrough(java.lang.Object, java.lang.Object, java.lang.Object)
   */
  @Override
  protected void flowThrough(FlowSet source, Unit unit, FlowSet dest) {

    if (unit instanceof AssignStmt) {
      AssignStmt assignment = (AssignStmt) unit;

      FeatureTag tag = (FeatureTag) assignment.getTag(FeatureTag.FEAT_TAG_NAME);
      IFeatureRep featureRep = tag.getFeatureRep();

      if (featureRep.belongsToConfiguration(configuration)) {
        kill(source, assignment, dest);
        gen(dest, assignment);
      } else {
        source.copy(dest);
      }
    } else {
      source.copy(dest);
    }
  }
  /**
   * This method pushes all newExpr down to be the stmt directly before every invoke of the init
   * only if they are in the types list
   */
  public void internalTransform(Body b, String phaseName, Map options) {
    JimpleBody body = (JimpleBody) b;

    if (Options.v().verbose())
      G.v().out.println("[" + body.getMethod().getName() + "] Folding Jimple constructors...");

    Chain units = body.getUnits();
    List<Unit> stmtList = new ArrayList<Unit>();
    stmtList.addAll(units);

    Iterator<Unit> it = stmtList.iterator();
    Iterator<Unit> nextStmtIt = stmtList.iterator();
    // start ahead one
    nextStmtIt.next();

    SmartLocalDefs localDefs = SmartLocalDefsPool.v().getSmartLocalDefsFor(body);
    UnitGraph graph = localDefs.getGraph();
    LocalUses localUses = new SimpleLocalUses(graph, localDefs);

    /* fold in NewExpr's with specialinvoke's */
    while (it.hasNext()) {
      Stmt s = (Stmt) it.next();

      if (!(s instanceof AssignStmt)) continue;

      /* this should be generalized to ArrayRefs */
      // only deal with stmts that are an local = newExpr
      Value lhs = ((AssignStmt) s).getLeftOp();
      if (!(lhs instanceof Local)) continue;

      Value rhs = ((AssignStmt) s).getRightOp();
      if (!(rhs instanceof NewExpr)) continue;

      // check if very next statement is invoke -->
      // this indicates there is no control flow between
      // new and invoke and should do nothing
      if (nextStmtIt.hasNext()) {
        Stmt next = (Stmt) nextStmtIt.next();
        if (next instanceof InvokeStmt) {
          InvokeStmt invoke = (InvokeStmt) next;

          if (invoke.getInvokeExpr() instanceof SpecialInvokeExpr) {
            SpecialInvokeExpr invokeExpr = (SpecialInvokeExpr) invoke.getInvokeExpr();
            if (invokeExpr.getBase() == lhs) {
              break;
            }
          }
        }
      }

      // check if new is in the types list - only process these
      if (!types.contains(((NewExpr) rhs).getType())) continue;

      List lu = localUses.getUsesOf(s);
      Iterator luIter = lu.iterator();
      boolean MadeNewInvokeExpr = false;

      while (luIter.hasNext()) {
        Unit use = ((UnitValueBoxPair) (luIter.next())).unit;
        if (!(use instanceof InvokeStmt)) continue;
        InvokeStmt is = (InvokeStmt) use;
        if (!(is.getInvokeExpr() instanceof SpecialInvokeExpr)
            || lhs != ((SpecialInvokeExpr) is.getInvokeExpr()).getBase()) continue;

        // make a new one here
        AssignStmt constructStmt =
            Jimple.v()
                .newAssignStmt(((DefinitionStmt) s).getLeftOp(), ((DefinitionStmt) s).getRightOp());
        constructStmt.setRightOp(Jimple.v().newNewExpr(((NewExpr) rhs).getBaseType()));
        MadeNewInvokeExpr = true;

        // redirect jumps
        use.redirectJumpsToThisTo(constructStmt);
        // insert new one here
        units.insertBefore(constructStmt, use);

        constructStmt.addTag(s.getTag("SourceLnPosTag"));
      }
      if (MadeNewInvokeExpr) {
        units.remove(s);
      }
    }
  }
示例#5
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;
    }
  }