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
/** * 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); } } }