Commit 41973651 authored by Skylot's avatar Skylot

fix: improve fallback mode dump (add types, remove label after if)

parent 389caf18
...@@ -205,11 +205,11 @@ public class InsnGen { ...@@ -205,11 +205,11 @@ public class InsnGen {
mgen.getClassGen().useType(code, type); mgen.getClassGen().useType(code, type);
} }
public boolean makeInsn(InsnNode insn, CodeWriter code) throws CodegenException { public void makeInsn(InsnNode insn, CodeWriter code) throws CodegenException {
return makeInsn(insn, code, null); makeInsn(insn, code, null);
} }
protected boolean makeInsn(InsnNode insn, CodeWriter code, Flags flag) throws CodegenException { protected void makeInsn(InsnNode insn, CodeWriter code, Flags flag) throws CodegenException {
try { try {
Set<Flags> state = EnumSet.noneOf(Flags.class); Set<Flags> state = EnumSet.noneOf(Flags.class);
if (flag == Flags.BODY_ONLY || flag == Flags.BODY_ONLY_NOWRAP) { if (flag == Flags.BODY_ONLY || flag == Flags.BODY_ONLY_NOWRAP) {
...@@ -231,7 +231,6 @@ public class InsnGen { ...@@ -231,7 +231,6 @@ public class InsnGen {
} catch (Exception th) { } catch (Exception th) {
throw new CodegenException(mth, "Error generate insn: " + insn, th); throw new CodegenException(mth, "Error generate insn: " + insn, th);
} }
return true;
} }
private void makeInsnBody(CodeWriter code, InsnNode insn, Set<Flags> state) throws CodegenException { private void makeInsnBody(CodeWriter code, InsnNode insn, Set<Flags> state) throws CodegenException {
......
...@@ -11,8 +11,10 @@ import jadx.core.Consts; ...@@ -11,8 +11,10 @@ import jadx.core.Consts;
import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.annotations.MethodParameters; import jadx.core.dex.attributes.annotations.MethodParameters;
import jadx.core.dex.attributes.nodes.JumpInfo;
import jadx.core.dex.info.AccessInfo; import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.info.ClassInfo; import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.instructions.IfNode;
import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.CodeVar; import jadx.core.dex.instructions.args.CodeVar;
...@@ -136,7 +138,6 @@ public class MethodGen { ...@@ -136,7 +138,6 @@ public class MethodGen {
} else { } else {
var = ssaVar.getCodeVar(); var = ssaVar.getCodeVar();
} }
ArgType argType = var.getType();
// add argument annotation // add argument annotation
if (paramsAnnotation != null) { if (paramsAnnotation != null) {
...@@ -145,6 +146,7 @@ public class MethodGen { ...@@ -145,6 +146,7 @@ public class MethodGen {
if (var.isFinal()) { if (var.isFinal()) {
code.add("final "); code.add("final ");
} }
ArgType argType = var.getType();
if (!it.hasNext() && mth.getAccessFlags().isVarArgs()) { if (!it.hasNext() && mth.getAccessFlags().isVarArgs()) {
// change last array argument to varargs // change last array argument to varargs
if (argType.isArray()) { if (argType.isArray()) {
...@@ -197,6 +199,7 @@ public class MethodGen { ...@@ -197,6 +199,7 @@ public class MethodGen {
if (mth.getInstructions() == null) { if (mth.getInstructions() == null) {
// load original instructions // load original instructions
try { try {
mth.unload();
mth.load(); mth.load();
DepthTraversal.visit(new FallbackModeVisitor(), mth); DepthTraversal.visit(new FallbackModeVisitor(), mth);
} catch (DecodeException e) { } catch (DecodeException e) {
...@@ -218,28 +221,58 @@ public class MethodGen { ...@@ -218,28 +221,58 @@ public class MethodGen {
public static void addFallbackInsns(CodeWriter code, MethodNode mth, InsnNode[] insnArr, boolean addLabels) { public static void addFallbackInsns(CodeWriter code, MethodNode mth, InsnNode[] insnArr, boolean addLabels) {
InsnGen insnGen = new InsnGen(getFallbackMethodGen(mth), true); InsnGen insnGen = new InsnGen(getFallbackMethodGen(mth), true);
InsnNode prevInsn = null;
for (InsnNode insn : insnArr) { for (InsnNode insn : insnArr) {
if (insn == null || insn.getType() == InsnType.NOP) { if (insn == null || insn.getType() == InsnType.NOP) {
continue; continue;
} }
if (addLabels && (insn.contains(AType.JUMP) || insn.contains(AType.EXC_HANDLER))) { if (addLabels && needLabel(insn, prevInsn)) {
code.decIndent(); code.decIndent();
code.startLine(getLabelName(insn.getOffset()) + ":"); code.startLine(getLabelName(insn.getOffset()) + ":");
code.incIndent(); code.incIndent();
} }
try { try {
if (insnGen.makeInsn(insn, code)) { code.startLine();
RegisterArg resArg = insn.getResult();
if (resArg != null) {
ArgType varType = resArg.getInitType();
if (varType.isTypeKnown()) {
code.add(varType.toString()).add(' ');
}
}
insnGen.makeInsn(insn, code, InsnGen.Flags.INLINE);
CatchAttr catchAttr = insn.get(AType.CATCH_BLOCK); CatchAttr catchAttr = insn.get(AType.CATCH_BLOCK);
if (catchAttr != null) { if (catchAttr != null) {
code.add("\t " + catchAttr); code.add(" // " + catchAttr);
}
} }
} catch (CodegenException e) { } catch (CodegenException e) {
LOG.debug("Error generate fallback instruction: ", e.getCause()); LOG.debug("Error generate fallback instruction: ", e.getCause());
code.startLine("// error: " + insn); code.startLine("// error: " + insn);
} }
prevInsn = insn;
}
}
private static boolean needLabel(InsnNode insn, InsnNode prevInsn) {
if (insn.contains(AType.EXC_HANDLER)) {
return true;
}
if (insn.contains(AType.JUMP)) {
// don't add label for ifs else branch
if (prevInsn != null && prevInsn.getType() == InsnType.IF) {
List<JumpInfo> jumps = insn.getAll(AType.JUMP);
if (jumps.size() == 1) {
JumpInfo jump = jumps.get(0);
if (jump.getSrc() == prevInsn.getOffset() && jump.getDest() == insn.getOffset()) {
int target = ((IfNode) prevInsn).getTarget();
return insn.getOffset() == target;
}
} }
} }
return true;
}
return false;
}
/** /**
* Return fallback variant of method codegen * Return fallback variant of method codegen
......
...@@ -5,6 +5,7 @@ import org.junit.Test; ...@@ -5,6 +5,7 @@ import org.junit.Test;
import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest; import jadx.tests.api.IntegrationTest;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
...@@ -30,8 +31,10 @@ public class TestFallbackMode extends IntegrationTest { ...@@ -30,8 +31,10 @@ public class TestFallbackMode extends IntegrationTest {
String code = cls.getCode().toString(); String code = cls.getCode().toString();
assertThat(code, containsString("public int test(int r2) {")); assertThat(code, containsString("public int test(int r2) {"));
assertThat(code, containsString("r1 = this;")); assertThat(code, containsOne("r1 = this;"));
assertThat(code, containsString("L_0x0004:")); assertThat(code, containsOne("L_0x0000:"));
assertThat(code, containsOne("L_0x0007:"));
assertThat(code, containsOne("int r2 = r2 + 1"));
assertThat(code, not(containsString("throw new UnsupportedOperationException"))); assertThat(code, not(containsString("throw new UnsupportedOperationException")));
} }
} }
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