core: guess variable name from assign instruction
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<IContainer, Integer> regionsOrder,
|
||||
|
||||
Reference in New Issue
Block a user