예제 #1
0
  public void staticBlockInlining(SootClass sootClass) {
    this.sootClass = sootClass;
    // retrieve the clinit method if any for sootClass
    if (!sootClass.declaresMethod("void <clinit>()")) {
      System.out.println("no clinit");
      return;
    }

    SootMethod clinit = sootClass.getMethod("void <clinit>()");
    // System.out.println(clinit);

    // retireve the active body
    if (!clinit.hasActiveBody())
      throw new RuntimeException("method " + clinit.getName() + " has no active body!");

    Body clinitBody = clinit.getActiveBody();

    Chain units = ((DavaBody) clinitBody).getUnits();

    if (units.size() != 1) {
      throw new RuntimeException("DavaBody AST doesn't have single root.");
    }

    ASTNode AST = (ASTNode) units.getFirst();
    if (!(AST instanceof ASTMethodNode))
      throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode");

    AST.apply(new MethodCallFinder(this));
  }
예제 #2
0
  private void printStatementsInBody(Body body, java.io.PrintWriter out) {

    if (Options.v().verbose()) System.out.println("Printing " + body.getMethod().getName());

    Chain<Unit> units = ((DavaBody) body).getUnits();

    if (units.size() != 1) {
      throw new RuntimeException("DavaBody AST doesn't have single root.");
    }

    UnitPrinter up = new DavaUnitPrinter((DavaBody) body);
    ((ASTNode) units.getFirst()).toString(up);
    out.print(up.toString());
  }
예제 #3
0
  protected void internalTransform(Body body, String phaseName, Map options) {
    if (Options.v().verbose())
      G.v().out.println("[" + body.getMethod().getName() + "] Tightening trap boundaries...");

    Chain trapChain = body.getTraps();
    Chain unitChain = body.getUnits();
    if (trapChain.size() > 0) {
      ExceptionalUnitGraph graph = new ExceptionalUnitGraph(body);

      for (Iterator trapIt = trapChain.iterator(); trapIt.hasNext(); ) {
        Trap trap = (Trap) trapIt.next();
        Unit firstTrappedUnit = trap.getBeginUnit();
        Unit firstTrappedThrower = null;
        Unit firstUntrappedUnit = trap.getEndUnit();
        Unit lastTrappedUnit = (Unit) unitChain.getPredOf(firstUntrappedUnit);
        Unit lastTrappedThrower = null;
        for (Unit u = firstTrappedUnit;
            u != null && u != firstUntrappedUnit;
            u = (Unit) unitChain.getSuccOf(u)) {
          if (mightThrowTo(graph, u, trap)) {
            firstTrappedThrower = u;
            break;
          }
        }
        if (firstTrappedThrower != null) {
          for (Unit u = lastTrappedUnit; u != null; u = (Unit) unitChain.getPredOf(u)) {
            if (mightThrowTo(graph, u, trap)) {
              lastTrappedThrower = u;
              break;
            }
          }
        }
        if (firstTrappedThrower != null && firstTrappedUnit != firstTrappedThrower) {
          trap.setBeginUnit(firstTrappedThrower);
        }
        if (lastTrappedThrower == null) {
          lastTrappedThrower = firstTrappedUnit;
        }
        if (lastTrappedUnit != lastTrappedThrower) {
          trap.setEndUnit((Unit) unitChain.getSuccOf(lastTrappedThrower));
        }
      }
    }
  }
예제 #4
0
  public ASTMethodNode inline(SootMethod maybeInline) {
    // check if this method should be inlined

    if (sootClass != null) {
      // 1, method should belong to the same class as the clinit method
      if (sootClass.declaresMethod(maybeInline.getSubSignature())) {
        // System.out.println("The method invoked is from the same class");
        // 2, method should be static

        if (Modifier.isStatic(maybeInline.getModifiers())) {
          // decided to inline
          // send the ASTMethod node of the TO BE INLINED METHOD

          // retireve the active body
          if (!maybeInline.hasActiveBody())
            throw new RuntimeException("method " + maybeInline.getName() + " has no active body!");

          Body bod = maybeInline.getActiveBody();

          Chain units = ((DavaBody) bod).getUnits();

          if (units.size() != 1) {
            throw new RuntimeException("DavaBody AST doesn't have single root.");
          }

          ASTNode ASTtemp = (ASTNode) units.getFirst();
          if (!(ASTtemp instanceof ASTMethodNode))
            throw new RuntimeException("Starting node of DavaBody AST is not an ASTMethodNode");

          // restricting to methods which do not have any variables declared
          ASTMethodNode toReturn = (ASTMethodNode) ASTtemp;

          ASTStatementSequenceNode declarations = toReturn.getDeclarations();
          if (declarations.getStatements().size() == 0) {
            // inline only if there are no declarations in the method inlined
            System.out.println("No declarations in the method. we can inline this method");
            return toReturn;
          }
        }
      }
    }
    return null; // meaning dont inline
  }
