Commit b29223c5 authored by Skylot's avatar Skylot

core: fix enum processing order, remove synchronization (#257)

parent d5cfdfb5
package jadx.core.dex.attributes.nodes; package jadx.core.dex.attributes.nodes;
import java.util.HashMap;
import java.util.Map;
import org.jetbrains.annotations.Nullable;
import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.IAttribute; import jadx.core.dex.attributes.IAttribute;
import jadx.core.dex.nodes.FieldNode; import jadx.core.dex.nodes.FieldNode;
import java.util.HashMap;
import java.util.Map;
public class EnumMapAttr implements IAttribute { public class EnumMapAttr implements IAttribute {
public static class KeyValueMap { public static class KeyValueMap {
...@@ -21,9 +23,14 @@ public class EnumMapAttr implements IAttribute { ...@@ -21,9 +23,14 @@ public class EnumMapAttr implements IAttribute {
} }
} }
private final Map<FieldNode, KeyValueMap> fieldsMap = new HashMap<>(); @Nullable
private Map<FieldNode, KeyValueMap> fieldsMap;
@Nullable
public KeyValueMap getMap(FieldNode field) { public KeyValueMap getMap(FieldNode field) {
if (fieldsMap == null) {
return null;
}
return fieldsMap.get(field); return fieldsMap.get(field);
} }
...@@ -31,11 +38,18 @@ public class EnumMapAttr implements IAttribute { ...@@ -31,11 +38,18 @@ public class EnumMapAttr implements IAttribute {
KeyValueMap map = getMap(field); KeyValueMap map = getMap(field);
if (map == null) { if (map == null) {
map = new KeyValueMap(); map = new KeyValueMap();
if (fieldsMap == null) {
fieldsMap = new HashMap<>();
}
fieldsMap.put(field, map); fieldsMap.put(field, map);
} }
map.put(key, value); map.put(key, value);
} }
public boolean isEmpty() {
return fieldsMap == null || fieldsMap.isEmpty();
}
@Override @Override
public AType<EnumMapAttr> getType() { public AType<EnumMapAttr> getType() {
return AType.ENUM_MAP; return AType.ENUM_MAP;
...@@ -45,5 +59,4 @@ public class EnumMapAttr implements IAttribute { ...@@ -45,5 +59,4 @@ public class EnumMapAttr implements IAttribute {
public String toString() { public String toString() {
return "Enum fields map: " + fieldsMap; return "Enum fields map: " + fieldsMap;
} }
} }
package jadx.core.dex.visitors; package jadx.core.dex.visitors;
import jadx.core.ProcessClass; import java.util.List;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.EnumMapAttr; import jadx.core.dex.attributes.nodes.EnumMapAttr;
...@@ -18,18 +23,13 @@ import jadx.core.dex.instructions.args.InsnWrapArg; ...@@ -18,18 +23,13 @@ import jadx.core.dex.instructions.args.InsnWrapArg;
import jadx.core.dex.instructions.args.LiteralArg; import jadx.core.dex.instructions.args.LiteralArg;
import jadx.core.dex.nodes.BlockNode; import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.DexNode;
import jadx.core.dex.nodes.FieldNode; import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.InstructionRemover; import jadx.core.utils.InstructionRemover;
import jadx.core.utils.exceptions.DecodeException;
import jadx.core.utils.exceptions.JadxException; import jadx.core.utils.exceptions.JadxException;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@JadxVisitor( @JadxVisitor(
name = "ReSugarCode", name = "ReSugarCode",
desc = "Simplify synthetic or verbose code", desc = "Simplify synthetic or verbose code",
...@@ -40,6 +40,12 @@ public class ReSugarCode extends AbstractVisitor { ...@@ -40,6 +40,12 @@ public class ReSugarCode extends AbstractVisitor {
private static final Logger LOG = LoggerFactory.getLogger(ReSugarCode.class); private static final Logger LOG = LoggerFactory.getLogger(ReSugarCode.class);
@Override @Override
public boolean visit(ClassNode cls) throws JadxException {
initClsEnumMap(cls);
return true;
}
@Override
public void visit(MethodNode mth) throws JadxException { public void visit(MethodNode mth) throws JadxException {
if (mth.isNoCode()) { if (mth.isNoCode()) {
return; return;
...@@ -115,7 +121,7 @@ public class ReSugarCode extends AbstractVisitor { ...@@ -115,7 +121,7 @@ public class ReSugarCode extends AbstractVisitor {
if (wrapInsn.getType() != InsnType.AGET) { if (wrapInsn.getType() != InsnType.AGET) {
return; return;
} }
EnumMapInfo enumMapInfo = checkEnumMapAccess(mth, wrapInsn); EnumMapInfo enumMapInfo = checkEnumMapAccess(mth.dex(), wrapInsn);
if (enumMapInfo == null) { if (enumMapInfo == null) {
return; return;
} }
...@@ -144,49 +150,40 @@ public class ReSugarCode extends AbstractVisitor { ...@@ -144,49 +150,40 @@ public class ReSugarCode extends AbstractVisitor {
checkAndHideClass(enumMapField.getParentClass()); checkAndHideClass(enumMapField.getParentClass());
} }
private static EnumMapAttr.KeyValueMap getEnumMap(MethodNode mth, FieldNode field) { private static void initClsEnumMap(ClassNode enumCls) {
ClassNode syntheticClass = field.getParentClass(); MethodNode clsInitMth = enumCls.getClassInitMth();
EnumMapAttr mapAttr = syntheticClass.get(AType.ENUM_MAP);
if (mapAttr != null) {
return mapAttr.getMap(field);
}
synchronized (ProcessClass.getSyncObj(syntheticClass)) {
mapAttr = new EnumMapAttr();
syntheticClass.addAttr(mapAttr);
MethodNode clsInitMth = syntheticClass.searchMethodByName("<clinit>()V");
if (clsInitMth == null || clsInitMth.isNoCode()) { if (clsInitMth == null || clsInitMth.isNoCode()) {
return null; return;
}
if (clsInitMth.getBasicBlocks() == null) {
try {
clsInitMth.load();
} catch (DecodeException e) {
LOG.error("Load failed", e);
return null;
}
if (clsInitMth.getBasicBlocks() == null) {
// TODO:
return null;
}
} }
EnumMapAttr mapAttr = new EnumMapAttr();
for (BlockNode block : clsInitMth.getBasicBlocks()) { for (BlockNode block : clsInitMth.getBasicBlocks()) {
for (InsnNode insn : block.getInstructions()) { for (InsnNode insn : block.getInstructions()) {
if (insn.getType() == InsnType.APUT) { if (insn.getType() == InsnType.APUT) {
addToEnumMap(mth, mapAttr, insn); addToEnumMap(enumCls.dex(), mapAttr, insn);
} }
} }
} }
return mapAttr.getMap(field); if (!mapAttr.isEmpty()) {
enumCls.addAttr(mapAttr);
} }
} }
private static void addToEnumMap(MethodNode mth, EnumMapAttr mapAttr, InsnNode aputInsn) { @Nullable
private static EnumMapAttr.KeyValueMap getEnumMap(MethodNode mth, FieldNode field) {
ClassNode syntheticClass = field.getParentClass();
EnumMapAttr mapAttr = syntheticClass.get(AType.ENUM_MAP);
if (mapAttr == null) {
return null;
}
return mapAttr.getMap(field);
}
private static void addToEnumMap(DexNode dex, EnumMapAttr mapAttr, InsnNode aputInsn) {
InsnArg litArg = aputInsn.getArg(2); InsnArg litArg = aputInsn.getArg(2);
if (!litArg.isLiteral()) { if (!litArg.isLiteral()) {
return; return;
} }
EnumMapInfo mapInfo = checkEnumMapAccess(mth, aputInsn); EnumMapInfo mapInfo = checkEnumMapAccess(dex, aputInsn);
if (mapInfo == null) { if (mapInfo == null) {
return; return;
} }
...@@ -203,7 +200,7 @@ public class ReSugarCode extends AbstractVisitor { ...@@ -203,7 +200,7 @@ public class ReSugarCode extends AbstractVisitor {
if (!(index instanceof FieldInfo)) { if (!(index instanceof FieldInfo)) {
return; return;
} }
FieldNode fieldNode = mth.dex().resolveField((FieldInfo) index); FieldNode fieldNode = dex.resolveField((FieldInfo) index);
if (fieldNode == null) { if (fieldNode == null) {
return; return;
} }
...@@ -211,7 +208,7 @@ public class ReSugarCode extends AbstractVisitor { ...@@ -211,7 +208,7 @@ public class ReSugarCode extends AbstractVisitor {
mapAttr.add(field, literal, fieldNode); mapAttr.add(field, literal, fieldNode);
} }
public static EnumMapInfo checkEnumMapAccess(MethodNode mth, InsnNode checkInsn) { public static EnumMapInfo checkEnumMapAccess(DexNode dex, InsnNode checkInsn) {
InsnArg sgetArg = checkInsn.getArg(0); InsnArg sgetArg = checkInsn.getArg(0);
InsnArg invArg = checkInsn.getArg(1); InsnArg invArg = checkInsn.getArg(1);
if (!sgetArg.isInsnWrap() || !invArg.isInsnWrap()) { if (!sgetArg.isInsnWrap() || !invArg.isInsnWrap()) {
...@@ -226,7 +223,7 @@ public class ReSugarCode extends AbstractVisitor { ...@@ -226,7 +223,7 @@ public class ReSugarCode extends AbstractVisitor {
if (!inv.getCallMth().getShortId().equals("ordinal()I")) { if (!inv.getCallMth().getShortId().equals("ordinal()I")) {
return null; return null;
} }
ClassNode enumCls = mth.dex().resolveClass(inv.getCallMth().getDeclClass()); ClassNode enumCls = dex.resolveClass(inv.getCallMth().getDeclClass());
if (enumCls == null || !enumCls.isEnum()) { if (enumCls == null || !enumCls.isEnum()) {
return null; return null;
} }
...@@ -234,7 +231,7 @@ public class ReSugarCode extends AbstractVisitor { ...@@ -234,7 +231,7 @@ public class ReSugarCode extends AbstractVisitor {
if (!(index instanceof FieldInfo)) { if (!(index instanceof FieldInfo)) {
return null; return null;
} }
FieldNode enumMapField = mth.dex().resolveField((FieldInfo) index); FieldNode enumMapField = dex.resolveField((FieldInfo) index);
if (enumMapField == null || !enumMapField.getAccessFlags().isSynthetic()) { if (enumMapField == null || !enumMapField.getAccessFlags().isSynthetic()) {
return null; return null;
} }
......
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