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