예제 #5
0
 public int size() {
   return unitChain.size();
 }
예제 #6
0
  /** Constructs a hierarchy from the current scene. */
  public Hierarchy() {
    this.sc = Scene.v();
    state = sc.getState();

    // Well, this used to be describable by 'Duh'.
    // Construct the subclasses hierarchy and the subinterfaces hierarchy.
    {
      Chain allClasses = sc.getClasses();

      classToSubclasses = new HashMap<SootClass, List<SootClass>>(allClasses.size() * 2 + 1, 0.7f);
      interfaceToSubinterfaces =
          new HashMap<SootClass, List<SootClass>>(allClasses.size() * 2 + 1, 0.7f);

      classToDirSubclasses = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f);
      interfaceToDirSubinterfaces = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f);
      interfaceToDirImplementers = new HashMap<SootClass, List>(allClasses.size() * 2 + 1, 0.7f);

      Iterator classesIt = allClasses.iterator();
      while (classesIt.hasNext()) {
        SootClass c = (SootClass) classesIt.next();
        if (c.resolvingLevel() < SootClass.HIERARCHY) continue;

        if (c.isInterface()) {
          interfaceToDirSubinterfaces.put(c, new ArrayList());
          interfaceToDirImplementers.put(c, new ArrayList());
        } else classToDirSubclasses.put(c, new ArrayList());
      }

      classesIt = allClasses.iterator();
      while (classesIt.hasNext()) {
        SootClass c = (SootClass) classesIt.next();
        if (c.resolvingLevel() < SootClass.HIERARCHY) continue;

        if (c.hasSuperclass()) {
          if (c.isInterface()) {
            Iterator subIt = c.getInterfaces().iterator();

            while (subIt.hasNext()) {
              SootClass i = (SootClass) subIt.next();
              if (c.resolvingLevel() < SootClass.HIERARCHY) continue;
              List<SootClass> l = interfaceToDirSubinterfaces.get(i);
              l.add(c);
            }
          } else {
            List<SootClass> l = classToDirSubclasses.get(c.getSuperclass());
            l.add(c);

            Iterator subIt = c.getInterfaces().iterator();

            while (subIt.hasNext()) {
              SootClass i = (SootClass) subIt.next();
              if (c.resolvingLevel() < SootClass.HIERARCHY) continue;
              l = interfaceToDirImplementers.get(i);
              l.add(c);
            }
          }
        }
      }

      // Fill the directImplementers lists with subclasses.
      {
        classesIt = allClasses.iterator();
        while (classesIt.hasNext()) {
          SootClass c = (SootClass) classesIt.next();
          if (c.resolvingLevel() < SootClass.HIERARCHY) continue;
          if (c.isInterface()) {
            List<SootClass> imp = interfaceToDirImplementers.get(c);
            Set<SootClass> s = new ArraySet();

            Iterator<SootClass> impIt = imp.iterator();
            while (impIt.hasNext()) {
              SootClass c0 = impIt.next();
              if (c.resolvingLevel() < SootClass.HIERARCHY) continue;
              s.addAll(getSubclassesOfIncluding(c0));
            }

            imp.clear();
            imp.addAll(s);
          }
        }
      }

      classesIt = allClasses.iterator();
      while (classesIt.hasNext()) {
        SootClass c = (SootClass) classesIt.next();
        if (c.resolvingLevel() < SootClass.HIERARCHY) continue;

        if (c.isInterface()) {
          interfaceToDirSubinterfaces.put(
              c, Collections.unmodifiableList(interfaceToDirSubinterfaces.get(c)));
          interfaceToDirImplementers.put(
              c, Collections.unmodifiableList(interfaceToDirImplementers.get(c)));
        } else
          classToDirSubclasses.put(c, Collections.unmodifiableList(classToDirSubclasses.get(c)));
      }
    }
  }
