diff --git a/jadx-core/src/main/java/jadx/core/ProcessClass.java b/jadx-core/src/main/java/jadx/core/ProcessClass.java index 94eb120068aeb60d0c7de5d3075fc54d2399f63b..35e82ebc309b4cb67a0e183df16138da1e49cd7a 100644 --- a/jadx-core/src/main/java/jadx/core/ProcessClass.java +++ b/jadx-core/src/main/java/jadx/core/ProcessClass.java @@ -7,7 +7,6 @@ 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 jadx.core.utils.exceptions.JadxRuntimeException; import static jadx.core.dex.nodes.ProcessState.LOADED; @@ -43,7 +42,7 @@ public final class ProcessClass { cls.setState(PROCESS_COMPLETE); } } catch (Throwable e) { - ErrorsCounter.classError(cls, e.getClass().getSimpleName(), e); + cls.addError("Class process error: " + e.getClass().getSimpleName(), e); } } } diff --git a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java index a35b7e7efb3dcbeb082b101c35048f4cad9f6b06..5044fa649856f723b71792a26a93c1ff09d2e394 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java @@ -268,7 +268,7 @@ public class ClassGen { inClGen.addClassCode(code); imports.addAll(inClGen.getImports()); } catch (Exception e) { - ErrorsCounter.classError(innerCls, "Inner class code generation error", e); + innerCls.addError("Inner class code generation error", e); } } @@ -293,7 +293,7 @@ public class ClassGen { throw new JadxRuntimeException("Method generation error", e); } code.newLine().add("/*"); - code.newLine().addMultiLine(ErrorsCounter.methodError(mth, "Method generation error", e)); + code.newLine().addMultiLine(ErrorsCounter.error(mth, "Method generation error", e)); Utils.appendStackTrace(code, e); code.newLine().add("*/"); code.setIndent(savedIndent); @@ -455,7 +455,7 @@ public class ClassGen { try { insnGen.makeInsn(insn, code, InsnGen.Flags.BODY_ONLY_NOWRAP); } catch (Exception e) { - ErrorsCounter.classError(cls, "Failed to generate init code", e); + cls.addError("Failed to generate init code", e); } } diff --git a/jadx-core/src/main/java/jadx/core/codegen/ConditionGen.java b/jadx-core/src/main/java/jadx/core/codegen/ConditionGen.java index f13f72152674d844249f29e3f57c0fb746ec8818..ee3ed1fb36c1dec5d92264d8d7a726e4dcd27608 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/ConditionGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/ConditionGen.java @@ -16,7 +16,6 @@ import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.regions.conditions.Compare; import jadx.core.dex.regions.conditions.IfCondition; import jadx.core.dex.regions.conditions.IfCondition.Mode; -import jadx.core.utils.ErrorsCounter; import jadx.core.utils.exceptions.CodegenException; import jadx.core.utils.exceptions.JadxRuntimeException; @@ -123,7 +122,7 @@ public class ConditionGen extends InsnGen { wrap(code, firstArg); return; } - ErrorsCounter.methodWarn(mth, "Unsupported boolean condition " + op.getSymbol()); + mth.addWarn("Unsupported boolean condition " + op.getSymbol()); } addArg(code, firstArg, isArgWrapNeeded(firstArg)); diff --git a/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java b/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java index 59069d679de00681894d4cbab3f4158e7614411f..eef789687cd162e7425deb99401a55da7a49501e 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/RegionGen.java @@ -39,7 +39,6 @@ import jadx.core.dex.regions.loops.LoopRegion; import jadx.core.dex.regions.loops.LoopType; import jadx.core.dex.trycatch.ExceptionHandler; import jadx.core.utils.BlockUtils; -import jadx.core.utils.ErrorsCounter; import jadx.core.utils.RegionUtils; import jadx.core.utils.exceptions.CodegenException; import jadx.core.utils.exceptions.JadxRuntimeException; @@ -186,7 +185,7 @@ public class RegionGen extends InsnGen { if (header != null) { List headerInsns = header.getInstructions(); if (headerInsns.size() > 1) { - ErrorsCounter.methodWarn(mth, "Found not inlined instructions from loop header"); + mth.addWarn("Found not inlined instructions from loop header"); int last = headerInsns.size() - 1; for (int i = 0; i < last; i++) { InsnNode insn = headerInsns.get(i); diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/NotificationAttrNode.java b/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/NotificationAttrNode.java new file mode 100644 index 0000000000000000000000000000000000000000..c2f72087b04680452310e613ecb3dcd344d21b25 --- /dev/null +++ b/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/NotificationAttrNode.java @@ -0,0 +1,40 @@ +package jadx.core.dex.attributes.nodes; + +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import jadx.core.dex.attributes.AType; +import jadx.core.dex.nodes.ICodeNode; +import jadx.core.utils.ErrorsCounter; + +public abstract class NotificationAttrNode extends LineAttrNode implements ICodeNode { + private static final Logger LOG = LoggerFactory.getLogger(NotificationAttrNode.class); + + public void addError(String errStr, Throwable e) { + ErrorsCounter.error(this, errStr, e); + } + + public void addWarn(String warnStr) { + ErrorsCounter.warning(this, warnStr); + } + + public void addWarnComment(String warn) { + addWarnComment(warn, null); + } + + public void addWarnComment(String warn, @Nullable Throwable exc) { + String commentStr = "JADX WARN: " + warn; + addAttr(AType.COMMENTS, commentStr); + if (exc != null) { + LOG.warn("{} in {}", warn, this, exc); + } else { + LOG.warn("{} in {}", warn, this); + } + } + + public void addComment(String commentStr) { + addAttr(AType.COMMENTS, commentStr); + LOG.info("{} in {}", commentStr, this); + } +} diff --git a/jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java b/jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java index 4ecf702714ffd82087533b55bce79c812314ae0b..d71095fdd80d2fc18559e02693a9a094eb248963 100644 --- a/jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java +++ b/jadx-core/src/main/java/jadx/core/dex/info/ConstStorage.java @@ -16,7 +16,6 @@ import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.DexNode; import jadx.core.dex.nodes.FieldNode; import jadx.core.dex.nodes.parser.FieldInitAttr; -import jadx.core.utils.ErrorsCounter; public class ConstStorage { @@ -155,7 +154,7 @@ public class ConstStorage { return innerClass.searchFieldByName(fieldName); } } - ErrorsCounter.classWarn(appResClass, "Not found resource field with id: " + value + ", name: " + str.replace('/', '.')); + appResClass.addWarn("Not found resource field with id: " + value + ", name: " + str.replace('/', '.')); return null; } 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 8d3867083e9c41f5773c11a254269040e77512e5..39ff60911701a44222b9774d99ef9fef54674550 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 @@ -25,7 +25,7 @@ import jadx.core.Consts; import jadx.core.ProcessClass; import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.annotations.Annotation; -import jadx.core.dex.attributes.nodes.LineAttrNode; +import jadx.core.dex.attributes.nodes.NotificationAttrNode; import jadx.core.dex.attributes.nodes.SourceFileAttr; import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.AccessInfo.AFType; @@ -45,7 +45,7 @@ import jadx.core.utils.exceptions.JadxRuntimeException; import static jadx.core.dex.nodes.ProcessState.LOADED; import static jadx.core.dex.nodes.ProcessState.NOT_LOADED; -public class ClassNode extends LineAttrNode implements ILoadable, ICodeNode { +public class ClassNode extends NotificationAttrNode implements ILoadable, ICodeNode { private static final Logger LOG = LoggerFactory.getLogger(ClassNode.class); private final DexNode dex; diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java index f76578df97136f74eba0d8da5e12efabe984ca1c..febb7a2ae5476fbfa3076e5c2368df79743c4a30 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/DexNode.java @@ -79,7 +79,7 @@ public class DexNode implements IDexNode { name = "CLASS_" + typeIndex; } ClassNode clsNode = new ClassNode(this, name, classDef.getAccessFlags()); - ErrorsCounter.classError(clsNode, "Load error", exc); + ErrorsCounter.error(clsNode, "Load error", exc); addClassNode(clsNode); } 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 fd2aee0fd1d51b3642d2d71ce8651b826a864d89..7e30b07af114d3b5ebc4285cd341a807b7cde2ac 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 @@ -22,8 +22,8 @@ import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.annotations.Annotation; import jadx.core.dex.attributes.nodes.JumpInfo; -import jadx.core.dex.attributes.nodes.LineAttrNode; import jadx.core.dex.attributes.nodes.LoopInfo; +import jadx.core.dex.attributes.nodes.NotificationAttrNode; import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.AccessInfo.AFType; import jadx.core.dex.info.ClassInfo; @@ -42,14 +42,13 @@ import jadx.core.dex.regions.Region; import jadx.core.dex.trycatch.ExcHandlerAttr; import jadx.core.dex.trycatch.ExceptionHandler; import jadx.core.dex.trycatch.TryCatchBlock; -import jadx.core.utils.ErrorsCounter; import jadx.core.utils.Utils; import jadx.core.utils.exceptions.DecodeException; import jadx.core.utils.exceptions.JadxRuntimeException; import static jadx.core.utils.Utils.lockList; -public class MethodNode extends LineAttrNode implements IMethodDetails, ILoadable, ICodeNode { +public class MethodNode extends NotificationAttrNode implements IMethodDetails, ILoadable, ICodeNode { private static final Logger LOG = LoggerFactory.getLogger(MethodNode.class); private final MethodInfo mthInfo; @@ -203,9 +202,7 @@ public class MethodNode extends LineAttrNode implements IMethodDetails, ILoadabl return null; } if (!tryFixArgsCounts(argsTypes, mthArgs)) { - if (LOG.isDebugEnabled()) { - LOG.debug("Incorrect method signature, types: ({}), method: {}", Utils.listToString(argsTypes), this); - } + addComment("Incorrect method signature, types: " + Utils.listToString(argsTypes)); return null; } } @@ -715,33 +712,6 @@ public class MethodNode extends LineAttrNode implements IMethodDetails, ILoadabl return "method"; } - public void addWarn(String warnStr) { - ErrorsCounter.methodWarn(this, warnStr); - } - - public void addWarnComment(String warn) { - addWarnComment(warn, null); - } - - public void addWarnComment(String warn, @Nullable Throwable exc) { - String commentStr = "JADX WARN: " + warn; - addAttr(AType.COMMENTS, commentStr); - if (exc != null) { - LOG.warn("{} in {}", warn, this, exc); - } else { - LOG.warn("{} in {}", warn, this); - } - } - - public void addComment(String commentStr) { - addAttr(AType.COMMENTS, commentStr); - LOG.info("{} in {}", commentStr, this); - } - - public void addError(String errStr, Throwable e) { - ErrorsCounter.methodError(this, errStr, e); - } - @Override public MethodInfo getMethodInfo() { return mthInfo; diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/DepthTraversal.java b/jadx-core/src/main/java/jadx/core/dex/visitors/DepthTraversal.java index dfe8445c8bd2a15ed9bc81f4a7f597000f6cb52d..a8ef3ca787c921ea287df5e6239e56e03ecf351e 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/DepthTraversal.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/DepthTraversal.java @@ -4,8 +4,6 @@ import jadx.core.dex.attributes.AType; import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.MethodNode; import jadx.core.utils.DebugChecks; -import jadx.core.utils.ErrorsCounter; -import jadx.core.utils.exceptions.JadxOverflowException; public class DepthTraversal { @@ -15,11 +13,8 @@ public class DepthTraversal { cls.getInnerClasses().forEach(inCls -> visit(visitor, inCls)); cls.getMethods().forEach(mth -> visit(visitor, mth)); } - } catch (StackOverflowError e) { - ErrorsCounter.classError(cls, "StackOverflow in pass: " + visitor.getClass().getSimpleName(), new JadxOverflowException("")); - } catch (Exception e) { - ErrorsCounter.classError(cls, - e.getClass().getSimpleName() + " in pass: " + visitor.getClass().getSimpleName(), e); + } catch (StackOverflowError | Exception e) { + cls.addError(e.getClass().getSimpleName() + " in pass: " + visitor.getClass().getSimpleName(), e); } } @@ -32,11 +27,8 @@ public class DepthTraversal { if (DebugChecks.checksEnabled) { DebugChecks.runChecksAfterVisitor(mth, visitor); } - } catch (StackOverflowError e) { - ErrorsCounter.methodError(mth, "StackOverflow in pass: " + visitor.getClass().getSimpleName(), new JadxOverflowException("")); - } catch (Exception e) { - ErrorsCounter.methodError(mth, - e.getClass().getSimpleName() + " in pass: " + visitor.getClass().getSimpleName(), e); + } catch (StackOverflowError | Exception e) { + mth.addError(e.getClass().getSimpleName() + " in pass: " + visitor.getClass().getSimpleName(), e); } } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java index a8b57758c223e1ae5c03a3ea8eeab81a21b2ea70..03b76533fa70ae2773ec9826f83578dfd75f508f 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java @@ -46,7 +46,6 @@ import jadx.core.dex.trycatch.ExcHandlerAttr; import jadx.core.dex.trycatch.ExceptionHandler; import jadx.core.dex.visitors.regions.variables.ProcessVariables; import jadx.core.dex.visitors.shrink.CodeShrinkVisitor; -import jadx.core.utils.ErrorsCounter; import jadx.core.utils.InsnRemover; import jadx.core.utils.InsnUtils; import jadx.core.utils.exceptions.JadxException; @@ -467,9 +466,8 @@ public class ModVisitor extends AbstractVisitor { elType = insnElementType; } if (!elType.equals(insnElementType) && !insnArrayType.equals(ArgType.OBJECT)) { - ErrorsCounter.methodWarn(mth, - "Incorrect type for fill-array insn " + InsnUtils.formatOffset(insn.getOffset()) - + ", element type: " + elType + ", insn element type: " + insnElementType); + mth.addWarn("Incorrect type for fill-array insn " + InsnUtils.formatOffset(insn.getOffset()) + + ", element type: " + elType + ", insn element type: " + insnElementType); } if (!elType.isTypeKnown()) { LOG.warn("Unknown array element type: {} in mth: {}", elType, mth); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java index a00b1f81f7a6cddf1c70d3cfe7fb9e3073650f7b..642ca5f5fac8a4515d7ff40ff0bf79e9a09a08a1 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/ProcessTryCatchRegions.java @@ -23,7 +23,6 @@ import jadx.core.dex.trycatch.ExceptionHandler; import jadx.core.dex.trycatch.SplitterBlockAttr; import jadx.core.dex.trycatch.TryCatchBlock; import jadx.core.utils.BlockUtils; -import jadx.core.utils.ErrorsCounter; import jadx.core.utils.RegionUtils; /** @@ -105,7 +104,7 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor { if (region.getSubBlocks().contains(dominator)) { TryCatchBlock tb = tryBlocksMap.get(dominator); if (!wrapBlocks(region, tb, dominator)) { - ErrorsCounter.methodWarn(mth, "Can't wrap try/catch for region: " + region); + mth.addWarn("Can't wrap try/catch for region: " + region); } tryBlocksMap.remove(dominator); return true; diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java index da956201eb98f53eec5899c7f5926eae4410546f..d538ce71460008e77b2dea1503ddecea669c324d 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java @@ -574,7 +574,7 @@ public class RegionMaker { BlockNode body = getNextBlock(block); if (body == null) { - ErrorsCounter.methodWarn(mth, "Unexpected end of synchronized block"); + mth.addWarn("Unexpected end of synchronized block"); return null; } BlockNode exit = null; diff --git a/jadx-core/src/main/java/jadx/core/utils/ErrorsCounter.java b/jadx-core/src/main/java/jadx/core/utils/ErrorsCounter.java index 304c382674585937e08c3f7dcfcc552d8827111e..c886a42ef4f0da8c04c326cb8facc1bc29e0e7de 100644 --- a/jadx-core/src/main/java/jadx/core/utils/ErrorsCounter.java +++ b/jadx-core/src/main/java/jadx/core/utils/ErrorsCounter.java @@ -14,7 +14,6 @@ import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.IAttributeNode; import jadx.core.dex.attributes.nodes.JadxError; -import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.IDexNode; import jadx.core.dex.nodes.MethodNode; import jadx.core.utils.exceptions.JadxOverflowException; @@ -28,12 +27,16 @@ public class ErrorsCounter { private final Set warnNodes = new HashSet<>(); private int warnsCount; - public int getErrorCount() { - return errorsCount; + public static String error(N node, String warnMsg, Throwable th) { + return node.root().getErrorsCounter().addError(node, warnMsg, th); } - public int getWarnsCount() { - return warnsCount; + public static String warning(N node, String warnMsg) { + return node.root().getErrorsCounter().addWarning(node, warnMsg); + } + + public static String formatMsg(IDexNode node, String msg) { + return msg + " in " + node.typeName() + ": " + node + ", dex: " + node.dex().getDexFile().getName(); } private synchronized String addError(N node, String error, @Nullable Throwable e) { @@ -47,10 +50,17 @@ public class ErrorsCounter { } if (e == null) { LOG.error(msg); + } else if (e instanceof StackOverflowError) { + LOG.error(msg); } else if (e instanceof JadxOverflowException) { // don't print full stack trace - e = new JadxOverflowException(e.getMessage()); - LOG.error("{}, details: {}", msg, e.getMessage()); + String details = e.getMessage(); + e = new JadxOverflowException(details); + if (details == null || details.isEmpty()) { + LOG.error("{}", msg); + } else { + LOG.error("{}, details: {}", msg, details); + } } else { LOG.error(msg, e); } @@ -74,26 +84,6 @@ public class ErrorsCounter { return msg; } - public static String classError(ClassNode cls, String errorMsg, Throwable e) { - return cls.dex().root().getErrorsCounter().addError(cls, errorMsg, e); - } - - public static String classWarn(ClassNode cls, String warnMsg) { - return cls.dex().root().getErrorsCounter().addWarning(cls, warnMsg); - } - - public static String methodError(MethodNode mth, String errorMsg, Throwable e) { - return mth.root().getErrorsCounter().addError(mth, errorMsg, e); - } - - public static String methodWarn(MethodNode mth, String warnMsg) { - return mth.root().getErrorsCounter().addWarning(mth, warnMsg); - } - - public static String formatMsg(IDexNode node, String msg) { - return msg + " in " + node.typeName() + ": " + node + ", dex: " + node.dex().getDexFile().getName(); - } - public void printReport() { if (getErrorCount() > 0) { LOG.error("{} errors occurred in following nodes:", getErrorCount()); @@ -111,4 +101,20 @@ public class ErrorsCounter { LOG.warn("{} warnings in {} nodes", getWarnsCount(), warnNodes.size()); } } + + public int getErrorCount() { + return errorsCount; + } + + public int getWarnsCount() { + return warnsCount; + } + + public Set getErrorNodes() { + return errorNodes; + } + + public Set getWarnNodes() { + return warnNodes; + } } diff --git a/jadx-core/src/main/java/jadx/core/utils/Utils.java b/jadx-core/src/main/java/jadx/core/utils/Utils.java index daf73e7e84c7000bbedb5383dc6a438bc0d89e0d..341517f7f44a7ab607aad39c30dd2cd61b397438 100644 --- a/jadx-core/src/main/java/jadx/core/utils/Utils.java +++ b/jadx-core/src/main/java/jadx/core/utils/Utils.java @@ -158,14 +158,17 @@ public class Utils { private static void filter(Throwable th) { StackTraceElement[] stackTrace = th.getStackTrace(); int length = stackTrace.length; + StackTraceElement prevElement = null; for (int i = 0; i < length; i++) { StackTraceElement stackTraceElement = stackTrace[i]; String clsName = stackTraceElement.getClassName(); if (clsName.equals(STACKTRACE_STOP_CLS_NAME) - || clsName.startsWith(JADX_API_PACKAGE)) { + || clsName.startsWith(JADX_API_PACKAGE) + || Objects.equals(prevElement, stackTraceElement)) { th.setStackTrace(Arrays.copyOfRange(stackTrace, 0, i)); return; } + prevElement = stackTraceElement; } }