Commit d905c96f authored by Skylot's avatar Skylot

core: refactor 'catch' clause variable processing

parent 03f03f85
...@@ -292,7 +292,7 @@ public class CodeWriter { ...@@ -292,7 +292,7 @@ public class CodeWriter {
out = new PrintWriter(file, "UTF-8"); out = new PrintWriter(file, "UTF-8");
String code = buf.toString(); String code = buf.toString();
code = removeFirstEmptyLine(code); code = removeFirstEmptyLine(code);
out.print(code); out.println(code);
} catch (Exception e) { } catch (Exception e) {
LOG.error("Save file error", e); LOG.error("Save file error", e);
} finally { } finally {
......
...@@ -436,14 +436,6 @@ public class InsnGen { ...@@ -436,14 +436,6 @@ public class InsnGen {
} }
break; break;
case MOVE_EXCEPTION:
if (isFallback()) {
code.add("move-exception");
} else {
addArg(code, insn.getArg(0));
}
break;
case TERNARY: case TERNARY:
makeTernary((TernaryInsn) insn, code, state); makeTernary((TernaryInsn) insn, code, state);
break; break;
...@@ -472,6 +464,11 @@ public class InsnGen { ...@@ -472,6 +464,11 @@ public class InsnGen {
code.add("goto ").add(MethodGen.getLabelName(((GotoNode) insn).getTarget())); code.add("goto ").add(MethodGen.getLabelName(((GotoNode) insn).getTarget()));
break; break;
case MOVE_EXCEPTION:
assert isFallback();
code.add("move-exception");
break;
case SWITCH: case SWITCH:
assert isFallback(); assert isFallback();
SwitchNode sw = (SwitchNode) insn; SwitchNode sw = (SwitchNode) insn;
......
...@@ -9,6 +9,7 @@ import jadx.core.dex.info.FieldInfo; ...@@ -9,6 +9,7 @@ import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.instructions.IndexInsnNode; import jadx.core.dex.instructions.IndexInsnNode;
import jadx.core.dex.instructions.SwitchNode; import jadx.core.dex.instructions.SwitchNode;
import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.NamedArg;
import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.nodes.BlockNode; import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.FieldNode; import jadx.core.dex.nodes.FieldNode;
...@@ -19,13 +20,13 @@ import jadx.core.dex.nodes.InsnNode; ...@@ -19,13 +20,13 @@ import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.regions.Region; import jadx.core.dex.regions.Region;
import jadx.core.dex.regions.SwitchRegion; import jadx.core.dex.regions.SwitchRegion;
import jadx.core.dex.regions.SynchronizedRegion; import jadx.core.dex.regions.SynchronizedRegion;
import jadx.core.dex.regions.TryCatchRegion;
import jadx.core.dex.regions.conditions.IfCondition; import jadx.core.dex.regions.conditions.IfCondition;
import jadx.core.dex.regions.conditions.IfRegion; import jadx.core.dex.regions.conditions.IfRegion;
import jadx.core.dex.regions.loops.ForEachLoop; import jadx.core.dex.regions.loops.ForEachLoop;
import jadx.core.dex.regions.loops.ForLoop; import jadx.core.dex.regions.loops.ForLoop;
import jadx.core.dex.regions.loops.LoopRegion; import jadx.core.dex.regions.loops.LoopRegion;
import jadx.core.dex.regions.loops.LoopType; import jadx.core.dex.regions.loops.LoopType;
import jadx.core.dex.trycatch.CatchAttr;
import jadx.core.dex.trycatch.ExceptionHandler; import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.trycatch.TryCatchBlock; import jadx.core.dex.trycatch.TryCatchBlock;
import jadx.core.utils.ErrorsCounter; import jadx.core.utils.ErrorsCounter;
...@@ -59,6 +60,8 @@ public class RegionGen extends InsnGen { ...@@ -59,6 +60,8 @@ public class RegionGen extends InsnGen {
makeSwitch((SwitchRegion) cont, code); makeSwitch((SwitchRegion) cont, code);
} else if (cont instanceof LoopRegion) { } else if (cont instanceof LoopRegion) {
makeLoop((LoopRegion) cont, code); makeLoop((LoopRegion) cont, code);
} else if (cont instanceof TryCatchRegion) {
makeTryCatch((TryCatchRegion) cont, code);
} else if (cont instanceof SynchronizedRegion) { } else if (cont instanceof SynchronizedRegion) {
makeSynchronizedRegion((SynchronizedRegion) cont, code); makeSynchronizedRegion((SynchronizedRegion) cont, code);
} }
...@@ -80,16 +83,11 @@ public class RegionGen extends InsnGen { ...@@ -80,16 +83,11 @@ public class RegionGen extends InsnGen {
} }
private void makeSimpleRegion(CodeWriter code, Region region) throws CodegenException { private void makeSimpleRegion(CodeWriter code, Region region) throws CodegenException {
CatchAttr tc = region.get(AType.CATCH_BLOCK);
if (tc != null) {
makeTryCatch(region, tc.getTryBlock(), code);
} else {
declareVars(code, region); declareVars(code, region);
for (IContainer c : region.getSubBlocks()) { for (IContainer c : region.getSubBlocks()) {
makeRegion(code, c); makeRegion(code, c);
} }
} }
}
public void makeRegionIndent(CodeWriter code, IContainer region) throws CodegenException { public void makeRegionIndent(CodeWriter code, IContainer region) throws CodegenException {
code.incIndent(); code.incIndent();
...@@ -283,11 +281,11 @@ public class RegionGen extends InsnGen { ...@@ -283,11 +281,11 @@ public class RegionGen extends InsnGen {
} }
} }
private void makeTryCatch(IContainer region, TryCatchBlock tryCatchBlock, CodeWriter code) private void makeTryCatch(TryCatchRegion region, CodeWriter code) throws CodegenException {
throws CodegenException { TryCatchBlock tryCatchBlock = region.geTryCatchBlock();
code.startLine("try {"); code.startLine("try {");
region.remove(AType.CATCH_BLOCK); makeRegionIndent(code, region.getTryRegion());
makeRegionIndent(code, region); // TODO: move search of 'allHandler' to 'TryCatchRegion'
ExceptionHandler allHandler = null; ExceptionHandler allHandler = null;
for (ExceptionHandler handler : tryCatchBlock.getHandlers()) { for (ExceptionHandler handler : tryCatchBlock.getHandlers()) {
if (!handler.isCatchAll()) { if (!handler.isCatchAll()) {
...@@ -309,20 +307,25 @@ public class RegionGen extends InsnGen { ...@@ -309,20 +307,25 @@ public class RegionGen extends InsnGen {
code.startLine('}'); code.startLine('}');
} }
private void makeCatchBlock(CodeWriter code, ExceptionHandler handler) private void makeCatchBlock(CodeWriter code, ExceptionHandler handler) throws CodegenException {
throws CodegenException {
IContainer region = handler.getHandlerRegion(); IContainer region = handler.getHandlerRegion();
if (region != null) { if (region == null) {
return;
}
code.startLine("} catch ("); code.startLine("} catch (");
InsnArg arg = handler.getArg();
if (arg instanceof RegisterArg) {
declareVar(code, (RegisterArg) arg);
} else if (arg instanceof NamedArg) {
if (handler.isCatchAll()) { if (handler.isCatchAll()) {
code.add("Throwable"); code.add("Throwable");
} else { } else {
useClass(code, handler.getCatchType()); useClass(code, handler.getCatchType());
} }
code.add(' '); code.add(' ');
code.add(mgen.getNameGen().assignNamedArg(handler.getArg())); code.add(mgen.getNameGen().assignNamedArg((NamedArg) arg));
}
code.add(") {"); code.add(") {");
makeRegionIndent(code, region); makeRegionIndent(code, region);
} }
}
} }
...@@ -4,7 +4,6 @@ import jadx.core.dex.info.FieldInfo; ...@@ -4,7 +4,6 @@ import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.MethodInfo; import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.NamedArg;
import jadx.core.dex.instructions.args.PrimitiveType; import jadx.core.dex.instructions.args.PrimitiveType;
import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.nodes.DexNode; import jadx.core.dex.nodes.DexNode;
...@@ -404,8 +403,7 @@ public class InsnDecoder { ...@@ -404,8 +403,7 @@ public class InsnDecoder {
case Opcodes.MOVE_EXCEPTION: case Opcodes.MOVE_EXCEPTION:
return insn(InsnType.MOVE_EXCEPTION, return insn(InsnType.MOVE_EXCEPTION,
InsnArg.reg(insn, 0, ArgType.unknown(PrimitiveType.OBJECT)), InsnArg.reg(insn, 0, ArgType.unknown(PrimitiveType.OBJECT)));
new NamedArg("e", ArgType.unknown(PrimitiveType.OBJECT)));
case Opcodes.RETURN_VOID: case Opcodes.RETURN_VOID:
return new InsnNode(InsnType.RETURN, 0); return new InsnNode(InsnType.RETURN, 0);
......
...@@ -30,8 +30,8 @@ public abstract class InsnArg extends Typed { ...@@ -30,8 +30,8 @@ public abstract class InsnArg extends Typed {
return reg(InsnUtils.getArg(insn, argNum), type); return reg(InsnUtils.getArg(insn, argNum), type);
} }
public static MthParameterArg parameterReg(int regNum, ArgType type) { public static TypeImmutableArg typeImmutableReg(int regNum, ArgType type) {
return new MthParameterArg(regNum, type); return new TypeImmutableArg(regNum, type);
} }
public static LiteralArg lit(long literal, ArgType type) { public static LiteralArg lit(long literal, ArgType type) {
......
package jadx.core.dex.instructions.args; package jadx.core.dex.instructions.args;
public class MthParameterArg extends RegisterArg { public class TypeImmutableArg extends RegisterArg {
private boolean isThis; private boolean isThis;
public MthParameterArg(int rn, ArgType type) { public TypeImmutableArg(int rn, ArgType type) {
super(rn, type); super(rn, type);
} }
...@@ -48,13 +48,13 @@ public class MthParameterArg extends RegisterArg { ...@@ -48,13 +48,13 @@ public class MthParameterArg extends RegisterArg {
if (this == obj) { if (this == obj) {
return true; return true;
} }
if (!(obj instanceof MthParameterArg)) { if (!(obj instanceof TypeImmutableArg)) {
return false; return false;
} }
if (!super.equals(obj)) { if (!super.equals(obj)) {
return false; return false;
} }
MthParameterArg that = (MthParameterArg) obj; TypeImmutableArg that = (TypeImmutableArg) obj;
return isThis == that.isThis; return isThis == that.isThis;
} }
......
...@@ -4,6 +4,8 @@ import jadx.core.dex.attributes.IAttributeNode; ...@@ -4,6 +4,8 @@ import jadx.core.dex.attributes.IAttributeNode;
public interface IContainer extends IAttributeNode { public interface IContainer extends IAttributeNode {
// unique id for use in 'toString()' method /**
* Unique id for use in 'toString()' method
*/
String baseString(); String baseString();
} }
...@@ -170,7 +170,6 @@ public class InsnNode extends LineAttrNode { ...@@ -170,7 +170,6 @@ public class InsnNode extends LineAttrNode {
case NEW_ARRAY: case NEW_ARRAY:
case NEW_MULTIDIM_ARRAY: case NEW_MULTIDIM_ARRAY:
case STR_CONCAT: case STR_CONCAT:
case MOVE_EXCEPTION:
return true; return true;
default: default:
......
...@@ -15,9 +15,9 @@ import jadx.core.dex.instructions.InsnDecoder; ...@@ -15,9 +15,9 @@ import jadx.core.dex.instructions.InsnDecoder;
import jadx.core.dex.instructions.SwitchNode; import jadx.core.dex.instructions.SwitchNode;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.MthParameterArg;
import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.args.SSAVar; import jadx.core.dex.instructions.args.SSAVar;
import jadx.core.dex.instructions.args.TypeImmutableArg;
import jadx.core.dex.nodes.parser.SignatureParser; import jadx.core.dex.nodes.parser.SignatureParser;
import jadx.core.dex.regions.Region; import jadx.core.dex.regions.Region;
import jadx.core.dex.trycatch.ExcHandlerAttr; import jadx.core.dex.trycatch.ExcHandlerAttr;
...@@ -183,7 +183,7 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -183,7 +183,7 @@ public class MethodNode extends LineAttrNode implements ILoadable {
if (accFlags.isStatic()) { if (accFlags.isStatic()) {
thisArg = null; thisArg = null;
} else { } else {
MthParameterArg arg = InsnArg.parameterReg(pos - 1, parentClass.getClassInfo().getType()); TypeImmutableArg arg = InsnArg.typeImmutableReg(pos - 1, parentClass.getClassInfo().getType());
arg.markAsThis(); arg.markAsThis();
thisArg = arg; thisArg = arg;
} }
...@@ -193,7 +193,7 @@ public class MethodNode extends LineAttrNode implements ILoadable { ...@@ -193,7 +193,7 @@ public class MethodNode extends LineAttrNode implements ILoadable {
} }
argsList = new ArrayList<RegisterArg>(args.size()); argsList = new ArrayList<RegisterArg>(args.size());
for (ArgType arg : args) { for (ArgType arg : args) {
argsList.add(InsnArg.parameterReg(pos, arg)); argsList.add(InsnArg.typeImmutableReg(pos, arg));
pos += arg.getRegCount(); pos += arg.getRegCount();
} }
} }
......
package jadx.core.dex.regions;
import jadx.core.dex.nodes.IContainer;
import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.trycatch.TryCatchBlock;
import jadx.core.utils.Utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public final class TryCatchRegion extends AbstractRegion {
private final IContainer tryRegion;
private List<IContainer> catchRegions = Collections.emptyList();
private TryCatchBlock tryCatchBlock;
public TryCatchRegion(IRegion parent, IContainer tryRegion) {
super(parent);
this.tryRegion = tryRegion;
}
public IContainer getTryRegion() {
return tryRegion;
}
public List<IContainer> getCatchRegions() {
return catchRegions;
}
public TryCatchBlock geTryCatchBlock() {
return tryCatchBlock;
}
public void setTryCatchBlock(TryCatchBlock tryCatchBlock) {
this.tryCatchBlock = tryCatchBlock;
this.catchRegions = new ArrayList<IContainer>(tryCatchBlock.getHandlersCount());
for (ExceptionHandler handler : tryCatchBlock.getHandlers()) {
catchRegions.add(handler.getHandlerRegion());
}
}
@Override
public List<IContainer> getSubBlocks() {
List<IContainer> all = new ArrayList<IContainer>(1 + catchRegions.size());
all.add(tryRegion);
all.addAll(catchRegions);
return Collections.unmodifiableList(all);
}
@Override
public String baseString() {
return tryRegion.baseString();
}
@Override
public String toString() {
return "Try: " + tryRegion
+ " catches: " + Utils.listToString(catchRegions);
}
}
...@@ -2,7 +2,7 @@ package jadx.core.dex.trycatch; ...@@ -2,7 +2,7 @@ package jadx.core.dex.trycatch;
import jadx.core.Consts; import jadx.core.Consts;
import jadx.core.dex.info.ClassInfo; import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.instructions.args.NamedArg; import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.nodes.BlockNode; import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IContainer; import jadx.core.dex.nodes.IContainer;
import jadx.core.utils.InsnUtils; import jadx.core.utils.InsnUtils;
...@@ -18,7 +18,7 @@ public class ExceptionHandler { ...@@ -18,7 +18,7 @@ public class ExceptionHandler {
private BlockNode handlerBlock; private BlockNode handlerBlock;
private final List<BlockNode> blocks = new ArrayList<BlockNode>(); private final List<BlockNode> blocks = new ArrayList<BlockNode>();
private IContainer handlerRegion; private IContainer handlerRegion;
private NamedArg arg; private InsnArg arg;
private TryCatchBlock tryBlock; private TryCatchBlock tryBlock;
...@@ -63,11 +63,11 @@ public class ExceptionHandler { ...@@ -63,11 +63,11 @@ public class ExceptionHandler {
this.handlerRegion = handlerRegion; this.handlerRegion = handlerRegion;
} }
public NamedArg getArg() { public InsnArg getArg() {
return arg; return arg;
} }
public void setArg(NamedArg arg) { public void setArg(InsnArg arg) {
this.arg = arg; this.arg = arg;
} }
......
...@@ -4,7 +4,7 @@ import jadx.core.dex.attributes.AType; ...@@ -4,7 +4,7 @@ import jadx.core.dex.attributes.AType;
import jadx.core.dex.instructions.IfNode; import jadx.core.dex.instructions.IfNode;
import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.NamedArg; import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.nodes.BlockNode; import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.InsnNode;
...@@ -43,30 +43,24 @@ public class BlockProcessingHelper { ...@@ -43,30 +43,24 @@ public class BlockProcessingHelper {
* Set exception handler attribute for whole block * Set exception handler attribute for whole block
*/ */
private static void markExceptionHandlers(BlockNode block) { private static void markExceptionHandlers(BlockNode block) {
if (!block.getInstructions().isEmpty()) { if (block.getInstructions().isEmpty()) {
return;
}
InsnNode me = block.getInstructions().get(0); InsnNode me = block.getInstructions().get(0);
ExcHandlerAttr handlerAttr = me.get(AType.EXC_HANDLER); ExcHandlerAttr handlerAttr = me.get(AType.EXC_HANDLER);
if (handlerAttr != null && me.getType() == InsnType.MOVE_EXCEPTION) { if (handlerAttr == null || me.getType() != InsnType.MOVE_EXCEPTION) {
return;
}
ExceptionHandler excHandler = handlerAttr.getHandler(); ExceptionHandler excHandler = handlerAttr.getHandler();
assert me.getOffset() == excHandler.getHandleOffset(); block.addAttr(handlerAttr);
// set correct type for 'move-exception' operation // set correct type for 'move-exception' operation
ArgType type = excHandler.isCatchAll() ? ArgType.THROWABLE : excHandler.getCatchType().getType();
RegisterArg resArg = me.getResult(); RegisterArg resArg = me.getResult();
NamedArg excArg = (NamedArg) me.getArg(0); resArg = InsnArg.reg(resArg.getRegNum(), type);
ArgType type; me.setResult(resArg);
if (excHandler.isCatchAll()) {
type = ArgType.THROWABLE;
excArg.setName("th");
} else {
type = excHandler.getCatchType().getType();
excArg.setName("e");
}
resArg.forceType(type);
excArg.setType(type);
excHandler.setArg(excArg); excHandler.setArg(resArg);
block.addAttr(handlerAttr);
}
}
} }
private static void processExceptionHandlers(MethodNode mth, BlockNode block) { private static void processExceptionHandlers(MethodNode mth, BlockNode block) {
......
...@@ -200,7 +200,9 @@ public class CodeShrinker extends AbstractVisitor { ...@@ -200,7 +200,9 @@ public class CodeShrinker extends AbstractVisitor {
continue; continue;
} }
InsnNode assignInsn = sVar.getAssign().getParentInsn(); InsnNode assignInsn = sVar.getAssign().getParentInsn();
if (assignInsn == null || assignInsn instanceof PhiInsn) { if (assignInsn == null
|| assignInsn instanceof PhiInsn
|| assignInsn.getType() == InsnType.MOVE_EXCEPTION) {
continue; continue;
} }
int assignPos = insnList.getIndex(assignInsn); int assignPos = insnList.getIndex(assignInsn);
......
...@@ -14,7 +14,9 @@ import jadx.core.dex.instructions.SwitchNode; ...@@ -14,7 +14,9 @@ import jadx.core.dex.instructions.SwitchNode;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.LiteralArg; import jadx.core.dex.instructions.args.LiteralArg;
import jadx.core.dex.instructions.args.NamedArg;
import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.args.SSAVar;
import jadx.core.dex.instructions.mods.ConstructorInsn; import jadx.core.dex.instructions.mods.ConstructorInsn;
import jadx.core.dex.nodes.BlockNode; import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
...@@ -298,9 +300,27 @@ public class ModVisitor extends AbstractVisitor { ...@@ -298,9 +300,27 @@ public class ModVisitor extends AbstractVisitor {
List<InsnNode> blockInsns = block.getInstructions(); List<InsnNode> blockInsns = block.getInstructions();
if (!blockInsns.isEmpty()) { if (!blockInsns.isEmpty()) {
InsnNode insn = blockInsns.get(0); InsnNode insn = blockInsns.get(0);
if (insn.getType() == InsnType.MOVE_EXCEPTION if (insn.getType() == InsnType.MOVE_EXCEPTION) {
&& insn.getResult().getSVar().getUseCount() == 0) { // result arg used both in this insn and exception handler,
RegisterArg resArg = insn.getResult();
ArgType type = excHandler.isCatchAll() ? ArgType.THROWABLE : excHandler.getCatchType().getType();
String name = excHandler.isCatchAll() ? "th" : "e";
if (resArg.getName() == null) {
resArg.setName(name);
}
SSAVar sVar = insn.getResult().getSVar();
if (sVar.getUseCount() == 0) {
excHandler.setArg(new NamedArg(name, type));
InstructionRemover.remove(mth, block, 0); InstructionRemover.remove(mth, block, 0);
} else if (sVar.isUsedInPhi()) {
// exception var moved to external variable => replace with 'move' insn
InsnNode moveInsn = new InsnNode(InsnType.MOVE, 1);
moveInsn.setResult(insn.getResult());
NamedArg namedArg = new NamedArg(name, type);
moveInsn.addArg(namedArg);
excHandler.setArg(namedArg);
replaceInsn(block, 0, moveInsn);
}
} }
} }
int totalSize = 0; int totalSize = 0;
......
...@@ -45,6 +45,7 @@ public class PrepareForCodeGen extends AbstractVisitor { ...@@ -45,6 +45,7 @@ public class PrepareForCodeGen extends AbstractVisitor {
case NOP: case NOP:
case MONITOR_ENTER: case MONITOR_ENTER:
case MONITOR_EXIT: case MONITOR_EXIT:
case MOVE_EXCEPTION:
it.remove(); it.remove();
break; break;
......
...@@ -7,6 +7,7 @@ import jadx.core.dex.nodes.IRegion; ...@@ -7,6 +7,7 @@ import jadx.core.dex.nodes.IRegion;
import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.regions.AbstractRegion; import jadx.core.dex.regions.AbstractRegion;
import jadx.core.dex.regions.Region; import jadx.core.dex.regions.Region;
import jadx.core.dex.regions.TryCatchRegion;
import jadx.core.dex.regions.loops.LoopRegion; import jadx.core.dex.regions.loops.LoopRegion;
import jadx.core.dex.trycatch.CatchAttr; import jadx.core.dex.trycatch.CatchAttr;
import jadx.core.dex.trycatch.ExceptionHandler; import jadx.core.dex.trycatch.ExceptionHandler;
...@@ -129,33 +130,36 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor { ...@@ -129,33 +130,36 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
region = loop.getBody(); region = loop.getBody();
} }
Region newRegion = new Region(region); Region tryRegion = new Region(region);
List<IContainer> subBlocks = region.getSubBlocks(); List<IContainer> subBlocks = region.getSubBlocks();
for (IContainer cont : subBlocks) { for (IContainer cont : subBlocks) {
if (RegionUtils.isDominatedBy(dominator, cont)) { if (RegionUtils.isDominatedBy(dominator, cont)) {
if (isHandlerPath(tb, cont)) { if (isHandlerPath(tb, cont)) {
break; break;
} }
newRegion.getSubBlocks().add(cont); tryRegion.getSubBlocks().add(cont);
} }
} }
if (newRegion.getSubBlocks().isEmpty()) { if (tryRegion.getSubBlocks().isEmpty()) {
return false; return false;
} }
TryCatchRegion tryCatchRegion = new TryCatchRegion(region, tryRegion);
tryRegion.setParent(tryCatchRegion);
tryCatchRegion.setTryCatchBlock(tb.getCatchAttr().getTryBlock());
// replace first node by region // replace first node by region
IContainer firstNode = newRegion.getSubBlocks().get(0); IContainer firstNode = tryRegion.getSubBlocks().get(0);
if (!region.replaceSubBlock(firstNode, newRegion)) { if (!region.replaceSubBlock(firstNode, tryCatchRegion)) {
return false; return false;
} }
subBlocks.removeAll(newRegion.getSubBlocks()); subBlocks.removeAll(tryRegion.getSubBlocks());
newRegion.addAttr(tb.getCatchAttr());
// fix parents // fix parents for tryRegion sub blocks
for (IContainer cont : newRegion.getSubBlocks()) { for (IContainer cont : tryRegion.getSubBlocks()) {
if (cont instanceof AbstractRegion) { if (cont instanceof AbstractRegion) {
AbstractRegion aReg = (AbstractRegion) cont; AbstractRegion aReg = (AbstractRegion) cont;
aReg.setParent(newRegion); aReg.setParent(tryRegion);
} }
} }
return true; return true;
......
...@@ -4,6 +4,7 @@ import jadx.core.codegen.NameGen; ...@@ -4,6 +4,7 @@ import jadx.core.codegen.NameGen;
import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.DeclareVariablesAttr; import jadx.core.dex.attributes.nodes.DeclareVariablesAttr;
import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.args.VarName; import jadx.core.dex.instructions.args.VarName;
...@@ -158,6 +159,22 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -158,6 +159,22 @@ public class ProcessVariables extends AbstractVisitor {
usageMap.remove(new Variable(arg)); usageMap.remove(new Variable(arg));
} }
Iterator<Entry<Variable, Usage>> umIt = usageMap.entrySet().iterator();
while (umIt.hasNext()) {
Entry<Variable, Usage> entry = umIt.next();
Usage u = entry.getValue();
// if no assigns => remove
if (u.getAssigns().isEmpty()) {
umIt.remove();
continue;
}
// variable declared at 'catch' clause
InsnNode parentInsn = u.getArg().getParentInsn();
if (parentInsn == null || parentInsn.getType() == InsnType.MOVE_EXCEPTION) {
umIt.remove();
}
}
if (usageMap.isEmpty()) { if (usageMap.isEmpty()) {
return; return;
} }
...@@ -168,13 +185,6 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -168,13 +185,6 @@ public class ProcessVariables extends AbstractVisitor {
for (Iterator<Entry<Variable, Usage>> it = usageMap.entrySet().iterator(); it.hasNext(); ) { for (Iterator<Entry<Variable, Usage>> it = usageMap.entrySet().iterator(); it.hasNext(); ) {
Entry<Variable, Usage> entry = it.next(); Entry<Variable, Usage> entry = it.next();
Usage u = entry.getValue(); Usage u = entry.getValue();
// if no assigns => remove
if (u.getAssigns().isEmpty()) {
it.remove();
continue;
}
// check if variable can be declared at current assigns // check if variable can be declared at current assigns
for (IRegion assignRegion : u.getAssigns()) { for (IRegion assignRegion : u.getAssigns()) {
if (u.getArgRegion() == assignRegion if (u.getArgRegion() == assignRegion
...@@ -186,6 +196,9 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -186,6 +196,9 @@ public class ProcessVariables extends AbstractVisitor {
} }
} }
} }
if (usageMap.isEmpty()) {
return;
}
// apply // apply
for (Entry<Variable, Usage> entry : usageMap.entrySet()) { for (Entry<Variable, Usage> entry : usageMap.entrySet()) {
...@@ -299,7 +312,7 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -299,7 +312,7 @@ public class ProcessVariables extends AbstractVisitor {
&& isAllRegionsAfter(region, pos, u.getUseRegions(), regionsOrder); && isAllRegionsAfter(region, pos, u.getUseRegions(), regionsOrder);
} }
private static boolean isAllRegionsAfter(IRegion region, Integer pos, private static boolean isAllRegionsAfter(IRegion region, int pos,
Set<IRegion> regions, Map<IContainer, Integer> regionsOrder) { Set<IRegion> regions, Map<IContainer, Integer> regionsOrder) {
for (IRegion r : regions) { for (IRegion r : regions) {
if (r == region) { if (r == region) {
...@@ -313,7 +326,7 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -313,7 +326,7 @@ public class ProcessVariables extends AbstractVisitor {
if (pos > rPos) { if (pos > rPos) {
return false; return false;
} }
if (pos.equals(rPos)) { if (pos == rPos) {
return isAllRegionsAfterRecursive(region, regions); return isAllRegionsAfterRecursive(region, regions);
} }
} }
......
...@@ -23,10 +23,11 @@ public class TestArgInline extends IntegrationTest { ...@@ -23,10 +23,11 @@ public class TestArgInline extends IntegrationTest {
@Test @Test
public void test() { public void test() {
noDebugInfo();
ClassNode cls = getClassNode(TestCls.class); ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString(); String code = cls.getCode().toString();
assertThat(code, containsString("a++;")); assertThat(code, containsString("i++;"));
assertThat(code, not(containsString("a = a + 1;"))); assertThat(code, not(containsString("i = i + 1;")));
} }
} }
...@@ -12,7 +12,6 @@ import static org.junit.Assert.assertThat; ...@@ -12,7 +12,6 @@ import static org.junit.Assert.assertThat;
public class TestIfTryInCatch extends IntegrationTest { public class TestIfTryInCatch extends IntegrationTest {
public static class TestCls { public static class TestCls {
private static final String TAG = "TAG";
private Exception exception; private Exception exception;
private java.lang.Object data; private java.lang.Object data;
...@@ -35,11 +34,11 @@ public class TestIfTryInCatch extends IntegrationTest { ...@@ -35,11 +34,11 @@ public class TestIfTryInCatch extends IntegrationTest {
} }
private static boolean b(Object obj) { private static boolean b(Object obj) {
return false; return obj == null;
} }
private static boolean a(Exception e) { private static boolean a(Exception e) {
return false; return e instanceof RuntimeException;
} }
private Object f() { private Object f() {
......
package jadx.tests.integration.trycatch;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest;
import org.junit.Test;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.junit.Assert.assertThat;
public class TestTryCatch7 extends IntegrationTest {
public static class TestCls {
private Exception test() {
Exception e = new Exception();
try {
Thread.sleep(50);
} catch (Exception ex) {
e = ex;
}
e.printStackTrace();
return e;
}
}
@Test
public void test() {
noDebugInfo();
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
String excVarName = "exception";
assertThat(code, containsOne("Exception " + excVarName + " = new Exception();"));
assertThat(code, containsOne("} catch (Exception e) {"));
assertThat(code, containsOne(excVarName + " = e;"));
assertThat(code, containsOne(excVarName + ".printStackTrace();"));
assertThat(code, containsOne("return " + excVarName + ";"));
}
}
...@@ -67,4 +67,10 @@ public class TestVariables4 extends IntegrationTest { ...@@ -67,4 +67,10 @@ public class TestVariables4 extends IntegrationTest {
assertThat(code, containsString("System.err.println(\"Class '\" + clsName + \"' not found\");")); assertThat(code, containsString("System.err.println(\"Class '\" + clsName + \"' not found\");"));
assertThat(code, containsString("return pass;")); assertThat(code, containsString("return pass;"));
} }
@Test
public void test2() {
noDebugInfo();
getClassNode(TestCls.class);
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment