Commit d2acaa03 authored by Skylot's avatar Skylot

core: guess variable name from assign instruction

parent f2aa4cd1
......@@ -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<String, String> OBJ_ALIAS;
private final Set<String> varNames = new HashSet<String>();
private final boolean fallback;
static {
OBJ_ALIAS = new HashMap<String, String>();
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;
}
}
......@@ -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);
}
}
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<IContainer, Integer> regionsOrder,
......
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