Commit 7844e554 authored by Skylot's avatar Skylot

core: refactor info classes for store only one instance

parent 10de4ff4
...@@ -6,7 +6,6 @@ import jadx.core.codegen.CodeGen; ...@@ -6,7 +6,6 @@ import jadx.core.codegen.CodeGen;
import jadx.core.codegen.CodeWriter; import jadx.core.codegen.CodeWriter;
import jadx.core.deobf.DefaultDeobfuscator; import jadx.core.deobf.DefaultDeobfuscator;
import jadx.core.deobf.Deobfuscator; import jadx.core.deobf.Deobfuscator;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.RootNode; import jadx.core.dex.nodes.RootNode;
import jadx.core.dex.visitors.IDexTreeVisitor; import jadx.core.dex.visitors.IDexTreeVisitor;
...@@ -90,7 +89,6 @@ public final class JadxDecompiler { ...@@ -90,7 +89,6 @@ public final class JadxDecompiler {
} }
void reset() { void reset() {
ClassInfo.clearCache();
classes = null; classes = null;
resources = null; resources = null;
xmlParser = null; xmlParser = null;
......
...@@ -192,7 +192,7 @@ public class ClassGen { ...@@ -192,7 +192,7 @@ public class ClassGen {
if (type.isGenericType()) { if (type.isGenericType()) {
code.add(type.getObject()); code.add(type.getObject());
} else { } else {
useClass(code, ClassInfo.fromType(type)); useClass(code, ClassInfo.fromType(cls.dex(), type));
} }
if (list != null && !list.isEmpty()) { if (list != null && !list.isEmpty()) {
code.add(" extends "); code.add(" extends ");
...@@ -201,7 +201,7 @@ public class ClassGen { ...@@ -201,7 +201,7 @@ public class ClassGen {
if (g.isGenericType()) { if (g.isGenericType()) {
code.add(g.getObject()); code.add(g.getObject());
} else { } else {
useClass(code, ClassInfo.fromType(g)); useClass(code, ClassInfo.fromType(cls.dex(), g));
} }
if (it.hasNext()) { if (it.hasNext()) {
code.add(" & "); code.add(" & ");
...@@ -407,7 +407,7 @@ public class ClassGen { ...@@ -407,7 +407,7 @@ public class ClassGen {
if (type.isGenericType()) { if (type.isGenericType()) {
code.add(type.getObject()); code.add(type.getObject());
} else { } else {
useClass(code, ClassInfo.fromType(type)); useClass(code, ClassInfo.fromType(cls.dex(), type));
} }
} else if (stype == PrimitiveType.ARRAY) { } else if (stype == PrimitiveType.ARRAY) {
useType(code, type.getArrayElement()); useType(code, type.getArrayElement());
......
...@@ -39,7 +39,7 @@ public class MethodGen { ...@@ -39,7 +39,7 @@ public class MethodGen {
this.mth = mth; this.mth = mth;
this.classGen = classGen; this.classGen = classGen;
this.annotationGen = classGen.getAnnotationGen(); this.annotationGen = classGen.getAnnotationGen();
this.nameGen = new NameGen(classGen.isFallbackMode()); this.nameGen = new NameGen(mth, classGen.isFallbackMode());
} }
public ClassGen getClassGen() { public ClassGen getClassGen() {
......
...@@ -14,6 +14,7 @@ import jadx.core.dex.instructions.args.RegisterArg; ...@@ -14,6 +14,7 @@ import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.args.SSAVar; import jadx.core.dex.instructions.args.SSAVar;
import jadx.core.dex.instructions.mods.ConstructorInsn; import jadx.core.dex.instructions.mods.ConstructorInsn;
import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.Utils; import jadx.core.utils.Utils;
import java.util.HashMap; import java.util.HashMap;
...@@ -26,6 +27,7 @@ public class NameGen { ...@@ -26,6 +27,7 @@ public class NameGen {
private static final Map<String, String> OBJ_ALIAS; private static final Map<String, String> OBJ_ALIAS;
private final Set<String> varNames = new HashSet<String>(); private final Set<String> varNames = new HashSet<String>();
private final MethodNode mth;
private final boolean fallback; private final boolean fallback;
static { static {
...@@ -45,7 +47,8 @@ public class NameGen { ...@@ -45,7 +47,8 @@ public class NameGen {
OBJ_ALIAS.put("java.lang.Double", "d"); OBJ_ALIAS.put("java.lang.Double", "d");
} }
public NameGen(boolean fallback) { public NameGen(MethodNode mth, boolean fallback) {
this.mth = mth;
this.fallback = fallback; this.fallback = fallback;
} }
...@@ -107,7 +110,7 @@ public class NameGen { ...@@ -107,7 +110,7 @@ public class NameGen {
} }
varName = name; varName = name;
} else { } else {
varName = makeNameForType(arg.getType()); varName = guessName(arg);
} }
if (NameMapper.isReserved(varName)) { if (NameMapper.isReserved(varName)) {
return varName + "R"; return varName + "R";
...@@ -119,7 +122,23 @@ public class NameGen { ...@@ -119,7 +122,23 @@ public class NameGen {
return "r" + arg.getRegNum(); return "r" + arg.getRegNum();
} }
private static String makeNameForType(ArgType type) { private String guessName(RegisterArg arg) {
SSAVar sVar = arg.getSVar();
if (sVar != null && sVar.getName() == null) {
RegisterArg assignArg = sVar.getAssign();
InsnNode assignInsn = assignArg.getParentInsn();
if (assignInsn != null) {
String name = makeNameFromInsn(assignInsn);
if (name != null && !NameMapper.isReserved(name)) {
assignArg.setName(name);
return name;
}
}
}
return makeNameForType(arg.getType());
}
private String makeNameForType(ArgType type) {
if (type.isPrimitive()) { if (type.isPrimitive()) {
return makeNameForPrimitive(type); return makeNameForPrimitive(type);
} else if (type.isArray()) { } else if (type.isArray()) {
...@@ -133,13 +152,13 @@ public class NameGen { ...@@ -133,13 +152,13 @@ public class NameGen {
return type.getPrimitiveType().getShortName().toLowerCase(); return type.getPrimitiveType().getShortName().toLowerCase();
} }
private static String makeNameForObject(ArgType type) { private String makeNameForObject(ArgType type) {
if (type.isObject()) { if (type.isObject()) {
String alias = getAliasForObject(type.getObject()); String alias = getAliasForObject(type.getObject());
if (alias != null) { if (alias != null) {
return alias; return alias;
} }
ClassInfo clsInfo = ClassInfo.fromType(type); ClassInfo clsInfo = ClassInfo.fromType(mth.dex(), type);
String shortName = clsInfo.getShortName(); String shortName = clsInfo.getShortName();
String vName = fromName(shortName); String vName = fromName(shortName);
if (vName != null) { if (vName != null) {
...@@ -167,24 +186,11 @@ public class NameGen { ...@@ -167,24 +186,11 @@ public class NameGen {
return null; 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);
}
}
private static String getAliasForObject(String name) { private static String getAliasForObject(String name) {
return OBJ_ALIAS.get(name); return OBJ_ALIAS.get(name);
} }
private static String makeNameFromInsn(InsnNode insn) { private String makeNameFromInsn(InsnNode insn) {
switch (insn.getType()) { switch (insn.getType()) {
case INVOKE: case INVOKE:
InvokeNode inv = (InvokeNode) insn; InvokeNode inv = (InvokeNode) insn;
......
...@@ -4,15 +4,12 @@ import jadx.core.Consts; ...@@ -4,15 +4,12 @@ import jadx.core.Consts;
import jadx.core.deobf.NameMapper; import jadx.core.deobf.NameMapper;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.nodes.DexNode; import jadx.core.dex.nodes.DexNode;
import jadx.core.utils.exceptions.JadxRuntimeException;
import java.io.File; import java.io.File;
import java.util.Map;
import java.util.WeakHashMap;
public final class ClassInfo { public final class ClassInfo {
private static final Map<ArgType, ClassInfo> CLASSINFO_CACHE = new WeakHashMap<ArgType, ClassInfo>();
private final ArgType type; private final ArgType type;
private String pkg; private String pkg;
private String name; private String name;
...@@ -20,11 +17,22 @@ public final class ClassInfo { ...@@ -20,11 +17,22 @@ public final class ClassInfo {
// for inner class not equals null // for inner class not equals null
private ClassInfo parentClass; private ClassInfo parentClass;
private ClassInfo(ArgType type) { private ClassInfo(DexNode dex, ArgType type) {
assert type.isObject() : "Not class type: " + type; if (!type.isObject()) {
throw new JadxRuntimeException("Not class type: " + type);
}
this.type = type; this.type = type;
splitNames(true); splitNames(dex, true);
}
public static ClassInfo fromType(DexNode dex, ArgType type) {
ClassInfo cls = dex.getInfoStorage().getCls(type);
if (cls != null) {
return cls;
}
cls = new ClassInfo(dex, type);
return dex.getInfoStorage().putCls(cls);
} }
public static ClassInfo fromDex(DexNode dex, int clsIndex) { public static ClassInfo fromDex(DexNode dex, int clsIndex) {
...@@ -35,27 +43,14 @@ public final class ClassInfo { ...@@ -35,27 +43,14 @@ public final class ClassInfo {
if (type.isArray()) { if (type.isArray()) {
type = ArgType.OBJECT; type = ArgType.OBJECT;
} }
return fromType(type); return fromType(dex, type);
}
public static ClassInfo fromName(String clsName) {
return fromType(ArgType.object(clsName));
}
public static ClassInfo fromType(ArgType type) {
ClassInfo cls = CLASSINFO_CACHE.get(type);
if (cls == null) {
cls = new ClassInfo(type);
CLASSINFO_CACHE.put(type, cls);
}
return cls;
} }
public static void clearCache() { public static ClassInfo fromName(DexNode dex, String clsName) {
CLASSINFO_CACHE.clear(); return fromType(dex, ArgType.object(clsName));
} }
private void splitNames(boolean canBeInner) { private void splitNames(DexNode dex, boolean canBeInner) {
String fullObjectName = type.getObject(); String fullObjectName = type.getObject();
assert fullObjectName.indexOf('/') == -1 : "Raw type: " + type; assert fullObjectName.indexOf('/') == -1 : "Raw type: " + type;
...@@ -73,7 +68,7 @@ public final class ClassInfo { ...@@ -73,7 +68,7 @@ public final class ClassInfo {
int sep = clsName.lastIndexOf('$'); int sep = clsName.lastIndexOf('$');
if (canBeInner && sep > 0 && sep != clsName.length() - 1) { if (canBeInner && sep > 0 && sep != clsName.length() - 1) {
String parClsName = pkg + "." + clsName.substring(0, sep); String parClsName = pkg + "." + clsName.substring(0, sep);
parentClass = fromName(parClsName); parentClass = fromName(dex, parClsName);
clsName = clsName.substring(sep + 1); clsName = clsName.substring(sep + 1);
} else { } else {
parentClass = null; parentClass = null;
...@@ -134,8 +129,8 @@ public final class ClassInfo { ...@@ -134,8 +129,8 @@ public final class ClassInfo {
return parentClass != null; return parentClass != null;
} }
public void notInner() { public void notInner(DexNode dex) {
splitNames(false); splitNames(dex, false);
} }
public ArgType getType() { public ArgType getType() {
......
...@@ -11,15 +11,20 @@ public class FieldInfo { ...@@ -11,15 +11,20 @@ public class FieldInfo {
private final String name; private final String name;
private final ArgType type; private final ArgType type;
public FieldInfo(ClassInfo declClass, String name, ArgType type) { private FieldInfo(ClassInfo declClass, String name, ArgType type) {
this.declClass = declClass; this.declClass = declClass;
this.name = name; this.name = name;
this.type = type; this.type = type;
} }
public static FieldInfo from(DexNode dex, ClassInfo declClass, String name, ArgType type) {
FieldInfo field = new FieldInfo(declClass, name, type);
return dex.getInfoStorage().getField(field);
}
public static FieldInfo fromDex(DexNode dex, int index) { public static FieldInfo fromDex(DexNode dex, int index) {
FieldId field = dex.getFieldId(index); FieldId field = dex.getFieldId(index);
return new FieldInfo( return from(dex,
ClassInfo.fromDex(dex, field.getDeclaringClassIndex()), ClassInfo.fromDex(dex, field.getDeclaringClassIndex()),
dex.getString(field.getNameIndex()), dex.getString(field.getNameIndex()),
dex.getType(field.getTypeIndex())); dex.getType(field.getTypeIndex()));
......
package jadx.core.dex.info;
import jadx.core.dex.instructions.args.ArgType;
import java.util.HashMap;
import java.util.Map;
public class InfoStorage {
private final Map<ArgType, ClassInfo> classes = new HashMap<ArgType, ClassInfo>();
private final Map<Integer, MethodInfo> methods = new HashMap<Integer, MethodInfo>();
private final Map<FieldInfo, FieldInfo> fields = new HashMap<FieldInfo, FieldInfo>();
public ClassInfo getCls(ArgType type) {
return classes.get(type);
}
public ClassInfo putCls(ClassInfo cls) {
synchronized (classes) {
ClassInfo prev = classes.put(cls.getType(), cls);
return prev == null ? cls : prev;
}
}
public MethodInfo getMethod(int mtdId) {
return methods.get(mtdId);
}
public MethodInfo putMethod(int mthId, MethodInfo mth) {
synchronized (methods) {
MethodInfo prev = methods.put(mthId, mth);
return prev == null ? mth : prev;
}
}
public FieldInfo getField(FieldInfo field) {
synchronized (fields) {
FieldInfo f = fields.get(field);
if (f != null) {
return f;
}
fields.put(field, field);
return field;
}
}
}
...@@ -40,7 +40,12 @@ public final class MethodInfo { ...@@ -40,7 +40,12 @@ public final class MethodInfo {
} }
public static MethodInfo fromDex(DexNode dex, int mthIndex) { public static MethodInfo fromDex(DexNode dex, int mthIndex) {
return new MethodInfo(dex, mthIndex); MethodInfo mth = dex.getInfoStorage().getMethod(mthIndex);
if (mth != null) {
return mth;
}
mth = new MethodInfo(dex, mthIndex);
return dex.getInfoStorage().putMethod(mthIndex, mth);
} }
public String getName() { public String getName() {
......
...@@ -191,12 +191,12 @@ public class ClassNode extends LineAttrNode implements ILoadable { ...@@ -191,12 +191,12 @@ public class ClassNode extends LineAttrNode implements ILoadable {
// parse class generic map // parse class generic map
genericMap = sp.consumeGenericMap(); genericMap = sp.consumeGenericMap();
// parse super class signature // parse super class signature
superClass = ClassInfo.fromType(sp.consumeType()); superClass = ClassInfo.fromType(dex, sp.consumeType());
// parse interfaces signatures // parse interfaces signatures
for (int i = 0; i < interfaces.size(); i++) { for (int i = 0; i < interfaces.size(); i++) {
ArgType type = sp.consumeType(); ArgType type = sp.consumeType();
if (type != null) { if (type != null) {
interfaces.set(i, ClassInfo.fromType(type)); interfaces.set(i, ClassInfo.fromType(dex, type));
} else { } else {
break; break;
} }
...@@ -228,7 +228,7 @@ public class ClassNode extends LineAttrNode implements ILoadable { ...@@ -228,7 +228,7 @@ public class ClassNode extends LineAttrNode implements ILoadable {
try { try {
mth.load(); mth.load();
} catch (Exception e) { } catch (Exception e) {
LOG.error("Method load error:", e); LOG.error("Method load error: {}", mth, e);
mth.addAttr(new JadxErrorAttr(e)); mth.addAttr(new JadxErrorAttr(e));
} }
} }
......
...@@ -2,6 +2,7 @@ package jadx.core.dex.nodes; ...@@ -2,6 +2,7 @@ package jadx.core.dex.nodes;
import jadx.core.dex.info.ClassInfo; import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.FieldInfo; import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.info.InfoStorage;
import jadx.core.dex.info.MethodInfo; import jadx.core.dex.info.MethodInfo;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.utils.exceptions.DecodeException; import jadx.core.utils.exceptions.DecodeException;
...@@ -36,6 +37,8 @@ public class DexNode { ...@@ -36,6 +37,8 @@ public class DexNode {
private final Map<Object, FieldNode> constFields = new HashMap<Object, FieldNode>(); private final Map<Object, FieldNode> constFields = new HashMap<Object, FieldNode>();
private final InfoStorage infoStorage = new InfoStorage();
public DexNode(RootNode root, InputFile input) { public DexNode(RootNode root, InputFile input) {
this.root = root; this.root = root;
this.dexBuf = input.getDexBuffer(); this.dexBuf = input.getDexBuffer();
...@@ -78,6 +81,10 @@ public class DexNode { ...@@ -78,6 +81,10 @@ public class DexNode {
return constFields; return constFields;
} }
public InfoStorage getInfoStorage() {
return infoStorage;
}
// DexBuffer wrappers // DexBuffer wrappers
public String getString(int index) { public String getString(int index) {
......
...@@ -9,7 +9,7 @@ public class ResRefField extends FieldNode { ...@@ -9,7 +9,7 @@ public class ResRefField extends FieldNode {
public ResRefField(DexNode dex, String str) { public ResRefField(DexNode dex, String str) {
super(dex.root().getAppResClass(), super(dex.root().getAppResClass(),
new FieldInfo(dex.root().getAppResClass().getClassInfo(), str, ArgType.INT), FieldInfo.from(dex, dex.root().getAppResClass().getClassInfo(), str, ArgType.INT),
AccessFlags.ACC_PUBLIC); AccessFlags.ACC_PUBLIC);
} }
} }
...@@ -117,7 +117,8 @@ public class RootNode { ...@@ -117,7 +117,8 @@ public class RootNode {
appResClass = resCls; appResClass = resCls;
return; return;
} }
appResClass = new ClassNode(dexNodes.get(0), ClassInfo.fromName("R")); DexNode firstDex = dexNodes.get(0);
appResClass = new ClassNode(firstDex, ClassInfo.fromName(firstDex, "R"));
} }
private static void initClassPath(List<ClassNode> classes) throws IOException, DecodeException { private static void initClassPath(List<ClassNode> classes) throws IOException, DecodeException {
...@@ -142,7 +143,7 @@ public class RootNode { ...@@ -142,7 +143,7 @@ public class RootNode {
ClassNode parent = resolveClass(cls.getClassInfo().getParentClass()); ClassNode parent = resolveClass(cls.getClassInfo().getParentClass());
if (parent == null) { if (parent == null) {
names.remove(cls.getFullName()); names.remove(cls.getFullName());
cls.getClassInfo().notInner(); cls.getClassInfo().notInner(cls.dex());
names.put(cls.getFullName(), cls); names.put(cls.getFullName(), cls);
} else { } else {
parent.addInnerClass(cls); parent.addInnerClass(cls);
......
...@@ -50,7 +50,8 @@ public class ClassModifier extends AbstractVisitor { ...@@ -50,7 +50,8 @@ public class ClassModifier extends AbstractVisitor {
// remove fields if it is synthetic and type is a outer class // remove fields if it is synthetic and type is a outer class
for (FieldNode field : cls.getFields()) { for (FieldNode field : cls.getFields()) {
if (field.getAccessFlags().isSynthetic() && field.getType().isObject()) { if (field.getAccessFlags().isSynthetic() && field.getType().isObject()) {
ClassNode fieldsCls = cls.dex().resolveClass(ClassInfo.fromType(field.getType())); ClassInfo clsInfo = ClassInfo.fromType(cls.dex(), field.getType());
ClassNode fieldsCls = cls.dex().resolveClass(clsInfo);
ClassInfo parentClass = cls.getClassInfo().getParentClass(); ClassInfo parentClass = cls.getClassInfo().getParentClass();
if (fieldsCls != null if (fieldsCls != null
&& parentClass.equals(fieldsCls.getClassInfo()) && parentClass.equals(fieldsCls.getClassInfo())
...@@ -62,7 +63,7 @@ public class ClassModifier extends AbstractVisitor { ...@@ -62,7 +63,7 @@ public class ClassModifier extends AbstractVisitor {
} }
} }
if (found != 0) { if (found != 0) {
FieldInfo replace = new FieldInfo(parentClass, "this", parentClass.getType()); FieldInfo replace = FieldInfo.from(cls.dex(), parentClass, "this", parentClass.getType());
field.addAttr(new FieldReplaceAttr(replace, true)); field.addAttr(new FieldReplaceAttr(replace, true));
field.add(AFlag.DONT_GENERATE); field.add(AFlag.DONT_GENERATE);
} }
......
package jadx.core.dex.visitors.regions; package jadx.core.dex.visitors.regions;
import jadx.core.codegen.NameGen;
import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.DeclareVariablesAttr; import jadx.core.dex.attributes.nodes.DeclareVariablesAttr;
...@@ -301,7 +300,6 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -301,7 +300,6 @@ public class ProcessVariables extends AbstractVisitor {
return false; return false;
} }
parentInsn.add(AFlag.DECLARE_VAR); parentInsn.add(AFlag.DECLARE_VAR);
processVar(arg);
return true; return true;
} }
...@@ -312,11 +310,6 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -312,11 +310,6 @@ public class ProcessVariables extends AbstractVisitor {
region.addAttr(dv); region.addAttr(dv);
} }
dv.addVar(arg); dv.addVar(arg);
processVar(arg);
}
private static void processVar(RegisterArg arg) {
NameGen.guessName(arg);
} }
private static int calculateOrder(IContainer container, Map<IContainer, Integer> regionsOrder, 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