use of jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair in project jadx by skylot.
the class BlockFinallyExtract method isStartBlock.
/**
* 'Finally' instructions can start in the middle of the first block.
*/
private static BlocksRemoveInfo isStartBlock(BlockNode remBlock, BlockNode startBlock) {
List<InsnNode> remInsns = remBlock.getInstructions();
List<InsnNode> startInsns = startBlock.getInstructions();
if (remInsns.size() < startInsns.size()) {
return null;
}
// first - fast check
int startPos = remInsns.size() - startInsns.size();
int endPos = 0;
if (!checkInsns(remInsns, startInsns, startPos, null)) {
if (checkInsns(remInsns, startInsns, 0, null)) {
startPos = 0;
endPos = startInsns.size();
} else {
boolean found = false;
for (int i = 1; i < startPos; i++) {
if (checkInsns(remInsns, startInsns, i, null)) {
startPos = i;
endPos = startInsns.size() + i;
found = true;
break;
}
}
if (!found) {
return null;
}
}
}
BlocksPair startPair = new BlocksPair(remBlock, startBlock);
BlocksRemoveInfo removeInfo = new BlocksRemoveInfo(startPair);
removeInfo.setStartSplitIndex(startPos);
removeInfo.setEndSplitIndex(endPos);
if (endPos != 0) {
removeInfo.setEnd(startPair);
}
// second - run checks again for collect registers mapping
if (!checkInsns(remInsns, startInsns, startPos, removeInfo)) {
return null;
}
return removeInfo;
}
use of jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair in project jadx by skylot.
the class BlockFinallyExtract method removeInsns.
private static BlocksRemoveInfo removeInsns(MethodNode mth, BlockNode remBlock, List<BlockNode> blocks, BitSet bs) {
if (blocks.isEmpty()) {
return null;
}
BlockNode startBlock = blocks.get(0);
BlocksRemoveInfo removeInfo = checkFromFirstBlock(remBlock, startBlock, bs);
if (removeInfo == null) {
return null;
}
Set<BlocksPair> outs = removeInfo.getOuts();
if (outs.size() == 1) {
return removeInfo;
}
// check if several 'return' blocks maps to one out
if (mergeReturns(mth, outs)) {
return removeInfo;
}
LOG.debug("Unexpected finally block outs count: {}", outs);
return null;
}
use of jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair in project jadx by skylot.
the class BlockFinallyExtract method mergeReturns.
private static boolean mergeReturns(MethodNode mth, Set<BlocksPair> outs) {
Set<BlockNode> rightOuts = new HashSet<BlockNode>();
boolean allReturns = true;
for (BlocksPair outPair : outs) {
BlockNode first = outPair.getFirst();
if (!first.isReturnBlock()) {
allReturns = false;
}
rightOuts.add(outPair.getSecond());
}
if (!allReturns || rightOuts.size() != 1) {
return false;
}
Iterator<BlocksPair> it = outs.iterator();
while (it.hasNext()) {
BlocksPair out = it.next();
BlockNode returnBlock = out.getFirst();
if (!returnBlock.contains(AFlag.ORIG_RETURN)) {
markForRemove(mth, returnBlock);
it.remove();
}
}
return true;
}
use of jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair in project jadx by skylot.
the class BlockFinallyExtract method checkBlocksTree.
private static boolean checkBlocksTree(BlockNode remBlock, BlockNode startBlock, BlocksRemoveInfo removeInfo, BitSet bs) {
// skip check on start block
if (!removeInfo.getProcessed().isEmpty() && !sameBlocks(remBlock, startBlock, removeInfo)) {
return false;
}
BlocksPair currentPair = new BlocksPair(remBlock, startBlock);
removeInfo.getProcessed().add(currentPair);
List<BlockNode> baseCS = startBlock.getCleanSuccessors();
List<BlockNode> remCS = remBlock.getCleanSuccessors();
if (baseCS.size() != remCS.size()) {
removeInfo.getOuts().add(currentPair);
return true;
}
for (int i = 0; i < baseCS.size(); i++) {
BlockNode sBlock = baseCS.get(i);
BlockNode rBlock = remCS.get(i);
if (bs.get(sBlock.getId())) {
if (removeInfo.getEndSplitIndex() != 0) {
// end block is not correct
return false;
}
if (!checkBlocksTree(rBlock, sBlock, removeInfo, bs)) {
return false;
}
} else {
removeInfo.getOuts().add(new BlocksPair(rBlock, sBlock));
}
}
return true;
}
use of jadx.core.dex.visitors.blocksmaker.helpers.BlocksPair in project jadx by skylot.
the class BlockFinallyExtract method sameBlocks.
private static boolean sameBlocks(BlockNode remBlock, BlockNode finallyBlock, BlocksRemoveInfo removeInfo) {
List<InsnNode> first = remBlock.getInstructions();
List<InsnNode> second = finallyBlock.getInstructions();
if (first.size() < second.size()) {
return false;
}
int size = second.size();
for (int i = 0; i < size; i++) {
if (!sameInsns(first.get(i), second.get(i), removeInfo)) {
return false;
}
}
if (first.size() > second.size()) {
removeInfo.setEndSplitIndex(second.size());
removeInfo.setEnd(new BlocksPair(remBlock, finallyBlock));
}
return true;
}
Aggregations