From 2b300341a0c55a0c64163d0bbb6e967f0e553bb5 Mon Sep 17 00:00:00 2001 From: Skylot Date: Tue, 25 Feb 2014 23:52:05 +0400 Subject: [PATCH] core: improve error reporting for inconsistent code --- .../main/java/jadx/core/codegen/ClassGen.java | 101 +++++++++--------- .../java/jadx/core/codegen/MethodGen.java | 32 +++--- .../core/dex/visitors/DotGraphVisitor.java | 2 +- 3 files changed, 71 insertions(+), 64 deletions(-) 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 e8b5d8bb4..34bd289da 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java @@ -6,7 +6,6 @@ import jadx.core.dex.attributes.AttributeFlag; import jadx.core.dex.attributes.AttributeType; import jadx.core.dex.attributes.EnumClassAttr; import jadx.core.dex.attributes.EnumClassAttr.EnumField; -import jadx.core.dex.attributes.IAttribute; import jadx.core.dex.attributes.SourceFileAttr; import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.ClassInfo; @@ -236,17 +235,20 @@ public class ClassGen { code.add(';'); } else { MethodGen mthGen = new MethodGen(this, mth); - if (mth.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE)) { - code.startLine("/* JADX WARNING: inconsistent code */"); + boolean badCode = mth.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE); + if (badCode) { + code.startLine("/* JADX WARNING: inconsistent code. */"); + code.startLine("/* Code decompiled incorrectly, please refer to instructions dump. */"); LOG.error(ErrorsCounter.formatErrorMsg(mth, " Inconsistent code")); - mthGen.makeMethodDump(code); } if (mthGen.addDefinition(code)) { code.add(' '); } code.add('{'); + code.incIndent(); insertSourceFileInfo(code, mth); - code.add(mthGen.makeInstructions(code.getIndent())); + mthGen.addInstructions(code); + code.decIndent(); code.startLine('}'); } } catch (Throwable e) { @@ -263,41 +265,7 @@ public class ClassGen { private CodeWriter makeFields(CodeWriter clsCode, ClassNode cls, List fields) throws CodegenException { CodeWriter code = new CodeWriter(clsCode.getIndent() + 1); - EnumClassAttr enumFields = (EnumClassAttr) cls.getAttributes().get(AttributeType.ENUM_CLASS); - if (enumFields != null) { - InsnGen igen = null; - for (Iterator it = enumFields.getFields().iterator(); it.hasNext(); ) { - EnumField f = it.next(); - code.startLine(f.getName()); - if (f.getArgs().size() != 0) { - code.add('('); - for (Iterator aIt = f.getArgs().iterator(); aIt.hasNext(); ) { - InsnArg arg = aIt.next(); - if (igen == null) { - // don't init mth gen if this is simple enum - MethodGen mthGen = new MethodGen(this, enumFields.getStaticMethod()); - igen = new InsnGen(mthGen, enumFields.getStaticMethod(), false); - } - code.add(igen.arg(arg)); - if (aIt.hasNext()) { - code.add(", "); - } - } - code.add(')'); - } - if (f.getCls() != null) { - new ClassGen(f.getCls(), this, fallback).makeClassBody(code); - } - if (it.hasNext()) { - code.add(','); - } - } - if (enumFields.getFields().isEmpty()) { - code.startLine(); - } - code.add(';'); - code.newLine(); - } + addEnumFields(cls, code); for (FieldNode f : fields) { if (f.getAttributes().contains(AttributeFlag.DONT_GENERATE)) { @@ -323,6 +291,44 @@ public class ClassGen { return code; } + private void addEnumFields(ClassNode cls, CodeWriter code) throws CodegenException { + EnumClassAttr enumFields = (EnumClassAttr) cls.getAttributes().get(AttributeType.ENUM_CLASS); + if (enumFields != null) { + InsnGen igen = null; + for (Iterator it = enumFields.getFields().iterator(); it.hasNext(); ) { + EnumField f = it.next(); + code.startLine(f.getName()); + if (f.getArgs().size() != 0) { + code.add('('); + for (Iterator aIt = f.getArgs().iterator(); aIt.hasNext(); ) { + InsnArg arg = aIt.next(); + if (igen == null) { + // don't init mth gen if this is simple enum + MethodGen mthGen = new MethodGen(this, enumFields.getStaticMethod()); + igen = new InsnGen(mthGen, enumFields.getStaticMethod(), false); + } + igen.addArg(code, arg); + if (aIt.hasNext()) { + code.add(", "); + } + } + code.add(')'); + } + if (f.getCls() != null) { + new ClassGen(f.getCls(), this, fallback).makeClassBody(code); + } + if (it.hasNext()) { + code.add(','); + } + } + if (enumFields.getFields().isEmpty()) { + code.startLine(); + } + code.add(';'); + code.newLine(); + } + } + public String useClass(ArgType clsType) { if (clsType.isGenericType()) { return clsType.getObject(); @@ -357,9 +363,9 @@ public class ClassGen { } private String useClassInternal(ClassInfo useCls, ClassInfo classInfo) { - String clsStr = classInfo.getFullName(); + String fullName = classInfo.getFullName(); if (fallback) { - return clsStr; + return fullName; } String shortName = classInfo.getShortName(); if (classInfo.getPackage().equals("java.lang") && classInfo.getParentClass() == null) { @@ -374,15 +380,15 @@ public class ClassGen { return shortName; } if (classInfo.getPackage().equals(useCls.getPackage())) { - clsStr = classInfo.getNameWithoutPackage(); + fullName = classInfo.getNameWithoutPackage(); } if (searchCollision(cls.dex(), useCls, shortName)) { - return clsStr; + return fullName; } for (ClassInfo importCls : imports) { if (!importCls.equals(classInfo) && importCls.getShortName().equals(shortName)) { - return clsStr; + return fullName; } } addImport(classInfo); @@ -425,10 +431,9 @@ public class ClassGen { } private void insertSourceFileInfo(CodeWriter code, AttrNode node) { - IAttribute sourceFileAttr = node.getAttributes().get(AttributeType.SOURCE_FILE); + SourceFileAttr sourceFileAttr = (SourceFileAttr) node.getAttributes().get(AttributeType.SOURCE_FILE); if (sourceFileAttr != null) { - code.startLine("// compiled from: "); - code.add(((SourceFileAttr) sourceFileAttr).getFileName()); + code.startLine("// compiled from: ").add(sourceFileAttr.getFileName()); } } 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 4713f2c90..2c01a5a20 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java @@ -12,6 +12,7 @@ import jadx.core.dex.instructions.args.NamedArg; import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.MethodNode; +import jadx.core.dex.regions.Region; import jadx.core.dex.trycatch.CatchAttr; import jadx.core.dex.visitors.DepthTraverser; import jadx.core.dex.visitors.FallbackModeVisitor; @@ -227,16 +228,14 @@ public class MethodGen { return r; } - public CodeWriter makeInstructions(int mthIndent) throws CodegenException { - CodeWriter code = new CodeWriter(mthIndent + 1); - + public void addInstructions(CodeWriter code) throws CodegenException { if (mth.getAttributes().contains(AttributeType.JADX_ERROR)) { code.startLine("throw new UnsupportedOperationException(\"Method not decompiled: "); code.add(mth.toString()); code.add("\");"); JadxErrorAttr err = (JadxErrorAttr) mth.getAttributes().get(AttributeType.JADX_ERROR); - code.startLine("// jadx: method processing error"); + code.startLine("/* JADX: method processing error */"); Throwable cause = err.getCause(); if (cause != null) { code.newLine(); @@ -245,32 +244,35 @@ public class MethodGen { code.add("*/"); } makeMethodDump(code); + } else if (mth.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE)) { + code.startLine("/*"); + addFallbackMethodCode(code); + code.startLine("*/"); + code.newLine(); } else { - if (mth.getRegion() != null) { - CodeWriter insns = new CodeWriter(mthIndent + 1); - (new RegionGen(this, mth)).makeRegion(insns, mth.getRegion()); - code.add(insns); + Region startRegion = mth.getRegion(); + if (startRegion != null) { + (new RegionGen(this, mth)).makeRegion(code, startRegion); } else { - makeFallbackMethod(code, mth); + addFallbackMethodCode(code); } } - return code; } - public void makeMethodDump(CodeWriter code) { + private void makeMethodDump(CodeWriter code) { code.startLine("/*"); getFallbackMethodGen(mth).addDefinition(code); code.add(" {"); code.incIndent(); - makeFallbackMethod(code, mth); + addFallbackMethodCode(code); code.decIndent(); code.startLine('}'); code.startLine("*/"); } - private static void makeFallbackMethod(CodeWriter code, MethodNode mth) { + public void addFallbackMethodCode(CodeWriter code) { if (mth.getInstructions() == null) { // loadFile original instructions try { @@ -285,10 +287,10 @@ public class MethodGen { if (mth.getThisArg() != null) { code.startLine(getFallbackMethodGen(mth).makeArgName(mth.getThisArg())).add(" = this;"); } - makeFallbackInsns(code, mth, mth.getInstructions(), true); + addFallbackInsns(code, mth, mth.getInstructions(), true); } - public static void makeFallbackInsns(CodeWriter code, MethodNode mth, List insns, boolean addLabels) { + public static void addFallbackInsns(CodeWriter code, MethodNode mth, List insns, boolean addLabels) { InsnGen insnGen = new InsnGen(getFallbackMethodGen(mth), mth, true); for (InsnNode insn : insns) { AttributesList attrs = insn.getAttributes(); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java index 945e33703..00bfa319c 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java @@ -165,7 +165,7 @@ public class DotGraphVisitor extends AbstractVisitor { return str.toString(); } else { CodeWriter code = new CodeWriter(0); - MethodGen.makeFallbackInsns(code, mth, block.getInstructions(), false); + MethodGen.addFallbackInsns(code, mth, block.getInstructions(), false); String str = escape(code.newLine().toString()); if (str.startsWith(NL)) { str = str.substring(NL.length());