core: fixed types for arguments from overloaded methods
This commit is contained in:
@@ -523,7 +523,29 @@ public class InsnGen {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
code.add(callMth.getName());
|
code.add(callMth.getName());
|
||||||
addArgs(code, insn, k);
|
if (callMthNode != null && callMthNode.isArgsOverload()) {
|
||||||
|
int argsCount = insn.getArgsCount();
|
||||||
|
List<ArgType> originalType = callMth.getArgumentsTypes();
|
||||||
|
int origPos = 0;
|
||||||
|
|
||||||
|
code.add('(');
|
||||||
|
for (int i = k; i < argsCount; i++) {
|
||||||
|
InsnArg arg = insn.getArg(i);
|
||||||
|
ArgType origType = originalType.get(origPos);
|
||||||
|
if (!arg.getType().equals(origType)) {
|
||||||
|
code.add('(').add(useType(origType)).add(')').add(arg(arg));
|
||||||
|
} else {
|
||||||
|
code.add(arg(arg));
|
||||||
|
}
|
||||||
|
if (i < argsCount - 1) {
|
||||||
|
code.add(", ");
|
||||||
|
}
|
||||||
|
origPos++;
|
||||||
|
}
|
||||||
|
code.add(')');
|
||||||
|
} else {
|
||||||
|
addArgs(code, insn, k);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void inlineMethod(MethodNode callMthNode, InvokeNode insn, CodeWriter code) throws CodegenException {
|
private void inlineMethod(MethodNode callMthNode, InvokeNode insn, CodeWriter code) throws CodegenException {
|
||||||
@@ -566,11 +588,14 @@ public class InsnGen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addArgs(CodeWriter code, InsnNode insn, int k) throws CodegenException {
|
private void addArgs(CodeWriter code, InsnNode insn, int k) throws CodegenException {
|
||||||
|
int argsCount = insn.getArgsCount();
|
||||||
code.add('(');
|
code.add('(');
|
||||||
for (int i = k; i < insn.getArgsCount(); i++) {
|
if (k < argsCount) {
|
||||||
code.add(arg(insn, i));
|
code.add(arg(insn, k));
|
||||||
if (i < insn.getArgsCount() - 1)
|
for (int i = k + 1; i < argsCount; i++) {
|
||||||
code.add(", ");
|
code.add(", ");
|
||||||
|
code.add(arg(insn, i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
code.add(')');
|
code.add(')');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -455,8 +455,23 @@ public class MethodNode extends LineAttrNode implements ILoadable {
|
|||||||
return exceptionHandlers;
|
return exceptionHandlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isMethodOverloaded() {
|
/**
|
||||||
// TODO
|
* Return true if exists method with same name and arguments count
|
||||||
|
*/
|
||||||
|
public boolean isArgsOverload() {
|
||||||
|
int argsCount = mthInfo.getArgumentsTypes().size();
|
||||||
|
if (argsCount == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String name = getName();
|
||||||
|
List<MethodNode> methods = parentClass.getMethods();
|
||||||
|
for (MethodNode method : methods) {
|
||||||
|
if (this != method
|
||||||
|
&& method.getName().equals(name)
|
||||||
|
&& method.mthInfo.getArgumentsTypes().size() == argsCount)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ public class FinishTypeResolver extends AbstractVisitor {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
do {
|
do {
|
||||||
change = false;
|
change = false;
|
||||||
for (BlockNode block : mth.getBasicBlocks())
|
for (BlockNode block : mth.getBasicBlocks()) {
|
||||||
for (InsnNode insn : block.getInstructions())
|
for (InsnNode insn : block.getInstructions())
|
||||||
if (PostTypeResolver.visit(insn))
|
if (PostTypeResolver.visit(mth, insn))
|
||||||
change = true;
|
change = true;
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
if (i > 1000)
|
if (i > 1000)
|
||||||
break;
|
break;
|
||||||
|
|||||||
+44
-17
@@ -1,35 +1,41 @@
|
|||||||
package jadx.core.dex.visitors.typeresolver.finish;
|
package jadx.core.dex.visitors.typeresolver.finish;
|
||||||
|
|
||||||
|
import jadx.core.dex.info.MethodInfo;
|
||||||
import jadx.core.dex.instructions.IfNode;
|
import jadx.core.dex.instructions.IfNode;
|
||||||
|
import jadx.core.dex.instructions.InvokeNode;
|
||||||
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.RegisterArg;
|
import jadx.core.dex.instructions.args.RegisterArg;
|
||||||
import jadx.core.dex.nodes.InsnNode;
|
import jadx.core.dex.nodes.InsnNode;
|
||||||
|
import jadx.core.dex.nodes.MethodNode;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class PostTypeResolver {
|
public class PostTypeResolver {
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(PostTypeResolver.class);
|
||||||
|
|
||||||
public static boolean visit(InsnNode insn) {
|
public static boolean visit(MethodNode mth, InsnNode insn) {
|
||||||
switch (insn.getType()) {
|
switch (insn.getType()) {
|
||||||
case CONST:
|
case CONST:
|
||||||
if (insn.getArgsCount() > 0) {
|
RegisterArg res = insn.getResult();
|
||||||
RegisterArg res = insn.getResult();
|
LiteralArg litArg = (LiteralArg) insn.getArg(0);
|
||||||
LiteralArg litArg = (LiteralArg) insn.getArg(0);
|
if (res.getType().isObject()) {
|
||||||
if (res.getType().isObject()) {
|
long lit = litArg.getLiteral();
|
||||||
long lit = litArg.getLiteral();
|
if (lit != 0) {
|
||||||
if (lit != 0) {
|
// incorrect literal value for object
|
||||||
// incorrect literal value for object
|
ArgType type = (lit == 1 ? ArgType.BOOLEAN : ArgType.INT);
|
||||||
ArgType type = (lit == 1 ? ArgType.BOOLEAN : ArgType.INT);
|
// can't merge with object -> force it
|
||||||
// can't merge with object -> force it
|
litArg.getTypedVar().forceSetType(type);
|
||||||
litArg.getTypedVar().forceSetType(type);
|
res.getTypedVar().forceSetType(type);
|
||||||
res.getTypedVar().forceSetType(type);
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// return litArg.getTypedVar().forceSetType(res.getType());
|
|
||||||
return litArg.merge(res);
|
|
||||||
}
|
}
|
||||||
break;
|
// return litArg.getTypedVar().forceSetType(res.getType());
|
||||||
|
return litArg.merge(res);
|
||||||
|
|
||||||
case MOVE: {
|
case MOVE: {
|
||||||
boolean change = false;
|
boolean change = false;
|
||||||
@@ -58,6 +64,27 @@ public class PostTypeResolver {
|
|||||||
return change;
|
return change;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check argument types for overloaded methods
|
||||||
|
case INVOKE: {
|
||||||
|
boolean change = false;
|
||||||
|
InvokeNode inv = (InvokeNode) insn;
|
||||||
|
MethodInfo callMth = inv.getCallMth();
|
||||||
|
MethodNode node = mth.dex().resolveMethod(callMth);
|
||||||
|
if (node != null && node.isArgsOverload()) {
|
||||||
|
List<ArgType> args = callMth.getArgumentsTypes();
|
||||||
|
int j = inv.getArgsCount() - 1;
|
||||||
|
for (int i = args.size() - 1; i >= 0; i--) {
|
||||||
|
ArgType argType = args.get(i);
|
||||||
|
InsnArg insnArg = inv.getArg(j--);
|
||||||
|
if (insnArg.isRegister() && !argType.equals(insnArg.getType())) {
|
||||||
|
insnArg.getTypedVar().forceSetType(argType);
|
||||||
|
change = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return change;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package jadx.samples;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Code example from
|
||||||
|
* <a href="http://stackoverflow.com/questions/2840183/is-there-any-java-decompiler-that-can-correctly-decompile-calls-to-overloaded-me">
|
||||||
|
* stackoverflow question</a>
|
||||||
|
*/
|
||||||
|
public class TestTypeResolver2 extends AbstractTest {
|
||||||
|
|
||||||
|
private static String result = "";
|
||||||
|
|
||||||
|
public void testOverloadedMethods() {
|
||||||
|
Object s1 = "The";
|
||||||
|
Object s2 = "answer";
|
||||||
|
doPrint((Object) "You should know:");
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
doPrint(s1);
|
||||||
|
doPrint(s2);
|
||||||
|
s1 = "is";
|
||||||
|
s2 = new Integer(42);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void doPrint(String s1) {
|
||||||
|
// incorrect call
|
||||||
|
assertTrue(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void doPrint(Integer s1) {
|
||||||
|
// incorrect call
|
||||||
|
assertTrue(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void doPrint(Object s1) {
|
||||||
|
// correct call
|
||||||
|
result += s1 + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean testRun() throws Exception {
|
||||||
|
testOverloadedMethods();
|
||||||
|
|
||||||
|
assertEquals(result, "You should know: The answer is 42 ");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
(new TestTypeResolver2()).testRun();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user