Beispiel #1
0
 private boolean orderGuaranteed(CFGNode n1, Branch br2, boolean interproc) {
   return orderGuaranteed(
       Options.reachability()
           ? ReachabilityAnalysis.reachesFromTop(br2.getTgt(), n1, interproc)
           : true,
       n1,
       br2);
 }
Beispiel #2
0
  private DUAAnalysis() {
    // prepare required collection and map
    List<SootMethod> allReachableMethods = ProgramFlowGraph.inst().getReachableAppMethods();
    Map<SootMethod, ReachableUsesDefs> methodsToReachUseDefs =
        dua.util.Util.convertToRUMap(ProgramFlowGraph.inst().getMethodToCFGMap());

    if (!Options.localDUAsOnly())
      computeFieldArrayObjDUAs(allReachableMethods, methodsToReachUseDefs);

    // goal: find inter-proc uses for each param of each method (reachable from entry)

    // ReachableUses already inited param to local real uses, and linked params to local call uses

    // iteratively:
    // for each method, add to each param all real uses of call uses for that param
    ArrayList<SootMethod> worklist = new ArrayList<SootMethod>(allReachableMethods);
    int propCount = 1;
    while (!worklist.isEmpty()) {
      System.out.println("Inter-procedural reachable uses to params iteration #" + propCount++);
      for (SootMethod m : (ArrayList<SootMethod>) worklist.clone()) {
        worklist.remove(m);

        ReachableUsesDefs ru = methodsToReachUseDefs.get(m);
        if (ru.propagateAllUsesDefsToParams(methodsToReachUseDefs)) {
          MethodTag mTag = (MethodTag) m.getTag(MethodTag.TAG_NAME);
          for (SootMethod mCaller : mTag.getCallerMethods()) {
            MethodTag mCallerTag = (MethodTag) mCaller.getTag(MethodTag.TAG_NAME);
            if (mCallerTag.isReachableFromEntry()) worklist.add(mCaller);
          }
        }
      }
    }

    for (SootMethod m : allReachableMethods) {
      ReachableUsesDefs ru = methodsToReachUseDefs.get(m);

      // DEBUG
      ru.dumpReachUsesDefs();

      ru.findLocalUsesDefsForDefs(methodsToReachUseDefs);
    }

    // for each def, create duas for local real uses and real uses of params in call uses
    // also, collect statistics
    // first, determine # interproc defs per use
    HashMap<Use, Integer> interProcDefsPerUse =
        new HashMap<Use, Integer>(); // maps use -> # interproc defs
    for (SootMethod m : allReachableMethods) {
      ReachableUsesDefs ru = methodsToReachUseDefs.get(m);
      HashMap<Def, HashMap<Use, ArrayList<Use>>> dus = ru.getDUs();
      for (Def def : dus.keySet()) {
        Map<Use, ArrayList<Use>> usesMap = dus.get(def);
        for (Use use : usesMap.keySet()) {
          // determine and update # of interproc defs for use
          Integer numInterDefs = interProcDefsPerUse.get(use);
          if (numInterDefs == null) {
            numInterDefs = 0;
            interProcDefsPerUse.put(use, numInterDefs); // just init entry in map
          }
        }
      }
    }

    // create local var DUAs
    int cDuas = 0, pDuas = 0, cIntraOnly = 0, cInterOnly = 0, pIntraOnly = 0, pInterOnly = 0;
    int numKills = 0, minKills = Integer.MAX_VALUE, maxKills = 0;
    int possibleKills = 0, subsDuasWithPossKill = 0;
    ArrayList<Integer> useCallDepthsCount = new ArrayList<Integer>();
    for (SootMethod m : allReachableMethods) { // methods are sorted
      if (verbose) System.out.print("Local-var duas for " + m + ": ");

      // build map stmt->idx
      ReachableUsesDefs ru = methodsToReachUseDefs.get(m);
      HashMap<Def, HashMap<Use, ArrayList<Use>>> dus = ru.getDUs();
      HashMap<Def, HashSet<Def>> dds = ru.getDDs();

      // determine subsumability and update stats for these DUAs / DDAs
      List<Def> sortedDefs = new ArrayList<Def>(dus.keySet());
      Collections.sort(sortedDefs, new DefComparator());
      for (Def def : sortedDefs) {
        HashSet<Def> defKills = dds.get(def);

        if (verbose) System.out.print(def + "={");

        Map<Use, ArrayList<Use>> realToLocalUsesMap = dus.get(def);
        List<Use> sortedUses = new ArrayList<Use>(realToLocalUsesMap.keySet());
        Collections.sort(sortedUses, new UseComparator());
        for (Use use : sortedUses) {
          // determine type of use (c or p; intra or inter)
          PUse pUse = (use instanceof PUse) ? (PUse) use : null;

          // determine D-U node order, taking use's src statement first, and tgt if puse
          CFGNode nDef = def.getN();
          CFGNode nUseSrc = use.getSrcNode();
          CFGNode nUseTgt = (pUse == null) ? null : use.getBranch().getTgt();
          Branch brUse = use.getBranch();
          final boolean useReachesDef =
              Options.reachability()
                  ? ((pUse == null)
                      ? ReachabilityAnalysis.reachesFromTop(nUseSrc, nDef, true)
                      : ReachabilityAnalysis.reachesFromTop(nUseTgt, nDef, true))
                  : true; // assume use reaches def, if no reachability analysis available
          final boolean duInNodeOrder =
              (pUse == null)
                  ? orderGuaranteed(useReachesDef, nDef, nUseSrc)
                  : orderGuaranteed(useReachesDef, nDef, brUse);

          // get # interproc defs for use
          final int numInterProcDefs = interProcDefsPerUse.get(use);

          // create and store DUA(s)
          // d-u event order is guaranteed if d-u node order is guaranteed,
          // and if use doesn't have multiple inter-proc defs
          // (p-uses with > 1 defs will be considered later)
          final boolean duEventOrderGuaranteed = duInNodeOrder && numInterProcDefs <= 1;
          ArrayList<Use> localUses = realToLocalUsesMap.get(use);
          Use[] localUsesArr = new Use[localUses.size()];
          int uId = 0;
          for (Use u : localUses) localUsesArr[uId++] = u;
          DUA dua = new DUA(def, use, localUsesArr, duEventOrderGuaranteed);
          duaSet.addDUA(dua);

          // DEBUG
          if (verbose) System.out.print((duEventOrderGuaranteed ? "" : "(P)") + use + "[");

          // increment c-use/p-use counter
          if (pUse == null) ++cDuas;
          else ++pDuas;

          // determine kills for this DUA, and update kill stats
          int killsForThisDua = 0;
          int possKillsForThisDua = 0;
          if (defKills != null) {
            for (Def kill : defKills) {
              if (kill != def) {
                // get dus for kill's method
                SootMethod mKill =
                    ProgramFlowGraph.inst().getContainingMethod(kill.getN().getStmt());
                HashMap<Def, HashMap<Use, ArrayList<Use>>> killDUs =
                    methodsToReachUseDefs.get(mKill).getDUs();
                Set<Use> usesForKill = null;
                if (killDUs.get(kill) != null) usesForKill = killDUs.get(kill).keySet();
                if (usesForKill != null && usesForKill.contains(use)) { // kills this DUA
                  CFGNode nKill = kill.getN();
                  final boolean killAligned =
                      orderGuaranteed(nDef, nKill, true)
                          && ((pUse == null)
                              ? orderGuaranteed(nKill, nUseSrc, true)
                              : orderGuaranteed(nKill, brUse, true));

                  if (verbose) System.out.print((killAligned ? "" : "(P)") + kill + ",");

                  ++killsForThisDua;
                  // not only kill must be aligned, but use must not reach def
                  if (!useReachesDef && killAligned) dua.addKillInOrder(kill);
                  else {
                    dua.addKillNotInOrder(kill);
                    ++possKillsForThisDua;
                  }
                }
              }
            }
          }
          numKills += killsForThisDua;
          if (killsForThisDua < minKills) minKills = killsForThisDua;
          if (killsForThisDua > maxKills) maxKills = killsForThisDua;
          possibleKills += possKillsForThisDua;
          if (duEventOrderGuaranteed) subsDuasWithPossKill += possKillsForThisDua;

          if (verbose) System.out.print("],");
        }

        if (verbose) System.out.print("}, ");
      }

      // after regular DUAs, store same-BB dus
      duaSet.addSameBBDUs(ru.getSameBBDUs());

      if (verbose) System.out.println();
    }
    duaSet.updateInferrability();

    // inferrability stats
    final int numAllDuas = duaSet.getAllDUAs().size();
    int inferrDuas = 0, condInfDuas = 0, nonInfDuas = 0;
    int inferrDuasIntra = 0, condInfDuasIntra = 0, nonInfDuasIntra = 0;
    for (DUA dua : duaSet.getAllDUAs()) {
      SootMethod m = ProgramFlowGraph.inst().getContainingMethod(dua.getDef().getN().getStmt());
      ReachableUsesDefs ru = methodsToReachUseDefs.get(m);

      if (dua.isInferrableOrCondInf()) {
        if (dua.isDefinitelyInferrable()) {
          ++inferrDuas;
        } else {
          ++condInfDuas;
        }
      } else {
        ++nonInfDuas;
      }
    }

    final int totalDuas = cDuas + pDuas;
    final int totalIntra = cIntraOnly + pIntraOnly;
    final int totalInter = cInterOnly + pInterOnly;

    System.out.println(
        "INFERRABILITY: inf "
            + inferrDuas
            + ", cond "
            + condInfDuas
            + ", non-inf "
            + (numAllDuas - inferrDuas - condInfDuas));
    System.out.println(
        "INF: intra " + inferrDuasIntra + ", inter " + (inferrDuas - inferrDuasIntra));
    System.out.println(
        "COND-INF: intra " + condInfDuasIntra + ", inter " + (condInfDuas - condInfDuasIntra));
    assert nonInfDuasIntra == (totalIntra - inferrDuasIntra - condInfDuasIntra);
    System.out.println(
        "NON-INF: intra " + nonInfDuasIntra + ", inter " + (nonInfDuas - nonInfDuasIntra));
    for (int i = 1; i < useCallDepthsCount.size(); ++i)
      System.out.print(i + ":" + useCallDepthsCount.get(i) + " ");
    System.out.println();
    if (!useCallDepthsCount.isEmpty() && useCallDepthsCount.get(0) != totalDuas - totalInter)
      System.out.println(
          "NOTE -- DUAs at depth 0 are "
              + useCallDepthsCount.get(0)
              + ", but intra duas are "
              + (totalDuas - totalInter));

    //		// TEST
    //		reportPaths(methodsToReachUseDefs);

    System.out.println(
        "DUA totals: "
            + totalDuas
            + "; c-duas "
            + cDuas
            + ", p-duas "
            + pDuas
            + "; intra "
            + totalIntra
            + ", inter "
            + totalInter
            + ", both "
            + (totalDuas - totalIntra - totalInter));
    System.out.println(
        "c-DUAs intra "
            + cIntraOnly
            + ", inter "
            + cInterOnly
            + ", both "
            + (cDuas - cIntraOnly - cInterOnly)
            + "; p-DUAs intra "
            + pIntraOnly
            + ", inter "
            + pInterOnly
            + ", both "
            + (pDuas - pIntraOnly - pInterOnly));
  }
Beispiel #3
0
 private boolean orderGuaranteed(CFGNode n1, CFGNode n2, boolean interproc) {
   return orderGuaranteed(
       Options.reachability() ? ReachabilityAnalysis.reachesFromTop(n2, n1, interproc) : true,
       n1,
       n2);
 }