fix: improve codegen methods for custom decompilation mode
This commit is contained in:
@@ -1,16 +1,22 @@
|
||||
package jadx.core;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.api.DecompilationMode;
|
||||
import jadx.api.ICodeInfo;
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.impl.SimpleCodeInfo;
|
||||
import jadx.core.codegen.CodeGen;
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.attributes.AType;
|
||||
import jadx.core.dex.attributes.nodes.DecompileModeOverrideAttr;
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.core.dex.nodes.LoadStage;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
@@ -154,6 +160,43 @@ public class ProcessClass {
|
||||
}
|
||||
}
|
||||
|
||||
private final Map<DecompilationMode, ProcessClass> modesMap = new EnumMap<>(DecompilationMode.class);
|
||||
|
||||
public @Nullable ICodeInfo forceGenerateCodeForMode(ClassNode cls, DecompilationMode mode) {
|
||||
synchronized (modesMap) {
|
||||
ProcessClass prCls = modesMap.computeIfAbsent(mode, m -> {
|
||||
RootNode root = cls.root();
|
||||
ProcessClass newPrCls = new ProcessClass(getPassesForMode(root.getArgs(), m));
|
||||
newPrCls.initPasses(root);
|
||||
return newPrCls;
|
||||
});
|
||||
try {
|
||||
cls.addAttr(new DecompileModeOverrideAttr(mode));
|
||||
return prCls.forceGenerateCode(cls);
|
||||
} finally {
|
||||
cls.remove(AType.DECOMPILE_MODE_OVERRIDE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<IDexTreeVisitor> getPassesForMode(JadxArgs baseArgs, DecompilationMode mode) {
|
||||
switch (mode) {
|
||||
case FALLBACK:
|
||||
return Jadx.getFallbackPassesList();
|
||||
|
||||
case SIMPLE:
|
||||
// copy properties into new args
|
||||
// keep in sync with properties usage in Jadx.getSimpleModePasses method
|
||||
JadxArgs args = new JadxArgs();
|
||||
args.setDebugInfo(baseArgs.isDebugInfo());
|
||||
args.setCommentsLevel(baseArgs.getCommentsLevel());
|
||||
return Jadx.getSimpleModePasses(args);
|
||||
|
||||
default:
|
||||
throw new JadxRuntimeException("Unexpected decompilation mode: " + mode);
|
||||
}
|
||||
}
|
||||
|
||||
public void initPasses(RootNode root) {
|
||||
for (IDexTreeVisitor pass : passes) {
|
||||
try {
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.api.CommentsLevel;
|
||||
import jadx.api.DecompilationMode;
|
||||
import jadx.api.ICodeWriter;
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.args.IntegerFormat;
|
||||
@@ -23,6 +24,7 @@ import jadx.core.Jadx;
|
||||
import jadx.core.codegen.utils.CodeGenUtils;
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.attributes.AType;
|
||||
import jadx.core.dex.attributes.nodes.DecompileModeOverrideAttr;
|
||||
import jadx.core.dex.attributes.nodes.JadxError;
|
||||
import jadx.core.dex.attributes.nodes.JumpInfo;
|
||||
import jadx.core.dex.attributes.nodes.MethodOverrideAttr;
|
||||
@@ -266,7 +268,14 @@ public class MethodGen {
|
||||
|
||||
public void addInstructions(ICodeWriter code) throws CodegenException {
|
||||
JadxArgs args = mth.root().getArgs();
|
||||
switch (args.getDecompilationMode()) {
|
||||
DecompileModeOverrideAttr modeOverrideAttr = mth.getTopParentClass().get(AType.DECOMPILE_MODE_OVERRIDE);
|
||||
DecompilationMode mode;
|
||||
if (modeOverrideAttr != null) {
|
||||
mode = modeOverrideAttr.getMode();
|
||||
} else {
|
||||
mode = args.getDecompilationMode();
|
||||
}
|
||||
switch (mode) {
|
||||
case AUTO:
|
||||
if (classGen.isFallbackMode() || mth.getRegion() == null) {
|
||||
// TODO: try simple mode first
|
||||
|
||||
@@ -7,6 +7,7 @@ import jadx.core.dex.attributes.nodes.AnonymousClassAttr;
|
||||
import jadx.core.dex.attributes.nodes.ClassTypeVarsAttr;
|
||||
import jadx.core.dex.attributes.nodes.CodeFeaturesAttr;
|
||||
import jadx.core.dex.attributes.nodes.DeclareVariablesAttr;
|
||||
import jadx.core.dex.attributes.nodes.DecompileModeOverrideAttr;
|
||||
import jadx.core.dex.attributes.nodes.EdgeInsnAttr;
|
||||
import jadx.core.dex.attributes.nodes.EnumClassAttr;
|
||||
import jadx.core.dex.attributes.nodes.EnumMapAttr;
|
||||
@@ -62,6 +63,7 @@ public final class AType<T extends IJadxAttribute> implements IJadxAttrType<T> {
|
||||
public static final AType<ClassTypeVarsAttr> CLASS_TYPE_VARS = new AType<>();
|
||||
public static final AType<AnonymousClassAttr> ANONYMOUS_CLASS = new AType<>();
|
||||
public static final AType<InlinedAttr> INLINED = new AType<>();
|
||||
public static final AType<DecompileModeOverrideAttr> DECOMPILE_MODE_OVERRIDE = new AType<>();
|
||||
|
||||
// field
|
||||
public static final AType<FieldInitInsnAttr> FIELD_INIT_INSN = new AType<>();
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package jadx.core.dex.attributes.nodes;
|
||||
|
||||
import jadx.api.DecompilationMode;
|
||||
import jadx.api.plugins.input.data.attributes.IJadxAttrType;
|
||||
import jadx.api.plugins.input.data.attributes.IJadxAttribute;
|
||||
import jadx.core.dex.attributes.AType;
|
||||
|
||||
public class DecompileModeOverrideAttr implements IJadxAttribute {
|
||||
|
||||
private final DecompilationMode mode;
|
||||
|
||||
public DecompileModeOverrideAttr(DecompilationMode mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public DecompilationMode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IJadxAttrType<DecompileModeOverrideAttr> getAttrType() {
|
||||
return AType.DECOMPILE_MODE_OVERRIDE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DECOMPILE_MODE_OVERRIDE: " + mode;
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ import org.slf4j.LoggerFactory;
|
||||
import jadx.api.DecompilationMode;
|
||||
import jadx.api.ICodeCache;
|
||||
import jadx.api.ICodeInfo;
|
||||
import jadx.api.JadxArgs;
|
||||
import jadx.api.JavaClass;
|
||||
import jadx.api.impl.SimpleCodeInfo;
|
||||
import jadx.api.impl.SimpleCodeWriter;
|
||||
@@ -38,8 +37,6 @@ import jadx.api.plugins.input.data.attributes.types.SourceFileAttr;
|
||||
import jadx.api.plugins.input.data.impl.ListConsumer;
|
||||
import jadx.api.usage.IUsageInfoData;
|
||||
import jadx.core.Consts;
|
||||
import jadx.core.Jadx;
|
||||
import jadx.core.ProcessClass;
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.attributes.AType;
|
||||
import jadx.core.dex.attributes.nodes.InlinedAttr;
|
||||
@@ -320,23 +317,25 @@ public class ClassNode extends NotificationAttrNode
|
||||
* WARNING: Slow operation! Use with caution!
|
||||
*/
|
||||
public ICodeInfo decompileWithMode(DecompilationMode mode) {
|
||||
DecompilationMode baseMode = root.getArgs().getDecompilationMode();
|
||||
if (mode == baseMode) {
|
||||
return decompile(true);
|
||||
}
|
||||
synchronized (DECOMPILE_WITH_MODE_SYNC) {
|
||||
JadxArgs args = root.getArgs();
|
||||
try {
|
||||
unload();
|
||||
args.setDecompilationMode(mode);
|
||||
ProcessClass process = new ProcessClass(Jadx.getPassesList(args));
|
||||
process.initPasses(root);
|
||||
ICodeInfo code = process.forceGenerateCode(this);
|
||||
return Utils.getOrElse(code, ICodeInfo.EMPTY);
|
||||
} finally {
|
||||
args.setDecompilationMode(baseMode);
|
||||
unload();
|
||||
}
|
||||
switch (mode) {
|
||||
case AUTO:
|
||||
case RESTRUCTURE:
|
||||
return decompile(true);
|
||||
|
||||
case SIMPLE:
|
||||
case FALLBACK:
|
||||
synchronized (DECOMPILE_WITH_MODE_SYNC) {
|
||||
try {
|
||||
unload();
|
||||
ICodeInfo code = root.getProcessClasses().forceGenerateCodeForMode(this, mode);
|
||||
return Utils.getOrElse(code, ICodeInfo.EMPTY);
|
||||
} finally {
|
||||
unload();
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
throw new JadxRuntimeException("Unknown mode: " + mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user