Commit c24cdf5c authored by Skylot's avatar Skylot

core: fix constructor instruction replacement

parent d748e004
...@@ -54,10 +54,7 @@ public class NameGen { ...@@ -54,10 +54,7 @@ public class NameGen {
return name; return name;
} }
name = getUniqueVarName(name); name = getUniqueVarName(name);
SSAVar sVar = arg.getSVar(); arg.setName(name);
if (sVar != null) {
sVar.setName(name);
}
return name; return name;
} }
......
...@@ -81,9 +81,10 @@ public class RegisterArg extends InsnArg implements Named { ...@@ -81,9 +81,10 @@ public class RegisterArg extends InsnArg implements Named {
setName(name); setName(name);
} }
@Deprecated public RegisterArg duplicate() {
public void forceType(ArgType type) { RegisterArg dup = new RegisterArg(getRegNum(), getType());
this.type = type; dup.setSVar(sVar);
return dup;
} }
/** /**
......
...@@ -27,6 +27,7 @@ import jadx.core.dex.trycatch.ExcHandlerAttr; ...@@ -27,6 +27,7 @@ import jadx.core.dex.trycatch.ExcHandlerAttr;
import jadx.core.dex.trycatch.ExceptionHandler; import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.utils.InstructionRemover; import jadx.core.utils.InstructionRemover;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -144,7 +145,21 @@ public class ModVisitor extends AbstractVisitor { ...@@ -144,7 +145,21 @@ public class ModVisitor extends AbstractVisitor {
} else { } else {
replaceInsn(block, insnNumber, co); replaceInsn(block, insnNumber, co);
if (co.isNewInstance()) { if (co.isNewInstance()) {
removeAssignChain(instArgAssignInsn, remover, InsnType.NEW_INSTANCE); InsnNode newInstInsn = removeAssignChain(instArgAssignInsn, remover, InsnType.NEW_INSTANCE);
if (newInstInsn != null) {
RegisterArg instArg = newInstInsn.getResult();
RegisterArg resultArg = co.getResult();
if (!resultArg.equals(instArg)) {
// replace all usages of 'instArg' with result of this constructor instruction
for (RegisterArg useArg : new ArrayList<RegisterArg>(instArg.getSVar().getUseList())) {
RegisterArg dup = resultArg.duplicate();
InsnNode parentInsn = useArg.getParentInsn();
parentInsn.replaceArg(useArg, dup);
dup.setParentInsn(parentInsn);
resultArg.getSVar().use(dup);
}
}
}
} }
ConstructorInsn replace = processConstructor(mth, co); ConstructorInsn replace = processConstructor(mth, co);
if (replace != null) { if (replace != null) {
...@@ -169,22 +184,25 @@ public class ModVisitor extends AbstractVisitor { ...@@ -169,22 +184,25 @@ public class ModVisitor extends AbstractVisitor {
*/ */
private static ConstructorInsn processConstructor(MethodNode mth, ConstructorInsn co) { private static ConstructorInsn processConstructor(MethodNode mth, ConstructorInsn co) {
MethodNode callMth = mth.dex().resolveMethod(co.getCallMth()); MethodNode callMth = mth.dex().resolveMethod(co.getCallMth());
if (callMth != null if (callMth == null
&& callMth.getAccessFlags().isSynthetic() || !callMth.getAccessFlags().isSynthetic()
&& allArgsNull(co)) { || !allArgsNull(co)) {
// if all arguments is null => replace with default constructor return null;
}
ClassNode classNode = mth.dex().resolveClass(callMth.getParentClass().getClassInfo()); ClassNode classNode = mth.dex().resolveClass(callMth.getParentClass().getClassInfo());
if (classNode == null) {
return null;
}
boolean passThis = co.getArgsCount() >= 1 && co.getArg(0).isThis(); boolean passThis = co.getArgsCount() >= 1 && co.getArg(0).isThis();
String ctrId = "<init>(" + (passThis ? TypeGen.signature(co.getArg(0).getType()) : "") + ")V"; String ctrId = "<init>(" + (passThis ? TypeGen.signature(co.getArg(0).getType()) : "") + ")V";
MethodNode defCtr = classNode.searchMethodByName(ctrId); MethodNode defCtr = classNode.searchMethodByName(ctrId);
if (defCtr != null) { if (defCtr == null) {
return null;
}
ConstructorInsn newInsn = new ConstructorInsn(defCtr.getMethodInfo(), co.getCallType(), co.getInstanceArg()); ConstructorInsn newInsn = new ConstructorInsn(defCtr.getMethodInfo(), co.getCallType(), co.getInstanceArg());
newInsn.setResult(co.getResult()); newInsn.setResult(co.getResult());
return newInsn; return newInsn;
} }
}
return null;
}
private static boolean allArgsNull(InsnNode insn) { private static boolean allArgsNull(InsnNode insn) {
for (InsnArg insnArg : insn.getArguments()) { for (InsnArg insnArg : insn.getArguments()) {
...@@ -203,19 +221,20 @@ public class ModVisitor extends AbstractVisitor { ...@@ -203,19 +221,20 @@ public class ModVisitor extends AbstractVisitor {
/** /**
* Remove instructions on 'move' chain until instruction with type 'insnType' * Remove instructions on 'move' chain until instruction with type 'insnType'
*/ */
private static void removeAssignChain(InsnNode insn, InstructionRemover remover, InsnType insnType) { private static InsnNode removeAssignChain(InsnNode insn, InstructionRemover remover, InsnType insnType) {
if (insn == null) { if (insn == null) {
return; return null;
} }
remover.add(insn); remover.add(insn);
InsnType type = insn.getType(); InsnType type = insn.getType();
if (type == insnType) { if (type == insnType) {
return; return insn;
} }
if (type == InsnType.MOVE) { if (type == InsnType.MOVE) {
RegisterArg arg = (RegisterArg) insn.getArg(0); RegisterArg arg = (RegisterArg) insn.getArg(0);
removeAssignChain(arg.getAssignInsn(), remover, insnType); return removeAssignChain(arg.getAssignInsn(), remover, insnType);
} }
return null;
} }
/** /**
......
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