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