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