core: improve error reporting for inconsistent code
This commit is contained in:
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user