Commit 37ed9cd2 authored by Skylot's avatar Skylot

core: make decompilation results more deterministic

parent 882af040
package jadx.core; package jadx.core;
import java.util.List;
import org.jetbrains.annotations.Nullable;
import jadx.core.codegen.CodeGen; import jadx.core.codegen.CodeGen;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.visitors.DepthTraversal; import jadx.core.dex.visitors.DepthTraversal;
import jadx.core.dex.visitors.IDexTreeVisitor; import jadx.core.dex.visitors.IDexTreeVisitor;
import jadx.core.utils.ErrorsCounter; import jadx.core.utils.ErrorsCounter;
import java.util.List;
import org.jetbrains.annotations.Nullable;
import static jadx.core.dex.nodes.ProcessState.GENERATED; import static jadx.core.dex.nodes.ProcessState.GENERATED;
import static jadx.core.dex.nodes.ProcessState.NOT_LOADED; import static jadx.core.dex.nodes.ProcessState.NOT_LOADED;
import static jadx.core.dex.nodes.ProcessState.PROCESSED; import static jadx.core.dex.nodes.ProcessState.PROCESSED;
...@@ -25,7 +25,7 @@ public final class ProcessClass { ...@@ -25,7 +25,7 @@ public final class ProcessClass {
if (codeGen == null && cls.getState() == PROCESSED) { if (codeGen == null && cls.getState() == PROCESSED) {
return; return;
} }
synchronized (cls.getClassInfo()) { synchronized (getSyncObj(cls)) {
try { try {
if (cls.getState() == NOT_LOADED) { if (cls.getState() == NOT_LOADED) {
cls.load(); cls.load();
...@@ -51,6 +51,10 @@ public final class ProcessClass { ...@@ -51,6 +51,10 @@ public final class ProcessClass {
} }
} }
public static Object getSyncObj(ClassNode cls) {
return cls.getClassInfo();
}
private static void processDependencies(ClassNode cls, List<IDexTreeVisitor> passes) { private static void processDependencies(ClassNode cls, List<IDexTreeVisitor> passes) {
for (ClassNode depCls : cls.getDependencies()) { for (ClassNode depCls : cls.getDependencies()) {
process(depCls, passes, null); process(depCls, passes, null);
......
...@@ -254,8 +254,9 @@ public class CodeWriter { ...@@ -254,8 +254,9 @@ public class CodeWriter {
} }
private void removeFirstEmptyLine() { private void removeFirstEmptyLine() {
if (buf.indexOf(NL) == 0) { int len = NL.length();
buf.delete(0, NL.length()); if (buf.substring(0, len).equals(NL)) {
buf.delete(0, len);
} }
} }
......
...@@ -19,6 +19,7 @@ import jadx.core.utils.StringUtils; ...@@ -19,6 +19,7 @@ import jadx.core.utils.StringUtils;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
...@@ -26,7 +27,7 @@ public class NameGen { ...@@ -26,7 +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<>(); private final Set<String> varNames = new LinkedHashSet<>();
private final MethodNode mth; private final MethodNode mth;
private final boolean fallback; private final boolean fallback;
......
...@@ -11,6 +11,7 @@ import jadx.core.utils.Utils; ...@@ -11,6 +11,7 @@ import jadx.core.utils.Utils;
import jadx.core.utils.exceptions.JadxRuntimeException; import jadx.core.utils.exceptions.JadxRuntimeException;
import java.util.IdentityHashMap; import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
...@@ -21,7 +22,7 @@ public final class PhiInsn extends InsnNode { ...@@ -21,7 +22,7 @@ public final class PhiInsn extends InsnNode {
public PhiInsn(int regNum, int predecessors) { public PhiInsn(int regNum, int predecessors) {
super(InsnType.PHI, predecessors); super(InsnType.PHI, predecessors);
this.blockBinds = new IdentityHashMap<>(predecessors); this.blockBinds = new LinkedHashMap<>(predecessors);
setResult(InsnArg.reg(regNum, ArgType.UNKNOWN)); setResult(InsnArg.reg(regNum, ArgType.UNKNOWN));
add(AFlag.DONT_INLINE); add(AFlag.DONT_INLINE);
} }
......
...@@ -16,7 +16,7 @@ public final class IfInfo { ...@@ -16,7 +16,7 @@ public final class IfInfo {
private BlockNode ifBlock; private BlockNode ifBlock;
public IfInfo(IfCondition condition, BlockNode thenBlock, BlockNode elseBlock) { public IfInfo(IfCondition condition, BlockNode thenBlock, BlockNode elseBlock) {
this(condition, thenBlock, elseBlock, new HashSet<BlockNode>(), new HashSet<BlockNode>()); this(condition, thenBlock, elseBlock, new HashSet<>(), new HashSet<>());
} }
public IfInfo(IfInfo info, BlockNode thenBlock, BlockNode elseBlock) { public IfInfo(IfInfo info, BlockNode thenBlock, BlockNode elseBlock) {
......
package jadx.core.dex.visitors; package jadx.core.dex.visitors;
import jadx.core.ProcessClass;
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;
...@@ -141,7 +142,6 @@ public class ReSugarCode extends AbstractVisitor { ...@@ -141,7 +142,6 @@ public class ReSugarCode extends AbstractVisitor {
} }
enumMapField.add(AFlag.DONT_GENERATE); enumMapField.add(AFlag.DONT_GENERATE);
checkAndHideClass(enumMapField.getParentClass()); checkAndHideClass(enumMapField.getParentClass());
return;
} }
private static EnumMapAttr.KeyValueMap getEnumMap(MethodNode mth, FieldNode field) { private static EnumMapAttr.KeyValueMap getEnumMap(MethodNode mth, FieldNode field) {
...@@ -150,33 +150,35 @@ public class ReSugarCode extends AbstractVisitor { ...@@ -150,33 +150,35 @@ public class ReSugarCode extends AbstractVisitor {
if (mapAttr != null) { if (mapAttr != null) {
return mapAttr.getMap(field); return mapAttr.getMap(field);
} }
mapAttr = new EnumMapAttr(); synchronized (ProcessClass.getSyncObj(syntheticClass)) {
syntheticClass.addAttr(mapAttr); mapAttr = new EnumMapAttr();
syntheticClass.addAttr(mapAttr);
MethodNode clsInitMth = syntheticClass.searchMethodByName("<clinit>()V"); MethodNode clsInitMth = syntheticClass.searchMethodByName("<clinit>()V");
if (clsInitMth == null || clsInitMth.isNoCode()) { if (clsInitMth == null || clsInitMth.isNoCode()) {
return null;
}
if (clsInitMth.getBasicBlocks() == null) {
try {
clsInitMth.load();
} catch (DecodeException e) {
LOG.error("Load failed", e);
return null; return null;
} }
if (clsInitMth.getBasicBlocks() == null) { if (clsInitMth.getBasicBlocks() == null) {
// TODO: try {
return null; clsInitMth.load();
} catch (DecodeException e) {
LOG.error("Load failed", e);
return null;
}
if (clsInitMth.getBasicBlocks() == null) {
// TODO:
return null;
}
} }
} 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(mth, mapAttr, insn); }
} }
} }
return mapAttr.getMap(field);
} }
return mapAttr.getMap(field);
} }
private static void addToEnumMap(MethodNode mth, EnumMapAttr mapAttr, InsnNode aputInsn) { private static void addToEnumMap(MethodNode mth, EnumMapAttr mapAttr, InsnNode aputInsn) {
......
...@@ -4,6 +4,7 @@ import java.io.File; ...@@ -4,6 +4,7 @@ import java.io.File;
import jadx.api.JadxArgs; import jadx.api.JadxArgs;
import jadx.core.codegen.CodeWriter; import jadx.core.codegen.CodeWriter;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
public class SaveCode { public class SaveCode {
...@@ -11,6 +12,9 @@ public class SaveCode { ...@@ -11,6 +12,9 @@ public class SaveCode {
private SaveCode() {} private SaveCode() {}
public static void save(File dir, JadxArgs args, ClassNode cls) { public static void save(File dir, JadxArgs args, ClassNode cls) {
if (cls.contains(AFlag.DONT_GENERATE)) {
return;
}
CodeWriter clsCode = cls.getCode(); CodeWriter clsCode = cls.getCode();
String fileName = cls.getClassInfo().getFullPath() + ".java"; String fileName = cls.getClassInfo().getFullPath() + ".java";
if (args.isFallbackMode()) { if (args.isFallbackMode()) {
......
...@@ -25,6 +25,7 @@ import java.util.HashMap; ...@@ -25,6 +25,7 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
...@@ -72,8 +73,8 @@ public class ProcessVariables extends AbstractVisitor { ...@@ -72,8 +73,8 @@ public class ProcessVariables extends AbstractVisitor {
private RegisterArg arg; private RegisterArg arg;
private VarName varName; private VarName varName;
private IRegion argRegion; private IRegion argRegion;
private final Set<IRegion> usage = new HashSet<>(2); private final Set<IRegion> usage = new LinkedHashSet<>(2);
private final Set<IRegion> assigns = new HashSet<>(2); private final Set<IRegion> assigns = new LinkedHashSet<>(2);
public void setArg(RegisterArg arg) { public void setArg(RegisterArg arg) {
this.arg = arg; this.arg = arg;
......
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