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