示例#1
0
  /**
   * Utility method used in the construction of {@link UnitGraph}s, to be called only after the
   * unitToPreds and unitToSuccs maps have been built.
   *
   * <p><code>UnitGraph</code> provides an implementation of <code>buildHeadsAndTails()</code> which
   * defines the graph's set of heads to include the first {@link Unit} in the graph's body,
   * together with any other <tt>Unit</tt> which has no predecessors. It defines the graph's set of
   * tails to include all <tt>Unit</tt>s with no successors. Subclasses of <code>UnitGraph</code>
   * may override this method to change the criteria for classifying a node as a head or tail.
   */
  protected void buildHeadsAndTails() {
    List tailList = new ArrayList();
    List headList = new ArrayList();

    for (Iterator unitIt = unitChain.iterator(); unitIt.hasNext(); ) {
      Unit s = (Unit) unitIt.next();
      List succs = (List) unitToSuccs.get(s);
      if (succs.size() == 0) {
        tailList.add(s);
      }
      List preds = (List) unitToPreds.get(s);
      if (preds.size() == 0) {
        headList.add(s);
      }
    }

    // Add the first Unit, even if it is the target of
    // a branch.
    Unit entryPoint = (Unit) unitChain.getFirst();
    if (!headList.contains(entryPoint)) {
      headList.add(entryPoint);
    }

    tails = Collections.unmodifiableList(tailList);
    heads = Collections.unmodifiableList(headList);
  }
示例#2
0
  /** Prints the given <code>JimpleBody</code> to the specified <code>PrintWriter</code>. */
  private void printLocalsInBody(Body body, UnitPrinter up) {
    // Print out local variables
    {
      Map typeToLocals = new DeterministicHashMap(body.getLocalCount() * 2 + 1, 0.7f);

      // Collect locals
      {
        Iterator localIt = body.getLocals().iterator();

        while (localIt.hasNext()) {
          Local local = (Local) localIt.next();

          List localList;

          Type t = local.getType();

          if (typeToLocals.containsKey(t)) localList = (List) typeToLocals.get(t);
          else {
            localList = new ArrayList();
            typeToLocals.put(t, localList);
          }

          localList.add(local);
        }
      }

      // Print locals
      {
        Iterator typeIt = typeToLocals.keySet().iterator();

        while (typeIt.hasNext()) {
          Type type = (Type) typeIt.next();

          List localList = (List) typeToLocals.get(type);
          Object[] locals = localList.toArray();
          up.type(type);
          up.literal(" ");

          for (int k = 0; k < locals.length; k++) {
            if (k != 0) up.literal(", ");

            up.local((Local) locals[k]);
          }

          up.literal(";");
          up.newline();
        }
      }

      if (!typeToLocals.isEmpty()) {
        up.newline();
      }
    }
  }
示例#3
0
    /**
     * Returns a <code>ThrowableSet</code> representing the set of exceptions included in <code>
     * include</code> minus the set of exceptions included in <code>exclude</code>. Creates a new
     * <code>ThrowableSet</code> only if there was not already one whose contents correspond to
     * <code>include</code> - <code>exclude</code>.
     *
     * @param include A set of {@link RefLikeType} objects representing exception types included in
     *     the result; may be <code>null</code> if there are no included types.
     * @param exclude A set of {@link AnySubType} objects representing exception types excluded from
     *     the result; may be <code>null</code> if there are no excluded types.
     * @return a <code>ThrowableSet</code> representing the set of exceptions corresponding to
     *     <code>include</code> - <code>exclude</code>.
     */
    private ThrowableSet registerSetIfNew(Set include, Set exclude) {
      if (INSTRUMENTING) {
        registrationCalls++;
      }
      if (include == null) {
        include = Collections.EMPTY_SET;
      }
      if (exclude == null) {
        exclude = Collections.EMPTY_SET;
      }
      int size = include.size() + exclude.size();
      Integer sizeKey = new Integer(size);

      List sizeList = (List) sizeToSets.get(sizeKey);
      if (sizeList == null) {
        sizeList = new LinkedList();
        sizeToSets.put(sizeKey, sizeList);
      }
      for (Iterator i = sizeList.iterator(); i.hasNext(); ) {
        ThrowableSet set = (ThrowableSet) i.next();
        if (set.exceptionsIncluded.equals(include) && set.exceptionsExcluded.equals(exclude)) {
          return set;
        }
      }
      if (INSTRUMENTING) {
        registeredSets++;
      }
      ThrowableSet result = new ThrowableSet(include, exclude);
      sizeList.add(result);
      return result;
    }
