From d2acaa03f52eed6f8b5b81b336b2d5c1de9bb457 Mon Sep 17 00:00:00 2001 From: Skylot Date: Thu, 5 Jun 2014 21:50:19 +0400 Subject: [PATCH] core: guess variable name from assign instruction --- .../main/java/jadx/core/codegen/NameGen.java | 132 ++++++++++++++---- .../instructions/args/MthParameterArg.java | 20 +++ .../visitors/regions/ProcessVariables.java | 7 + 3 files changed, 135 insertions(+), 24 deletions(-) diff --git a/jadx-core/src/main/java/jadx/core/codegen/NameGen.java b/jadx-core/src/main/java/jadx/core/codegen/NameGen.java index eb60acc44..a59e4741a 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/NameGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/NameGen.java @@ -3,20 +3,46 @@ package jadx.core.codegen; import jadx.core.Consts; import jadx.core.deobf.NameMapper; import jadx.core.dex.info.ClassInfo; +import jadx.core.dex.instructions.InvokeNode; import jadx.core.dex.instructions.args.ArgType; +import jadx.core.dex.instructions.args.InsnArg; +import jadx.core.dex.instructions.args.InsnWrapArg; 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.InsnNode; import jadx.core.utils.Utils; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; public class NameGen { + private static final Map OBJ_ALIAS; + private final Set varNames = new HashSet(); private final boolean fallback; + static { + OBJ_ALIAS = new HashMap(); + OBJ_ALIAS.put(Consts.CLASS_STRING, "str"); + OBJ_ALIAS.put(Consts.CLASS_CLASS, "cls"); + OBJ_ALIAS.put(Consts.CLASS_THROWABLE, "th"); + OBJ_ALIAS.put(Consts.CLASS_OBJECT, "obj"); + OBJ_ALIAS.put("java.util.Iterator", "it"); + OBJ_ALIAS.put("java.lang.Boolean", "bool"); + OBJ_ALIAS.put("java.lang.Short", "sh"); + OBJ_ALIAS.put("java.lang.Integer", "num"); + OBJ_ALIAS.put("java.lang.Character", "ch"); + OBJ_ALIAS.put("java.lang.Byte", "b"); + OBJ_ALIAS.put("java.lang.Float", "f"); + OBJ_ALIAS.put("java.lang.Long", "l"); + OBJ_ALIAS.put("java.lang.Double", "d"); + } + public NameGen(boolean fallback) { this.fallback = fallback; } @@ -72,7 +98,7 @@ public class NameGen { } String varName; if (name != null) { - if (name.equals("this")) { + if ("this".equals(name)) { return name; } varName = name; @@ -101,34 +127,92 @@ public class NameGen { private static String makeNameForObject(ArgType type) { if (type.isObject()) { - String obj = type.getObject(); - if (obj.startsWith("java.lang.")) { - if (obj.equals(Consts.CLASS_STRING)) { - return "str"; - } - if (obj.equals(Consts.CLASS_OBJECT)) { - return "obj"; - } - if (obj.equals(Consts.CLASS_CLASS)) { - return "cls"; - } - if (obj.equals(Consts.CLASS_THROWABLE)) { - return "th"; - } + String alias = getAliasForObject(type.getObject()); + if (alias != null) { + return alias; } ClassInfo clsInfo = ClassInfo.fromType(type); String shortName = clsInfo.getShortName(); - if (shortName.toUpperCase().equals(shortName)) { - // all characters are upper case - return shortName.toLowerCase(); - } - if (!shortName.isEmpty()) { - String v1 = Character.toLowerCase(shortName.charAt(0)) + shortName.substring(1); - if (!v1.equals(shortName)) { - return v1; - } + String vName = fromName(shortName); + if (vName != null) { + return vName; } } return Utils.escape(type.toString()); } + + private static String fromName(String name) { + if (name == null || name.isEmpty()) { + return null; + } + if (name.toUpperCase().equals(name)) { + // all characters are upper case + return name.toLowerCase(); + } + String v1 = Character.toLowerCase(name.charAt(0)) + name.substring(1); + if (!v1.equals(name)) { + return v1; + } + if (name.length() < 3) { + return name + "Var"; + } + return null; + } + + public static void guessName(RegisterArg arg) { + SSAVar sVar = arg.getSVar(); + if (sVar == null || sVar.getName() != null) { + return; + } + RegisterArg assignArg = sVar.getAssign(); + InsnNode assignInsn = assignArg.getParentInsn(); + String name = makeNameFromInsn(assignInsn); + if (name != null && !NameMapper.isReserved(name)) { + assignArg.setName(name); + } + } + + public static String getAliasForObject(String name) { + return OBJ_ALIAS.get(name); + } + + private static String makeNameFromInsn(InsnNode insn) { + switch (insn.getType()) { + case INVOKE: + InvokeNode inv = (InvokeNode) insn; + String name = inv.getCallMth().getName(); + if (name.startsWith("get") || name.startsWith("set")) { + return fromName(name.substring(3)); + } + if ("iterator".equals(name)) { + return "it"; + } + return name; + + case CONSTRUCTOR: + ConstructorInsn co = (ConstructorInsn) insn; + return makeNameForObject(co.getClassType().getType()); + + case ARRAY_LENGTH: + return "length"; + + case ARITH: + case TERNARY: + case CAST: + for (InsnArg arg : insn.getArguments()) { + if (arg.isInsnWrap()) { + InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn(); + String wName = makeNameFromInsn(wrapInsn); + if (wName != null) { + return wName; + } + } + } + break; + + default: + break; + } + return null; + } } diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/MthParameterArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/MthParameterArg.java index a6e9a4fb1..fd575bcb5 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/MthParameterArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/MthParameterArg.java @@ -41,4 +41,24 @@ public class MthParameterArg extends RegisterArg { } super.setSVar(sVar); } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof MthParameterArg)) { + return false; + } + if (!super.equals(obj)) { + return false; + } + MthParameterArg that = (MthParameterArg) obj; + return isThis == that.isThis; + } + + @Override + public int hashCode() { + return 31 * super.hashCode() + (isThis ? 1 : 0); + } } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java index 508f48f4c..c481b5ca9 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessVariables.java @@ -1,5 +1,6 @@ package jadx.core.dex.visitors.regions; +import jadx.core.codegen.NameGen; import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.nodes.DeclareVariablesAttr; @@ -179,6 +180,7 @@ public class ProcessVariables extends AbstractVisitor { if (u.getArgRegion() == assignRegion && canDeclareInRegion(u, assignRegion, regionsOrder)) { u.getArg().getParentInsn().add(AFlag.DECLARE_VAR); + processVar(u.getArg()); it.remove(); break; } @@ -248,6 +250,11 @@ public class ProcessVariables extends AbstractVisitor { region.addAttr(dv); } dv.addVar(arg); + processVar(arg); + } + + private static void processVar(RegisterArg arg) { + NameGen.guessName(arg); } private static int calculateOrder(IContainer container, Map regionsOrder,