core: improve error reporting for inconsistent code

This commit is contained in:
Skylot
2014-02-25 23:52:05 +04:00
parent 01fabca358
commit 2b300341a0
3 changed files with 71 additions and 64 deletions
@@ -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<FieldNode> 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<EnumField> it = enumFields.getFields().iterator(); it.hasNext(); ) {
EnumField f = it.next();
code.startLine(f.getName());
if (f.getArgs().size() != 0) {
code.add('(');
for (Iterator<InsnArg> 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<EnumField> it = enumFields.getFields().iterator(); it.hasNext(); ) {
EnumField f = it.next();
code.startLine(f.getName());
if (f.getArgs().size() != 0) {
code.add('(');
for (Iterator<InsnArg> 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());
}
}
@@ -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<InsnNode> insns, boolean addLabels) {
public static void addFallbackInsns(CodeWriter code, MethodNode mth, List<InsnNode> insns, boolean addLabels) {
InsnGen insnGen = new InsnGen(getFallbackMethodGen(mth), mth, true);
for (InsnNode insn : insns) {
AttributesList attrs = insn.getAttributes();
@@ -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());