core: skip finally extract visitor on error
This commit is contained in:
@@ -34,4 +34,7 @@ public class DepthTraversal {
|
||||
e.getClass().getSimpleName() + " in pass: " + visitor.getClass().getSimpleName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private DepthTraversal() {
|
||||
}
|
||||
}
|
||||
|
||||
+67
-36
@@ -1,25 +1,5 @@
|
||||
package jadx.core.dex.visitors.blocksmaker;
|
||||
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.attributes.AType;
|
||||
import jadx.core.dex.attributes.nodes.IgnoreEdgeAttr;
|
||||
import jadx.core.dex.instructions.InsnType;
|
||||
import jadx.core.dex.instructions.args.InsnArg;
|
||||
import jadx.core.dex.instructions.args.RegisterArg;
|
||||
import jadx.core.dex.nodes.BlockNode;
|
||||
import jadx.core.dex.nodes.InsnNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.trycatch.CatchAttr;
|
||||
import jadx.core.dex.trycatch.ExceptionHandler;
|
||||
import jadx.core.dex.trycatch.SplitterBlockAttr;
|
||||
import jadx.core.dex.trycatch.TryCatchBlock;
|
||||
import jadx.core.dex.visitors.AbstractVisitor;
|
||||
import jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair;
|
||||
import jadx.core.dex.visitors.blocksmaker.helpers.BlocksRemoveInfo;
|
||||
import jadx.core.dex.visitors.ssa.LiveVarAnalysis;
|
||||
import jadx.core.utils.BlockUtils;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.HashSet;
|
||||
@@ -34,6 +14,30 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.core.Jadx;
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.attributes.AType;
|
||||
import jadx.core.dex.attributes.nodes.IgnoreEdgeAttr;
|
||||
import jadx.core.dex.instructions.InsnType;
|
||||
import jadx.core.dex.instructions.args.InsnArg;
|
||||
import jadx.core.dex.instructions.args.RegisterArg;
|
||||
import jadx.core.dex.nodes.BlockNode;
|
||||
import jadx.core.dex.nodes.InsnNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.trycatch.CatchAttr;
|
||||
import jadx.core.dex.trycatch.ExceptionHandler;
|
||||
import jadx.core.dex.trycatch.SplitterBlockAttr;
|
||||
import jadx.core.dex.trycatch.TryCatchBlock;
|
||||
import jadx.core.dex.visitors.AbstractVisitor;
|
||||
import jadx.core.dex.visitors.DepthTraversal;
|
||||
import jadx.core.dex.visitors.IDexTreeVisitor;
|
||||
import jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair;
|
||||
import jadx.core.dex.visitors.blocksmaker.helpers.BlocksRemoveInfo;
|
||||
import jadx.core.dex.visitors.ssa.LiveVarAnalysis;
|
||||
import jadx.core.utils.BlockUtils;
|
||||
import jadx.core.utils.ErrorsCounter;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
import static jadx.core.dex.visitors.blocksmaker.BlockSplitter.connect;
|
||||
import static jadx.core.dex.visitors.blocksmaker.BlockSplitter.insertBlockBetween;
|
||||
import static jadx.core.dex.visitors.blocksmaker.BlockSplitter.removeConnection;
|
||||
@@ -46,16 +50,34 @@ public class BlockFinallyExtract extends AbstractVisitor {
|
||||
if (mth.isNoCode() || mth.isNoExceptionHandlers()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean reloadBlocks = false;
|
||||
for (ExceptionHandler excHandler : mth.getExceptionHandlers()) {
|
||||
if (processExceptionHandler(mth, excHandler)) {
|
||||
reloadBlocks = true;
|
||||
try {
|
||||
boolean reloadBlocks = false;
|
||||
for (ExceptionHandler excHandler : mth.getExceptionHandlers()) {
|
||||
if (processExceptionHandler(mth, excHandler)) {
|
||||
reloadBlocks = true;
|
||||
}
|
||||
}
|
||||
if (reloadBlocks) {
|
||||
mergeReturnBlocks(mth);
|
||||
BlockProcessor.rerun(mth);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Undo finally extract visitor, mth: {}", mth, e);
|
||||
try {
|
||||
// reload method without applying this visitor
|
||||
// TODO: make more common and less hacky
|
||||
mth.unload();
|
||||
mth.load();
|
||||
List<IDexTreeVisitor> passes = Jadx.getPassesList(mth.root().getArgs());
|
||||
for (IDexTreeVisitor visitor : passes) {
|
||||
if (visitor instanceof BlockFinallyExtract) {
|
||||
break;
|
||||
}
|
||||
DepthTraversal.visit(visitor, mth);
|
||||
}
|
||||
} catch (Exception ee) {
|
||||
LOG.error("Undo finally extract failed, mth: {}", mth, e);
|
||||
}
|
||||
}
|
||||
if (reloadBlocks) {
|
||||
mergeReturnBlocks(mth);
|
||||
BlockProcessor.rerun(mth);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,7 +243,7 @@ public class BlockFinallyExtract extends AbstractVisitor {
|
||||
}
|
||||
|
||||
private static void performVariablesReMap(MethodNode mth, List<BlocksRemoveInfo> removes,
|
||||
LiveVarAnalysis laBefore, LiveVarAnalysis laAfter) {
|
||||
LiveVarAnalysis laBefore, LiveVarAnalysis laAfter) {
|
||||
BitSet processed = new BitSet(mth.getRegsCount());
|
||||
for (BlocksRemoveInfo removeInfo : removes) {
|
||||
processed.clear();
|
||||
@@ -390,7 +412,7 @@ public class BlockFinallyExtract extends AbstractVisitor {
|
||||
}
|
||||
|
||||
private static boolean checkInsns(List<InsnNode> remInsns, List<InsnNode> startInsns, int delta,
|
||||
@Nullable BlocksRemoveInfo removeInfo) {
|
||||
@Nullable BlocksRemoveInfo removeInfo) {
|
||||
for (int i = startInsns.size() - 1; i >= 0; i--) {
|
||||
InsnNode startInsn = startInsns.get(i);
|
||||
InsnNode remInsn = remInsns.get(delta + i);
|
||||
@@ -402,7 +424,7 @@ public class BlockFinallyExtract extends AbstractVisitor {
|
||||
}
|
||||
|
||||
private static boolean checkBlocksTree(BlockNode remBlock, BlockNode startBlock,
|
||||
@NotNull BlocksRemoveInfo removeInfo, BitSet bs) {
|
||||
@NotNull BlocksRemoveInfo removeInfo, BitSet bs) {
|
||||
// skip check on start block
|
||||
if (!removeInfo.getProcessed().isEmpty()
|
||||
&& !sameBlocks(remBlock, startBlock, removeInfo)) {
|
||||
@@ -436,7 +458,7 @@ public class BlockFinallyExtract extends AbstractVisitor {
|
||||
}
|
||||
|
||||
private static boolean sameBlocks(BlockNode remBlock, BlockNode finallyBlock,
|
||||
@NotNull BlocksRemoveInfo removeInfo) {
|
||||
@NotNull BlocksRemoveInfo removeInfo) {
|
||||
List<InsnNode> first = remBlock.getInstructions();
|
||||
List<InsnNode> second = finallyBlock.getInstructions();
|
||||
if (first.size() < second.size()) {
|
||||
@@ -495,6 +517,12 @@ public class BlockFinallyExtract extends AbstractVisitor {
|
||||
LOG.warn("Finally extract failed: remBlock pred: {}, {}, method: {}", remBlock, remBlock.getPredecessors(), mth);
|
||||
return false;
|
||||
}
|
||||
if (removeInfo.getOuts().isEmpty()) {
|
||||
ErrorsCounter.methodError(mth, "Failed to extract finally block: empty outs");
|
||||
return false;
|
||||
}
|
||||
// safe checks finished, altering blocks tree
|
||||
// all error must throw exception to undo changes
|
||||
|
||||
BlockNode remBlockPred = remBlock.getPredecessors().get(0);
|
||||
removeInfo.setStartPredecessor(remBlockPred);
|
||||
@@ -534,7 +562,11 @@ public class BlockFinallyExtract extends AbstractVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
BlocksPair out = removeInfo.getOuts().iterator().next();
|
||||
Set<BlocksPair> outs = removeInfo.getOuts();
|
||||
if (outs.isEmpty()) {
|
||||
throw new JadxRuntimeException("Failed to extract finally block: all outs is deleted");
|
||||
}
|
||||
BlocksPair out = outs.iterator().next();
|
||||
BlockNode rOut = out.getFirst();
|
||||
BlockNode sOut = out.getSecond();
|
||||
|
||||
@@ -556,8 +588,7 @@ public class BlockFinallyExtract extends AbstractVisitor {
|
||||
BlockNode pred = filtPreds.get(0);
|
||||
BlockNode repl = removeInfo.getBySecond(pred);
|
||||
if (repl == null) {
|
||||
LOG.error("Block not found by {}, in {}, method: {}", pred, removeInfo, mth);
|
||||
return false;
|
||||
throw new JadxRuntimeException("Block not found by " + pred + ", in " + removeInfo);
|
||||
}
|
||||
removeConnection(pred, rOut);
|
||||
addIgnoredEdge(repl, rOut);
|
||||
|
||||
Reference in New Issue
Block a user