From 4fb6ada5ecdb957fe054a403ac3eff0f1117827c Mon Sep 17 00:00:00 2001 From: Skylot Date: Fri, 26 Sep 2014 22:19:23 +0400 Subject: [PATCH] core: fix type inference for phi nodes --- .../dex/visitors/ssa/EliminatePhiNodes.java | 24 +++-- .../typeinference/PostTypeInference.java | 16 ++++ .../visitors/typeinference/TypeInference.java | 16 ++-- .../test/java/jadx/tests/smali/TestN21.java | 16 ++++ jadx-core/src/test/smali/TestN21.smali | 93 +++++++++++++++++++ 5 files changed, 149 insertions(+), 16 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/tests/smali/TestN21.java create mode 100644 jadx-core/src/test/smali/TestN21.smali diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/EliminatePhiNodes.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/EliminatePhiNodes.java index 18304f72b..b686e96eb 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/EliminatePhiNodes.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ssa/EliminatePhiNodes.java @@ -12,7 +12,12 @@ import jadx.core.utils.exceptions.JadxException; import java.util.Iterator; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class EliminatePhiNodes extends AbstractVisitor { + private static final Logger LOG = LoggerFactory.getLogger(EliminatePhiNodes.class); + @Override public void visit(MethodNode mth) throws JadxException { if (mth.isNoCode()) { @@ -29,13 +34,20 @@ public class EliminatePhiNodes extends AbstractVisitor { } List list = phiList.getList(); for (PhiInsn phiInsn : list) { - for (Iterator iterator = block.getInstructions().iterator(); iterator.hasNext(); ) { - InsnNode insn = iterator.next(); - if (insn == phiInsn) { - iterator.remove(); - } - } + removeInsn(mth, block, phiInsn); } } } + + private static void removeInsn(MethodNode mth, BlockNode block, PhiInsn phiInsn) { + Iterator it = block.getInstructions().iterator(); + while (it.hasNext()) { + InsnNode insn = it.next(); + if (insn == phiInsn) { + it.remove(); + return; + } + } + LOG.warn("Phi node not removed: {}, mth: {}", phiInsn, mth); + } } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/PostTypeInference.java b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/PostTypeInference.java index 30d1d96be..b79ba81da 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/PostTypeInference.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/PostTypeInference.java @@ -3,6 +3,7 @@ package jadx.core.dex.visitors.typeinference; import jadx.core.dex.info.MethodInfo; import jadx.core.dex.instructions.IndexInsnNode; import jadx.core.dex.instructions.InvokeNode; +import jadx.core.dex.instructions.PhiInsn; import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.LiteralArg; @@ -94,6 +95,21 @@ public class PostTypeInference { return true; } + case PHI: { + PhiInsn phi = (PhiInsn) insn; + SSAVar resultSVar = phi.getResult().getSVar(); + if (resultSVar != null && !resultSVar.getType().isTypeKnown()) { + for (InsnArg arg : phi.getArguments()) { + ArgType argType = arg.getType(); + if (argType.isTypeKnown()) { + resultSVar.setType(argType); + return true; + } + } + } + return false; + } + default: break; } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInference.java b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInference.java index 42fc00f9f..af458ba0a 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInference.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInference.java @@ -1,6 +1,5 @@ package jadx.core.dex.visitors.typeinference; -import jadx.core.dex.attributes.AFlag; import jadx.core.dex.instructions.PhiInsn; import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.InsnArg; @@ -9,7 +8,6 @@ import jadx.core.dex.instructions.args.SSAVar; import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.visitors.AbstractVisitor; import jadx.core.utils.exceptions.JadxException; -import jadx.core.utils.exceptions.JadxRuntimeException; import java.util.List; @@ -43,7 +41,7 @@ public class TypeInference extends AbstractVisitor { } } - private ArgType processType(SSAVar var) { + private static ArgType processType(SSAVar var) { RegisterArg assign = var.getAssign(); List useList = var.getUseList(); if (assign != null @@ -58,17 +56,15 @@ public class TypeInference extends AbstractVisitor { } for (RegisterArg arg : useList) { ArgType useType = arg.getType(); - if (useType.isTypeKnown()) { - type = ArgType.merge(type, useType); - } - if (arg.getParentInsn().contains(AFlag.INCONSISTENT_CODE)) { - throw new JadxRuntimeException("not removed arg"); + ArgType newType = ArgType.merge(type, useType); + if (newType != null) { + type = newType; } } return type; } - private void processPhiNode(PhiInsn phi) { + private static void processPhiNode(PhiInsn phi) { ArgType type = phi.getResult().getType(); if (!type.isTypeKnown()) { for (InsnArg arg : phi.getArguments()) { @@ -86,7 +82,7 @@ public class TypeInference extends AbstractVisitor { } } - private String processVarName(SSAVar var) { + private static String processVarName(SSAVar var) { String name = null; if (var.getAssign() != null) { name = var.getAssign().getName(); diff --git a/jadx-core/src/test/java/jadx/tests/smali/TestN21.java b/jadx-core/src/test/java/jadx/tests/smali/TestN21.java new file mode 100644 index 000000000..b0ee0de96 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/smali/TestN21.java @@ -0,0 +1,16 @@ +package jadx.tests.smali; + +import jadx.core.dex.nodes.ClassNode; +import jadx.tests.api.SmaliTest; + +import org.junit.Test; + +public class TestN21 extends SmaliTest { + + @Test + public void test() { + ClassNode cls = getClassNodeFromSmali("TestN21"); + String code = cls.getCode().toString(); + System.out.println(code); + } +} diff --git a/jadx-core/src/test/smali/TestN21.smali b/jadx-core/src/test/smali/TestN21.smali new file mode 100644 index 000000000..adaea935e --- /dev/null +++ b/jadx-core/src/test/smali/TestN21.smali @@ -0,0 +1,93 @@ +.class public LTestN21; +.super Ljava/lang/Object; + +.method private static test([BI)I + .locals 5 + + const/4 v1, 0x0 + + const/16 v0, 0xe + + aget-byte v0, p0, v0 + + shl-int/lit8 v0, v0, 0x10 + + move v2, v1 + + :goto_0 + if-nez v2, :cond_1 + + const/4 v2, 0x3 + + and-int/lit16 v3, p1, 0xff + + :try_start_0 + aget-byte v3, p0, v3 + + and-int/lit16 v3, v3, 0xff + + shr-int/lit8 v4, p1, 0x8 + + and-int/lit16 v4, v4, 0xff + + aget-byte v4, p0, v4 + + and-int/lit16 v4, v4, 0xff + + shl-int/lit8 v4, v4, 0x8 + + or-int/2addr v3, v4 + + shr-int/lit8 v4, p1, 0x10 + + and-int/lit16 v4, v4, 0xff + + aget-byte v4, p0, v4 + + and-int/lit16 v4, v4, 0xff + + shl-int/lit8 v4, v4, 0x10 + + or-int/2addr v3, v4 + + shr-int/lit8 v4, p1, 0x18 + + and-int/lit16 v4, v4, 0xff + + aget-byte v0, p0, v4 + :try_end_0 + .catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_1 + + shl-int/lit8 v0, v0, 0x18 + + or-int/2addr v0, v3 + + :cond_0 + :goto_1 + return v0 + + :catch_0 + move-exception v2 + + :cond_1 + if-nez v1, :cond_0 + + const/4 v1, 0x2 + + and-int/lit8 v2, p1, 0x7f + + :try_start_1 + aget-byte v0, p0, v2 + :try_end_1 + .catch Ljava/lang/Exception; {:try_start_1 .. :try_end_1} :catch_0 + + shr-int/lit8 v0, v0, 0x8 + + goto :goto_1 + + :catch_1 + move-exception v3 + + goto :goto_0 +.end method +