diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/GotoNode.java b/jadx-core/src/main/java/jadx/core/dex/instructions/GotoNode.java index c4a424dd2fb2e1a03216385c9b4b49c405a82040..a89f9bf4528353542183c68d8f4c62adc92fd526 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/GotoNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/GotoNode.java @@ -5,7 +5,7 @@ import jadx.core.utils.InsnUtils; public class GotoNode extends TargetInsnNode { - protected int target; + protected final int target; public GotoNode(int target) { this(InsnType.GOTO, target, 0); diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/IfNode.java b/jadx-core/src/main/java/jadx/core/dex/instructions/IfNode.java index e7a4ed337ce803e083a55c29daa8939d44cd76e9..a14ace1df6e821483a797ca714abb25df8be4699 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/IfNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/IfNode.java @@ -47,7 +47,6 @@ public class IfNode extends GotoNode { BlockNode tmp = thenBlock; thenBlock = elseBlock; elseBlock = tmp; - target = thenBlock.getStartOffset(); } public void changeCondition(IfOp op, InsnArg arg1, InsnArg arg2) { @@ -88,6 +87,11 @@ public class IfNode extends GotoNode { return elseBlock; } + @Override + public int getTarget() { + return thenBlock == null ? target : thenBlock.getStartOffset(); + } + @Override public boolean isSame(InsnNode obj) { if (this == obj) { diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java index 12b816ad301ae7b3811a7f93eb720d424351c3f1..757070fa72db2f4067f85c8a894df35af40875ee 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/ClassNode.java @@ -240,7 +240,6 @@ public class ClassNode extends LineAttrNode implements ILoadable, IDexNode { } } this.addAttr(new SourceFileAttr(fileName)); - LOG.debug("Class '{}' compiled from '{}'", this, fileName); } @Override @@ -486,7 +485,6 @@ public class ClassNode extends LineAttrNode implements ILoadable, IDexNode { return clsInfo.equals(other.clsInfo); } return false; - } @Override diff --git a/jadx-core/src/main/java/jadx/core/dex/regions/Region.java b/jadx-core/src/main/java/jadx/core/dex/regions/Region.java index 31d547f29a23c91fa9098dfdf410bfd5ab3d1512..9a6d9aefcf00da498edc8601ac2ad6a701caab62 100644 --- a/jadx-core/src/main/java/jadx/core/dex/regions/Region.java +++ b/jadx-core/src/main/java/jadx/core/dex/regions/Region.java @@ -5,6 +5,7 @@ import java.util.List; import jadx.core.dex.nodes.IContainer; import jadx.core.dex.nodes.IRegion; +import jadx.core.utils.Utils; public final class Region extends AbstractRegion { @@ -39,15 +40,19 @@ public final class Region extends AbstractRegion { @Override public String baseString() { StringBuilder sb = new StringBuilder(); - sb.append(blocks.size()); - for (IContainer cont : blocks) { - sb.append(cont.baseString()); + int size = blocks.size(); + sb.append('('); + sb.append(size); + if (size > 0) { + sb.append(':'); + Utils.listToString(sb, blocks, "|", IContainer::baseString); } + sb.append(')'); return sb.toString(); } @Override public String toString() { - return "R:" + baseString(); + return "R" + baseString(); } } diff --git a/jadx-core/src/main/java/jadx/core/dex/regions/conditions/IfCondition.java b/jadx-core/src/main/java/jadx/core/dex/regions/conditions/IfCondition.java index 3a2a01fb3755cb73788097f281fe00f63d8c4a4c..2d2e2454998278db1e4c26e8cdeff80ee9184b15 100644 --- a/jadx-core/src/main/java/jadx/core/dex/regions/conditions/IfCondition.java +++ b/jadx-core/src/main/java/jadx/core/dex/regions/conditions/IfCondition.java @@ -142,11 +142,10 @@ public final class IfCondition { Compare c = cond.getCompare(); simplifyCmpOp(c); if (c.getOp() == IfOp.EQ && c.getB().isLiteral() && c.getB().equals(LiteralArg.FALSE)) { - return not(new IfCondition(c.invert())); + cond = not(new IfCondition(c.invert())); } else { c.normalize(); } - return cond; } List args = null; for (int i = 0; i < cond.getArgs().size(); i++) { @@ -225,7 +224,7 @@ public final class IfCondition { case TERNARY: return first() + " ? " + second() + " : " + third(); case NOT: - return "!" + first(); + return "!(" + first() + ")"; case AND: case OR: String op = mode == Mode.OR ? " || " : " && "; diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/BlockProcessor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/BlockProcessor.java index 053d020477a2dc7d03e00d44a7c0bc0deec9f9ee..03e77dc43d7f956cad223586ab3c0b9475d4e6a0 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/BlockProcessor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/blocksmaker/BlockProcessor.java @@ -79,7 +79,6 @@ public class BlockProcessor extends AbstractVisitor { private static boolean removeEmptyBlock(BlockNode block) { if (canRemoveBlock(block)) { - LOG.debug("Removing empty block: {}", block); if (block.getSuccessors().size() == 1) { BlockNode successor = block.getSuccessors().get(0); block.getPredecessors().forEach(pred -> { diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java index e2f5035876cfd376cbc36de0bdb6b56ecad4874a..de23207f9e6da47afc7577ea4cb509370ac5c900 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/regions/RegionMaker.java @@ -12,7 +12,6 @@ import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import jadx.core.Consts; import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.nodes.EdgeInsnAttr; @@ -43,7 +42,6 @@ import jadx.core.utils.BlockUtils; import jadx.core.utils.ErrorsCounter; import jadx.core.utils.InstructionRemover; import jadx.core.utils.RegionUtils; -import jadx.core.utils.exceptions.JadxOverflowException; import jadx.core.utils.exceptions.JadxRuntimeException; import static jadx.core.dex.visitors.regions.IfMakerHelper.confirmMerge; @@ -62,12 +60,20 @@ public class RegionMaker { private final MethodNode mth; private int regionsCount; + private Region[] regionByBlock; public RegionMaker(MethodNode mth) { this.mth = mth; + this.regionByBlock = new Region[mth.getBasicBlocks().size()]; } public Region makeRegion(BlockNode startBlock, RegionStack stack) { + int startBlockId = startBlock.getId(); + Region region = regionByBlock[startBlockId]; + if (region != null) { + return region; + } + Region r = new Region(stack.peekRegion()); BlockNode next = startBlock; while (next != null) { @@ -77,6 +83,7 @@ public class RegionMaker { throw new JadxRuntimeException("Regions count limit reached"); } } + regionByBlock[startBlockId] = r; return r; } diff --git a/jadx-core/src/main/java/jadx/core/utils/BlockUtils.java b/jadx-core/src/main/java/jadx/core/utils/BlockUtils.java index 037c537c0b24271f61c8ba26bdb3ba46655501b5..5a7fc5a71c2ec756da300aa471271b043c5f2c16 100644 --- a/jadx-core/src/main/java/jadx/core/utils/BlockUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/BlockUtils.java @@ -79,9 +79,7 @@ public class BlockUtils { } if (b.contains(AFlag.SYNTHETIC)) { List s = b.getSuccessors(); - if (s.size() == 1 && s.get(0).contains(AType.EXC_HANDLER)) { - return true; - } + return s.size() == 1 && s.get(0).contains(AType.EXC_HANDLER); } return false; } @@ -156,7 +154,10 @@ public class BlockUtils { } @Nullable - public static InsnNode getLastInsn(IBlock block) { + public static InsnNode getLastInsn(@Nullable IBlock block) { + if (block == null) { + return null; + } List insns = block.getInstructions(); if (insns.isEmpty()) { return null; diff --git a/jadx-core/src/main/java/jadx/core/utils/Utils.java b/jadx-core/src/main/java/jadx/core/utils/Utils.java index 019e80f8306c4675bdd10965cd0444d415e5e857..87dd77e723b89a22f30abac0765e425f77709b07 100644 --- a/jadx-core/src/main/java/jadx/core/utils/Utils.java +++ b/jadx-core/src/main/java/jadx/core/utils/Utils.java @@ -4,6 +4,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.Arrays; import java.util.Iterator; +import java.util.function.Function; import jadx.api.JadxDecompiler; @@ -26,19 +27,30 @@ public class Utils { return 'L' + obj.replace('.', '/') + ';'; } - public static String listToString(Iterable list) { - if (list == null) { + public static String listToString(Iterable objects) { + return listToString(objects, ", "); + } + + public static String listToString(Iterable objects, String joiner) { + if (objects == null) { return ""; } - StringBuilder str = new StringBuilder(); - for (Iterator it = list.iterator(); it.hasNext(); ) { - Object o = it.next(); - str.append(o); - if (it.hasNext()) { - str.append(", "); - } + StringBuilder sb = new StringBuilder(); + listToString(sb, objects, joiner, Object::toString); + return sb.toString(); + } + + public static void listToString(StringBuilder sb, Iterable objects, String joiner, Function toStr) { + if (objects == null) { + return; + } + Iterator it = objects.iterator(); + if (it.hasNext()) { + sb.append(toStr.apply(it.next())); + } + while (it.hasNext()) { + sb.append(joiner).append(toStr.apply(it.next())); } - return str.toString(); } public static String arrayToString(Object[] array) {