Commit 29840e03 authored by Skylot's avatar Skylot

Generate code for 'if-else-if' construction

parent 326b1979
......@@ -5,7 +5,7 @@ import jadx.dex.info.ClassInfo;
import jadx.dex.nodes.ClassNode;
import jadx.dex.nodes.RootNode;
import jadx.dex.visitors.BlockMakerVisitor;
import jadx.dex.visitors.ClassCheck;
import jadx.dex.visitors.ClassModifier;
import jadx.dex.visitors.CodeShrinker;
import jadx.dex.visitors.ConstInlinerVisitor;
import jadx.dex.visitors.DotGraphVisitor;
......@@ -14,6 +14,7 @@ import jadx.dex.visitors.FallbackModeVisitor;
import jadx.dex.visitors.IDexTreeVisitor;
import jadx.dex.visitors.ModVisitor;
import jadx.dex.visitors.regions.CheckRegions;
import jadx.dex.visitors.regions.CleanRegions;
import jadx.dex.visitors.regions.PostRegionVisitor;
import jadx.dex.visitors.regions.ProcessVariables;
import jadx.dex.visitors.regions.RegionMakerVisitor;
......@@ -94,11 +95,11 @@ public class Main {
passes.add(new ConstInlinerVisitor());
passes.add(new FinishTypeResolver());
passes.add(new ClassCheck());
if (args.isRawCFGOutput())
passes.add(new DotGraphVisitor(args.getOutDir(), false, true));
passes.add(new ClassModifier());
passes.add(new ModVisitor());
passes.add(new EnumVisitor());
......@@ -113,6 +114,8 @@ public class Main {
passes.add(new CheckRegions());
if (args.isCFGOutput())
passes.add(new DotGraphVisitor(args.getOutDir(), true));
passes.add(new CleanRegions());
}
passes.add(new CodeGen(args));
return passes;
......
......@@ -66,7 +66,7 @@ public class MethodGen {
} else {
if (mth.getAttributes().contains(AttributeFlag.INCONSISTENT_CODE)) {
code.startLine("// FIXME: Jadx generate inconsistent code");
// ErrorsCounter.methodError(mth, "Inconsistent code");
LOG.debug(ErrorsCounter.formatErrorMsg(mth, " Inconsistent code"));
}
annotationGen.addForMethod(code, mth);
......
......@@ -58,6 +58,7 @@ public class RegionGen extends InsnGen {
makeRegion(code, c);
}
} else if (cont instanceof IfRegion) {
code.startLine();
makeIf((IfRegion) cont, code);
} else if (cont instanceof SwitchRegion) {
makeSwitch((SwitchRegion) cont, code);
......@@ -104,13 +105,25 @@ public class RegionGen extends InsnGen {
private void makeIf(IfRegion region, CodeWriter code) throws CodegenException {
IfNode insn = region.getIfInsn();
code.startLine("if ").add(makeCondition(insn)).add(" {");
code.add("if ").add(makeCondition(insn)).add(" {");
makeRegionIndent(code, region.getThenRegion());
code.startLine("}");
IContainer els = region.getElseRegion();
if (els != null && RegionUtils.notEmpty(els)) {
code.add(" else {");
code.add(" else ");
// connect if-else-if block
if (els instanceof Region) {
Region re = (Region) els;
if (re.getSubBlocks().size() == 1
&& re.getSubBlocks().get(0) instanceof IfRegion) {
makeIf((IfRegion) re.getSubBlocks().get(0), code);
return;
}
}
code.add("{");
code.incIndent();
makeRegion(code, els);
code.decIndent();
......
......@@ -6,6 +6,7 @@ import jadx.dex.nodes.IContainer;
import jadx.dex.nodes.IRegion;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public final class IfRegion extends AbstractRegion {
......@@ -52,7 +53,7 @@ public final class IfRegion extends AbstractRegion {
all.add(thenRegion);
if (elseRegion != null)
all.add(elseRegion);
return all;
return Collections.unmodifiableList(all);
}
@Override
......
......@@ -8,6 +8,7 @@ import jadx.dex.nodes.IRegion;
import jadx.dex.nodes.InsnNode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public final class LoopRegion extends AbstractRegion {
......@@ -112,7 +113,7 @@ public final class LoopRegion extends AbstractRegion {
if (conditionBlock != null)
all.add(conditionBlock);
all.add(body);
return all;
return Collections.unmodifiableList(all);
}
@Override
......
......@@ -5,6 +5,7 @@ import jadx.dex.nodes.IContainer;
import jadx.dex.nodes.IRegion;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public final class SwitchRegion extends AbstractRegion {
......@@ -54,7 +55,7 @@ public final class SwitchRegion extends AbstractRegion {
all.addAll(cases);
if (defCase != null)
all.add(defCase);
return all;
return Collections.unmodifiableList(all);
}
@Override
......
......@@ -7,7 +7,7 @@ import jadx.utils.exceptions.JadxException;
import java.util.Iterator;
public class ClassCheck extends AbstractVisitor {
public class ClassModifier extends AbstractVisitor {
@Override
public boolean visit(ClassNode cls) throws JadxException {
......
......@@ -7,8 +7,6 @@ import jadx.utils.ErrorsCounter;
public class DepthTraverser {
public static void visit(IDexTreeVisitor visitor, ClassNode cls) {
// if (!cls.toString().contains("ProcessClass"))
// return;
try {
if (visitor.visit(cls)) {
for (ClassNode inCls : cls.getInnerClasses())
......
......@@ -174,6 +174,8 @@ public class DotGraphVisitor extends AbstractVisitor {
private String escape(String string) {
return string
.replace("\\", "") // TODO replace \"
.replace("/", "\\/")
.replace(">", "\\>").replace("<", "\\<")
.replace("{", "\\{").replace("}", "\\}")
.replace("\"", "\\\"")
......
package jadx.dex.visitors.regions;
import jadx.dex.nodes.BlockNode;
import jadx.dex.nodes.IContainer;
import jadx.dex.nodes.IRegion;
import jadx.dex.nodes.MethodNode;
import jadx.dex.regions.Region;
import jadx.dex.visitors.AbstractVisitor;
import jadx.utils.exceptions.JadxException;
import java.util.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CleanRegions extends AbstractVisitor {
private static final Logger LOG = LoggerFactory.getLogger(CleanRegions.class);
@Override
public void visit(MethodNode mth) throws JadxException {
if (mth.isNoCode() || mth.getBasicBlocks().size() == 0)
return;
IRegionVisitor removeEmptyBlocks = new AbstractRegionVisitor() {
@Override
public void enterRegion(MethodNode mth, IRegion region) {
if (!(region instanceof Region))
return;
for (Iterator<IContainer> it = region.getSubBlocks().iterator(); it.hasNext();) {
IContainer container = it.next();
if (container instanceof BlockNode) {
BlockNode block = (BlockNode) container;
if (block.getInstructions().isEmpty()) {
try {
it.remove();
} catch (UnsupportedOperationException e) {
LOG.warn("Can't remove block: {} from: {}, mth: {}", block, region, mth);
}
}
}
}
}
};
DepthRegionTraverser.traverseAll(mth, removeEmptyBlocks);
}
}
......@@ -79,7 +79,7 @@ public class MarkTryCatchRegions extends AbstractRegionVisitor {
TryCatchBlock prevTB = tryBlocksMap.put(domBlock, tb);
if (prevTB != null) {
LOG.info("!!! TODO merge try blocks");
LOG.info("!!! TODO merge try blocks in " + mth);
}
}
......
......@@ -113,7 +113,7 @@ public class RegionMaker {
next = BlockUtils.getNextBlock(block);
}
if (!stack.containsExit(block) && next != null && !stack.containsExit(next))
if (next != null && !stack.containsExit(block) && !stack.containsExit(next))
return next;
else
return null;
......
......@@ -28,10 +28,12 @@ public class RegionStack {
exits = new HashSet<BlockNode>();
}
private State(State c) {
exits = new HashSet<BlockNode>(c.exits);
}
public State copy() {
State c = new State();
c.exits.addAll(exits);
return c;
return new State(this);
}
@Override
......@@ -57,8 +59,10 @@ public class RegionStack {
curState = curState.copy();
curState.region = region;
if (DEBUG)
if (DEBUG) {
LOG.debug("Stack push: {} = {}", region, curState);
LOG.debug("Stack size: {}", size());
}
}
public void pop() {
......@@ -89,4 +93,9 @@ public class RegionStack {
public int size() {
return stack.size();
}
@Override
public String toString() {
return "Region stack size: " + size() + ", last: " + curState;
}
}
......@@ -19,6 +19,8 @@ public class RegionUtils {
} else if (container instanceof IRegion) {
IRegion region = (IRegion) container;
List<IContainer> blocks = region.getSubBlocks();
if (blocks.isEmpty())
return false;
return hasExitEdge(blocks.get(blocks.size() - 1));
} else {
throw new JadxRuntimeException("Unknown container type: " + container.getClass());
......
......@@ -132,6 +132,23 @@ public class TestCF extends AbstractTest {
return c;
}
public int testIfElse(String str) {
int r;
if (str.equals("a"))
r = 1;
else if (str.equals("b"))
r = 2;
else if (str.equals("3"))
r = 3;
else if (str.equals("$"))
r = 4;
else
r = -1;
r = r * 10;
return Math.abs(r);
}
public void testInfiniteLoop() {
while (true) {
System.out.println("test");
......@@ -174,6 +191,9 @@ public class TestCF extends AbstractTest {
assertEquals(c.test4(5, 9), 3240);
assertEquals(c.test4(8, 15), 0);
assertEquals(c.testIfElse("b"), 20);
assertEquals(c.testIfElse("c"), 10);
return true;
}
......
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