提交 3fcbca94 编写于 作者: S Skylot

Fix try/catch/finally block processing

上级 56eac437
......@@ -2,7 +2,7 @@ package jadx.dex.trycatch;
import jadx.Consts;
import jadx.dex.info.ClassInfo;
import jadx.dex.instructions.args.InsnArg;
import jadx.dex.instructions.args.RegisterArg;
import jadx.dex.nodes.BlockNode;
import jadx.dex.nodes.IContainer;
import jadx.utils.InsnUtils;
......@@ -18,7 +18,9 @@ public class ExceptionHandler {
private BlockNode handleBlock;
private final List<BlockNode> blocks = new ArrayList<BlockNode>();
private IContainer handlerRegion;
private InsnArg arg;
private RegisterArg arg;
private TryCatchBlock tryBlock;
public ExceptionHandler(int addr, ClassInfo type) {
this.handleOffset = addr;
......@@ -61,14 +63,22 @@ public class ExceptionHandler {
this.handlerRegion = handlerRegion;
}
public InsnArg getArg() {
public RegisterArg getArg() {
return arg;
}
public void setArg(InsnArg arg) {
public void setArg(RegisterArg arg) {
this.arg = arg;
}
public void setTryBlock(TryCatchBlock tryBlock) {
this.tryBlock = tryBlock;
}
public TryCatchBlock getTryBlock() {
return tryBlock;
}
@Override
public int hashCode() {
return (catchType == null ? 0 : 31 * catchType.hashCode()) + handleOffset;
......
package jadx.dex.trycatch;
import jadx.dex.attributes.AttributeType;
import jadx.dex.attributes.IAttribute;
import jadx.dex.info.ClassInfo;
import jadx.dex.nodes.BlockNode;
import jadx.dex.nodes.IBlock;
import jadx.dex.nodes.IContainer;
import jadx.dex.nodes.InsnContainer;
import jadx.dex.nodes.InsnNode;
import jadx.dex.nodes.MethodNode;
import jadx.dex.visitors.InstructionRemover;
import jadx.utils.Utils;
import java.util.ArrayList;
......@@ -36,6 +40,7 @@ public class TryCatchBlock {
ExceptionHandler handler = new ExceptionHandler(addr, type);
handler = mth.addExceptionHandler(handler);
handlers.add(handler);
handler.setTryBlock(this);
return handler;
}
......@@ -52,14 +57,29 @@ public class TryCatchBlock {
}
private void removeWholeBlock(MethodNode mth) {
if (finalBlock != null) {
// search catch attr
for (BlockNode block : mth.getBasicBlocks()) {
CatchAttr cb = (CatchAttr) block.getAttributes().get(AttributeType.CATCH_BLOCK);
if (cb == attr) {
for (ExceptionHandler eh : mth.getExceptionHandlers()) {
if (eh.getBlocks().contains(block)) {
TryCatchBlock tb = eh.getTryBlock();
tb.setFinalBlockFromInsns(mth, ((IBlock) finalBlock).getInstructions());
}
}
}
}
return;
}
// self destruction
for (InsnNode insn : insns)
insn.getAttributes().remove(AttributeType.CATCH_BLOCK);
insn.getAttributes().remove(attr);
insns.clear();
for (BlockNode block : mth.getBasicBlocks()) {
block.getAttributes().remove(AttributeType.CATCH_BLOCK);
}
for (BlockNode block : mth.getBasicBlocks())
block.getAttributes().remove(attr);
}
public void addInsn(InsnNode insn) {
......@@ -92,11 +112,34 @@ public class TryCatchBlock {
this.finalBlock = finalBlock;
}
public void setFinalBlockFromInsns(MethodNode mth, List<InsnNode> insns) {
InsnContainer cont = new InsnContainer();
List<InsnNode> finalBlockInsns = new ArrayList<InsnNode>(insns);
cont.setInstructions(finalBlockInsns);
setFinalBlock(cont);
InstructionRemover.unbindInsnList(finalBlockInsns);
// remove these instructions from other handlers
for (ExceptionHandler h : getHandlers()) {
for (BlockNode ehb : h.getBlocks())
ehb.getInstructions().removeAll(finalBlockInsns);
}
// remove from blocks with this catch
for (BlockNode b : mth.getBasicBlocks()) {
IAttribute ca = b.getAttributes().get(AttributeType.CATCH_BLOCK);
if (attr == ca)
b.getInstructions().removeAll(finalBlockInsns);
}
}
public void merge(MethodNode mth, TryCatchBlock tryBlock) {
for (InsnNode insn : tryBlock.getInsns())
this.addInsn(insn);
this.handlers.addAll(tryBlock.getHandlers());
for (ExceptionHandler eh : handlers)
eh.setTryBlock(this);
// clear
tryBlock.handlers.clear();
......
......@@ -2,7 +2,6 @@ package jadx.dex.visitors;
import jadx.Consts;
import jadx.dex.attributes.AttributeType;
import jadx.dex.attributes.IAttribute;
import jadx.dex.info.MethodInfo;
import jadx.dex.instructions.IndexInsnNode;
import jadx.dex.instructions.InsnType;
......@@ -12,7 +11,6 @@ import jadx.dex.instructions.args.RegisterArg;
import jadx.dex.instructions.mods.ConstructorInsn;
import jadx.dex.nodes.BlockNode;
import jadx.dex.nodes.FieldNode;
import jadx.dex.nodes.InsnContainer;
import jadx.dex.nodes.InsnNode;
import jadx.dex.nodes.MethodNode;
import jadx.dex.trycatch.ExcHandlerAttr;
......@@ -21,7 +19,6 @@ import jadx.dex.trycatch.TryCatchBlock;
import jadx.utils.BlockUtils;
import jadx.utils.exceptions.JadxRuntimeException;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
......@@ -195,24 +192,8 @@ public class ModVisitor extends AbstractVisitor {
// move not removed instructions to 'finally' block
if (size != 0) {
InsnContainer cont = new InsnContainer();
List<InsnNode> finalBlockInsns = new ArrayList<InsnNode>(insns);
cont.setInstructions(finalBlockInsns);
tryBlock.setFinalBlock(cont);
InstructionRemover.unbindInsnList(finalBlockInsns);
// remove these instructions from other handlers
for (ExceptionHandler h : tryBlock.getHandlers()) {
for (BlockNode ehb : h.getBlocks())
ehb.getInstructions().removeAll(finalBlockInsns);
}
// remove from blocks with this catch
for (BlockNode b : mth.getBasicBlocks()) {
IAttribute ca = b.getAttributes().get(AttributeType.CATCH_BLOCK);
if (tryBlock.getCatchAttr() == ca)
b.getInstructions().removeAll(finalBlockInsns);
}
// TODO: support instructions from several blocks
tryBlock.setFinalBlockFromInsns(mth, insns);
size = insns.size();
}
}
......
......@@ -118,6 +118,31 @@ public class TestTryCatch extends AbstractTest {
}
}
private boolean test8(Object obj) {
this.mDiscovering = false;
try {
exc(obj);
} catch (Exception e) {
e.toString();
} finally {
mDiscovering = true;
}
return mDiscovering;
}
private boolean test8a(Object obj) {
this.mDiscovering = false;
try {
exc(obj);
} catch (Exception e) {
e.toString();
} finally {
if (!mDiscovering)
mDiscovering = true;
}
return mDiscovering;
}
private static boolean testSynchronize(Object obj) throws InterruptedException {
synchronized (obj) {
if (obj instanceof String)
......@@ -127,6 +152,7 @@ public class TestTryCatch extends AbstractTest {
return true;
}
// TODO: remove 'synchronized(TestTryCatch.class)' block in decompiled version
private synchronized static boolean testSynchronize2(Object obj) throws InterruptedException {
return obj.toString() != null;
}
......@@ -159,6 +185,12 @@ public class TestTryCatch extends AbstractTest {
assertTrue(testSynchronize2("str"));
assertTrue(testSynchronize3());
assertTrue(test8("a"));
assertTrue(test8(null));
assertTrue(test8a("a"));
assertTrue(test8a(null));
return true;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册