示例#4
0
  public void outALocalImmediate(ALocalImmediate node) {
    String local = (String) mProductions.removeLast();

    Local l = (Local) mLocals.get(local);
    if (l == null) throw new RuntimeException("did not find local: " + local);
    mProductions.addLast(l);
  }
示例#5
0
  public void outANonstaticInvokeExpr(ANonstaticInvokeExpr node) {
    List args;

    if (node.getArgList() != null) args = (List) mProductions.removeLast();
    else args = new ArrayList();

    SootMethodRef method = (SootMethodRef) mProductions.removeLast();

    String local = (String) mProductions.removeLast();

    Local l = (Local) mLocals.get(local);
    if (l == null) throw new RuntimeException("did not find local: " + local);

    Node invokeType = (Node) node.getNonstaticInvoke();
    Expr invokeExpr;

    if (invokeType instanceof ASpecialNonstaticInvoke) {
      invokeExpr = Jimple.v().newSpecialInvokeExpr(l, method, args);
    } else if (invokeType instanceof AVirtualNonstaticInvoke) {
      invokeExpr = Jimple.v().newVirtualInvokeExpr(l, method, args);
    } else {
      if (debug)
        if (!(invokeType instanceof AInterfaceNonstaticInvoke))
          throw new RuntimeException("expected interface invoke.");
      invokeExpr = Jimple.v().newInterfaceInvokeExpr(l, method, args);
    }

    mProductions.addLast(invokeExpr);
  }
示例#6
0
  /**
   * Utility method that produces a new map from the {@link Unit}s of this graph's body to the union
   * of the values stored in the two argument {@link Map}s, used to combine the maps of exceptional
   * and unexceptional predecessors and successors into maps of all predecessors and successors. The
   * values stored in both argument maps must be {@link List}s of {@link Unit}s, which are assumed
   * not to contain any duplicate <tt>Unit</tt>s.
   *
   * @param mapA The first map to be combined.
   * @param mapB The second map to be combined.
   */
  protected Map combineMapValues(Map mapA, Map mapB) {
    // The duplicate screen
    Map result = new HashMap(mapA.size() * 2 + 1, 0.7f);
    for (Iterator chainIt = unitChain.iterator(); chainIt.hasNext(); ) {
      Unit unit = (Unit) chainIt.next();
      List listA = (List) mapA.get(unit);
      if (listA == null) {
        listA = Collections.EMPTY_LIST;
      }
      List listB = (List) mapB.get(unit);
      if (listB == null) {
        listB = Collections.EMPTY_LIST;
      }

      int resultSize = listA.size() + listB.size();
      if (resultSize == 0) {
        result.put(unit, Collections.EMPTY_LIST);
      } else {
        List resultList = new ArrayList(resultSize);
        Iterator listIt = null;
        // As a minor optimization of the duplicate screening,
        // copy the longer list first.
        if (listA.size() >= listB.size()) {
          resultList.addAll(listA);
          listIt = listB.iterator();
        } else {
          resultList.addAll(listB);
          listIt = listA.iterator();
        }
        while (listIt.hasNext()) {
          Object element = listIt.next();
          // It is possible for there to be both an exceptional
          // and an unexceptional edge connecting two Units
          // (though probably not in a class generated by
          // javac), so we need to screen for duplicates. On the
          // other hand, we expect most of these lists to have
          // only one or two elements, so it doesn't seem worth
          // the cost to build a Set to do the screening.
          if (!resultList.contains(element)) {
            resultList.add(element);
          }
        }
        result.put(unit, Collections.unmodifiableList(resultList));
      }
    }
    return result;
  }
