/* * Copyright (c) 2009-2012 Panxiaobo * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.googlecode.dex2jar.ir.ts; import com.googlecode.dex2jar.ir.IrMethod; import com.googlecode.dex2jar.ir.Trap; import com.googlecode.dex2jar.ir.expr.Exprs; import com.googlecode.dex2jar.ir.expr.Local; import com.googlecode.dex2jar.ir.expr.Value.VT; import com.googlecode.dex2jar.ir.stmt.GotoStmt; import com.googlecode.dex2jar.ir.stmt.LabelStmt; import com.googlecode.dex2jar.ir.stmt.Stmt; import com.googlecode.dex2jar.ir.stmt.Stmt.ST; import com.googlecode.dex2jar.ir.stmt.Stmts; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * issue 63 * <p/> * * <pre> * L1: * STMTs * L2: * RETURN * L1~L2 > L2 Exception * </pre> * <p/> * currect to * <p/> * * <pre> * L1: * STMTs * L2: * RETURN * L3: * MOVE-EXCEPTION * GOTO L2: * L1~L2 > L3 Exception * </pre> * * we insert MOVE-EXCEPTION at tail of code to prevent the following * * <pre> * L1: * ... * goto L2: * ... * L2: * return; * L1~L2 > L3 Exception * </pre> * * @author <a href="mailto:pxb1988@gmail.com">Panxiaobo</a> * @version $Rev$ */ public class ExceptionHandlerCurrectTransformer implements Transformer { @Override public void transform(IrMethod irMethod) { if (irMethod.traps.size() == 0) { return; } Local ex = null; Set<LabelStmt> handlers=new HashSet<>(); Map<LabelStmt, LabelStmt> newLocations = new HashMap<>(); for (Trap t : irMethod.traps) { for (int i = 0; i < t.handlers.length; i++) { LabelStmt handler = t.handlers[i]; Stmt st = handler.getNext(); while (st.st == ST.LABEL) { st = st.getNext(); } LabelStmt x = (LabelStmt) st.getPre(); if (needInsertMoveExceptionRef(st)) { LabelStmt newHandler = newLocations.get(x); if (newHandler == null) { if (ex == null) { ex = Exprs.nLocal("unRefEx"); } newHandler = Stmts.nLabel(); GotoStmt g = Stmts.nGoto(x); irMethod.stmts.add(newHandler); irMethod.stmts.add(Stmts.nIdentity(ex, Exprs.nExceptionRef("Ljava/lang/Throwable;"))); irMethod.stmts.add(g); newLocations.put(x, newHandler); } t.handlers[i] = newHandler; } else if (x != handler) { t.handlers[i] = x; } handlers.add(t.handlers[i]); } } newLocations.clear(); if (ex != null) { irMethod.locals.add(ex); } } private boolean needInsertMoveExceptionRef(Stmt st) { return st.st != ST.IDENTITY || st.getOp2().vt != VT.EXCEPTION_REF; } }