예제 #7
0
  void doWeave(
      SootMethod method,
      LocalGeneratorEx lg,
      AdviceApplication adviceappl,
      Residue residue,
      WeavingContext wc) {
    AdviceInliner.v().addShadowMethod(method);
    ShadowPoints shadowpoints = adviceappl.shadowmatch.sp;
    AbstractAdviceDecl advicedecl = adviceappl.advice;

    Body b = method.getActiveBody();
    Chain units = b.getUnits().getNonPatchingChain();

    // end of shadow
    Stmt endshadow = shadowpoints.getEnd();

    NopStmt nop2 = Jimple.v().newNopStmt();
    GotoStmt goto1 = Jimple.v().newGotoStmt(nop2);
    if (advicedecl instanceof CflowSetup) {
      Tagger.tagStmt(goto1, InstructionKindTag.CFLOW_EXIT);
    } else if (advicedecl instanceof PerCflowSetup) {
      Tagger.tagStmt(goto1, InstructionKindTag.PERCFLOW_EXIT);
    } else if (advicedecl instanceof DeclareSoft) {
      Tagger.tagStmt(goto1, InstructionKindTag.EXCEPTION_SOFTENER);
    } else if (advicedecl instanceof DeclareMessage) {
      Tagger.tagStmt(goto1, InstructionKindTag.DECLARE_MESSAGE);
    } else {
      Tagger.tagStmt(goto1, InstructionKindTag.AFTER_THROWING_HANDLER);
    }
    Tagger.tagStmt(goto1, new InstructionSourceTag(advicedecl.sourceId));
    Tagger.tagStmt(goto1, new InstructionShadowTag(adviceappl.shadowmatch.shadowId));
    units.insertBefore(nop2, endshadow);
    units.insertBefore(goto1, nop2);

    // have ...
    //    goto1:      goto nop2;
    //    nop2:       nop;
    //    endshadow:  nop;

    RefType catchType = getCatchType();
    Local exception = lg.generateLocal(catchType, "exception");
    bindException(wc, advicedecl, exception);

    CaughtExceptionRef exceptRef = Jimple.v().newCaughtExceptionRef();
    IdentityStmt idStmt = Jimple.v().newIdentityStmt(exception, exceptRef);
    units.insertAfter(idStmt, goto1);

    ThrowStmt throwStmt = Jimple.v().newThrowStmt(exception);
    throwStmt.addTag(new ThrowCreatedByCompilerTag());

    if (advicedecl instanceof CflowSetup) {
      Tagger.tagStmt(throwStmt, InstructionKindTag.CFLOW_EXIT);
    } else if (advicedecl instanceof PerCflowSetup) {
      Tagger.tagStmt(throwStmt, InstructionKindTag.PERCFLOW_EXIT);
    } else if (advicedecl instanceof DeclareSoft) {
      Tagger.tagStmt(throwStmt, InstructionKindTag.EXCEPTION_SOFTENER);
    } else if (advicedecl instanceof DeclareMessage) {
      Tagger.tagStmt(throwStmt, InstructionKindTag.DECLARE_MESSAGE);
    } else {
      Tagger.tagStmt(throwStmt, InstructionKindTag.AFTER_THROWING_HANDLER);
    }
    Tagger.tagStmt(throwStmt, new InstructionSourceTag(advicedecl.sourceId));
    Tagger.tagStmt(throwStmt, new InstructionShadowTag(adviceappl.shadowmatch.shadowId));

    // store shadow/source tag for this residue in weaving context
    if (advicedecl instanceof CflowSetup) {
      wc.setKindTag(InstructionKindTag.CFLOW_TEST);
    }
    if (advicedecl instanceof PerCflowSetup) {
      wc.setKindTag(InstructionKindTag.CFLOW_TEST);
    }
    wc.setShadowTag(new InstructionShadowTag(adviceappl.shadowmatch.shadowId));
    wc.setSourceTag(new InstructionSourceTag(adviceappl.advice.sourceId));

    Stmt endresidue = residue.codeGen(method, lg, units, idStmt, throwStmt, true, wc);

    // have ...
    //    java.lang.Exception exception;
    //
    //    goto1:      goto nop2;
    //    idStmt:     exception := @caughtexception
    //    nop2:       nop;
    //    endshadow:  nop;

    units.insertAfter(throwStmt, endresidue);

    Chain invokestmts = advicedecl.makeAdviceExecutionStmts(adviceappl, lg, wc);

    for (Iterator stmtlist = invokestmts.iterator(); stmtlist.hasNext(); ) {
      Stmt nextstmt = (Stmt) stmtlist.next();
      units.insertBefore(nextstmt, throwStmt);
    }

    if (method.getName().equals("<clinit>"))
    // have to handle case of ExceptionInInitialzerError
    { //  if (exception instanceof java.lang.ExceptionInIntializerError)
      //     throw (exception);
      debug("Adding extra check in clinit");

      Local isInitError = lg.generateLocal(soot.BooleanType.v(), "isInitError");

      Stmt assignbool =
          Jimple.v()
              .newAssignStmt(
                  isInitError,
                  Jimple.v()
                      .newInstanceOfExpr(
                          exception, RefType.v("java.lang.ExceptionInInitializerError")));

      Stmt ifstmt =
          Jimple.v().newIfStmt(Jimple.v().newNeExpr(isInitError, IntConstant.v(0)), throwStmt);

      //	     ThrowStmt throwInitError = Jimple.v().newThrowStmt(exception);

      //	     units.insertAfter(throwInitError, idStmt);
      units.insertAfter(ifstmt, idStmt);
      units.insertAfter(assignbool, idStmt);
    }

    Stmt beginshadow = shadowpoints.getBegin();
    Stmt begincode = (Stmt) units.getSuccOf(beginshadow);

    // have ...
    //    java.lang.Exception exception;
    //    <AspectType> theAspect;
    //
    //    beginshadow:   nop
    //    begincode:     <some statement>
    //       ....        <stuff in between>
    //    goto1:         goto nop2;
    //    idStmt:        exception := @caughtexception;
    //    assignStmt:    theAspect = new AspectOf();
    //             .... invoke statements ....
    //    throwStmt:     throw exception;
    //    nop2:          nop;
    //    endshadow:     nop;

    Chain traps = b.getTraps();
    Trap t = traps.size() > 0 ? (Trap) traps.getFirst() : null;

    // assume no exception ranges overlap with this one; make sure
    // we go after any that would be enclosed within this one.
    while (t != null
        && (units.follows(t.getBeginUnit(), begincode)
            || (t.getBeginUnit() == begincode && units.follows(idStmt, t.getEndUnit()))))
      t = (Trap) traps.getSuccOf(t);

    Trap newt = Jimple.v().newTrap(catchType.getSootClass(), begincode, idStmt, idStmt);

    if (t == null) traps.addLast(newt);
    else traps.insertBefore(newt, t);

    //  added
    //     catch java.lang.Throwable
    //         from begincode upto idStmt handlewith idStmt

  } // method doWeave