示例#7
0
 /**
  * Utility method for adding an edge to maps representing the CFG.
  *
  * @param unitToSuccs The {@link Map} from {@link Unit}s to {@link List}s of their successors.
  * @param unitToPreds The {@link Map} from {@link Unit}s to {@link List}s of their successors.
  * @param head The {@link Unit} from which the edge starts.
  * @param tail The {@link Unit} to which the edge flows.
  */
 protected void addEdge(Map unitToSuccs, Map unitToPreds, Unit head, Unit tail) {
   List headsSuccs = (List) unitToSuccs.get(head);
   if (headsSuccs == null) {
     headsSuccs = new ArrayList(3); // We expect this list to
     // remain short.
     unitToSuccs.put(head, headsSuccs);
   }
   if (!headsSuccs.contains(tail)) {
     headsSuccs.add(tail);
     List tailsPreds = (List) unitToPreds.get(tail);
     if (tailsPreds == null) {
       tailsPreds = new ArrayList();
       unitToPreds.put(tail, tailsPreds);
     }
     tailsPreds.add(head);
   }
 }
示例#8
0
  public void outAIdentityNoTypeStatement(AIdentityNoTypeStatement node) {
    mProductions.removeLast(); // get rid of @caughtexception string presently on top of the stack
    Value local =
        (Value) mLocals.get(mProductions.removeLast()); // the local ref from it's identifier

    Unit u = Jimple.v().newIdentityStmt(local, Jimple.v().newCaughtExceptionRef());
    mProductions.addLast(u);
  }
示例#9
0
  private void addBoxToPatch(String aLabelName, UnitBox aUnitBox) {
    List patchList = (List) mLabelToPatchList.get(aLabelName);
    if (patchList == null) {
      patchList = new ArrayList();
      mLabelToPatchList.put(aLabelName, patchList);
    }

    patchList.add(aUnitBox);
  }
示例#10
0
  public void outAArrayRef(AArrayRef node) {
    Value immediate = (Value) mProductions.removeLast();
    String identifier = (String) mProductions.removeLast();

    Local l = (Local) mLocals.get(identifier);
    if (l == null) throw new RuntimeException("did not find local: " + identifier);

    mProductions.addLast(Jimple.v().newArrayRef(l, immediate));
  }
示例#11
0
  public void outALocalFieldRef(ALocalFieldRef node) {
    SootFieldRef field = (SootFieldRef) mProductions.removeLast();

    String local = (String) mProductions.removeLast();

    Local l = (Local) mLocals.get(local);
    if (l == null) throw new RuntimeException("did not find local: " + local);

    mProductions.addLast(Jimple.v().newInstanceFieldRef(l, field));
  }
示例#12
0
  /**
   * Utility method for <tt>UnitGraph</tt> constructors. It computes the edges corresponding to
   * unexceptional control flow.
   *
   * @param unitToSuccs A {@link Map} from {@link Unit}s to {@link List}s of {@link Unit}s. This is
   *     an ``out parameter''; callers must pass an empty {@link Map}.
   *     <tt>buildUnexceptionalEdges</tt> will add a mapping for every <tt>Unit</tt> in the body to
   *     a list of its unexceptional successors.
   * @param unitToPreds A {@link Map} from {@link Unit}s to {@link List}s of {@link Unit}s. This is
   *     an ``out parameter''; callers must pass an empty {@link Map}.
   *     <tt>buildUnexceptionalEdges</tt> will add a mapping for every <tt>Unit</tt> in the body to
   *     a list of its unexceptional predecessors.
   */
  protected void buildUnexceptionalEdges(Map unitToSuccs, Map unitToPreds) {

    // Initialize the predecessor sets to empty
    for (Iterator unitIt = unitChain.iterator(); unitIt.hasNext(); ) {
      unitToPreds.put(unitIt.next(), new ArrayList());
    }

    Iterator unitIt = unitChain.iterator();
    Unit currentUnit, nextUnit;

    nextUnit = unitIt.hasNext() ? (Unit) unitIt.next() : null;

    while (nextUnit != null) {
      currentUnit = nextUnit;
      nextUnit = unitIt.hasNext() ? (Unit) unitIt.next() : null;

      List successors = new ArrayList();

      if (currentUnit.fallsThrough()) {
        // Add the next unit as the successor
        if (nextUnit != null) {
          successors.add(nextUnit);
          ((List) unitToPreds.get(nextUnit)).add(currentUnit);
        }
      }

      if (currentUnit.branches()) {
        for (Iterator targetIt = currentUnit.getUnitBoxes().iterator(); targetIt.hasNext(); ) {
          Unit target = ((UnitBox) targetIt.next()).getUnit();
          // Arbitrary bytecode can branch to the same
          // target it falls through to, so we screen for duplicates:
          if (!successors.contains(target)) {
            successors.add(target);
            ((List) unitToPreds.get(target)).add(currentUnit);
          }
        }
      }

      // Store away successors
      unitToSuccs.put(currentUnit, successors);
    }
  }
