public MethodExceptionAnalysis( SootClass c, SootMethod m, Map<SootClass, ClassExceptionAnalysis> cm) { method = m; soot_class = c; class_map = cm; body = m.retrieveActiveBody(); trap_begin_exception_sets = new HashMap<Unit, List<TwoValuePair<Trap, Set<SootClass>>>>(); trap_end_exception_sets = new HashMap<Unit, List<TwoValuePair<Trap, Set<SootClass>>>>(); method_exception_set = new HashSet<SootClass>(); for (Trap t : body.getTraps()) { List<TwoValuePair<Trap, Set<SootClass>>> trap_pairs; TwoValuePair<Trap, Set<SootClass>> tvp; if (trap_begin_exception_sets.containsKey( t.getBeginUnit())) { // we assume that if traps have the same begin unit, they must // have the same end unit and the same exception set as well trap_pairs = trap_begin_exception_sets.get(t.getBeginUnit()); tvp = new TwoValuePair<Trap, Set<SootClass>>(t, trap_pairs.get(0).w); // use the same set } else { trap_pairs = new ArrayList<TwoValuePair<Trap, Set<SootClass>>>(); tvp = new TwoValuePair<Trap, Set<SootClass>>(t, new HashSet<SootClass>()); } trap_pairs.add(tvp); trap_begin_exception_sets.put(t.getBeginUnit(), trap_pairs); trap_end_exception_sets.put( t.getEndUnit(), trap_pairs); // May overwrite different list if we don't make the assumption above } }
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)); } } } }
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
@Override @SuppressWarnings("rawtypes") public void internalTransform(Body body, String phaseName, Map options) { final SootMethod method = body.getMethod(); System.out.println(); System.out.println( method.getDeclaringClass().getName() + " :: " + method.getBytecodeSignature()); System.out.println("--- locals ---"); for (Local l : body.getLocals()) System.out.println(" " + l.getName() + " : " + l.getType()); System.out.println("--- units ---"); Unit[] units = body.getUnits().toArray(new Unit[0]); for (int i = 0; i < units.length; i++) { if (units[i].hasTag("StringTag")) { String info = ((StringTag) units[i].getTag("StringTag")).getInfo(); if (info.endsWith("Pre")) System.out.println("\n " + info); } System.out.printf("%4d ", i); if (units[i] instanceof GotoStmt) { System.out.println("goto " + getIndex(units, ((GotoStmt) units[i]).getTarget())); } else if (units[i] instanceof IfStmt) { System.out.println( "if " + ((IfStmt) units[i]).getCondition() + " goto " + getIndex(units, ((IfStmt) units[i]).getTarget())); } else if (units[i] instanceof TableSwitchStmt) { TableSwitchStmt sw = (TableSwitchStmt) units[i]; System.out.println("tswitch(" + sw.getKey() + ")"); final int lowIndex = sw.getLowIndex(); for (int t = 0; t <= sw.getHighIndex() - lowIndex; t++) System.out.println( " case " + (t + lowIndex) + ": goto " + getIndex(units, sw.getTarget(t))); System.out.println(" default: goto " + getIndex(units, sw.getDefaultTarget())); } else if (units[i] instanceof LookupSwitchStmt) { LookupSwitchStmt sw = (LookupSwitchStmt) units[i]; System.out.println("lswitch(" + sw.getKey() + ")"); for (int v = 0; v < sw.getTargetCount(); v++) System.out.println( " case " + sw.getLookupValue(v) + ": goto " + getIndex(units, sw.getTarget(v))); System.out.println(" default: goto " + getIndex(units, sw.getDefaultTarget())); } else if (units[i] instanceof InvokeStmt) { System.out.println(toString(((InvokeStmt) units[i]).getInvokeExpr())); } else if (units[i] instanceof AssignStmt) { if (((AssignStmt) units[i]).getRightOp() instanceof InvokeExpr) System.out.println( ((AssignStmt) units[i]).getLeftOp() + " = " + toString((InvokeExpr) ((AssignStmt) units[i]).getRightOp())); else System.out.println(units[i]); } else { System.out.println(units[i]); } if (units[i].hasTag("StringTag")) { String info = ((StringTag) units[i].getTag("StringTag")).getInfo(); if (!info.endsWith("Pre")) System.out.println(" " + info); if (info.endsWith("After")) System.out.println(); } } System.out.println("--- traps ---"); for (Trap t : body.getTraps()) System.out.println( " [" + getIndex(units, t.getBeginUnit()) + "-" + getIndex(units, t.getEndUnit()) + ") -> (" + t.getException() + ") -> " + getIndex(units, t.getHandlerUnit())); System.out.println(); }