diff --git a/jadx-core/src/main/java/jadx/core/Consts.java b/jadx-core/src/main/java/jadx/core/Consts.java index 32b98286c..db6154ee3 100644 --- a/jadx-core/src/main/java/jadx/core/Consts.java +++ b/jadx-core/src/main/java/jadx/core/Consts.java @@ -9,6 +9,7 @@ public class Consts { public static final boolean DEBUG_EXC_HANDLERS = false; public static final boolean DEBUG_FINALLY = false; public static final boolean DEBUG_ATTRIBUTES = false; + public static final boolean DEBUG_RESTRUCTURE = false; public static final boolean DEBUG_EVENTS = true; public static final String CLASS_OBJECT = "java.lang.Object"; diff --git a/jadx-core/src/main/java/jadx/core/ProcessClass.java b/jadx-core/src/main/java/jadx/core/ProcessClass.java index 762f19a76..0394b1db3 100644 --- a/jadx-core/src/main/java/jadx/core/ProcessClass.java +++ b/jadx-core/src/main/java/jadx/core/ProcessClass.java @@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory; 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.nodes.ClassNode; @@ -27,6 +28,8 @@ import static jadx.core.dex.nodes.ProcessState.PROCESS_STARTED; public class ProcessClass { private static final Logger LOG = LoggerFactory.getLogger(ProcessClass.class); + private static final ICodeInfo NOT_GENERATED = new SimpleCodeInfo(""); + private final List passes; public ProcessClass(JadxArgs args) { @@ -101,7 +104,8 @@ public class ProcessClass { try { if (cls.contains(AFlag.DONT_GENERATE)) { process(cls, false); - return ICodeInfo.EMPTY; + LOG.warn("Requested code for class with DONT_GENERATE flag: {}", cls); + return NOT_GENERATED; } for (ClassNode depCls : cls.getDependencies()) { process(depCls, false); diff --git a/jadx-core/src/main/java/jadx/core/dex/info/MethodInfo.java b/jadx-core/src/main/java/jadx/core/dex/info/MethodInfo.java index ff06caa24..a9d94344a 100644 --- a/jadx-core/src/main/java/jadx/core/dex/info/MethodInfo.java +++ b/jadx-core/src/main/java/jadx/core/dex/info/MethodInfo.java @@ -106,6 +106,10 @@ public final class MethodInfo implements Comparable { return declClass.getFullName() + '.' + name; } + public String getAliasFullName() { + return declClass.getAliasFullName() + '.' + alias; + } + public String getFullId() { return declClass.getFullName() + '.' + shortId; } diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java index e4294eaef..a0aff4b5f 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java @@ -13,6 +13,8 @@ import java.util.stream.Collectors; 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.ICodeCache; @@ -56,6 +58,8 @@ import static jadx.core.dex.nodes.ProcessState.NOT_LOADED; public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeNode, IPackageUpdate, Comparable { + private static final Logger LOG = LoggerFactory.getLogger(ClassNode.class); + private final RootNode root; private final IClassData clsData; @@ -381,6 +385,9 @@ public class ClassNode extends NotificationAttrNode } ICodeInfo codeInfo; try { + if (Consts.DEBUG) { + LOG.debug("Decompiling class: {}", this); + } codeInfo = root.getProcessClasses().generateCode(this); } catch (Throwable e) { addError("Code generation failed", e); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/CheckRegions.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/CheckRegions.java index ec7c6143b..a4b5ed550 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/CheckRegions.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/CheckRegions.java @@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory; import jadx.api.ICodeWriter; import jadx.api.impl.SimpleCodeWriter; +import jadx.core.Consts; import jadx.core.codegen.InsnGen; import jadx.core.codegen.MethodGen; import jadx.core.dex.attributes.AFlag; @@ -46,7 +47,8 @@ public class CheckRegions extends AbstractVisitor { if (blocksInRegions.add(block)) { return; } - if (LOG.isDebugEnabled() + if (Consts.DEBUG_RESTRUCTURE + && LOG.isDebugEnabled() && !block.contains(AFlag.RETURN) && !block.contains(AFlag.REMOVE) && !block.contains(AFlag.SYNTHETIC) diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/IfMakerHelper.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/IfMakerHelper.java index 890eabe77..cc7617be9 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/IfMakerHelper.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/IfMakerHelper.java @@ -9,6 +9,7 @@ import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import jadx.core.Consts; import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.nodes.LoopInfo; @@ -74,7 +75,9 @@ public class IfMakerHelper { boolean badThen = isBadBranchBlock(info, thenBlock); boolean badElse = isBadBranchBlock(info, elseBlock); if (badThen && badElse) { - LOG.debug("Stop processing blocks after 'if': {}, method: {}", info.getMergedBlocks(), mth); + if (Consts.DEBUG_RESTRUCTURE) { + LOG.debug("Stop processing blocks after 'if': {}, method: {}", info.getMergedBlocks(), mth); + } return null; } if (badElse) { diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java index 065d400e7..7a62c2bb9 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java @@ -182,7 +182,7 @@ public final class TypeInferenceVisitor extends AbstractVisitor { } catch (JadxOverflowException e) { throw e; } catch (Exception e) { - LOG.error("Failed to set immutable type for var: {}", ssaVar, e); + mth.addWarnComment("Failed to set immutable type for var: " + ssaVar, e); } } @@ -192,7 +192,7 @@ public final class TypeInferenceVisitor extends AbstractVisitor { } catch (JadxOverflowException e) { throw e; } catch (Exception e) { - LOG.error("Failed to calculate best type for var: {}", ssaVar, e); + mth.addWarnComment("Failed to calculate best type for var: " + ssaVar, e); return false; } } @@ -201,7 +201,7 @@ public final class TypeInferenceVisitor extends AbstractVisitor { TypeInfo typeInfo = ssaVar.getTypeInfo(); Set bounds = typeInfo.getBounds(); Optional bestTypeOpt = selectBestTypeFromBounds(bounds); - if (!bestTypeOpt.isPresent()) { + if (bestTypeOpt.isEmpty()) { if (Consts.DEBUG_TYPE_INFERENCE) { LOG.warn("Failed to select best type from bounds, count={} : ", bounds.size()); for (ITypeBound bound : bounds) { @@ -456,6 +456,7 @@ public final class TypeInferenceVisitor extends AbstractVisitor { return fixed; } + @SuppressWarnings("RedundantIfStatement") private boolean deduceType(MethodNode mth, SSAVar var) { if (var.isTypeImmutable()) { return false; diff --git a/jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java b/jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java index 114da9b34..e20bf2a9b 100644 --- a/jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java +++ b/jadx-gui/src/main/java/jadx/gui/jobs/BackgroundExecutor.java @@ -309,7 +309,7 @@ public class BackgroundExecutor { return "TaskWorker{status=" + status + ", jobsCount=" + jobsCount + ", jobsComplete=" + jobsComplete - + ", time=" + time + '}'; + + ", time=" + time + "ms}"; } } } diff --git a/jadx-gui/src/main/java/jadx/gui/search/providers/ClassSearchProvider.java b/jadx-gui/src/main/java/jadx/gui/search/providers/ClassSearchProvider.java index 269e28484..ad1fef777 100644 --- a/jadx-gui/src/main/java/jadx/gui/search/providers/ClassSearchProvider.java +++ b/jadx-gui/src/main/java/jadx/gui/search/providers/ClassSearchProvider.java @@ -1,6 +1,7 @@ package jadx.gui.search.providers; import java.util.List; +import java.util.stream.Collectors; import org.jetbrains.annotations.Nullable; @@ -16,7 +17,16 @@ public final class ClassSearchProvider extends BaseSearchProvider { private int clsNum = 0; public ClassSearchProvider(MainWindow mw, SearchSettings searchSettings, List classes) { - super(mw, searchSettings, classes); + super(mw, searchSettings, filterClasses(classes)); + } + + /** + * Collect top class with code + */ + private static List filterClasses(List classes) { + return classes.stream() + .filter(cls -> !cls.isInner() && !cls.isNoCode()) + .collect(Collectors.toList()); } @Override diff --git a/jadx-gui/src/main/java/jadx/gui/search/providers/MethodSearchProvider.java b/jadx-gui/src/main/java/jadx/gui/search/providers/MethodSearchProvider.java index ce64c9811..ef1954619 100644 --- a/jadx-gui/src/main/java/jadx/gui/search/providers/MethodSearchProvider.java +++ b/jadx-gui/src/main/java/jadx/gui/search/providers/MethodSearchProvider.java @@ -5,8 +5,8 @@ import java.util.List; import org.jetbrains.annotations.Nullable; import jadx.api.JavaClass; -import jadx.api.JavaMethod; import jadx.core.dex.info.MethodInfo; +import jadx.core.dex.nodes.MethodNode; import jadx.gui.jobs.Cancelable; import jadx.gui.search.SearchSettings; import jadx.gui.treemodel.JNode; @@ -28,11 +28,11 @@ public final class MethodSearchProvider extends BaseSearchProvider { return null; } JavaClass cls = classes.get(clsNum); - List methods = cls.getMethods(); + List methods = cls.getClassNode().getMethods(); if (mthNum < methods.size()) { - JavaMethod mth = methods.get(mthNum++); - if (checkMth(mth)) { - return convert(mth); + MethodNode mth = methods.get(mthNum++); + if (checkMth(mth.getMethodInfo())) { + return convert(mth.getJavaNode()); } } else { clsNum++; @@ -44,10 +44,11 @@ public final class MethodSearchProvider extends BaseSearchProvider { } } - private boolean checkMth(JavaMethod mth) { - MethodInfo mthInfo = mth.getMethodNode().getMethodInfo(); + private boolean checkMth(MethodInfo mthInfo) { return isMatch(mthInfo.getShortId()) - || isMatch(mthInfo.getAlias()); + || isMatch(mthInfo.getAlias()) + || isMatch(mthInfo.getFullId()) + || isMatch(mthInfo.getAliasFullName()); } @Override