예제 #8
0
  /**
   * Constructs a graph for the units found in the provided Body instance. Each node in the graph
   * corresponds to a unit. The edges are derived from the control flow.
   *
   * @param body The underlying body we want to make a graph for.
   * @param addExceptionEdges If true then the control flow edges associated with exceptions are
   *     added.
   * @param dontAddEdgeFromStmtBeforeAreaOfProtectionToCatchBlock This was added for Dava. If true,
   *     edges are not added from statement before area of protection to catch. If false, edges ARE
   *     added. For Dava, it should be true. For flow analyses, it should be false.
   * @param Hierarchy Using class hierarchy analysis to find the run method of started thread
   * @param PointsToAnalysis Using point to analysis (SPARK package) to improve the precision of
   *     results
   */
  public PegGraph(
      CallGraph callGraph,
      Hierarchy hierarchy,
      PAG pag,
      Set methodsNeedingInlining,
      Set allocNodes,
      List<List> inlineSites,
      Map<SootMethod, String> synchObj,
      Set multiRunAllocNodes,
      Map<AllocNode, String> allocNodeToObj,
      Body unitBody,
      String threadName,
      SootMethod sm,
      boolean addExceEdge,
      boolean dontAddEdgeFromStmtBeforeAreaOfProtectionToCatchBlock) {
    this.allocNodeToObj = allocNodeToObj;
    this.multiRunAllocNodes = multiRunAllocNodes;
    this.synchObj = synchObj;
    this.inlineSites = inlineSites;
    this.allocNodes = allocNodes;
    this.methodsNeedingInlining = methodsNeedingInlining;
    logFile = new File("log.txt");
    try {
      fileWriter = new FileWriter(logFile);
    } catch (IOException io) {
      System.err.println("Errors occur during create FileWriter !");
      //			throw io;
    }

    body = unitBody;
    synch = new HashSet<List>();
    exceHandlers = new HashSet<Unit>();
    needInlining = true;
    monitorObjs = new HashSet<Object>();
    startToBeginNodes = new HashMap();
    unitChain = body.getUnits();
    int size = unitChain.size();
    // initial unitToSuccs, unitToPreds, unitToPegMap, and startToThread
    unitToSuccs = new HashMap(size * 2 + 1, 0.7f);
    unitToPreds = new HashMap(size * 2 + 1, 0.7f);
    // unitToPegMap is the map of a chain to its corresponding (cfg node --> peg node ) map.
    unitToPegMap = new HashMap(size * 2 + 1, 0.7f);
    startToThread = new HashMap(size * 2 + 1, 0.7f);
    startToAllocNodes = new HashMap(size * 2 + 1, 0.7f);
    waitingNodes = new HashMap<String, FlowSet>(size * 2 + 1, 0.7f);
    joinStmtToThread = new HashMap<JPegStmt, Chain>();
    threadNo = new HashMap();
    threadNameToStart = new HashMap();
    this.allocNodeToObj = new HashMap<AllocNode, String>(size * 2 + 1, 0.7f);
    allocNodeToThread = new HashMap<AllocNode, PegChain>(size * 2 + 1, 0.7f);
    notifyAll = new HashMap<String, Set<JPegStmt>>(size * 2 + 1, 0.7f);

    methodsNeedingInlining = new HashSet();
    allNodes = new ArraySparseSet();
    canNotBeCompacted = new HashSet();
    threadAllocSites = new HashSet();
    specialJoin = new HashSet<JPegStmt>();
    //       if(Main.isVerbose)
    //   System.out.println("     Constructing PegGraph...");

    // if(Main.isProfilingOptimization)
    //   Main.graphTimer.start();
    // make a peg for debug
    /*
    mainPegChain = new HashChain();
    specialTreatment1();
    */
    // end make a peg

    UnitGraph mainUnitGraph = new CompleteUnitGraph(body);
    //	mainPegChain = new HashChain();
    mainPegChain =
        new PegChain(
            callGraph,
            hierarchy,
            pag,
            threadAllocSites,
            methodsNeedingInlining,
            allocNodes,
            inlineSites,
            synchObj,
            multiRunAllocNodes,
            allocNodeToObj,
            body,
            sm,
            threadName,
            true,
            this);

    // testPegChain();

    //		System.out.println("finish building chain");
    // testStartToThread();
    // buildSuccessor(mainUnitGraph, mainPegChain,addExceptionEdges);
    //	buildSuccessorForExtendingMethod(mainPegChain);
    // testSet(exceHandlers, "exceHandlers");
    buildSuccessor(mainPegChain);
    // System.out.println("finish building successors");
    // unmodifiableSuccs(mainPegChain);
    // testUnitToSucc );
    buildPredecessor(mainPegChain);
    // System.out.println("finish building predcessors");
    // unmodifiablePreds(mainPegChain);
    // testSynch();
    addMonitorStmt();
    addTag();
    //	System.out.println(this.toString());
    buildHeadsAndTails();

    // testIterator();
    // testWaitingNodes();

    //	System.out.println("finish building heads and tails");

    // testSet(canNotBeCompacted, "canNotBeCompacted");
    //	computeEdgeAndThreadNo();
    //	testExtendingPoints();
    //	testUnitToSucc();

    // testPegChain();
    /*	if (print) {
    PegToDotFile printer1 = new PegToDotFile(this, false, sm.getName());
    }
    */
    try {
      fileWriter.flush();
      fileWriter.close();
    } catch (IOException io) {
      System.err.println("Errors occur during close file  " + logFile.getName());
      //        throw io;
    }
    // System.out.println("==threadAllocaSits==\n"+threadAllocSites.toString());

  }