diff --git a/jadx-cli/src/main/java/jadx/cli/JadxCLI.java b/jadx-cli/src/main/java/jadx/cli/JadxCLI.java index f72a1e98a..ae7e836ba 100644 --- a/jadx-cli/src/main/java/jadx/cli/JadxCLI.java +++ b/jadx-cli/src/main/java/jadx/cli/JadxCLI.java @@ -55,7 +55,7 @@ public class JadxCLI { private static JadxArgs buildArgs(JadxCLIArgs cliArgs) { LogHelper.initLogLevel(cliArgs); - LogHelper.setLogLevelsForLoadingStage(); + LogHelper.applyLogLevels(); JadxArgs jadxArgs = cliArgs.toJadxArgs(); jadxArgs.setCodeCache(new NoOpCodeCache()); jadxArgs.setUsageInfoCache(new EmptyUsageInfoCache()); @@ -72,7 +72,6 @@ public class JadxCLI { if (checkForErrors(jadx)) { return 1; } - LogHelper.setLogLevelsForDecompileStage(); if (!SingleClassMode.process(jadx, cliArgs)) { save(jadx); } @@ -110,10 +109,10 @@ public class JadxCLI { jadx.getArgs().setSkipSources(true); } } - if (jadx.getErrorsCount() > 0) { - LOG.error("Load with errors! Check log for details"); + int errorsCount = jadx.getErrorsCount(); + if (errorsCount > 0) { + LOG.error("Loading finished with errors! Count: {}", errorsCount); // continue processing - return false; } return false; } diff --git a/jadx-cli/src/main/java/jadx/cli/LogHelper.java b/jadx-cli/src/main/java/jadx/cli/LogHelper.java index 8cf47ef5c..2565de1f6 100644 --- a/jadx-cli/src/main/java/jadx/cli/LogHelper.java +++ b/jadx-cli/src/main/java/jadx/cli/LogHelper.java @@ -56,20 +56,7 @@ public class LogHelper { applyLogLevel(logLevelValue); } - public static void setLogLevelsForLoadingStage() { - if (logLevelValue == null) { - return; - } - if (logLevelValue == LogLevelEnum.PROGRESS) { - // show load errors - LogHelper.applyLogLevel(LogLevelEnum.ERROR); - fixForShowProgress(); - return; - } - applyLogLevel(logLevelValue); - } - - public static void setLogLevelsForDecompileStage() { + public static void applyLogLevels() { if (logLevelValue == null) { return; } diff --git a/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java b/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java index a7dc0c4d6..bf96e54cb 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java @@ -3,8 +3,6 @@ package jadx.core.codegen; import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Objects; -import java.util.stream.Stream; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -381,6 +379,20 @@ public class MethodGen { } public void addFallbackMethodCode(ICodeWriter code, FallbackOption fallbackOption) { + if (fallbackOption == COMMENTED_DUMP && mth.getCommentsLevel() != CommentsLevel.DEBUG) { + long insnCountEstimate = mth.getInsnsCount(); + if (insnCountEstimate > 200) { + code.incIndent(); + code.startLine("Method dump skipped, instruction units count: " + insnCountEstimate); + if (code.isMetadataSupported()) { + code.startLine("To view this dump change 'Code comments level' option to 'DEBUG'"); + } else { + code.startLine("To view this dump add '--comments-level debug' option"); + } + code.decIndent(); + return; + } + } if (fallbackOption != FALLBACK_MODE) { List errors = mth.getAll(AType.JADX_ERROR); // preserve error before unload try { @@ -404,23 +416,6 @@ public class MethodGen { code.startLine("// Can't load method instructions."); return; } - if (fallbackOption == COMMENTED_DUMP && mth.getCommentsLevel() != CommentsLevel.DEBUG) { - long insnCountEstimate = Stream.of(insnArr) - .filter(Objects::nonNull) - .filter(insn -> insn.getType() != InsnType.NOP) - .count(); - if (insnCountEstimate > 100) { - code.incIndent(); - code.startLine("Method dump skipped, instructions count: " + insnArr.length); - if (code.isMetadataSupported()) { - code.startLine("To view this dump change 'Code comments level' option to 'DEBUG'"); - } else { - code.startLine("To view this dump add '--comments-level debug' option"); - } - code.decIndent(); - return; - } - } code.incIndent(); if (mth.getThisArg() != null) { code.startLine(nameGen.useArg(mth.getThisArg())).add(" = this;"); diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java b/jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java index 248b12a51..58c98e11d 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/InsnDecoder.java @@ -50,7 +50,12 @@ public class InsnDecoder { rawInsn.decode(); insn = decode(rawInsn); } catch (Exception e) { + boolean mthWithErrors = method.contains(AType.JADX_ERROR); method.addError("Failed to decode insn: " + rawInsn, e); + if (mthWithErrors) { + // second error in this method => abort processing + throw new JadxRuntimeException("Failed to decode insn: " + rawInsn, e); + } insn = new InsnNode(InsnType.NOP, 0); insn.addAttr(AType.JADX_ERROR, new JadxError("decode failed: " + e.getMessage(), e)); } diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/ArgType.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/ArgType.java index 6a04204a3..2f16c0b46 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/ArgType.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/ArgType.java @@ -746,6 +746,9 @@ public abstract class ArgType { case '[': return array(parse(type.substring(1))); default: + if (type.length() != 1) { + throw new JadxRuntimeException("Unknown type string: \"" + type + '"'); + } return parse(f); } } @@ -772,7 +775,7 @@ public abstract class ArgType { return VOID; default: - return null; + throw new JadxRuntimeException("Unknown type char: '" + f + "' (0x" + Integer.toHexString(f) + ')'); } } diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java index ed8d4536b..55fde5fe1 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java @@ -48,6 +48,7 @@ import static jadx.core.utils.Utils.lockList; public class MethodNode extends NotificationAttrNode implements IMethodDetails, ILoadable, ICodeNode, Comparable { private static final Logger LOG = LoggerFactory.getLogger(MethodNode.class); + private static final InsnNode[] EMPTY_INSN_ARRAY = new InsnNode[0]; private final MethodInfo mthInfo; private final ClassNode parentClass; @@ -154,8 +155,14 @@ public class MethodNode extends NotificationAttrNode implements IMethodDetails, this.regsCount = codeReader.getRegistersCount(); this.argsStartReg = codeReader.getArgsStartReg(); initArguments(this.argTypes); - InsnDecoder decoder = new InsnDecoder(this); - this.instructions = decoder.process(codeReader); + + if (contains(AType.JADX_ERROR)) { + // don't load instructions for method with errors + this.instructions = EMPTY_INSN_ARRAY; + } else { + InsnDecoder decoder = new InsnDecoder(this); + this.instructions = decoder.process(codeReader); + } } catch (Exception e) { if (!noCode) { unload(); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/kotlin/ProcessKotlinInternals.java b/jadx-core/src/main/java/jadx/core/dex/visitors/kotlin/ProcessKotlinInternals.java index e670c58a5..7ea28ac45 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/kotlin/ProcessKotlinInternals.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/kotlin/ProcessKotlinInternals.java @@ -13,6 +13,7 @@ import jadx.api.JadxArgs.UseKotlinMethodsForVarNames; import jadx.api.plugins.input.data.attributes.JadxAttrType; import jadx.core.deobf.NameMapper; import jadx.core.dex.attributes.AFlag; +import jadx.core.dex.attributes.AType; import jadx.core.dex.info.ClassInfo; import jadx.core.dex.info.FieldInfo; import jadx.core.dex.info.MethodInfo; @@ -87,7 +88,7 @@ public class ProcessKotlinInternals extends AbstractVisitor { } private void processMth(MethodNode mth) { - if (mth.isNoCode()) { + if (mth.isNoCode() || mth.contains(AType.JADX_ERROR)) { return; } for (BlockNode block : mth.getBasicBlocks()) { diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/usage/UsageInfoVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/usage/UsageInfoVisitor.java index 1358ea80b..6e2e3dd1f 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/usage/UsageInfoVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/usage/UsageInfoVisitor.java @@ -129,7 +129,8 @@ public class UsageInfoVisitor extends AbstractVisitor { try { processInsn(root, mth, insnData, usageInfo); } catch (Exception e) { - mth.addError("Dependency scan failed at insn: " + insnData, e); + throw new JadxRuntimeException( + "Usage info collection failed with error: " + e.getMessage() + " at insn: " + insnData, e); } }); } diff --git a/jadx-gui/src/main/java/jadx/gui/JadxGUI.java b/jadx-gui/src/main/java/jadx/gui/JadxGUI.java index 2076092f7..07a250716 100644 --- a/jadx-gui/src/main/java/jadx/gui/JadxGUI.java +++ b/jadx-gui/src/main/java/jadx/gui/JadxGUI.java @@ -31,7 +31,7 @@ public class JadxGUI { return; } LogHelper.initLogLevel(cliArgs); - LogHelper.setLogLevelsForDecompileStage(); + LogHelper.applyLogLevels(); LogCollector.register(); printSystemInfo();