Commit 13a6b1c8 authored by Skylot's avatar Skylot

core: add 'show inconsistent code' parameter

parent 0bc37e5d
......@@ -29,9 +29,12 @@ public final class JadxCLIArgs implements IJadxArgs {
@Parameter(names = {"-j", "--threads-count"}, description = "processing threads count")
protected int threadsCount = Runtime.getRuntime().availableProcessors();
@Parameter(names = {"-f", "--fallback"}, description = "make simple dump (using goto instead of 'if', 'for', etc)", help = true)
@Parameter(names = {"-f", "--fallback"}, description = "make simple dump (using goto instead of 'if', 'for', etc)")
protected boolean fallbackMode = false;
@Parameter(names = {"--show-bad-code"}, description = "show inconsistent code (incorrectly decompiled)")
protected boolean showInconsistentCode = false;
@Parameter(names = {"--cfg"}, description = "save methods control flow graph to dot file")
protected boolean cfgOutput = false;
......@@ -182,6 +185,11 @@ public final class JadxCLIArgs implements IJadxArgs {
}
@Override
public boolean isShowInconsistentCode() {
return showInconsistentCode;
}
@Override
public boolean isVerbose() {
return verbose;
}
......
......@@ -30,6 +30,11 @@ public class DefaultJadxArgs implements IJadxArgs {
}
@Override
public boolean isShowInconsistentCode() {
return false;
}
@Override
public boolean isVerbose() {
return false;
}
......
......@@ -13,5 +13,7 @@ public interface IJadxArgs {
boolean isFallbackMode();
boolean isShowInconsistentCode();
boolean isVerbose();
}
package jadx.core.codegen;
import jadx.api.IJadxArgs;
import jadx.core.Consts;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
......@@ -43,9 +44,16 @@ public class ClassGen {
private final AnnotationGen annotationGen;
private final boolean fallback;
private boolean showInconsistentCode = false;
private final Set<ClassInfo> imports = new HashSet<ClassInfo>();
private int clsDeclLine;
public ClassGen(ClassNode cls, ClassGen parentClsGen, IJadxArgs jadxArgs) {
this(cls, parentClsGen, jadxArgs.isFallbackMode());
this.showInconsistentCode = jadxArgs.isShowInconsistentCode();
}
public ClassGen(ClassNode cls, ClassGen parentClsGen, boolean fallback) {
this.cls = cls;
this.parentGen = parentClsGen;
......@@ -269,6 +277,9 @@ public class ClassGen {
code.startLine("/* JADX WARNING: inconsistent code. */");
code.startLine("/* Code decompiled incorrectly, please refer to instructions dump. */");
ErrorsCounter.methodError(mth, "Inconsistent code");
if (showInconsistentCode) {
mth.remove(AFlag.INCONSISTENT_CODE);
}
}
MethodGen mthGen;
if (badCode || mth.contains(AType.JADX_ERROR)) {
......
......@@ -15,15 +15,11 @@ public class CodeGen extends AbstractVisitor {
@Override
public boolean visit(ClassNode cls) throws CodegenException {
ClassGen clsGen = new ClassGen(cls, null, isFallbackMode());
ClassGen clsGen = new ClassGen(cls, null, args);
CodeWriter clsCode = clsGen.makeClass();
clsCode.finish();
cls.setCode(clsCode);
return false;
}
public boolean isFallbackMode() {
return args.isFallbackMode();
}
}
......@@ -132,7 +132,7 @@ public class InsnGen {
ClassNode pCls = mth.getParentClass();
FieldNode fieldNode = pCls.searchField(field);
while ((fieldNode == null)
while ((fieldNode == null)
&& (pCls.getParentClass() != pCls) && (pCls.getParentClass() != null))
{
pCls = pCls.getParentClass();
......@@ -519,9 +519,10 @@ public class InsnGen {
"Incorrect type for fill-array insn " + InsnUtils.formatOffset(insn.getOffset())
+ ", element type: " + elType + ", insn element type: " + insnElementType
);
if (!elType.isTypeKnown()) {
elType = insnElementType.isTypeKnown() ? insnElementType : elType.selectFirst();
}
}
if (!elType.isTypeKnown()) {
LOG.warn("Unknown array element type: {} in mth: {}", elType);
elType = insnElementType.isTypeKnown() ? insnElementType : elType.selectFirst();
}
StringBuilder str = new StringBuilder();
Object data = insn.getData();
......
......@@ -27,6 +27,7 @@ import jadx.core.dex.regions.loops.LoopType;
import jadx.core.dex.trycatch.CatchAttr;
import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.trycatch.TryCatchBlock;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.RegionUtils;
import jadx.core.utils.exceptions.CodegenException;
import jadx.core.utils.exceptions.JadxRuntimeException;
......@@ -155,8 +156,7 @@ public class RegionGen extends InsnGen {
if (header != null) {
List<InsnNode> headerInsns = header.getInstructions();
if (headerInsns.size() > 1) {
// write not inlined instructions from header
mth.add(AFlag.INCONSISTENT_CODE);
ErrorsCounter.methodError(mth, "Found not inlined instructions from loop header");
int last = headerInsns.size() - 1;
for (int i = 0; i < last; i++) {
InsnNode insn = headerInsns.get(i);
......
......@@ -18,6 +18,7 @@ import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.exceptions.JadxException;
import java.util.ArrayList;
......@@ -79,9 +80,8 @@ public class EnumVisitor extends AbstractVisitor {
cls.addAttr(attr);
if (staticMethod == null) {
LOG.warn("Enum class init method not found: {}", cls);
ErrorsCounter.classError(cls, "Enum class init method not found");
// for this broken enum puts found fields and mark as inconsistent
cls.add(AFlag.INCONSISTENT_CODE);
for (FieldNode field : enumFields) {
attr.getFields().add(new EnumField(field.getName(), 0));
}
......
......@@ -72,7 +72,6 @@ public class CheckRegions extends AbstractVisitor {
BlockNode loopHeader = ((LoopRegion) region).getHeader();
if (loopHeader != null && loopHeader.getInstructions().size() != 1) {
ErrorsCounter.methodError(mth, "Incorrect condition in loop: " + loopHeader);
mth.add(AFlag.INCONSISTENT_CODE);
}
}
}
......
package jadx.core.dex.visitors.regions;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.IContainer;
......@@ -12,6 +11,7 @@ import jadx.core.dex.trycatch.CatchAttr;
import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.trycatch.TryCatchBlock;
import jadx.core.utils.BlockUtils;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.RegionUtils;
import jadx.core.utils.exceptions.JadxRuntimeException;
......@@ -110,8 +110,7 @@ public class ProcessTryCatchRegions extends AbstractRegionVisitor {
if (region.getSubBlocks().contains(dominator)) {
TryCatchBlock tb = tryBlocksMap.get(dominator);
if (!wrapBlocks(region, tb, dominator)) {
LOG.warn("Can't wrap try/catch for {}, method: {}", region, mth);
mth.add(AFlag.INCONSISTENT_CODE);
ErrorsCounter.methodError(mth, "Can't wrap try/catch for " + region);
}
tryBlocksMap.remove(dominator);
return;
......
......@@ -359,8 +359,7 @@ public class RegionMaker {
BlockNode body = getNextBlock(block);
if (body == null) {
mth.add(AFlag.INCONSISTENT_CODE);
LOG.warn("Unexpected end of synchronized block");
ErrorsCounter.methodError(mth, "Unexpected end of synchronized block");
return null;
}
BlockNode exit;
......
......@@ -57,19 +57,22 @@ public class ErrorsCounter {
return msg;
}
public static String classError(ClassNode mth, String errorMsg) {
return classError(mth, errorMsg, null);
}
public static String methodError(MethodNode mth, String errorMsg, Throwable e) {
String msg = formatErrorMsg(mth, errorMsg);
mth.dex().root().getErrorsCounter().addError(mth, msg, e);
return msg;
}
public static String methodError(MethodNode mth, String errorMsg) {
return methodError(mth, errorMsg, null);
}
public void printReport() {
if (getErrorCount() > 0) {
LOG.error(getErrorCount() + " errors occured in following nodes:");
LOG.error(getErrorCount() + " errors occurred in following nodes:");
List<Object> nodes = new ArrayList<Object>(errorNodes);
Collections.sort(nodes, new Comparator<Object>() {
@Override
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment