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 e8b5d8bb43e34b10dbc76e1370ac4312f4cecba9..34bd289daeb2642ef681062b0d1fb0e8ae562741 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,6 +265,33 @@ public class ClassGen { private CodeWriter makeFields(CodeWriter clsCode, ClassNode cls, List fields) throws CodegenException { CodeWriter code = new CodeWriter(clsCode.getIndent() + 1); + addEnumFields(cls, code); + + for (FieldNode f : fields) { + if (f.getAttributes().contains(AttributeFlag.DONT_GENERATE)) { + continue; + } + annotationGen.addForField(code, f); + code.startLine(f.getAccessFlags().makeString()); + code.add(TypeGen.translate(this, f.getType())); + code.add(' '); + code.add(f.getName()); + FieldValueAttr fv = (FieldValueAttr) f.getAttributes().get(AttributeType.FIELD_VALUE); + if (fv != null) { + code.add(" = "); + if (fv.getValue() == null) { + code.add(TypeGen.literalToString(0, f.getType())); + } else { + code.add(annotationGen.encValueToString(fv.getValue())); + } + } + code.add(';'); + code.attachAnnotation(f); + } + 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; @@ -278,7 +307,7 @@ public class ClassGen { MethodGen mthGen = new MethodGen(this, enumFields.getStaticMethod()); igen = new InsnGen(mthGen, enumFields.getStaticMethod(), false); } - code.add(igen.arg(arg)); + igen.addArg(code, arg); if (aIt.hasNext()) { code.add(", "); } @@ -298,29 +327,6 @@ public class ClassGen { code.add(';'); code.newLine(); } - - for (FieldNode f : fields) { - if (f.getAttributes().contains(AttributeFlag.DONT_GENERATE)) { - continue; - } - annotationGen.addForField(code, f); - code.startLine(f.getAccessFlags().makeString()); - code.add(TypeGen.translate(this, f.getType())); - code.add(' '); - code.add(f.getName()); - FieldValueAttr fv = (FieldValueAttr) f.getAttributes().get(AttributeType.FIELD_VALUE); - if (fv != null) { - code.add(" = "); - if (fv.getValue() == null) { - code.add(TypeGen.literalToString(0, f.getType())); - } else { - code.add(annotationGen.encValueToString(fv.getValue())); - } - } - code.add(';'); - code.attachAnnotation(f); - } - return code; } public String useClass(ArgType clsType) { @@ -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 4713f2c9021d5993cc8a0e3829742400b0f7d276..2c01a5a200ae7e7255d92a4dbc890151c049d982 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 945e337032a30a145f643dfde5bb1477f87eebb2..00bfa319c864ae66f9dd8777fd5c6445676647ed 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());