Commit 17d8516d authored by Skylot's avatar Skylot

fix: made correct instructions remove in new filled array replacement (#461)

parent b78349ae
...@@ -10,7 +10,6 @@ println("jadx version: ${jadxVersion}") ...@@ -10,7 +10,6 @@ println("jadx version: ${jadxVersion}")
allprojects { allprojects {
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'groovy'
apply plugin: 'jacoco' apply plugin: 'jacoco'
version = jadxVersion version = jadxVersion
......
...@@ -495,7 +495,7 @@ public class InsnGen { ...@@ -495,7 +495,7 @@ public class InsnGen {
case NEW_INSTANCE: case NEW_INSTANCE:
// only fallback - make new instance in constructor invoke // only fallback - make new instance in constructor invoke
fallbackOnlyInsn(insn); fallbackOnlyInsn(insn);
code.add("new ").add(insn.getResult().getType().toString()); code.add("new ").add(insn.getResult().getInitType().toString());
break; break;
case PHI: case PHI:
......
...@@ -11,7 +11,7 @@ import jadx.core.dex.instructions.args.InsnArg; ...@@ -11,7 +11,7 @@ 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;
import jadx.core.utils.InstructionRemover; import jadx.core.utils.InsnRemover;
import jadx.core.utils.Utils; import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
...@@ -64,7 +64,7 @@ public final class PhiInsn extends InsnNode { ...@@ -64,7 +64,7 @@ public final class PhiInsn extends InsnNode {
if (super.removeArg(reg)) { if (super.removeArg(reg)) {
blockBinds.remove(reg); blockBinds.remove(reg);
reg.getSVar().removeUse(reg); reg.getSVar().removeUse(reg);
InstructionRemover.fixUsedInPhiFlag(reg); InsnRemover.fixUsedInPhiFlag(reg);
return true; return true;
} }
return false; return false;
......
...@@ -19,8 +19,8 @@ import jadx.core.dex.instructions.args.LiteralArg; ...@@ -19,8 +19,8 @@ import jadx.core.dex.instructions.args.LiteralArg;
import jadx.core.dex.instructions.args.NamedArg; 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.args.SSAVar;
import jadx.core.utils.InsnRemover;
import jadx.core.utils.InsnUtils; import jadx.core.utils.InsnUtils;
import jadx.core.utils.InstructionRemover;
import jadx.core.utils.Utils; import jadx.core.utils.Utils;
public class InsnNode extends LineAttrNode { public class InsnNode extends LineAttrNode {
...@@ -68,6 +68,15 @@ public class InsnNode extends LineAttrNode { ...@@ -68,6 +68,15 @@ public class InsnNode extends LineAttrNode {
public void addArg(InsnArg arg) { public void addArg(InsnArg arg) {
arguments.add(arg); arguments.add(arg);
attachArg(arg);
}
public void setArg(int n, InsnArg arg) {
arguments.set(n, arg);
attachArg(arg);
}
private void attachArg(InsnArg arg) {
arg.setParentInsn(this); arg.setParentInsn(this);
if (arg.isRegister()) { if (arg.isRegister()) {
RegisterArg reg = (RegisterArg) arg; RegisterArg reg = (RegisterArg) arg;
...@@ -108,22 +117,15 @@ public class InsnNode extends LineAttrNode { ...@@ -108,22 +117,15 @@ public class InsnNode extends LineAttrNode {
return false; return false;
} }
public void setArg(int n, InsnArg arg) {
arg.setParentInsn(this);
arguments.set(n, arg);
}
/** /**
* Replace instruction arg with another using recursive search. * Replace instruction arg with another using recursive search.
* <br>
* <b>Caution:</b> this method don't change usage information for replaced argument.
*/ */
public boolean replaceArg(InsnArg from, InsnArg to) { public boolean replaceArg(InsnArg from, InsnArg to) {
int count = getArgsCount(); int count = getArgsCount();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
InsnArg arg = arguments.get(i); InsnArg arg = arguments.get(i);
if (arg == from) { if (arg == from) {
InstructionRemover.unbindArgUsage(null, arg); InsnRemover.unbindArgUsage(null, arg);
setArg(i, to); setArg(i, to);
return true; return true;
} }
...@@ -139,7 +141,7 @@ public class InsnNode extends LineAttrNode { ...@@ -139,7 +141,7 @@ public class InsnNode extends LineAttrNode {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
if (arg == arguments.get(i)) { if (arg == arguments.get(i)) {
arguments.remove(i); arguments.remove(i);
InstructionRemover.unbindArgUsage(null, arg); InsnRemover.unbindArgUsage(null, arg);
return true; return true;
} }
} }
......
...@@ -29,7 +29,7 @@ import jadx.core.dex.nodes.FieldNode; ...@@ -29,7 +29,7 @@ import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.BlockUtils; import jadx.core.utils.BlockUtils;
import jadx.core.utils.InstructionRemover; import jadx.core.utils.InsnRemover;
import jadx.core.utils.exceptions.JadxException; import jadx.core.utils.exceptions.JadxException;
@JadxVisitor( @JadxVisitor(
...@@ -131,7 +131,7 @@ public class ClassModifier extends AbstractVisitor { ...@@ -131,7 +131,7 @@ public class ClassModifier extends AbstractVisitor {
return false; return false;
} }
mth.skipFirstArgument(); mth.skipFirstArgument();
InstructionRemover.remove(mth, block, insn); InsnRemover.remove(mth, block, insn);
// other arg usage -> wrap with IGET insn // other arg usage -> wrap with IGET insn
if (arg.getSVar().getUseCount() != 0) { if (arg.getSVar().getUseCount() != 0) {
InsnNode iget = new IndexInsnNode(InsnType.IGET, fieldInfo, 1); InsnNode iget = new IndexInsnNode(InsnType.IGET, fieldInfo, 1);
......
...@@ -20,7 +20,7 @@ import jadx.core.dex.nodes.InsnNode; ...@@ -20,7 +20,7 @@ import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.visitors.ssa.SSATransform; import jadx.core.dex.visitors.ssa.SSATransform;
import jadx.core.dex.visitors.typeinference.TypeInferenceVisitor; import jadx.core.dex.visitors.typeinference.TypeInferenceVisitor;
import jadx.core.utils.InstructionRemover; import jadx.core.utils.InsnRemover;
import jadx.core.utils.exceptions.JadxException; import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.exceptions.JadxOverflowException; import jadx.core.utils.exceptions.JadxOverflowException;
...@@ -46,7 +46,7 @@ public class ConstInlineVisitor extends AbstractVisitor { ...@@ -46,7 +46,7 @@ public class ConstInlineVisitor extends AbstractVisitor {
for (InsnNode insn : block.getInstructions()) { for (InsnNode insn : block.getInstructions()) {
checkInsn(mth, insn, toRemove); checkInsn(mth, insn, toRemove);
} }
InstructionRemover.removeAll(mth, block, toRemove); InsnRemover.removeAllAndUnbind(mth, block, toRemove);
} }
} }
......
...@@ -17,7 +17,7 @@ import jadx.core.dex.nodes.MethodNode; ...@@ -17,7 +17,7 @@ import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.visitors.ssa.SSATransform; import jadx.core.dex.visitors.ssa.SSATransform;
import jadx.core.dex.visitors.typeinference.TypeInferenceVisitor; import jadx.core.dex.visitors.typeinference.TypeInferenceVisitor;
import jadx.core.utils.BlockUtils; import jadx.core.utils.BlockUtils;
import jadx.core.utils.InstructionRemover; import jadx.core.utils.InsnRemover;
@JadxVisitor( @JadxVisitor(
name = "ConstructorVisitor", name = "ConstructorVisitor",
...@@ -36,7 +36,7 @@ public class ConstructorVisitor extends AbstractVisitor { ...@@ -36,7 +36,7 @@ public class ConstructorVisitor extends AbstractVisitor {
} }
private static void replaceInvoke(MethodNode mth) { private static void replaceInvoke(MethodNode mth) {
InstructionRemover remover = new InstructionRemover(mth); InsnRemover remover = new InsnRemover(mth);
for (BlockNode block : mth.getBasicBlocks()) { for (BlockNode block : mth.getBasicBlocks()) {
remover.setBlock(block); remover.setBlock(block);
int size = block.getInstructions().size(); int size = block.getInstructions().size();
...@@ -50,7 +50,7 @@ public class ConstructorVisitor extends AbstractVisitor { ...@@ -50,7 +50,7 @@ public class ConstructorVisitor extends AbstractVisitor {
} }
} }
private static void processInvoke(MethodNode mth, BlockNode block, int indexInBlock, InstructionRemover remover) { private static void processInvoke(MethodNode mth, BlockNode block, int indexInBlock, InsnRemover remover) {
ClassNode parentClass = mth.getParentClass(); ClassNode parentClass = mth.getParentClass();
InsnNode insn = block.getInstructions().get(indexInBlock); InsnNode insn = block.getInstructions().get(indexInBlock);
InvokeNode inv = (InvokeNode) insn; InvokeNode inv = (InvokeNode) insn;
...@@ -75,25 +75,24 @@ public class ConstructorVisitor extends AbstractVisitor { ...@@ -75,25 +75,24 @@ public class ConstructorVisitor extends AbstractVisitor {
remove = true; remove = true;
} }
if (remove) { if (remove) {
remover.add(insn); remover.addAndUnbind(insn);
return; return;
} }
if (co.isNewInstance()) { if (co.isNewInstance()) {
InsnNode newInstInsn = removeAssignChain(mth, instArgAssignInsn, remover, InsnType.NEW_INSTANCE); InsnNode newInstInsn = removeAssignChain(mth, instArgAssignInsn, remover, InsnType.NEW_INSTANCE);
if (newInstInsn != null) { if (newInstInsn != null) {
remover.addWithoutUnbind(newInstInsn);
RegisterArg instArg = newInstInsn.getResult(); RegisterArg instArg = newInstInsn.getResult();
RegisterArg resultArg = co.getResult(); RegisterArg resultArg = co.getResult();
if (!resultArg.equals(instArg)) { if (!resultArg.equals(instArg)) {
// replace all usages of 'instArg' with result of this constructor instruction // replace all usages of 'instArg' with result of this constructor instruction
for (RegisterArg useArg : new ArrayList<>(instArg.getSVar().getUseList())) { for (RegisterArg useArg : new ArrayList<>(instArg.getSVar().getUseList())) {
RegisterArg dup = resultArg.duplicate();
InsnNode parentInsn = useArg.getParentInsn(); InsnNode parentInsn = useArg.getParentInsn();
parentInsn.replaceArg(useArg, dup); if (parentInsn != null) {
dup.setParentInsn(parentInsn); parentInsn.replaceArg(useArg, resultArg.duplicate());
resultArg.getSVar().use(dup); }
} }
} }
newInstInsn.setResult(null); // don't unbind result arg on remove
} }
} }
ConstructorInsn replace = processConstructor(mth, co); ConstructorInsn replace = processConstructor(mth, co);
...@@ -146,19 +145,19 @@ public class ConstructorVisitor extends AbstractVisitor { ...@@ -146,19 +145,19 @@ public class ConstructorVisitor extends AbstractVisitor {
/** /**
* Remove instructions on 'move' chain until instruction with type 'insnType' * Remove instructions on 'move' chain until instruction with type 'insnType'
*/ */
private static InsnNode removeAssignChain(MethodNode mth, InsnNode insn, InstructionRemover remover, InsnType insnType) { private static InsnNode removeAssignChain(MethodNode mth, InsnNode insn, InsnRemover remover, InsnType insnType) {
if (insn == null) { if (insn == null) {
return null; return null;
} }
if (insn.isAttrStorageEmpty()) {
remover.add(insn);
} else {
BlockUtils.replaceInsn(mth, insn, new InsnNode(InsnType.NOP, 0));
}
InsnType type = insn.getType(); InsnType type = insn.getType();
if (type == insnType) { if (type == insnType) {
return insn; return insn;
} }
if (insn.isAttrStorageEmpty()) {
remover.addWithoutUnbind(insn);
} else {
BlockUtils.replaceInsn(mth, insn, new InsnNode(InsnType.NOP, 0));
}
if (type == InsnType.MOVE) { if (type == InsnType.MOVE) {
RegisterArg arg = (RegisterArg) insn.getArg(0); RegisterArg arg = (RegisterArg) insn.getArg(0);
return removeAssignChain(mth, arg.getAssignInsn(), remover, insnType); return removeAssignChain(mth, arg.getAssignInsn(), remover, insnType);
......
...@@ -22,7 +22,7 @@ import jadx.core.dex.nodes.InsnNode; ...@@ -22,7 +22,7 @@ import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.parser.FieldInitAttr; import jadx.core.dex.nodes.parser.FieldInitAttr;
import jadx.core.utils.BlockUtils; import jadx.core.utils.BlockUtils;
import jadx.core.utils.InstructionRemover; import jadx.core.utils.InsnRemover;
import jadx.core.utils.exceptions.JadxException; import jadx.core.utils.exceptions.JadxException;
@JadxVisitor( @JadxVisitor(
...@@ -92,7 +92,7 @@ public class ExtractFieldInit extends AbstractVisitor { ...@@ -92,7 +92,7 @@ public class ExtractFieldInit extends AbstractVisitor {
if (initInsns.size() == 1) { if (initInsns.size() == 1) {
InsnNode insn = initInsns.get(0); InsnNode insn = initInsns.get(0);
if (checkInsn(insn)) { if (checkInsn(insn)) {
InstructionRemover.remove(classInitMth, insn); InsnRemover.remove(classInitMth, insn);
addFieldInitAttr(classInitMth, field, insn); addFieldInitAttr(classInitMth, field, insn);
} }
} }
...@@ -165,7 +165,7 @@ public class ExtractFieldInit extends AbstractVisitor { ...@@ -165,7 +165,7 @@ public class ExtractFieldInit extends AbstractVisitor {
// all checks passed // all checks passed
for (InitInfo info : infoList) { for (InitInfo info : infoList) {
for (InsnNode putInsn : info.getPutInsns()) { for (InsnNode putInsn : info.getPutInsns()) {
InstructionRemover.remove(info.getConstrMth(), putInsn); InsnRemover.remove(info.getConstrMth(), putInsn);
} }
} }
for (InsnNode insn : common.getPutInsns()) { for (InsnNode insn : common.getPutInsns()) {
......
...@@ -40,7 +40,7 @@ import jadx.core.dex.trycatch.ExceptionHandler; ...@@ -40,7 +40,7 @@ import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.visitors.shrink.CodeShrinkVisitor; import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
import jadx.core.utils.ErrorsCounter; import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.InsnUtils; import jadx.core.utils.InsnUtils;
import jadx.core.utils.InstructionRemover; import jadx.core.utils.InsnRemover;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
import static jadx.core.utils.BlockUtils.replaceInsn; import static jadx.core.utils.BlockUtils.replaceInsn;
...@@ -63,12 +63,12 @@ public class ModVisitor extends AbstractVisitor { ...@@ -63,12 +63,12 @@ public class ModVisitor extends AbstractVisitor {
return; return;
} }
InstructionRemover remover = new InstructionRemover(mth); InsnRemover remover = new InsnRemover(mth);
replaceStep(mth, remover); replaceStep(mth, remover);
removeStep(mth, remover); removeStep(mth, remover);
} }
private static void replaceStep(MethodNode mth, InstructionRemover remover) { private static void replaceStep(MethodNode mth, InsnRemover remover) {
ClassNode parentClass = mth.getParentClass(); ClassNode parentClass = mth.getParentClass();
for (BlockNode block : mth.getBasicBlocks()) { for (BlockNode block : mth.getBasicBlocks()) {
remover.setBlock(block); remover.setBlock(block);
...@@ -120,7 +120,7 @@ public class ModVisitor extends AbstractVisitor { ...@@ -120,7 +120,7 @@ public class ModVisitor extends AbstractVisitor {
InsnNode filledArr = makeFilledArrayInsn(mth, (NewArrayNode) insn, (FillArrayNode) ni); InsnNode filledArr = makeFilledArrayInsn(mth, (NewArrayNode) insn, (FillArrayNode) ni);
if (filledArr != null) { if (filledArr != null) {
replaceInsn(block, i, filledArr); replaceInsn(block, i, filledArr);
remover.add(ni); remover.addAndUnbind(ni);
} }
} }
} }
...@@ -182,7 +182,7 @@ public class ModVisitor extends AbstractVisitor { ...@@ -182,7 +182,7 @@ public class ModVisitor extends AbstractVisitor {
/** /**
* Remove unnecessary instructions * Remove unnecessary instructions
*/ */
private static void removeStep(MethodNode mth, InstructionRemover remover) { private static void removeStep(MethodNode mth, InsnRemover remover) {
for (BlockNode block : mth.getBasicBlocks()) { for (BlockNode block : mth.getBasicBlocks()) {
remover.setBlock(block); remover.setBlock(block);
for (InsnNode insn : block.getInstructions()) { for (InsnNode insn : block.getInstructions()) {
...@@ -190,7 +190,7 @@ public class ModVisitor extends AbstractVisitor { ...@@ -190,7 +190,7 @@ public class ModVisitor extends AbstractVisitor {
case NOP: case NOP:
case GOTO: case GOTO:
case NEW_INSTANCE: case NEW_INSTANCE:
remover.add(insn); remover.addAndUnbind(insn);
break; break;
default: default:
...@@ -335,7 +335,7 @@ public class ModVisitor extends AbstractVisitor { ...@@ -335,7 +335,7 @@ public class ModVisitor extends AbstractVisitor {
return filledArr; return filledArr;
} }
private static void processMoveException(BlockNode block, InsnNode insn, InstructionRemover remover) { private static void processMoveException(BlockNode block, InsnNode insn, InsnRemover remover) {
ExcHandlerAttr excHandlerAttr = block.get(AType.EXC_HANDLER); ExcHandlerAttr excHandlerAttr = block.get(AType.EXC_HANDLER);
if (excHandlerAttr == null) { if (excHandlerAttr == null) {
return; return;
...@@ -352,7 +352,7 @@ public class ModVisitor extends AbstractVisitor { ...@@ -352,7 +352,7 @@ public class ModVisitor extends AbstractVisitor {
SSAVar sVar = insn.getResult().getSVar(); SSAVar sVar = insn.getResult().getSVar();
if (sVar.getUseCount() == 0) { if (sVar.getUseCount() == 0) {
excHandler.setArg(new NamedArg(name, type)); excHandler.setArg(new NamedArg(name, type));
remover.add(insn); remover.addAndUnbind(insn);
} else if (sVar.isUsedInPhi()) { } else if (sVar.isUsedInPhi()) {
// exception var moved to external variable => replace with 'move' insn // exception var moved to external variable => replace with 'move' insn
InsnNode moveInsn = new InsnNode(InsnType.MOVE, 1); InsnNode moveInsn = new InsnNode(InsnType.MOVE, 1);
......
...@@ -33,7 +33,7 @@ import jadx.core.dex.nodes.MethodNode; ...@@ -33,7 +33,7 @@ import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.visitors.shrink.CodeShrinkVisitor; import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
import jadx.core.utils.InsnList; import jadx.core.utils.InsnList;
import jadx.core.utils.InsnUtils; import jadx.core.utils.InsnUtils;
import jadx.core.utils.InstructionRemover; import jadx.core.utils.InsnRemover;
import jadx.core.utils.Utils; import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxException; import jadx.core.utils.exceptions.JadxException;
...@@ -57,7 +57,7 @@ public class ReSugarCode extends AbstractVisitor { ...@@ -57,7 +57,7 @@ public class ReSugarCode extends AbstractVisitor {
if (mth.isNoCode()) { if (mth.isNoCode()) {
return; return;
} }
InstructionRemover remover = new InstructionRemover(mth); InsnRemover remover = new InsnRemover(mth);
for (BlockNode block : mth.getBasicBlocks()) { for (BlockNode block : mth.getBasicBlocks()) {
remover.setBlock(block); remover.setBlock(block);
List<InsnNode> instructions = block.getInstructions(); List<InsnNode> instructions = block.getInstructions();
...@@ -69,14 +69,14 @@ public class ReSugarCode extends AbstractVisitor { ...@@ -69,14 +69,14 @@ public class ReSugarCode extends AbstractVisitor {
} }
} }
private static void process(MethodNode mth, List<InsnNode> instructions, int i, InstructionRemover remover) { private static void process(MethodNode mth, List<InsnNode> instructions, int i, InsnRemover remover) {
InsnNode insn = instructions.get(i); InsnNode insn = instructions.get(i);
if (insn.contains(AFlag.REMOVE)) { if (insn.contains(AFlag.REMOVE)) {
return; return;
} }
switch (insn.getType()) { switch (insn.getType()) {
case NEW_ARRAY: case NEW_ARRAY:
processNewArray(mth, instructions, i, remover); processNewArray(mth, (NewArrayNode) insn, instructions, remover);
break; break;
case SWITCH: case SWITCH:
...@@ -91,9 +91,8 @@ public class ReSugarCode extends AbstractVisitor { ...@@ -91,9 +91,8 @@ public class ReSugarCode extends AbstractVisitor {
/** /**
* Replace new array and sequence of array-put to new filled-array instruction. * Replace new array and sequence of array-put to new filled-array instruction.
*/ */
private static void processNewArray(MethodNode mth, List<InsnNode> instructions, int i, private static void processNewArray(MethodNode mth, NewArrayNode newArrayInsn,
InstructionRemover remover) { List<InsnNode> instructions, InsnRemover remover) {
NewArrayNode newArrayInsn = (NewArrayNode) instructions.get(i);
InsnArg arrLenArg = newArrayInsn.getArg(0); InsnArg arrLenArg = newArrayInsn.getArg(0);
if (!arrLenArg.isLiteral()) { if (!arrLenArg.isLiteral()) {
return; return;
...@@ -136,12 +135,13 @@ public class ReSugarCode extends AbstractVisitor { ...@@ -136,12 +135,13 @@ public class ReSugarCode extends AbstractVisitor {
// checks complete, apply // checks complete, apply
ArgType arrType = newArrayInsn.getArrayType(); ArgType arrType = newArrayInsn.getArrayType();
InsnNode filledArr = new FilledNewArrayNode(arrType.getArrayElement(), len); InsnNode filledArr = new FilledNewArrayNode(arrType.getArrayElement(), len);
filledArr.setResult(arrArg.duplicate()); filledArr.setResult(arrArg);
for (InsnNode put : arrPuts) { for (InsnNode put : arrPuts) {
filledArr.addArg(put.getArg(2).duplicate()); filledArr.addArg(put.getArg(2));
remover.addAndUnbind(mth, put); remover.addWithoutUnbind(put);
InsnRemover.unbindArgUsage(mth, put.getArg(0));
} }
remover.addAndUnbind(mth, newArrayInsn); remover.addWithoutUnbind(newArrayInsn);
int replaceIndex = InsnList.getIndex(instructions, Utils.last(arrPuts)); int replaceIndex = InsnList.getIndex(instructions, Utils.last(arrPuts));
instructions.set(replaceIndex, filledArr); instructions.set(replaceIndex, filledArr);
......
...@@ -16,7 +16,7 @@ import jadx.core.dex.trycatch.ExceptionHandler; ...@@ -16,7 +16,7 @@ import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.trycatch.TryCatchBlock; import jadx.core.dex.trycatch.TryCatchBlock;
import jadx.core.dex.visitors.AbstractVisitor; import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.utils.BlockUtils; import jadx.core.utils.BlockUtils;
import jadx.core.utils.InstructionRemover; import jadx.core.utils.InsnRemover;
public class BlockExceptionHandler extends AbstractVisitor { public class BlockExceptionHandler extends AbstractVisitor {
...@@ -77,13 +77,13 @@ public class BlockExceptionHandler extends AbstractVisitor { ...@@ -77,13 +77,13 @@ public class BlockExceptionHandler extends AbstractVisitor {
} }
for (BlockNode excBlock : excHandler.getBlocks()) { for (BlockNode excBlock : excHandler.getBlocks()) {
// remove 'monitor-exit' from exception handler blocks // remove 'monitor-exit' from exception handler blocks
InstructionRemover remover = new InstructionRemover(mth, excBlock); InsnRemover remover = new InsnRemover(mth, excBlock);
for (InsnNode insn : excBlock.getInstructions()) { for (InsnNode insn : excBlock.getInstructions()) {
if (insn.getType() == InsnType.MONITOR_ENTER) { if (insn.getType() == InsnType.MONITOR_ENTER) {
break; break;
} }
if (insn.getType() == InsnType.MONITOR_EXIT) { if (insn.getType() == InsnType.MONITOR_EXIT) {
remover.add(insn); remover.addAndUnbind(insn);
} }
} }
remover.perform(); remover.perform();
......
...@@ -41,7 +41,7 @@ import jadx.core.dex.trycatch.SplitterBlockAttr; ...@@ -41,7 +41,7 @@ import jadx.core.dex.trycatch.SplitterBlockAttr;
import jadx.core.dex.trycatch.TryCatchBlock; import jadx.core.dex.trycatch.TryCatchBlock;
import jadx.core.utils.BlockUtils; import jadx.core.utils.BlockUtils;
import jadx.core.utils.ErrorsCounter; import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.InstructionRemover; import jadx.core.utils.InsnRemover;
import jadx.core.utils.RegionUtils; import jadx.core.utils.RegionUtils;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
...@@ -567,7 +567,7 @@ public class RegionMaker { ...@@ -567,7 +567,7 @@ public class RegionMaker {
} }
exitInsn.add(AFlag.DONT_GENERATE); exitInsn.add(AFlag.DONT_GENERATE);
exitInsn.add(AFlag.REMOVE); exitInsn.add(AFlag.REMOVE);
InstructionRemover.unbindInsn(mth, exitInsn); InsnRemover.unbindInsn(mth, exitInsn);
} }
BlockNode body = getNextBlock(block); BlockNode body = getNextBlock(block);
......
...@@ -25,7 +25,7 @@ import jadx.core.dex.regions.SwitchRegion; ...@@ -25,7 +25,7 @@ import jadx.core.dex.regions.SwitchRegion;
import jadx.core.dex.regions.SynchronizedRegion; import jadx.core.dex.regions.SynchronizedRegion;
import jadx.core.dex.regions.loops.LoopRegion; import jadx.core.dex.regions.loops.LoopRegion;
import jadx.core.dex.visitors.AbstractVisitor; import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.utils.InstructionRemover; import jadx.core.utils.InsnRemover;
import jadx.core.utils.RegionUtils; import jadx.core.utils.RegionUtils;
import jadx.core.utils.exceptions.JadxException; import jadx.core.utils.exceptions.JadxException;
...@@ -176,10 +176,10 @@ public class RegionMakerVisitor extends AbstractVisitor { ...@@ -176,10 +176,10 @@ public class RegionMakerVisitor extends AbstractVisitor {
// replace synchronized block with inner region // replace synchronized block with inner region
startRegion.getSubBlocks().set(0, synchRegion.getRegion()); startRegion.getSubBlocks().set(0, synchRegion.getRegion());
// remove 'monitor-enter' instruction // remove 'monitor-enter' instruction
InstructionRemover.remove(mth, synchInsn); InsnRemover.remove(mth, synchInsn);
// remove 'monitor-exit' instruction // remove 'monitor-exit' instruction
for (InsnNode exit : synchRegion.getExitInsns()) { for (InsnNode exit : synchRegion.getExitInsns()) {
InstructionRemover.remove(mth, exit); InsnRemover.remove(mth, exit);
} }
// run region cleaner again // run region cleaner again
CleanRegions.process(mth); CleanRegions.process(mth);
......
...@@ -28,6 +28,7 @@ import jadx.core.dex.regions.loops.LoopRegion; ...@@ -28,6 +28,7 @@ import jadx.core.dex.regions.loops.LoopRegion;
import jadx.core.dex.visitors.AbstractVisitor; import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.dex.visitors.regions.DepthRegionTraversal; import jadx.core.dex.visitors.regions.DepthRegionTraversal;
import jadx.core.utils.RegionUtils; import jadx.core.utils.RegionUtils;
import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxException; import jadx.core.utils.exceptions.JadxException;
public class ProcessVariables extends AbstractVisitor { public class ProcessVariables extends AbstractVisitor {
...@@ -148,9 +149,7 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -148,9 +149,7 @@ public class ProcessVariables extends AbstractVisitor {
list.add(usage); list.add(usage);
} }
} }
if (!list.isEmpty()) { codeVarUsage.put(codeVar, Utils.lockList(list));
codeVarUsage.put(codeVar, list);
}
} }
return codeVarUsage; return codeVarUsage;
} }
......
...@@ -22,7 +22,7 @@ import jadx.core.dex.visitors.AbstractVisitor; ...@@ -22,7 +22,7 @@ import jadx.core.dex.visitors.AbstractVisitor;
import jadx.core.dex.visitors.JadxVisitor; import jadx.core.dex.visitors.JadxVisitor;
import jadx.core.dex.visitors.blocksmaker.BlockFinish; import jadx.core.dex.visitors.blocksmaker.BlockFinish;
import jadx.core.utils.InsnList; import jadx.core.utils.InsnList;
import jadx.core.utils.InstructionRemover; import jadx.core.utils.InsnRemover;
import jadx.core.utils.exceptions.JadxException; import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
...@@ -235,7 +235,7 @@ public class SSATransform extends AbstractVisitor { ...@@ -235,7 +235,7 @@ public class SSATransform extends AbstractVisitor {
InsnNode parentInsn = arg.getAssignInsn(); InsnNode parentInsn = arg.getAssignInsn();
if (parentInsn != null && parentInsn.contains(AFlag.REMOVE)) { if (parentInsn != null && parentInsn.contains(AFlag.REMOVE)) {
phi.removeArg(arg); phi.removeArg(arg);
InstructionRemover.remove(mth, block, parentInsn); InsnRemover.remove(mth, block, parentInsn);
removed = true; removed = true;
} }
} }
...@@ -283,7 +283,7 @@ public class SSATransform extends AbstractVisitor { ...@@ -283,7 +283,7 @@ public class SSATransform extends AbstractVisitor {
phi.removeArg(useArg); phi.removeArg(useArg);
} }
} }
InstructionRemover.remove(mth, block, phi); InsnRemover.remove(mth, block, phi);
return true; return true;
} }
boolean allSame = phi.getArgsCount() == 1 || isSameArgs(phi); boolean allSame = phi.getArgsCount() == 1 || isSameArgs(phi);
...@@ -326,7 +326,7 @@ public class SSATransform extends AbstractVisitor { ...@@ -326,7 +326,7 @@ public class SSATransform extends AbstractVisitor {
sVar.setUsedInPhi(null); sVar.setUsedInPhi(null);
} }
} }
InstructionRemover.remove(mth, block, phiInsn); InsnRemover.remove(mth, block, phiInsn);
} }
} }
if (list.isEmpty()) { if (list.isEmpty()) {
...@@ -396,7 +396,7 @@ public class SSATransform extends AbstractVisitor { ...@@ -396,7 +396,7 @@ public class SSATransform extends AbstractVisitor {
assignInsn.add(AFlag.DONT_INLINE); assignInsn.add(AFlag.DONT_INLINE);
} }
} }
InstructionRemover.unbindInsn(mth, phi); InsnRemover.unbindInsn(mth, phi);
return true; return true;
} }
......
...@@ -19,17 +19,17 @@ import jadx.core.dex.nodes.MethodNode; ...@@ -19,17 +19,17 @@ import jadx.core.dex.nodes.MethodNode;
* Helper class for correct instructions removing, * Helper class for correct instructions removing,
* can be used while iterating over instructions list * can be used while iterating over instructions list
*/ */
public class InstructionRemover { public class InsnRemover {
private final MethodNode mth; private final MethodNode mth;
private final List<InsnNode> toRemove; private final List<InsnNode> toRemove;
private List<InsnNode> instrList; private List<InsnNode> instrList;
public InstructionRemover(MethodNode mth) { public InsnRemover(MethodNode mth) {
this(mth, null); this(mth, null);
} }
public InstructionRemover(MethodNode mth, BlockNode block) { public InsnRemover(MethodNode mth, BlockNode block) {
this.mth = mth; this.mth = mth;
this.toRemove = new ArrayList<>(); this.toRemove = new ArrayList<>();
if (block != null) { if (block != null) {
...@@ -41,20 +41,20 @@ public class InstructionRemover { ...@@ -41,20 +41,20 @@ public class InstructionRemover {
this.instrList = block.getInstructions(); this.instrList = block.getInstructions();
} }
public void add(InsnNode insn) { public void addAndUnbind(InsnNode insn) {
toRemove.add(insn); toRemove.add(insn);
unbindInsn(mth, insn);
} }
public void addAndUnbind(MethodNode mth, InsnNode insn) { public void addWithoutUnbind(InsnNode insn) {
toRemove.add(insn); toRemove.add(insn);
unbindInsn(mth, insn);
} }
public void perform() { public void perform() {
if (toRemove.isEmpty()) { if (toRemove.isEmpty()) {
return; return;
} }
removeAll(mth, instrList, toRemove); removeAll(instrList, toRemove);
toRemove.clear(); toRemove.clear();
} }
...@@ -111,7 +111,7 @@ public class InstructionRemover { ...@@ -111,7 +111,7 @@ public class InstructionRemover {
// Don't use 'instrList.removeAll(toRemove)' because it will remove instructions by content // Don't use 'instrList.removeAll(toRemove)' because it will remove instructions by content
// and here can be several instructions with same content // and here can be several instructions with same content
private static void removeAll(MethodNode mth, List<InsnNode> insns, List<InsnNode> toRemove) { private static void removeAll(List<InsnNode> insns, List<InsnNode> toRemove) {
if (toRemove == null || toRemove.isEmpty()) { if (toRemove == null || toRemove.isEmpty()) {
return; return;
} }
...@@ -120,7 +120,6 @@ public class InstructionRemover { ...@@ -120,7 +120,6 @@ public class InstructionRemover {
for (int i = 0; i < insnsCount; i++) { for (int i = 0; i < insnsCount; i++) {
if (insns.get(i) == rem) { if (insns.get(i) == rem) {
insns.remove(i); insns.remove(i);
unbindInsn(mth, rem);
break; break;
} }
} }
...@@ -147,8 +146,11 @@ public class InstructionRemover { ...@@ -147,8 +146,11 @@ public class InstructionRemover {
} }
} }
public static void removeAll(MethodNode mth, BlockNode block, List<InsnNode> insns) { public static void removeAllAndUnbind(MethodNode mth, BlockNode block, List<InsnNode> insns) {
removeAll(mth, block.getInstructions(), insns); for (InsnNode insn : insns) {
unbindInsn(mth, insn);
}
removeAll(block.getInstructions(), insns);
} }
public static void remove(MethodNode mth, BlockNode block, int index) { public static void remove(MethodNode mth, BlockNode block, int index) {
......
package jadx.tests.integration.inline;
import org.junit.jupiter.api.Test;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
public class TestInline7 extends SmaliTest {
/*
public void onViewCreated(View view, @Nullable Bundle bundle) {
super.onViewCreated(view, bundle);
view.findViewById(R.id.done_button_early_release_failure).setOnClickListener(new SafeClickListener(this));
Bundle arguments = getArguments();
if (arguments != null) {
((TextView) view.findViewById(R.id.summary_content_early_release_failure)).setText(
getString(R.string.withdraw_id_capture_failure_content,
new Object[]{arguments.getString("withdrawAmount"), arguments.getString ("withdrawHoldTime")})
);
}
}
*/
@Test
public void test() {
disableCompilation();
ClassNode cls = getClassNodeFromSmaliWithPkg("inline", "TestInline7");
String code = cls.getCode().toString();
assertThat(code, not(containsString("Bundle arguments;")));
assertThat(code, containsOne("Bundle arguments = getArguments();"));
assertThat(code, containsOne("@Nullable Bundle bundle"));
}
}
...@@ -2,36 +2,48 @@ package jadx.tests.integration.invoke; ...@@ -2,36 +2,48 @@ package jadx.tests.integration.invoke;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import jadx.NotYetImplemented;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest; import jadx.tests.api.IntegrationTest;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
public class TestConstructorInvoke extends IntegrationTest { public class TestConstructorInvoke extends IntegrationTest {
public class TestCls { void test(String root, String name) {
void test(String root, String name) { ViewHolder holder = new ViewHolder(root, name);
ViewHolder viewHolder = new ViewHolder(root, name); }
}
private final class ViewHolder {
private int mElements = 0;
private final String mRoot;
private String mName;
private ViewHolder(String root, String name) { private final class ViewHolder {
this.mRoot = root; private ViewHolder(String root, String name) {
this.mName = name;
}
} }
} }
@Test @Test
@NotYetImplemented("Variable lost name from debug info")
public void test() { public void test() {
ClassNode cls = getClassNode(TestConstructorInvoke.class); ClassNode cls = getClassNode(TestConstructorInvoke.class);
String code = cls.getCode().toString(); String code = cls.getCode().toString();
assertThat(code, containsString("new ViewHolder(root, name);")); assertThat(code, containsOne(indent() + "ViewHolder holder = new ViewHolder(root, name);"));
}
// Remove after fix above @NYI
@Test
public void test2() {
ClassNode cls = getClassNode(TestConstructorInvoke.class);
String code = cls.getCode().toString();
assertThat(code, containsOne(indent() + "ViewHolder viewHolder = new ViewHolder(root, name);"));
}
@Test
public void testNoDebug() {
noDebugInfo();
ClassNode cls = getClassNode(TestConstructorInvoke.class);
String code = cls.getCode().toString();
assertThat(code, containsOne(indent() + "ViewHolder viewHolder = new ViewHolder("));
} }
} }
...@@ -13,7 +13,7 @@ import jadx.core.dex.trycatch.ExcHandlerAttr; ...@@ -13,7 +13,7 @@ import jadx.core.dex.trycatch.ExcHandlerAttr;
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.BlockUtils; import jadx.core.utils.BlockUtils;
import jadx.core.utils.InstructionRemover; import jadx.core.utils.InsnRemover;
import jadx.tests.api.IntegrationTest; import jadx.tests.api.IntegrationTest;
import static jadx.tests.api.utils.JadxMatchers.containsOne; import static jadx.tests.api.utils.JadxMatchers.containsOne;
...@@ -33,13 +33,13 @@ public class TestContinueInLoop2 extends IntegrationTest { ...@@ -33,13 +33,13 @@ public class TestContinueInLoop2 extends IntegrationTest {
excHandler.addBlock(node); excHandler.addBlock(node);
} }
for (BlockNode excBlock : excHandler.getBlocks()) { for (BlockNode excBlock : excHandler.getBlocks()) {
InstructionRemover remover = new InstructionRemover(mth, excBlock); InsnRemover remover = new InsnRemover(mth, excBlock);
for (InsnNode insn : excBlock.getInstructions()) { for (InsnNode insn : excBlock.getInstructions()) {
if (insn.getType() == InsnType.MONITOR_ENTER) { if (insn.getType() == InsnType.MONITOR_ENTER) {
break; break;
} }
if (insn.getType() == InsnType.MONITOR_EXIT) { if (insn.getType() == InsnType.MONITOR_EXIT) {
remover.add(insn); remover.addAndUnbind(insn);
} }
} }
remover.perform(); remover.perform();
......
.class public Linline/TestInline7;
.super Ljava/lang/Object;
.method public onViewCreated(Landroid/view/View;Landroid/os/Bundle;)V
.locals 4
.param p2 # Landroid/os/Bundle;
.annotation build Landroid/support/annotation/Nullable;
.end annotation
.end param
.line 42
invoke-super {p0, p1, p2}, Lapp/navigation/fragment/NodeFragment;->onViewCreated(Landroid/view/View;Landroid/os/Bundle;)V
.line 43
sget p2, Lapp/wallet/R$id;->done_button_early_release_failure:I
invoke-virtual {p1, p2}, Landroid/view/View;->findViewById(I)Landroid/view/View;
move-result-object p2
new-instance v0, Lapp/common/utils/SafeClickListener;
invoke-direct {v0, p0}, Lapp/common/utils/SafeClickListener;-><init>(Lapp/common/utils/ISafeClickVerifierListener;)V
invoke-virtual {p2, v0}, Landroid/view/View;->setOnClickListener(Landroid/view/View$OnClickListener;)V
.line 44
invoke-virtual {p0}, Linline/TestInline7;->getArguments()Landroid/os/Bundle;
move-result-object p2
if-eqz p2, :cond_0
.line 46
sget v0, Lapp/wallet/R$id;->summary_content_early_release_failure:I
invoke-virtual {p1, v0}, Landroid/view/View;->findViewById(I)Landroid/view/View;
move-result-object p1
check-cast p1, Landroid/widget/TextView;
sget v0, Lapp/wallet/R$string;->withdraw_id_capture_failure_content:I
const/4 v1, 0x2
new-array v1, v1, [Ljava/lang/Object;
const/4 v2, 0x0
const-string v3, "withdrawAmount"
invoke-virtual {p2, v3}, Landroid/os/Bundle;->getString(Ljava/lang/String;)Ljava/lang/String;
move-result-object v3
aput-object v3, v1, v2
const/4 v2, 0x1
const-string v3, "withdrawHoldTime"
invoke-virtual {p2, v3}, Landroid/os/Bundle;->getString(Ljava/lang/String;)Ljava/lang/String;
move-result-object p2
aput-object p2, v1, v2
invoke-virtual {p0, v0, v1}, Linline/TestInline7;->getString(I[Ljava/lang/Object;)Ljava/lang/String;
move-result-object p2
invoke-virtual {p1, p2}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
:cond_0
return-void
.end method
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