示例#13
0
  public void outAIdentityStatement(AIdentityStatement node) {
    Type identityRefType = (Type) mProductions.removeLast();
    String atClause = (String) mProductions.removeLast();
    Value local =
        (Value) mLocals.get(mProductions.removeLast()); // the local ref from it's identifier

    Value ref = null;
    if (atClause.startsWith("@this")) {
      ref = Jimple.v().newThisRef((RefType) identityRefType);
    } else if (atClause.startsWith("@parameter")) {
      int index = Integer.parseInt(atClause.substring(10, atClause.length() - 1));

      ref = Jimple.v().newParameterRef(identityRefType, index);
    } else
      throw new RuntimeException(
          "shouldn't @caughtexception be handled by outAIdentityNoTypeStatement: got" + atClause);

    Unit u = Jimple.v().newIdentityStmt(local, ref);
    mProductions.addLast(u);
  }
示例#14
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;
  }
示例#15
0
  public List getSuccsOf(Object u) {
    if (!unitToSuccs.containsKey(u)) throw new RuntimeException("Invalid unit " + u);

    return (List) unitToSuccs.get(u);
  }
示例#16
0
  public void outAFullMethodBody(AFullMethodBody node) {
    Object catchClause = null;
    JimpleBody jBody = Jimple.v().newBody();

    if (node.getCatchClause() != null) {
      int size = node.getCatchClause().size();
      for (int i = 0; i < size; i++) jBody.getTraps().addFirst((Trap) mProductions.removeLast());
    }

    if (node.getStatement() != null) {
      int size = node.getStatement().size();
      Unit lastStmt = null;
      for (int i = 0; i < size; i++) {
        Object o = mProductions.removeLast();
        if (o instanceof Unit) {
          jBody.getUnits().addFirst(o);
          lastStmt = (Unit) o;
        } else if (o instanceof String) {
          if (lastStmt == null) throw new RuntimeException("impossible");
          mLabelToStmtMap.put(o, lastStmt);
        } else throw new RuntimeException("impossible");
      }
    }

    if (node.getDeclaration() != null) {
      int size = node.getDeclaration().size();
      for (int i = 0; i < size; i++) {
        List localList = (List) mProductions.removeLast();

        int listSize = localList.size();
        for (int j = listSize - 1; j >= 0; j--) jBody.getLocals().addFirst(localList.get(j));
      }
    }

    Iterator it = mLabelToPatchList.keySet().iterator();
    while (it.hasNext()) {
      String label = (String) it.next();
      Unit target = (Unit) mLabelToStmtMap.get(label);

      Iterator patchIt = ((List) mLabelToPatchList.get(label)).iterator();
      while (patchIt.hasNext()) {
        UnitBox box = (UnitBox) patchIt.next();
        box.setUnit(target);
      }
    }

    /*
    Iterator it = mLabelToStmtMap.keySet().iterator();
    while(it.hasNext()) {
        String label = (String) it.next();
        Unit target = (Unit) mLabelToStmtMap.get(label);

        List l =         (List) mLabelToPatchList.get(label);
        if(l != null) {
            Iterator patchIt = l.iterator();
            while(patchIt.hasNext()) {
                UnitBox box = (UnitBox) patchIt.next();
                box.setUnit(target);
            }
        }
    }
    */

    mProductions.addLast(jBody);
  }
示例#17
0
 private ThrowableSet getMemoizedAdds(Object key) {
   if (memoizedAdds == null) {
     memoizedAdds = new HashMap();
   }
   return (ThrowableSet) memoizedAdds.get(key);
 }